Revert to a commit by a SHA hash in Git?
我不清楚git revert 是如何工作的。例如,我想在头部后面恢复到提交6个提交,在中间提交之间恢复所有更改。
假设它的sha散列是56e05fced214c44a37759efa2dfc25a65d8ae98d 。那我为什么不能做这样的事呢?
1
git revert 56e05fced214c44a37759efa2dfc25a65d8ae98d
尽管这个问题实际上比它现在标记为的问题旧,但这个问题有更好的答案。meta.stackexchange.com/questions/147643/…
这个问题和上面的答案可能会让git用户感到困惑。为了帮助理解术语,您不必返回到提交状态。您可以重置为提交(就像使用Time Machine及时返回一样)或还原提交(就像提取一个从未存在过的提交一样-但是它在历史记录中保留了还原信息,允许您在需要时还原还原一个还原),还请注意,如果您使用过程中的ET冲突。Git提供的自动消息在回顾历史时提供了更多信息。
这是非常好的反馈。谢谢@Alexrogins
@Alexrogins如果一个承诺从未存在,那它意味着什么?不确定"还原还原"指的是什么——不过,请欣赏评论,好信息,只需在您的角度上寻找更多细节。
@Joe就像在中一样,如果添加一行代码,然后提交该行,如果要还原该行代码,则将撤消该行代码(在历史记录中首次写入的位置,不必是最后一次提交)。然后进行恢复提交。如果恢复恢复提交,则实际上是撤消撤消(即重新恢复原始行)
如果您希望在当前头上提交,并在另一个提交时使用正确的状态,撤消所有中间提交,那么可以使用reset 创建索引的正确状态以进行提交。
1 2 3 4 5 6 7 8
# Reset the index and working tree to the desired tree
# Ensure you have no uncommitted changes that you want to keep
git reset --hard 56e05fced
# Move the branch pointer back to the previous HEAD
git reset --soft HEAD@{1}
git commit -m"Revert to 56e05fced"
这样做是否等同于(并且缩短了一个命令):git reset --hard 56e05fced 作为第一个命令,然后跳过最后一个git reset --hard ?
当我这样做的时候,我在工作树上发现了一堆Untracked Files 。但是,查看历史记录,我可以看到这些文件在"还原到sha"提交中有相应的删除提交。因此,在git reset --hard 结束后,您可以执行git clean -f -d 来清理任何未跟踪的文件。另外,非常感谢这帮助我解决了一场危机!
我是否必须无条件地执行git reset --soft HEAD@{1} ?我的意思是总是1的值?
@是的,除非你想放弃在分支尖端的承诺。git reset 56e05fced 在reflog中添加了另一个条目(运行git reflog ,所以git reset --soft HEAD@{1} 只是在调用git reset 56e05fced 之前将指针移回HEAD 。使用更高的数字(如git reset --soft HEAD@{2} )将在以前的提交中附加新的提交。也就是说,增加这个数字基本上会使N-1 承诺失效,其中N 是您替换1 的数字。
git reset——软头@1似乎是一个无效命令。我的树枝现在分叉了。这把我搞砸了。
@汤姆,这个办法行得通。您一定做了一些错误的事情,否则reflog中可能没有任何条目(例如,如果它是一个非常新的克隆)。无论如何,在这个答案中你会找到更直观的"恢复"分支的解决方案。
哦,天哪,你给我找错路了!这工作!!!!我只希望(任何代码、任何二进制文件)与我以前的提交完全相同。
正如@nzifnab所说,您需要执行EDOCX1[6]来清理任何未跟踪的文件,否则该过程没有完全完成。请更新您的答案
@Cupcake请您将提交消息更改为"重置为",以避免与Git Revert的功能混淆,这是我在对问题的评论中描述的。
@tom HEAD@{1} 应该被引用为'HEAD{@1}' 否则,它对我(可能是每个zsh用户)都不起作用。
我找到了这个更好的stackoverflow.com/questions/4114095/…,签出提交哈希,然后从那里创建一个新的分支并处理该分支;这样就不会错过任何内容。
已更新,因此不再需要clean 。
他问起了吉特·里夫。你的答案是使用git重置。"如果Git还原是撤消更改的"安全"方法,您可以将Git重置视为危险的方法。
我有1000张赞成票。
Git Revert所做的是创建一个commit,它撤消在给定commit中所做的更改,创建一个与给定commit相反的commit。因此
应该而且确实有效。
如果要倒带回指定的提交,并且可以这样做,因为这部分历史记录尚未发布,则需要使用git reset,而不是git revert:
1
git reset --hard <SHA-1>
(请注意,--hard 会使您丢失工作目录中任何未提交的更改)。
附加说明
顺便说一下,也许这并不明显,但是在文档中说明 或 或 的任何地方,您都可以将sha-1标识符(完整或缩短)设置为commit。
如果您的历史记录在执行硬重置之前已被推送到远程,则需要使用git push -f 强制推送新重置的分支,但警告您这可能会无意中删除其他用户的提交,如果不删除新提交,则会强制其他用户重新同步其工作重置分支,因此首先确保您的合作者可以这样做。
这似乎是最好的答案。它还清楚地告诉Git Revert和Git Reset之间的区别。
它恢复所说的提交,即添加与之相反的提交。如果要签出早期版本,请执行以下操作:
1
git checkout 56e05fced214c44a37759efa2dfc25a65d8ae98d
那我可以把这个和头合并吗?如果我预计会有大量的冲突,我是否可以强制这个承诺成为"原样"的头,并覆盖任何冲突?
我不知道你在说什么头。你可以把你的头移回这个任务。(例如,通过删除和创建分支)。如果您想在头部进行"合并"提交,这实际上是中间提交的反转,那么您可以使用"我们的"策略进行合并。选择您的选项并阅读手册。电源正在等待您使用;-)
这是有道理的,我问的原因是Git现在告诉我我不在任何分支机构。
因为你没有。如果你输入git branch ,你会清楚地看到它。例如,您可以使用git checkout -b mybranch 56e05 来获取分支。
我想他在问如何做快进
回滚到特定提交的最佳方法是:
1
git reset --hard <commit-id>
然后:
新手应该意识到,push -f 可以摧毁历史。然而,有时候这就是你想要的:)
有时候你真的很高兴历史被删除了…在寻找这个-f选项,thks!
谢谢,为了字面意思,我必须输入->git push origin master-f,其中不能仅仅是origin,至少对我来说是这样。
正如上面提到的,如果我们希望我们的repo头指向一个特定的提交,而不维护历史记录,那么使用上面的步骤,或者我们可以使用git revert。
我们是否知道是谁重置了(即回滚提交)并强制推送了一个特定的分支?
如果您的更改已经被推送到一个公共的、共享的远程服务器上,并且您希望恢复HEAD 和 之间的所有提交,那么您可以向git revert 传递一个提交范围,
它将恢复56e05f 和HEAD 之间的所有承诺(不包括范围的起点,56e05f )。
请注意,如果要还原几百个提交,这可能需要一段时间,因为必须分别提交每个还原。
@拼接器您不必单独恢复每个提交,您可以通过--no-edit 选项来避免发出单独的提交消息,也可以使用--no-commit 一次提交所有的恢复。
@em git revert HEAD..56e05f 完全是错误的命令,git revert 56e05f..HEAD 已经以相反的顺序恢复了承诺,以避免冲突。
@你是对的头…56e05f对我不起作用,但56e05f…头成功了
这是到目前为止我最喜欢的方法,不管你是否推动它。我把这个添加到了我的全局~/.gitconfig 的别名部分:rollback ="!git revert --no-commit $1..HEAD #" --所以现在我可以直观地执行$ git rollback a1s2d3 。
更新:
这个答案比我的答案简单:如何将Git存储库恢复到以前的提交?
原始答案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
# Create a backup of master branch
git branch backup_master
# Point master to '56e05fce' and
# make working directory the same with '56e05fce'
git reset --hard 56e05fce
# Point master back to 'backup_master' and
# leave working directory the same with '56e05fce'.
git reset --soft backup_master
# Now working directory is the same '56e05fce' and
# master points to the original revision. Then we create a commit.
git commit -a -m"Revert to 56e05fce"
# Delete unused branch
git branch -d backup_master
在这里,两个命令git reset --hard 和git reset --soft 是魔法。第一个改变了工作目录,但它也改变了头部。我们用第二个固定头。
你的承诺中的-a是不必要的。
很完美。这应该成为git cli、imo中的一个命令。
很不错的!这比git revert 56e05fce..HEAD 好多了,因为这只是一个承诺
嗯,我收回,这更简单:stackoverflow.com/questions/4114095/&hellip;
这更容易理解:
1 2 3
git checkout 56e05fced -- .
git add .
git commit -m 'Revert to 56e05fced'
为了证明它有效:
恐怕一般来说这是不对的。签出只会(我认为)更新存在的路径,因此,如果文件自56e05fced 以来已被删除,则不会通过执行git checkout 56e05fced -- . 进行转移。
该解决方案不会删除自56e05fced 以来添加的新文件,就像git reset --hard 或git revert 一样。如果您真的想要恢复56e05fced 的状态,而不是git checkout 的状态,那么您真的想要使用这些命令。
注意:这将使您处于分离的头部状态。不可取!
这对我很有用,但是在这种情况下"—"是什么意思?
应该简单到:
这会让你回到那个特定的时间点。
…而且也是非常危险的,因为这将抹去所有的历史,包括其他民族的工作。当心这个!
这可能有效:
1 2 3
git checkout 56e05f
echo ref: refs/heads/master > .git/HEAD
git commit
这基本上与git reset --hard 56e05f 的做法相同,只是它不太安全,更容易被黑客攻击。你也可以使用查理的解决方案或雅库布的解决方案。