Thursday, May 22, 2014

git add --update :/

What git command should be used to add files to your git index?

It depends ™
  • Do you want to recursively add every file modification (created, modified, deleted)?
  • Are you using git client version 2.0 or more recent?

If so, then this command should work great for you.

Want to add absolutely every file, whether it's tracked or not, and process deleted files, too?

If so, please continue reading...

Create a Git Aliases

You can create a global git aliases like this:

$ git config --global alias.untracked 'ls-files --other --exclude-standard'
$ git config --global alias.add-untracked '!f() { files=(`git untracked`);for file in "${files[@]}"; do cmd="git add \""$file"\""; eval $cmd; done; }; f'
$ git config --global alias.add-updated 'add --update :/'
$ git config --global alias.add-all '!git add-updated && git add-untracked'

Subsequently, you can add all file modifications (including untracked files) like this:

$ git add-all


Fix for files with spaces in the filename

Previously, the following failed to add files with spaces in the filename:

git config --global alias.add-untracked '!git add $(git untracked)'

The exclamation point character "!" allows us to execute shell commands.

You should get a warning message if you run the git add-all command and there were no files to add to the git index aka "staging area".

$ git add-all
Nothing specified, nothing added.
Maybe you wanted to say 'git add .'?

Commit and Push

After adding files to the index, you'll want to atomically commit the changes, with a comment, and push those changes to the git repo.

$ git commit -m "Descriptive comment here"

If you want to push your changes to a remote repo, configure it like this:

$ git remote add origin<account>/<projectname>.git

Now, you can push your changes from your local git repo to the remote git repo:

$ git push

add-all is Better Than add -A

Most Git commands that can be used with or without pathspec operate tree-wide by default, the pathspec being used to restrict their scope. A few exceptions are: 'git grep', 'git clean', 'git add -u' and 'git add -A'. When run in a subdirectory without pathspec, they operate only on paths in the current directory.

The inconsistency of 'git add -u' and 'git add -A' is particularly problematic since other 'git add' subcommands (namely 'git add -p' and 'git add -e') are tree-wide by default. It also means that "git add -u && git commit" will record a state that is different from what is recorded with "git commit -a".

Flipping the default now is unacceptable, so let's start training users to type 'git add -u|-A :/' or 'git add -u|-A .' explicitly, to prepare for the next steps:

* forbid 'git add -u|-A' without pathspec (like 'git add' without option)

* much later, maybe, re-allow 'git add -u|-A' without pathspec, that will add all tracked and modified files, or all files, tree-wide.

A nice side effect of this patch is that it makes the :/ magic pathspec easier to discover for users.

When the command is called from the root of the tree, there is no ambiguity and no need to change the behavior, hence no need to warn.

One Command to Add, Commit and Push

Leveraging the git aliases that we previously created, we create two more:

$ git config --global alias.add-commit '!f() { git add-all && git commit -m "$1"; }; f'
$ git config --global alias.acp '!f() { git add-commit "$1" && git push; }; f'

Subsequently, you can add all file modifications (including untracked files), commit with comment and push the commit to your repo like this:

git acp 'Descriptive comment here'


Notice that we defined a shell script function to pass parameters to multiple chained shell commands.

Tell Git to Only Push the HEAD of Your Branch

If you get and error like the following...

$ git acp 'update 1, add 1'
[master ff5b42b] update 1, add 1
 2 files changed, 25 insertions(+), 3 deletions(-)
 create mode 100755 new-file-name-here
fatal: The current branch master has multiple upstream branches, refusing to push.

...Then, tell git to push the HEAD of your branch, which is likely "master".

$ git config remote.origin.push HEAD


No comments:

Post a Comment