I have got changes in my staging area, and others not staged yet (some files have changes both in and out the staging area). I would like to invert the content of the staging area and the changes which are not staged. Does a shortcut exist in order to do that, without doing more complex actions like local side-branch commits, or diffs, or stashes [etc.]? Thanks.
-
10possible duplicate of [What is the shortest way to swap staged and unstaged changes in git?](http://stackoverflow.com/questions/3573410/what-is-the-shortest-way-to-swap-staged-and-unstaged-changes-in-git) – CB Bailey Jan 31 '13 at 18:45
-
Wow, thanks for the link. Not the same search terms, but the same issue, indeed. – moala Feb 01 '13 at 10:59
-
3Possible duplicate of [What is the shortest way to swap staged and unstaged changes in git?](https://stackoverflow.com/questions/3573410/what-is-the-shortest-way-to-swap-staged-and-unstaged-changes-in-git) – Joshua Goldberg May 02 '19 at 15:17
4 Answers
Here’s how I do it:
- Commit the index to a temporary commit
- Commit the remainder to a secondary temporary commit
- Switch the order of the commits with interactive rebase
- Mixed reset
- Soft reset
It can be typed out manually pretty fast, especially if you use Vim for commit messages:
git commit -m tmp1
git add . # optionally with `git add -u` if there are deletions
git commit -m tmp2
git rebase -i HEAD~2 # swap the order of the commits; `ddp:wq` in vi
git reset HEAD~1
git reset HEAD~1 --soft

- 29,210
- 11
- 96
- 131

- 16,956
- 6
- 49
- 65
-
I like this except for the manual edit to swap the commits. http://stackoverflow.com/questions/16203562/programmatically-swap-last-two-commits – Eric Woodruff Dec 08 '13 at 19:19
-
Good point. But the problem for me personally is I don't do this enough to write a shortcut script and remember what it's called and how it works. Interactive rebasing I do almost every day and it's extremely intuitive and efficient for me. – gtd Dec 11 '13 at 20:43
There’s probably more than one way to do this, but I think I would take this approach – there’s currently no pre-built shortcut to this, but you could pretty easily write your own script to follow this process:
Generate a patch for the stuff that is currently in your working directory but not in your index yet (things you haven’t done
git add
for)git diff-files -p > /tmp/unstaged.patch
Generate a patch for what you’ve already added to the index against your current
HEAD
git diff-index --cached -p HEAD > /tmp/staged.patch
Reset your index and working directory to your
HEAD
git reset --hard HEAD
Apply your unstaged patch to both your working directory and your index, resulting in those changes being staged
git apply --index /tmp/unstaged.patch
Apply your staged patch against only your working directory
git apply /tmp/staged.patch
Depending on the exact nature of your changes, steps 4 and/or 5 may result in some merge conflicts that you need to resolve by hand, but I’m not sure there’s a clean way to completely avoid that possibility.
You could probably use git stash
to accomplish steps 1 and 4 instead of the above commands, but I’m not sure that would really gain you anything…
Also, you may want to review the man pages for the git diff-*
and git apply
commands first to see if there are other options that might make sense for you to use.

- 29,210
- 11
- 96
- 131

- 59,951
- 11
- 89
- 84
Based on gtd's answer and the ability to script inverting the commits this is what I'm using now:
[alias]
swaplast = !git tag _invert && git reset --hard HEAD~2 && git cherry-pick _invert _invert~1 && git tag -d _invert
invertindex = !git commit -m tmp1 && git add -A && git commit -m tmp2 && git swaplast && git reset HEAD~1 && git reset HEAD~1 --soft
Posted on my blog here: http://blog.ericwoodruff.me/2013/12/inverting-git-index.html

- 6,380
- 3
- 36
- 33
-
4I’ve done some investigation and testing and this is my unauthorized documentation: `swaplast` swaps the last and one-before-last commit. Attention: It discards uncommitted changes without notice. `invertindex` swaps staged and unstaged changes, including untracked files. – Melebius Nov 20 '14 at 09:17
-
If for some reason this fails, you may need to run `git cherry-pick --abort` before you can run `git invertindex` again. – u01jmg3 Jul 18 '16 at 14:40
-
Thanks a lot! I've turned these into separate [git swaplast](https://github.com/inkarkat/git-extensions/blob/master/git-swaplast) and [git invertstage](https://github.com/inkarkat/git-extensions/blob/master/git-invertstage) scripts (you'll also need [git existsbr](https://github.com/inkarkat/git-extensions/blob/master/git-existsbr)) that also offer continuation (with `--continue`) in case of conflicts. The original aliases just abort and leave the user stranded. – Ingo Karkat Jul 17 '19 at 14:00
-
I changed `git add -A` to `git add -u` so it won't try to commit the untracked files. – earboxer May 18 '23 at 15:37
This is what I use to solve this issue.
First git reset
which will remove all the files from 'staging' to 'files not staged for commit'. The files that are in both 'staging' and 'files not staged for commit' will keep your most recent changes that are currently in your 'files not staged for commit'
then
git add /path/to/file
the specific files you need to add to staging
Not exactly a short-cut, but it gets the job done
Inversely, After you git reset
, you could git checkout /path/to/file
for the files that are currently 'not staged for commit' which you don't want to add to staging. This will remove specific files from 'not staged to commit'
then run git add .
which will add all files in 'not staged for commit' to 'staging' - whichever is easier for your situation

- 2,052
- 1
- 20
- 37
-
Actually, I would precisely prefer not to do that by hand, because the limit between staged and non-staged is rather complex: even inside some files, some lines are staged and other non-staged. – moala Jan 31 '13 at 15:20
-
Did you seem my recent edit regarding files both staged and not staged? – Alex Naspo Jan 31 '13 at 15:24
-
What do you mean by "you could git checkout the files you don't want [...]"? it is pretty obscure to me... – moala Jan 31 '13 at 15:24
-
I'll try that but currently I don't understand how it could get the job done. – moala Jan 31 '13 at 15:26