Commit only part of a file's changes in Git

Asked 2023-09-20 20:16:18 View 881,217

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?

  • related stackoverflow.com/q/34609924/52074: if you need to split a hunk into smaller hunks. - anyone
  • Summary: in terms of capability: git gui = git add -e > git add -i -p; in terms of convenience: git gui > git add -i -p > git add -e. So: pick git gui when you have access to X. pick git add -i -p for simple stuff and when you don't have or want to use X. git add -e for complex staging without X. - anyone
  • If using VSCode, see stackoverflow.com/a/65649756/7881859. - anyone

Answers

You can use:

git add --patch <filename>

or for short:

git add -p <filename>

Git will 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

Answered   2023-09-20 20:16:18

  • It's might be useful to note that -p/--patch is a shortcut to the patch action inside the -i/--interactive command that initiates the useful Interactive mode. - anyone
  • >What happens if that file is already staged? It will show only unstaged changes. Same as git diff does. - anyone
  • How can I edit the current hunk manually? I don't know what to do after I type e. - anyone
  • After pressing e, You can edit the hunk manually by replacing + or - by # - anyone
  • hmm... when I do git commit file it commits everything, not just the specific changes I wanted (even though git diff --staged showed only the specific changes I wanted) edit: git commit -p will let you select the "hunk"s and commit in one go; and it does commit only the specific changes - anyone

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 by right clicking them and selecting:

Stage Hunk For Commit

If you want to add only certain lines of the hunk, you can also select the lines you want, right click them and:

Stage Lines For Commit

enter image description here

I personally find it easier than using git add -i. Other git GUIs, like QGit or GitX, might also have this functionality as well.

Answered   2023-09-20 20:16:18

  • Interestingly, windows.github.com had support for partial file commits but seems to have dropped it recently.. - anyone
  • @Juri I think the support for partial file commits is back in. - anyone
  • @Juri You're welcome. I actually never noticed that it had been in there before - I saw it last week and thought "oh, what an amazing new feature"! :-) - anyone
  • Nowadays windows.github.com redirects to the rebranded GitHub Desktop which is nicer than Git GUI and supports partial commits...but doesn't support commit signing. Sigh. - anyone
  • @user4942583 : GPG commit signing was added to GitHub Desktop a year ago. - anyone

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.

Answered   2023-09-20 20:16:18

  • for complex patches this is usually the fastest approach for me. - anyone
  • This is a very efficient and intuitive way to add changes to the staging area in a fine grained manner. Also multiple lines can be selected and all changes within that selection will be added. - anyone
  • Note that this is not gitk, but it is included with Git Bash for Windows; you should have a start menu entry for it or can start it with the command git gui. There's also stage this hunk which is probably more useful than stage this line. Might be new since this answer was created 10 years ago. - anyone
  • That what I was looking for :) - anyone
  • It also seems to be the only software with this ability, that is supported on Linux :/ - anyone

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

Answered   2023-09-20 20:16:18

  • This would be more useful if there were a clear explanation somewhere of how to actually choose those lines (i.e. the actual commands to enter). I couldn't find one in the documentation. Could you add a reference? - anyone
  • For those who don't like shorthand options, -e is --edit. - anyone
  • @Alex The reference quotes added by theFreedomBanana are from the section EDITING PATCHES in git --help add - anyone
  • This is the only answer (requiring only git) that solves the problem of adding/removing line wise when you cannot make hunks smaller with s in interactive patch mode. - anyone
  • It may be helpful to understand that this command (git add -e) *doesn't * change file content on disk. It just moves part of changes from unstaged to staged (index). - anyone

If you happen to be 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:

enter image description here

Answered   2023-09-20 20:16:18

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).

Answered   2023-09-20 20:16:18

  • Thank you so much for this links. Exactly same what I need. Especially :diffget/:diffput in visual mode, where I can choose specific lines, which I want to reset/commit. So, make sure again: vim is awesome. - anyone

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

Answered   2023-09-20 20:16:18

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.

enter image description here

Answered   2023-09-20 20:16:18

  • I agree that SourceTree is a good tool for this purpose, because it gives you more fine-grained control than what is possible through the command line. - anyone
  • @cupcake I would argue the opposite, seeing that SourceTree probably uses those command line git executables, inherently it will always be possible to do the same (or more) fine-grained actions via the "command line". - anyone
  • Regardless the fine-grained argument I'd highly recommend SourceTree as staging hunks and individual lines is super easy: i.imgur.com/85bNu4C.png - anyone
  • What if part of the "hunk" you don't want to stage. For example, I only want to commit lines 50-100, but not 1-50, but SourceTree sees line 1-100 as one "hunk" - anyone
  • @Sun you can click on line 50 and shift+click line 100 then stage. You can easily stage line 50-100 in Sourcetree :) - anyone

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.

Answered   2023-09-20 20:16:18

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:

enter image description here

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.

Answered   2023-09-20 20:16:18

  • What previous answer? Answers are stored based on the number of points they have. So your answer is in a different place now than it was when you wrote it compared to other answers. - anyone
  • I believe the referenced answer is from @theFreedomBanana - anyone

IntelliJ IDEA (and I guess all other products of the series) has built-in support for partial commits since v2018.1.

enter image description here

Answered   2023-09-20 20:16:18

  • Too easy method. I'm afraid Intellij IDEA is trying to kill the last console aficionados which git is trying to save. - anyone
  • How can you break down what you added on the right to add only a few lines? (green elements on the right diff displayed when it is on multiples lines) So far, PyCharm v2020.1.2, you can only add all continuous changes in one block. - anyone
  • @amiabl You can't (as of v2020.1). Tracked by youtrack.jetbrains.com/issue/IDEA-186988 - anyone
  • Select git commit, then, in the Default Changelist pane on the LHS, right click the file and select "Show Diff". From there, you can uncheck the diffs you don't want committed. - anyone
  • @Beauty VS 2022 17.03 actually supports interactive staging! - anyone

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.

Answered   2023-09-20 20:16:18

  • I often trip over a git command wanting to open an editor, when I've run it from an M-x shell window. Does magit intercept that craziness, and open just a new buffer for that? (please no background-emacs-daemon hints; thanks anyway but life's too short). - anyone
  • No, as far as I can tell it does not intercept this. But don't just take my word for it because (1) I hardly ever use the shell window in Emacs, and (2) I normally use emacsclient. Having said that, if emacsclient is an option for you, that at least prevented an additional window with emacs from being opened and the "COMMIT_EDITMSG" buffer was opened in my existing Emacs window. - anyone
  • Magit is excellent. It allows you to stage and unstage hunks and even delete them, with single keystrokes (with confirmation on deletion!). Although formerly a relatively proficient git command line user, I've never had to learn the patch command because Magit makes it (and so many other things) so easy. It's so convenient, in fact, that I use hunk deletion in preference to manual deletion sometimes, and worktree/index stashing and unstashing to remove and restore chunks of code for testing - in other words, I use Magit to assist with routine coding tasks, not just version control. - anyone
  • I think the link is outdated. Look for Staging changes in emacsair.me/2017/09/01/magit-walk-through - anyone
  • tldr; Go to your changes and press s - anyone

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.

Answered   2023-09-20 20:16:18

  • The keyboard shortcut in Git Extensions for 'Stage selected lines' is s -- very useful for quickly staging portions of files for a commit. - anyone
  • I tried this but you can't select deleted lines though am using vs code - anyone
  • Selecting deleted lines for staging does work in GitExtensions, and has worked for years. How are you trying to select and stage deleted lines? - anyone

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 usageExample

Answered   2023-09-20 20:16:18

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.

Answered   2023-09-20 20:16:18

  • this works well, but if you use git commit --amend, it seems that you can't pop the stash afterwards, or is there a way of doing this? - anyone

First, we can look at what the changes are.

git diff <file>

If it shows in different chunks, we can use

git add -p <file>

by accepting or rejecting changes ( y or n).

enter image description here

If not we can still do it with help of VS Code

enter image description here

Answered   2023-09-20 20:16:18

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.

Answered   2023-09-20 20:16:18

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.

Answered   2023-09-20 20:16:18

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.

Answered   2023-09-20 20:16:18

  • Yep (only) for this purpose I use TortoiseGit. I know it back from TortoiseSVN and it's superb - anyone
  • Note: You don't see this entry in the context menu of the Explorer (file explorer of Windows). You only see it when you commit by use of TortoiseGit in the commit dialog window. A tutorial you find here. - anyone

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).

Answered   2023-09-20 20:16:18

  • Yes that's pretty easy. Select the code, right click, "Stage selection". - anyone

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

Answered   2023-09-20 20:16:18

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.

Answered   2023-09-20 20:16:18

  • As of 2021, this is the best option for people who prefer command-line tools/text UIs. - anyone

From the comments of this 2018 answer:

It's a pity that Visual Studio doesn't have this option.
About 10 years ago the alternative source control system Mercurial supported this feature inside of Visual Studio. I really miss it since I use Git.

It is now (Aug. 2022) supported:

Git Line-staging Released!

We are excited to announce the release of Line-staging support in Visual Studio 2022.

Line-staging, a.k.a. interactive staging, enables you to split your changed lines of code across different commits.
Line-staging could also be utilized in reviewing your changes before committing them. Mark your changed lines or sections of code as reviewed by staging them and commit your staged changes when you are done.

Start using Line-staging by updating your Visual Studio 2022 to version 17.3 or later.

VS 17.03 interactive staging -- https://devblogs.microsoft.com/visualstudio/wp-content/uploads/sites/4/2022/08/Line-stagingM.mp4

Read our Line-staging documentation to learn more about how to use and customize this feature.

Answered   2023-09-20 20:16:18

For emacs there is also gitsum

Answered   2023-09-20 20:16:18

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.

Answered   2023-09-20 20:16:18

  • What does that give you over "git add -p filename.txt" besides less room for error? If you mess up the partial-file change, undoing an add is better than undoing a commit. - anyone
  • I don't know why, but when i say 'n' the line gets included....and when I say 'y' on the 2nd hunk, it also gets included. - anyone

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.

Answered   2023-09-20 20:16:18

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.

Answered   2023-09-20 20:16:18

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

Answered   2023-09-20 20:16:18

Among all these tools, I love Fork the most (though not free)!

Compared with other ones, it is very sleek and elegant to use, click the button alongside your mouse would do hunk or line staging.

Another option is GitKraken, fun but more complex and powerful!

Answered   2023-09-20 20:16:18