About Articles Projects Links Apps Feed

Git Pro-tips

Add hunks selectively

One of Git’s best practice is to limit every commit to an atomic change. Should your contribution require several changes to the code, it should result in just as many commits.

Sometimes we get carried away, or we simply don’t foresee the extent of our current work. When the time has come to commit, we realize that several, independent changes have occurend into the same file.

Git has a nice command that lets the user select individual hunks for staging:

$ git add --patch

This might prove daunting from the command-line. A UI can be very practical for this.

Converting repositories from another VCS

Want to revamp a project using another VCS? No problem, Git can import many VCS, such as Subversion. See git-svn(1) for the gory details.


$ git stash

In the middle of an intense hacking session, stashes allow you to save some chunks, revert to a clean workspace, keep on hacking, re-apply the previous chunk, revert, etc. All without commiting anything.

It is also possible to stash the current hack and to keep working on it. A temporary save, in a way.

$ git stash && git stash apply

Custom logs

Logs decoration can be heavily customized. For instance:

$ git log --graph --decorate --pretty=format:'%C(yellow)%h %Cgreen%cd%C(bold red)%d%Creset %s' --abbrev-commit --date=short


To highlight differences to the word:

$ git diff --color-words

Most importantly, use a UI for diff’ing between any commits, it helps a lot.

Merging with Ediff

Add this to .gitconfig:

cmd = emacs --eval \" (progn (defun ediff-write-merge-buffer () (let ((file ediff-merge-store-file)) (set-buffer ediff-buffer-C) (write-region (point-min) (point-max) file) (message \\\"Merge buffer saved in: %s\\\" file) (set-buffer-modified-p nil) (sit-for 1))) (setq ediff-quit-hook 'kill-emacs ediff-quit-merge-hook 'ediff-write-merge-buffer) (ediff-merge-files-with-ancestor \\\"$LOCAL\\\" \\\"$REMOTE\\\" \\\"$BASE\\\" nil \\\"$MERGED\\\"))\"

tool = ediff


Some text files may not be “versionable” in that they are hardly human-readable, it not at all (e.g.¬†generated content). A few good examples include .ps, .svg, and most XML-based files.

Git will treat all text files as such and store the diffs when necessary. This will increase disk-space consumption (and bandwidth) and slow down the repository.

You can tell Git to ignore the diff’s for specific extensions:

$ cat .gitattributes
*.pdf -diff
*.ps -diff
*.svg -diff
*.xml -diff

With such a setting, a Git repository can serve as a powerful cloud-based storage service.



$ git gc

and be surprised by how much your repository just shrank!

Rebase interactively

Rebasing can be a hassle. Thankfully Git comes with the very handy --interactive option to overview the whole operation from your favorite text editor:

$ git rebase -i

Delete file from history

Sometimes we need to carry a big binary blob with us. And more often than not we regret our decision!

It is never too late, and assuming the history is not public, you can rewrite it, alleviating it from its binary burden.

A few initial checks are in order:

  • Check for the largest files:

    $ git verify-pack -v .git/objects/pack/${pack-name}.idx | sort -k 3 -n | tail -5
  • Check what files those are:

    $ git rev-list --objects --all | grep ${object}

Time to remove the file ${FILENAME} from the revision: Action!

$ git filter-branch --index-filter 'git rm --cached --ignore-unmatch ${FILENAME}'

Next, some clean-up might be necessary:

  • Remove Git’s backup

    $ rm -rf .git/refs/original/
  • Expire all the loose objects:

    $ git reflog expire --all --expire='0 days'
  • Check if there are any loose objects:

    $ git fsck --full --unreachable
  • Repack everything, leaving loose objects behind:

    git repack -A -d
  • At last, remove the loose objects:

    $ git prune


While the git CLI is great and will get you far, I recommend using a dedicated UI such as the excellent Magit. It will ease many operations:

  • Adding hunks of code.
  • Choosing commits for diffing, etc.
  • Displaying commit contents interactively.
  • And much more. (See the website.)


Date: 2016-09-28 (Last update: 2018-08-11)

Made with Emacs 27.2 (Org mode 9.4.4)

Creative Commons License