Git : Tips & Tricks

Git is a really powerful tool but it can sometimes be hard to grasp some concepts and the way of doing some things is convoluted.

In the following post, I’ll try to list a few tips and tricks to make your life easier.

Thanks to my colleagues and all the people on the Internet for those !

Ignore whitespace changes

We start with probably the most known one : ignore whitespace when doing a diff. Some of you may know that it suffice to add ?w=1 to the github changes URL to start ignore whitespaces, you can do exactly the same on the command line by adding the -w argument to git :

This will make code reviews a lot easier when you had to change the indentation of your code for example.

Delete whitespace changes

In the same vein as the previous tip, there is also a way to stage only non-whitespace changed by running the following command :

We first generate a diff without them, and disable colors to be on the safe side, and then apply this patch. After running this, you will have the changes staged and all the whitespace will be unstaged. You can clear them by running git checkout -- ..

If you want to can add this to your git aliases to have a handy command :

Highlight word changes

Github users will know that the exact change is highlighted there instead of just the whole line, this makes reviewing code easier. You can achieve the same thing on the command line multiple way.

The easier one is to simply use the --word-diff=color argument :

You can even change the regex used to match words, for example, to add the comma as word separator, --word-diff-regex="[^[:space:],]+".

There is also a bit more complicated way which leads to better result : using the the diff-highlight script shipped with git. The script is not available in all git installation, you may need to download it and put it somewhere on your hard drive. Once you have located the script, simply add the following to your configuration file :

This will activate it for all commands, if you want to limit it to some only, you can configure each pager individually : pager.diff, pager.log, pager.show, pager.<cmd>.

Quickly see all tags

git tag lists all tags, but does not really display useful informations. You can do a lot better with :

Or as an alias :

Graphical Log

git log does not really convey information about merges, this is where the --graph attribute is coming handy. With some more tuning, it becomes this alias :

This alias is just a start, you can configure the output a lot more. For example see this StackOverflow answer : Pretty git branch graphs

Clean merged branches

In most git workflow, you end up creating a lot of branches. Once they are merged in your master branch, they usually aren’t useful anymore. You can easily list all branches merged in the current branch :

Here’s how you can delete them :

Be careful running those. You can just display the branched that will be deleted by removing the last | and everything after.

Once you’ve cleaned remote branches, you should advise everyone including you to run the following to cleanup any renmants of those branches :

git remote prune origin

If you want more tips about git spring cleaning head to Git housekeeping tutorial

Package of your repository

You can easily create archives of your repository with the archive command :

What is a little less known, is that archive will respect the export-ignore attribute in your .gitattributes file.

As an added bonus, some packaging tools, like Composer, will also ignore those files when creating the package thus saving bandwidth and disk space for everyone.

Add only part of the changes

How many times are you ready to commit some code only to realize that it would make a lot more sense if you could do it in multiple commits. It’s pretty easy to do when you just want to separate changes made to different files, but you can also easily stage only part of the modifications done to a single file by using the -p switch.

When running git add -p, git will ask you what to do with each “hunk” (or code part). It will interactively ask you what to do for each group of changes it detects in a file. At any time you can issue the ? to see all possible answers, the most used being :

  • y to stage this modification
  • n to keep this modification in the working copy
  • s to split the modification in smaller parts

Ignore modifications to a committed file

It happens more often than not that you need to do some modifications on a file that you don’t want committed. It maybe to change some configuration specific to your own environment or simply some debug code you use often.

If the file you’ve modified is already committed, .gitignore will not help you and the modification will always show when running status or diff and you have the risk of accidentally commit it.

You can use the update-index command to tell git to ignore changes made to a certain file like this :

Be aware than any further change to this file will also be ignored by git. If you want to revert the “assume unchanged” status, simply run :

Diff contextual information

Depending on the language you use, you eventually already saw that git tries to give you context information for each modification when doing a diff. This is called a hunk header and you can modify it to suites your need.

Say we want to modifiy how PHP hunks are contextualized. First we need to specify the diff driver to use for PHP files in your .gitattributes file :

For PHP this should suffice, because git already ships a corresponding diff driver. However, if you want to change the header anyway or add a new definition, add this in your .gitconfig :

Git will then go backward from the modification and display the first line that matches the regex you configured. For more details, you can head to the official gitattributes documentation.

Easy commit fixup

When working on a feature, it happens that you want to do a commit that fixes something you commited earlier. Sure you can simply commit and then do some rebase magic, but what if I told you there’s a better way ?

Say my history looks like this :

If I want to fix something introduced in the second commit I can simply do :

Notice the fixup! prefix of the commit message ? Now git can use this information to automatically rebase your changes :

This will open an interactive rebase editor session like you are accustomed to, but your fixup commit will be automatically placed correctly in the list with the correct action :

Usually, it’s now only a matter of accepting the rebase as is and tada !

If you want to aleays autosquash you can simply add it to your config :

I also defined some aliases to help :

rerere : Reuse Recorded Resolution

rerere is a feature of git that automatically records conflict resolution upon merges and is then able to reapply them automatically when the same conflicts arise again.

I personnaly didn’t find any usecase in my day to day job justifying the use of rerere, but the following Medium article can be of help to people having sharing the same workflow as the other : Fix conflicts only once with git rerere

The reflog : never loose a commit again

History modification is great in some cases but can also lead to loosing some commits on your branches. Fear not, you can retrieve them.

The git reflog command displays all action that were made on the working copy including all commits. Just find the lost commit in the list, copy its hash and then reapply it where ever you want by using the cherry-pick command.

reflog is also a great command to use when you are wondering what the heck you could have done today ;)

Tig

Tig is a console Git browser a bit like the GitHub client or Sourcetree but that works in any terminal. It is a great tool if you don’t like the command line but still have to sometimes work over SSH on some servers.

Describing the features would be out of scope from this blog post, so I’ll just link you to the homepage : Tig.

Autocorrect commands

If you often do typos when writing git commands, just do :

Now git can autocorrect your errors for you :

Only blame on certain things

Sometimes a coworker reindent some code or move some lines around or to a completely different files. When trying to understand the origin of some lines those kind of changes get of the way of using blame efficiently. Fortunately, git is so powerful that even that can’t stop you :

Be aware that this renders the command slower however.

Add comments to commmit

Even wanted to add some comments to a commit ? It is possible with Git.

However, the feature is not really usable, but it may be come in handy some times so here’s the link to a nice blog post explaining everything : Note to Self.

Safer push force (Thanks Odi !)

It shouldn’t happen, but we all know how things are, sometimes you have to make a push --force on a branch. Let met tell you it can be a lot more secure using git push --force-with-lease. Using this option, Git will first check if the last commit you fetched from the remote is still the last one. If not, the push will be aborted, avoiding that you overwrite changes made by your co-workers !

There’s no shorthand for this command, but you can create an alias :

Final words

Those are the tips and tricks I learned during the years I’ve been using Git. Some I use daily, some I just keep around for when the need arise. I hope those will be useful to you !

If you find the list lacking, please feel free to add your own tips in the comments and I’ll update the post with them !

You can also have a look at the following ressources :

Added a new tip from http://metaodi.ch/ about safer push –force. Thanks !

Great tips, especially the “fixup!” one. thanks!

Have you ever considered about adding a little bit more than just your articles?
I mean, what you say is valuable and everything.
But think of if you added some great photos or videos to
give your posts more, “pop”! Your content is excellent but with pics and video clips,
this blog could certainly be one of the very best in its field.
Awesome blog!

Leave a Reply