7

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

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

设想:

最后一个提交之前的提交(我是否将其称为“2 HEADs ago”?)是重构提交。我目前在索引中有许多未暂存的更改,但只有一些我想添加到上一个到最后一个提交中。

我想象这样做的方法是:

  1. stash我当前的所有更改
  2. rebase -i到上一个到最后一个提交(更改索引和移动 Head,对吗?)
  3. 在不更改 Head 的情况下将存储加载到我的索引中(如何?)
  4. 使用add -pcommit --amend有选择地修改这个旧的提交
  5. rebase --continue完成(更新孩子,将头移回我开始的地方,索引会发生什么?)
  6. 然后弹出/清除存储(索引回到我开始的位置)。

它是否正确?如果是,我该如何执行第 3 步?如果不是,我应该怎么做?

另外,请注意,我仍在学习 git 并且仍然不能 100% 确定我是否正确引用了 git 中的内容(头、索引、存储等)。


解决方案:

对于其他任何人,这可能会有所帮助,这些是我实际采取的步骤:

  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. 然后弹出存储以将索引带回我开始的位置。另一个分支也被清除。
4

4 回答 4

5

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

  • 变基
  • 同时保持本地未分级的更改!

" git rebase"学到了 " --[no-]autostash" 保存本地更改而不是拒绝运行的选项(人们的正常反应是存储它们并重新运行)。

因此,在您的情况下,这可能有效(同时保存您正在进行的工作):

git rebase --autostash -i <ID>

请参阅提交 587947750bd73544a6a99811f0ddfd64e1ff1445

这个新功能允许在脏工作树或索引上执行变基。
它的工作原理是从工作树和索引更改(通过'git stash create')中创建一个临时的“悬空合并提交”,并在成功变基或中止后自动应用它。

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

这种方法的优点是我们不会影响普通存储的 reflogs,从而使autostash最终用户不可见。
这意味着您可以像往常一样在变基期间使用“git stash”。

autostash应用程序导致冲突时,我们推$state_dir/autostash送到正常存储并删除$state_dir结束 rebase。
用户可以检查存储,并随时弹出或删除。


注意:git 2.0.1(2014 年 7 月 25 日)处理 autostash 情况。
请参阅Ramkumar Ramachandra ( )提交 e4244eb(也在他的博客中):artagnon

rebase -i:处理“无事可做”的情况autostash

当用户调用

$ git rebase -i @~3

带有脏文件并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 truerebase [-i]脏工作树中工作即可。

这个新功能允许在脏工作树或索引上执行变基。
它的工作原理是从工作树和索引更改(通过'')中创建一个临时的“悬空合并提交” git stash create,并在成功变基或中止后自动应用它。

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

这种方法的优点是我们不会影响普通存储的 reflogs,从而使最终用户无法看到自动存储。这意味着您可以git stash像往常一样在变基期间使用 ' '。

于 2013-06-24T20:44:31.963 回答
4

如果我了解您想要做什么,这与您的第一个链接上的答案没有太大不同,您只需将不想添加到旧提交中的更改存储起来。你可以这样做:

  1. 提交您想要添加到倒数第二次提交的更改。只需给它一个简单的提交消息,例如“添加这个”,因为它不会存在很长时间。
  2. 存储您不想添加到提交中的剩余更改。
  3. 查找您要添加到的提交的父级。例如,如果您要修改的提交具有 SHA1aaaaaaa且其父级为bbbbbbb,则您需要bbbbbbb.
  4. 执行git rebase -i bbbbbbb(替换步骤 3 中确定的正确提交)。将最近的提交(“添加这个”)移动到您正在修改的提交下方,并将其从 更改pickfixup. 这会将其添加到该提交中,而不会更改该提交的消息。
  5. 从步骤 1 中取消存储更改,然后从那里进行更改。
于 2012-12-14T00:41:29.027 回答
3

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

于 2012-12-14T00:28:49.827 回答
0
`git stash`
`git checkout <COMMIT HASH from 2 commits ago>`
`git stash pop`
`git add` (selectively--one file at a time)
`git commit --amend`
`git stash` (to re-stash all the changes you didn't commit)
`git branch temp`
`git checkout master`
`git rebase temp -i`

这将打开一个带有提交列表的文本编辑器——每行一个提交。删除第一行,这是您要替换的旧提交。保存并关闭。

`git branch -d temp` (to clean up the branch you created)
于 2012-12-14T00:37:19.860 回答