Commit only part of a file in Git

When I make changes to a file in Git, how can I commit only some of the changes?

For example, how could I commit only 15 lines out of 30 lines that have been changed in a file?


Solution 1:

You can use git add --patch <filename> (or -p for short), and git will begin to break down your file into what it thinks are sensible "hunks" (portions of the file). It will then prompt you with this question:

Stage this hunk [y,n,q,a,d,/,j,J,g,s,e,?]?

Here is a description of each option:

  • y stage this hunk for the next commit
  • n do not stage this hunk for the next commit
  • q quit; do not stage this hunk or any of the remaining hunks
  • a stage this hunk and all later hunks in the file
  • d do not stage this hunk or any of the later hunks in the file
  • g select a hunk to go to
  • / search for a hunk matching the given regex
  • 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
  • e manually edit the current hunk
    • You can then edit the hunk manually by replacing +/- by # (thanks veksen)
  • ? print hunk help

If the file is not in the repository yet, you can first do git add -N <filename>. Afterwards you can go on with git add -p <filename>.

Afterwards, you can use:

  • git diff --staged to check that you staged the correct changes
  • git reset -p to unstage mistakenly added hunks
  • git commit -v to view your commit while you edit the commit message.

Note this is far different than the git format-patch command, whose purpose is to parse commit data into a .patch files.

Reference for future: Git Tools - Interactive Staging

Solution 2:

You can use git add --interactive or git add -p <file>, and then git commit (not git commit -a); see Interactive mode in git-add manpage, or simply follow instructions.

Modern Git has also git commit --interactive (and git commit --patch, which is shortcut to patch option in interactive commit).

If you prefer doing it from GUI, you can use git-gui. You can simply mark chunks which you want to have included in commit. I personally find it easier than using git add -i. Other git GUIs, like QGit or GitX, might also have this functionality as well.

Solution 3:

git gui provides this functionality under the diff view. Just right click the line(s) you're interested in and you should see a "stage this line to commit" menu item.

Solution 4:

I believe that git add -e myfile is the easiest way (my preference at least) since it simply opens a text editor and lets you choose which line you want to stage and which line you don't. Regarding editing commands:

added content:

Added content is represented by lines beginning with "+". You can prevent staging any addition lines by deleting them.

removed content:

Removed content is represented by lines beginning with "-". You can prevent staging their removal by converting the "-" to a " " (space).

modified content:

Modified content is represented by "-" lines (removing the old content) followed by "+" lines (adding the replacement content). You can prevent staging the modification by converting "-" lines to " ", and removing "+" lines. Beware that modifying only half of the pair is likely to introduce confusing changes to the index.

Every details about git add are available on git --help add

Solution 5:

If you are using vim, you may want to try the excellent plugin called fugitive.

You can see the diff of a file between working copy and index with :Gdiff, and then add lines or hunks to the index using classic vim diff commands like dp. Save the modifications in the index and commit with :Gcommit, and you're done.

Very good introductory screencasts here (see esp. part 2).