Git反转暂存区

14

我的暂存区中有更改,而其他的更改尚未暂存(某些文件在暂存区内外都有更改)。

我想颠倒暂存区的内容以及未暂存的更改。是否存在快捷方法来完成这个操作,而不需要执行更复杂的操作,例如本地分支提交、差异或者存储等?谢谢。


哇,谢谢你提供这个链接。虽然搜索关键词不同,但确实是同样的问题。 - moala
3
可能是 What is the shortest way to swap staged and unstaged changes in git? 的重复问题。 - Joshua Goldberg
4个回答

6

以下是我的做法:

  1. 将索引提交到临时提交中
  2. 将其余部分提交到辅助的临时提交中
  3. 使用交互式变基来更改提交顺序
  4. Mixed重置
  5. Soft重置

这可以很快地手动输入,尤其是在使用Vim进行提交消息时。

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

除了手动编辑以交换提交之外,我喜欢这个解决方案。https://dev59.com/mmQo5IYBdhLWcg3wQNb4 - Eric Woodruff
好观点。但对我个人来说,问题在于我没有经常做这件事情,无法编写一个快捷脚本并记住它的名称和工作方式。交互式变基我几乎每天都会做,对我来说非常直观和高效。 - gtd

5

也许有多种方法可以实现这个目标,但我认为我会采取以下方法:目前没有预先建好的快捷方式,但你可以很容易地编写自己的脚本来按照以下步骤操作:

  1. 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
    
  2. 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
    
  3. Reset your index and working directory to your HEAD

    git reset --hard HEAD
    
  4. Apply your unstaged patch to both your working directory and your index, resulting in those changes being staged

    git apply --index /tmp/unstaged.patch
    
  5. Apply your staged patch against only your working directory

    git apply /tmp/staged.patch
    
根据您所做的更改的确切性质,步骤4和/或5可能会导致一些合并冲突,您需要手动解决,但我不确定是否有一种干净的方法完全避免这种可能性。
您可以使用git stash来完成步骤1和4,而不是上面的命令,但我不确定这样做是否真的对您有所帮助...
此外,您可能需要先查看git diff-*git apply命令的man页面,以查看是否有其他选项对您有意义。

4

根据gtd的回答和编写倒转提交的能力,这是我现在使用的方法:

[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

这篇文章来自我的博客:http://blog.ericwoodruff.me/2013/12/inverting-git-index.html

它是关于反转Git索引的。

4
经过一些调查和测试,这是我的非官方文档:swaplast 交换最后两次提交的顺序。注意:它会在没有提示的情况下丢弃未提交的更改。 invertindex 交换已暂存和未暂存的更改,包括未被追踪的文件。 - Melebius
如果由于某些原因失败了,你可能需要在再次运行“git invertindex”之前运行“git cherry-pick--abort”。 - u01jmg3
非常感谢!我已经将它们转换为单独的git swaplastgit invertstage脚本(您还需要git existsbr),这些脚本在冲突时也提供了继续执行(使用--continue)的选项。原始别名只会中止并使用户陷入困境。 - Ingo Karkat
我将 git add -A 改为 git add -u,这样它就不会尝试提交未跟踪的文件了。 - earboxer

0

这是我用来解决这个问题的方法。

首先执行 git reset 命令,将所有文件从“暂存区”移动到“未暂存区”。在“暂存区”和“未暂存区”中都存在的文件将保留您当前在“未暂存区”中的最新更改。

然后,使用 git add /path/to/file 命令添加需要添加到暂存区的特定文件。

虽然不是一个快捷方式,但它可以完成工作。

相反,在执行 git reset 命令之后,您可以使用 git checkout /path/to/file 命令获取当前处于“未暂存区”的文件,这些文件您不想添加到暂存区。这将从“未暂存区”中删除特定文件。

然后运行 git add . 命令,将“未暂存区”中的所有文件添加到“暂存区”中 - 这取决于您的情况哪种更容易。


实际上,我宁愿不手动处理这个问题,因为分阶段和非分阶段之间的界限相当复杂:即使在某些文件中,有些行是分阶段的,而其他行则是非分阶段的。 - moala
你看到我最近关于已暂存和未暂存文件的编辑了吗? - Alex Naspo
“你说的“you could git checkout the files you don't want”是什么意思?我有点不理解…” - moala
我会尝试,但目前我不明白它如何完成工作。 - moala

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接