如果索引中添加了一些更改,而还有一些更改未添加到索引中,我应该如何交换这两组更改?
我认为这是最容易通过使用临时提交来完成的。当您有已暂存和未暂存的提交时,尝试重新排序更改时可能会发生冲突。
使用已暂存的更改进行提交,并创建一个分支以备将来使用:
git commit -m "Saved staged"
git branch save-staged
对于未暂存的更改,进行提交(如果包括新文件,则需要先显式地使用git add
添加):
git commit -a -m "Unstaged changes"
将未暂存的更改变基于原始 HEAD (可能需要解决冲突):
git rebase --onto HEAD^^ HEAD^
将暂存的更改合并到未暂存的更改中(可能涉及冲突解决):
git reset --hard save-staged
git rebase --onto HEAD@{1} HEAD^
最后,将索引重置为(最初的)未暂存更改:
git reset HEAD^
并将分支指针移回原始HEAD位置:
git reset --soft HEAD^
删除临时分支:
git branch -D save-staged
如果想要一个更底层的解决方案,你可以通过一些基础操作直接与索引进行通信:
INDEXTREE=`git write-tree`
git add -A
WORKTREE=`git write-tree`
git checkout $INDEXTREE -- .
git clean -f
git read-tree $WORKTREE
通过补丁的方式(对于二进制更改无效):
保存暂存状态和未暂存状态的补丁
git diff >> unstaged.patch
git diff --cached >> staged.patch
git reset --hard
git apply unstaged.patch
除了补丁文件外,将这些更改放入暂存区
git add -A
git reset -- staged.patch unstaged.patch
git apply staged.patch
删除补丁文件
rm staged.patch unstaged.patch
git stash
答案? - VonC这是基于 Walter Mundt 的回答 改进的,适用于新文件已暂存的情况下。它旨在作为脚本使用,例如 git-invert-index
。
#!/bin/sh
# first, go to the root of the git repo
pushd `git rev-parse --show-toplevel`
# write out a tree with only the stuff in staging
INDEXTREE=`git write-tree`
# now write out a tree with everything
git add -A
ALL=`git write-tree`
# get back to a clean state with no changes, staged or otherwise
git reset -q --hard
git clean -fd
# apply the changes that were originally staged, that we want to
# be unstaged
git checkout $INDEXTREE -- .
git reset
# apply the originally unstaged changes to the index
git diff-tree -p $INDEXTREE $ALL | git apply --index --reject
# return to the original folder
popd
Charles Bailey提供了一个更完整的解决方案,涉及提交和管理潜在的冲突解决。
我最初尝试只使用git stash
,但我一开始忽略了git stash
save会保存索引(已暂存的更改)和未暂存的更改(当您想交换索引内容和未暂存的更改时不方便)。
因此,我改为以下方法:
git commit
-m "临时提交"(为当前索引创建一个提交)git stash
(将未添加到索引的内容存储起来)git reset --soft HEAD^
(保留先前提交的文件)git stash
再次执行git stash pop stash@{1}
(应用之前存储的内容,即尚未添加到索引的初始更改)git add -A
git stash drop stash@{1}
以清除我们之前应用的存储(stash@ {0} 仍包含最初在索引中的内容)最终结果:
git stash
意味着 git reset --hard
,因此 git reset --mixed
是无操作的,第二个 git stash
没有任何作用? - CB Baileygit stash save --keep-index
,我猜在第四步放弃之前必须先应用第一个存储。但无论如何,这种方式对我来说不起作用,因为如果我有两个存储并尝试应用其中一个,两个存储都会被应用,原因无法解释。 - whiteredgit stash
”版本。 - VonCgit stash push -S
git add .
git stash pop
alias swap='git stash push -S && git add . && git stash pop'
swap
。替代方案(太长):
Note the name of your current branch as:
<name-of-your-branch>
git checkout -b temp-unstaged
git commit -m "staged"
git branch temp-staged
git add .
git commit -m "unstaged"
git rebase --onto HEAD~2 HEAD~1
git checkout temp-staged
git rebase temp-unstaged
git reset HEAD~1
git reset --soft HEAD~1
git checkout <name-of-your-branch>
git branch -D temp-staged
git branch -D temp-unstaged