Cute Git Tip

July 17, 2009
Happiness by Sabrina Campagna cc-by

Happiness by Sabrina Campagna cc-by

I was hanging out in the lobby of the Catalina Park Appartments last week writing some code when I was approached by Diederik van der Boor (of KMess fame) who was also hacking away and had a question about Git.

  • Diederik: are you an expert on git by any chance?
  • Me: hardly, but what is the question?
  • Diederik: I just made a few changes to a single file and was wondering if it is possible to commit specific chunks?
  • Me: hmmmm… don’t think so but that would be really cool!!!

He went back to his chair and I immediately starting scouring the web for more information about this. Luckly, one of the very first hits I got back was Ryan Tomayko‘s post called “The Thing About Git“! I had barely read the entire article when I shouted to Diederik: “I think I found a solution! You better come over here and sit down!” What followed then were several minutes of more reading, sprinkled with a lot of drooling and happy exclamations from both of us!

I highly recommend you read the article, but the short answer is to use:

git add --patch [modifed-file-name]

In other words, say you’ve modifed the files foo.py and bar.py. Committing these 2 files with all their changes is straight forward, but what if you only wanted to perform a partial commit of your changes to bar.py? Easy enough! Commit foo.py as usual and use the –patch “flag” to commit bar.py.

“This instructs Git to display all changes to the files specified on a hunk-by-hunk basis and lets you choose one of the following options for each hunk:

  • y – stage this hunk
  • n – do not stage this hunk
  • a – stage this and all the remaining hunks in the file
  • d – do not stage this hunk nor any of the remaining hunks in the file
  • j – leave this hunk undecided, see next undecided hunk
  • J – leave this hunk undecided, see next hunk
  • k – leave this hunk undecided, see previous undecided hunk
  • K – leave this hunk undecided, see previous hunk
  • s – split the current hunk into smaller hunks” (Ryan Tomayko)
  • So, in other words:

    git add foo.py
    git add --patch bar.py

    I don’t know about you but this neat little trick made my day!

    9 Comments for this entry

    • git add -i is an interactive form of the same thing. It has little helpful menus and everything. Highly recommended.

    • david says:

      see also git add –interactive for handling multiple files.
      git add -A –interactive

    • Jose says:

      An easier way to do this is to use ‘git gui’ or ‘git citool’.
      Right click anywhere in the diff and you can add chuncks or lines. It’s really easy to reset chunks from the index also.

      I use it all the time.

    • Matt Enright says:

      Git 101 – easily one of the most-used features once you get in the habit of it!

      Coming in the next release will also be add -e (currently in ‘next’), which allows you to manually edit the patch, which is also surprisingly addictive.

    • I absolutely love git add -p, but there’s an important gotcha to look out for: when you use this, you will be committing a set of code that you have probably never actually even compiled as-is, let alone tested. And if you have a lot of chunks and don’t want a decent number of them, it’s easy to accidentally say ‘n’ when you mean ‘y’, or vice versa.

      So it’s usually a good idea to do something like:

      git add -p $FILES &&
      git commit -m “$COMMIT_MSG” &&
      git stash &&
      make &&
      $RUN_APP &&
      git stash apply

      … just to make sure everything works as you expect. If not, you can always ‘git reset –soft HEAD^’ after committing.

    • Anders says:

      I have been missing this feature from Subversion since … forever. Any similar tricks for Subversion?

    • Jose Fonseca says:

      “git gui” can do the same things from a much easier to use graphical interface. It can even (un)stage individual lines, and adjust the number of context lines around the hunks (to split nearby hunks in smaller ones).

    • Sven says:

      Thanks for pointing out this tip, I transfered it to my blog with some details. Thank you :-)

    • Simon says:

      That’s handy (as are all the other comments about git gui)…

    2 Trackbacks / Pingbacks for this entry

    Leave a Reply

    Your email address will not be published. Required fields are marked *

    *

    *


    You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>