Commit only part of a file in Git
GitGit CommitGit Problem Overview
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?
Git Solutions
Solution 1 - Git
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)
- You can then edit the hunk manually by replacing
- ? 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 changesgit reset -p
to unstage mistakenly added hunksgit 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 - Git
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-add]: http://www.kernel.org/pub/software/scm/git/docs/git-add.html "git-add - Add file contents to the index" [git-gui]: http://www.kernel.org/pub/software/scm/git/docs/git-gui.html "it-gui - A portable graphical interface to Git" [gitk]: http://www.kernel.org/pub/software/scm/git/docs/gitk.html "gitk - The git repository browser" [answer:1085202]: http://stackoverflow.com/questions/1085162/i-want-to-do-commit-of-the-part-of-the-file-in-git/1085202#1085202
Solution 3 - Git
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 - Git
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 - Git
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.
Solution 6 - Git
If you're using VS Code, you're in luck. Select the range that you want to stage, then use Git: Stage Selected Ranges
to stage them, and commit if you want.
I recorded a gif to demonstrate what I meant:
Solution 7 - Git
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.
Solution 8 - Git
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
Solution 9 - Git
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.
Solution 10 - Git
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:
- To not stage an addition just delete that line.
- To not stage a deletion just replace
-
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.
Solution 11 - Git
Should you use emacs, take a look at https://github.com/magit/magit">Magit</a>;, which provides a git interface for emacs. It supports https://magit.vc/manual/magit/Staging-and-Unstaging.html">staging hunks (parts of files) quite well.
Solution 12 - Git
IntelliJ IDEA (and I guess all other products of the series) has built-in support for partial commits since v2018.1.
Solution 13 - Git
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.
Solution 14 - Git
It's been 10 years since this question was asked. And I hope this answer will be useful to someone. As mentioned in the answer here, where GUI is not an option, Andrej Shadura's git-crecord tool helps bring an interactive window in which we can select the lines to commit.
Set up the extension as follows:
git clone https://github.com/andrewshadura/git-crecord
cd git-crecord
./setup.py install
ln -s $PWD/git-crecord ~/.local/bin/git-crecord
cd to your git repo and invoke it as follows:
git crecord
This would bring up an interactive interface which can be used as shown below. Pressing the following keys will do certain actions:
f hunk toggle fold (arrow keys can also be used)
space toggle hunk selection
a toggle commit or amend
c confirm and open commit window
Screencast showing a sample usage
Solution 15 - Git
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.
Solution 16 - Git
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.
Solution 17 - Git
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.
Solution 18 - Git
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.
Solution 19 - Git
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).
Solution 20 - Git
If it's on Windows
platform, in my opinion git gui
is very good tool to stage
/commit
few lines from unstaged
file
1. Hunk wise:
- Select the file from
unstagged Changes
section - Right click chunk of code which needs to be staged
- Select
Stage Hunk for commit
2. Line wise:
- Select the file from
unstagged Changes
section - Select the line/lines to be staged
- Right click and select
Stage Lines for commit
3. If you want to stage the complete file except couple of lines:
- Select the file from
unstagged Changes
section - Press
Ctrl+T (Stage file to commit)
- Selected file now moves to
Staged Changes
Section - Select the line/lines be staged
- Right click and select
UnStage Lines for commit
Solution 21 - Git
For emacs there is also http://github.com/chneukirchen/gitsum">gitsum</a>
Solution 22 - Git
I want to add lazygit to the list of tools. It's a nice command-line gui (i.e., works through ssh even if X forwarding is not allowed). It has extensive functionalities (e.g., select lines to commit, interactive rebase), helpful coloring, and is relatively simple to use. Can install in a variety of ways (go, conda, package manager,...). Still actively developed/maintained.
Solution 23 - Git
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.
Solution 24 - Git
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:
- see more context
- see intra-line diffs
- edit by hand and see 'live' diff updates (updated after every keypress)
- navigate to a change without saying 'n' to every change you want to skip
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.
Solution 25 - Git
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.
Solution 26 - Git
You can use Eclipse IDE, each modified local files can be compared vs the staged area and in this side by side diff view, you are free to choose which hunk to copy from local to staged area, or in the opposite, rollback local change from the staged area.
But there's more :), all graphical git clients do that hunk staging too (git add -p), but none I know can do that : directly edit in the staged area so several changes on same line or same hunk can be more fined picked up (or even write/delete/update stuff that never exists locally), like a "git add -e" working at patch level but without the risk to break the patch content. Moreover since it's with the regular text editor in the diff view, you have syntax color to help and you can do text replace operations (change all indentation types, rename a local variable use in many place, ...) to start committing separately some reformat / refactor before committing your "real" change but without embedding all file changes in the same commit.
Sure Eclipse is more Java oriented but because of its powerful git staging editor, it can be used for other language too. There is an Eclipse based free product only focusing git operation called GitEye : https://www.collab.net/downloads/giteye but seems not maintained so better to use a basic Eclipse distrib like : https://www.eclipse.org/downloads/packages/release/2020-12/r/eclipse-ide-java-developers
Edit : since IntelliJ 2020.3 allows to work with real git index, it is now capable to edit directly the staged area like Eclipse