繁体   English   中英

重写 git 历史记录时,如何应用将所有内容返回到其之前的 state 的提交?

[英]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 HEADgit read-tree的一些选择逻辑; git checkout也是围绕git update-ref HEADgit read-tree的一些选择逻辑; git merge是对git read-tree的结果进行的一些相当繁重的清理工作……是的。 顺便说一句, git commit是围绕git update-ref HEAD git write-treegit commit-tree的一些选项选择逻辑(后者将一个小的 object 添加到 object db)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM