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?
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?
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:
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 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, which purpose is to parse commit data into a .patch
files.
Reference for future: https://git-scm.com/book/en/v2/Git-Tools-Interactive-Staging
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.
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.
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
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).
I would strongly recommend using SourceTree from Atlassian. (It\'s free.) It makes this trivial. You can stage individual hunks of code or individual lines of code quickly and easily.
Worth noting that to use git add --patch
for a new file you need to first add the file to index with git add --intent-to-add
:
git add -N file
git add -p file
When I have a lot of changes, and will end up creating a few commits from the changes, then I want to save my starting point temporarily before staging things.
Like this:
$ git stash -u
Saved working directory and index state WIP on master: 47a1413 ...
$ git checkout -p stash
... step through patch hunks
$ git commit -m \"message for 1st commit\"
$ git checkout -p stash
... step through patch hunks
$ git commit -m \"message for 2nd commit\"
$ git stash pop
Whymarrh\'s answer is what I usually do, except sometimes there are lots of changes and I can tell I might make a mistake while staging things, and I want a committed state I can fall back on for a second pass.
Should you use emacs, take a look at Magit, which provides a git interface for emacs. It supports staging hunks (parts of files) quite well.
Much like jdsumsion\'s answer you can also stash your current work but then use a difftool like meld to pull selected changes from the stash. That way you can even edit the hunks manually very easy, which is a bit of a pain when in git add -p
:
$ git stash -u
$ git difftool -d -t meld stash
$ git commit -a -m \"some message\"
$ git stash pop
Using the stash method gives you the opportunity to test, if your code still works, before you commit it.
For those who use Git Extensions:
In the Commit window, select the file you want to partially commit, then select the text you want to commit in the right pane, then right-click on the selection and choose \'Stage selected lines\' from the context menu.
Intellij IDEA (and I guess all other products of the series) has built in support for partial commits since v2018.1
vim-gitgutter plugin can stage hunks without leaving vim editor using
:GitGutterStageHunk
Beside this, it provides other cool features like a diff sign column as in some modern IDEs
If only part of hunk should be staged vim-fugitive
:Gdiff
allows visual range selection then :\'<,\'>diffput
or :\'<,\'>diffget
to stage/revert individual line changes.
Tried out git add -p filename.x
, but on a mac, I found gitx (http://gitx.frim.nl/ or https://github.com/pieter/gitx) to be much easier to commit exactly the lines I wanted to.
With TortoiseGit:
right click on the file and use
Context Menu → Restore after commit
. This will create a copy of the file as it is. Then you can edit the file, e.g. in TortoiseGitMerge and undo all the changes you don\'t want to commit. After saving those changes you can commit the file.
For emacs there is also gitsum
git-meld-index -- quoting from the website:
git-meld-index runs meld -- or any other git difftool (kdiff3, diffuse, etc.) -- to allow you to interactively stage changes to the git index (also known as the git staging area).
This is similar to the functionality of git add -p, and git add --interactive. In some cases meld is easier / quicker to use than git add -p. That\'s because meld allows you, for example, to:
Usage
In a git repository, run:
git meld-index
You\'ll see meld (or your configured git difftool) pop up with:
LEFT: temporary directory contining files copied from your working tree
RIGHT: temporary directory with the contents of the index. This also includes files that are not yet in the index but are modified or untracked in the working copy -- in this case you\'ll see the file contents from HEAD.
Edit the index (right hand side) until happy. Remember to save when needed.
When you\'re done, close meld, and git-meld-index will update the index to match the contents of the temporary directory on the right hand side of meld that you just edited.
As one answer above shows, you can use
git add --patch filename.txt
or the short-form
git add -p filename.txt
... but for files already in you repository, there is, in s are much better off using --patch flag on the commit command directly (if you are using a recent enough version of git):
git commit --patch filename.txt
... or, again, the short-form
git commit -p filename.txt
... and then using the mentioned keys, (y/n etc), for choosing lines to be included in the commit.
For Atom users, the package github includes interactive staging, in the style of git gui
. For shortcuts see the package\'s documentation.
Using Atom allows working with a theme that has dark background (by default, git gui
has a white background).
Adding on a previous answer, if you prefer using the command line, entering git add -e myfile
gives you the choice to choose line by line what you want to commit because this command will open an editor with the differences, like so:
As you may known lines that start with +
are addtions, lines that start with -
are deletions. So:
-
with space
.This is what git add -h
says about adding files this way (patching files):
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.
Caution: do not change the content of the file, this is not a good place to do so. Just change the operators of deleted or added lines.
If it\'s on Windows
platform, in my opinion git gui
is the best tool to stage
/commit
few lines from unstaged
file
1. Hunk wise:
unstagged Changes
sectionStage Hunk for commit
2. Line wise:
unstagged Changes
section Stage Lines for commit
3. If you want to stage the complete file except couple of lines:
unstagged Changes
sectionCtrl+T (Stage file to commit)
Staged Changes
SectionUnStage Lines for commit
git-cola is a great GUI and also has this feature built-in. Just select the lines to stage and press S. If no selection is made, the complete hunk is staged.