[英]When rewriting git history, how can I apply a commit that returns everything to its prior state?
通常我想分解一个大的提交:
git commit -a -m "Monolith"
我知道如何拆分提交( git gui
是我的朋友)但有时我真的想手工修改它......
git branch temp # Keep a reference to all my hard work
git reset --hard HEAD~ # Rewind 'my-topic' branch
# hack hack
git commit -a -m "Refactor 1"
# hack hack
git commit -a -m "Refactor 2"
为了完成它,然后我想应用另一个提交,将代码准确地恢复到存储在分支temp
中的 state,通常包括原始提交消息。
是否有捷径可寻?
我以为cherry-pick
上的合并策略可能会完成工作,但可惜这些都没有:
git cherry-pick --strategy=theirs temp # I am told about conflicts
git status # ... But here I find no changes to commit!
git cherry-pick --strategy=ours temp # Worth a try. Nope, empty commit.
git cherry-pick --strategy=recursive --strategy-option=ours temp # Partial result, bits are missing
我知道实现这一目标的一种方法:
git log -1 temp # note the SHA
git checkout temp
git reset --soft my-topic
git commit -C <SHA-from-above> # branch 'temp' now contains the desired commit
git checkout HEAD -B my-topic
git br -d temp
不过这个好像很容易出错的方法 go 一下吧。 任何小错误和我想保留的提交可能不在任何分支中( git reflog
来救援......)。 我想找到更合乎逻辑且更容易记住/做的东西。
要在temp
重新创建树,有(至少)两种相当简单的方法:一种是
git checkout temp -- .
另一个是
git diff temp | git apply --index
之后,您使用相同的提交消息创建提交
git commit -C temp
这两种选择各有利弊。 checkout
路由不会删除temp
文件中不存在的文件。 apply
路由不适用于二进制文件。
旁注:对于现代 Git,您将使用git restore
而不是git checkout
,但我是老手,还没有学会使用它。
j6t 的答案有一些合理的选择,但我更喜欢您自己建议的程序的简化版本。 (我不确定你害怕犯什么错误,但我怀疑它们是由于你采取了不必要的步骤而引起的。)
git checkout temp
git reset --soft my_topic
git checkout my_topic
git commit -C temp
git branch -D temp
这似乎是一个奇怪的偏好,因为git checkout --.
(他们的一个建议)看起来像一条线; 但请注意我对他们的回答的评论。 它们是其他可能潜入的微妙陷阱——比如如果您忘记自己不在工作树根目录下会怎样。 当然,您可以解决所有这些问题......
因此,您可以养成先执行git rm
的习惯,或者在需要时“知道”(犯错的机会)。 您可以使用:/:
而不是.
作为习惯问题(并习惯于向与您一起工作的每个人解释),或者始终仔细检查您是否处于根目录(另一个犯错的机会)。 然后你得到
git rm -- :/:
git checkout temp -- :/:
git commit -C temp
git branch -D temp
这只是一个比我建议的解决方案“少”的简单命令。
忘记你的临时分支。 与其硬重置,不如混合重置。
结果是索引被重置但工作树没有。 现在您可以添加并提交您喜欢的任何组合,然后只需添加其他所有内容并提交即可完成。
有关更多信息,请参阅我的https://stackoverflow.com/a/59675191/341994 。
直接导入另一个提交快照的直接路径是执行此操作的核心命令:
git read-tree -u temp
其次是
git commit -C temp
使用temp
的提交消息提交。
git read-tree
是几乎所有从现有 repo 内容更新索引和工作树的命令的基础。 git reset
是围绕git update-ref HEAD
和git read-tree
的一些选择逻辑; git checkout
也是围绕git update-ref HEAD
和git read-tree
的一些选择逻辑; git merge
是对git read-tree
的结果进行的一些相当繁重的清理工作……是的。 顺便说一句, git commit
是围绕git update-ref HEAD
git write-tree
和git commit-tree
的一些选项选择逻辑(后者将一个小的 object 添加到 object db)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.