Date Category tech

Git is a fast, lightweight, and powerful revision control system. One of its strengths is that it is built on simple primitive actions, which can be woven together to build some robust workflows. This can come in the form of third-party tools, or even in the more advanced commands available in git itself.

One such advanced workflow is offered by the -p (--patch) option that is available in several everyday git commands:

git add -p
git reset -p
git checkout -p

These are simple commands that allow you to manipulate the index and/or working copies of files in your tree. While using git, you probably use each of these on a daily basis. When you’ve made a single change, or a couple small changes, a quick add and commit generally gets the job done and lets you move on.

However, often these commands can be too coarse, as they operate at the level of entire files rather than the individual changes within those files. If you need to perform fine-grained operations, the -p option makes it trivial:

$ git add -p
diff --git a/NEWS b/NEWS
index c12bd99..d644597 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,6 @@
+  * Fixed a bug opening files (and toggling breakpoints in files) with
+    special characters (e.g. space) in their names.
cgdb-0.6.6 (09/06/2011)

* Fixed a compile error on Cygwin 1.7 (signature for path conversion
Stage this hunk [y,n,q,a,d,/,e,?]?

With -p, git walks through each “hunk” of changes in your working tree and prompts you to stage them (or not). This way, you get to review each change and decide whether or not it belongs in your next commit.

Sometimes using git at the command line can feel like working in the dark — you’re performing operations on files whose contents and changes are not even visible right now. Often, out of paranoia, you end up running a command like diff --cached (or similar) to see what’s about to happen before you commit. -p can be a candle in the dark, allowing you to manipulate your changes with more confidence.

Advantages of this approach:

  • Easily break up logically distinct changes into multiple commits, rather than having one monster commit that touches many features.
  • Stage your intentional, functional changes while leaving any temporary debugging code unstaged. This lets you keep your debugging statements around while you work on the next change.
  • Perhaps most importantly, this is a mini-code review of the changes you’re about to commit. Use this opportunity to catch stupid mistakes before they end up in the repository: typos, TODOs you forgot, temporary changes (commented out code, debugging statements), and so on.

Finally, as I mentioned above, the -p option is also available for reset and checkout, and behaves analagously to the add command. This lets you unstage individual hunks from the index (with reset) or roll them back from your working files (with checkout).