Git - 如何使用当前索引(当前状态)中的一些非暂存更改来编辑旧(不是之前的)提交?

Kac*_*che 6 git

我已经看过这些先前的问题了:

但它们并没有完全解决特定问题 - 索引中还有其他变化!运行rebase命令时,git抱怨:Cannot rebase: You have unstaged changes.

场景:

最后一个之前的提交(我将其称为"2 HEADs前"吗?)是一个重构提交.我目前在索引中有许多非分段更改,但我只想将其中一些添加到上一次提交的上一次.

我想象这样做的方法是:

  1. stash 我目前的所有变化
  2. rebase -i 到最后一次提交(更改索引并移动Head,对吧?)
  3. 将存储加载到我的索引而不更改Head(如何?)
  4. 使用add -pcommit --amend有选择地修改此旧提交
  5. rebase --continue 完成(更新孩子,移动回到我开始的地方,索引会发生什么?)
  6. 然后弹出/清除存储(索引回到我开始的地方).

它是否正确?如果是,我该如何做第3步?如果不是,我应该做什么呢?

另外,请注意我还在学习git,我仍然不能100%确定我正确地引用了git(Head,index,stash等)中的东西.


解:

对于其他任何人都可以提供帮助,这些是我实际采取的步骤:

  1. git stash 我目前的所有变化
  2. git rebase -i <ID>到前一次提交的父级,更改索引并移动Head
  3. git stash apply 将存储加载到我的索引中而不更改Head
    • 如果您有冲突,git reset HEAD <file>请卸载文件暂存.确保分期清晰.
  4. 使用add -pcommit --amend有选择地进行更改并提交它们
  5. git reset --hard 丢弃索引,使其与Head匹配
  6. git rebase --continue完成.更新孩子,移动头回到最开始,但有变化
    • 历史现在分为两个版本.另一个分支在WIP之前结束
  7. 然后弹出存储将索引带回我开始的地方.另一个分支也被清除.

Von*_*onC 5

使用git1.8.4(2013年7月),您可以选择:

  • 变基
  • 同时保持您当地的非分期更改!

" git rebase"学会了" --[no-]autostash"选项来保存本地更改而不是拒绝运行(人们的正常响应是将其存储并重新运行).

所以在你的情况下,这可以工作(并在此期间保存你正在进行的工作):

git rebase --autostash -i <ID>
Run Code Online (Sandbox Code Playgroud)

请参阅commit 587947750bd73544a6a99811f0ddfd64e1ff1445:

此新功能允许在脏工作树或索引上执行rebase.
它的工作原理是在工作树和索引更改之外创建一个临时的"悬空合并提交"(通过'git stash create'),并在成功的rebase或abort之后自动应用它.

rebase存储临时合并提交的SHA-1十六进​​制以及其余的rebase状态,.git/{rebase-merge,rebase-apply}/autostash具体取决于rebase的类型.
因为$state_dir在成功的rebase或abort结束时自动删除,所以是autostash.

这种方法的优点是我们不会影响正常存储的reflog,使autostash最终用户看不见.
这意味着您可以像往常一样在rebase期间使用'git stash'.

autostash应用程序导致冲突时,我们将推$state_dir/autostash送到正常存储并删除$state_dir结束rebase.
用户可以随时检查藏匿物,然后弹出或放下.


注意:git 2.0.1(Jult 25th,2014)处理自动转发情况.
提交e4244ebRamkumar拉玛昌德拉(artagnon)(也在他的博客):

rebase -i:处理"无所事事"的情况 autostash

当用户调用时

$ git rebase -i @~3
Run Code Online (Sandbox Code Playgroud)

使用脏文件并rebase.autostash打开,并$EDITOR使用空缓冲区退出,自动转发无法应用.

虽然rr/rebase-autostash的主要焦点是让git-rebase--backend.sh脚本返回控制权git-rebase.sh,但是它错过了这种情况git-rebase--interactive.sh.
由于此案例不同于其他返回内务处理控制的情况,因此请为其指定一个特殊的返回状态,并在git-rebase.sh中明确处理该返回值.


随着最新的git,根本就git config rebase.autostash true使rebase [-i]工作在一个肮脏的worktree.

此新功能允许在脏工作树或索引上执行rebase.
它通过在工作树和索引更改(通过' git stash create')之外创建临时"悬空合并提交" ,并在成功重组或中止后自动应用它.

rebase存储临时合并提交的SHA-1十六进​​制以及其余的rebase状态,.git/{rebase-merge,rebase-apply}/autostash具体取决于rebase的类型.因为$state_dir在成功的rebase或abort结束时自动删除,所以是autostash.

这种方法的优点是我们不会影响正常存储的reflog,使自动转发对最终用户不可见.这意味着您可以git stash像往常一样在rebase期间使用' '.


Kev*_*eid 3

你的计划听起来不错。A git stash applyorgit stash pop将修改工作树和/或索引,但不会更改 HEAD,因此您应该能够在变基编辑中执行此操作。