我有一个Git存储库,看起来像这样:
A <- B <- C <- D <- HEAD
我希望分支的头部指向A,即,我希望B、C、D和head消失,我希望头部与A同义。
听起来我可以尝试重新设置基础(不适用,因为我已经在两者之间进行了更改),也可以恢复。但如何恢复多次提交?我一次回复一个吗?订单重要吗?
我有一个Git存储库,看起来像这样:
A <- B <- C <- D <- HEAD
我希望分支的头部指向A,即,我希望B、C、D和head消失,我希望头部与A同义。
听起来我可以尝试重新设置基础(不适用,因为我已经在两者之间进行了更改),也可以恢复。但如何恢复多次提交?我一次回复一个吗?订单重要吗?
当前回答
在我看来,一个非常简单和干净的方法可以是:
回到A
git checkout -f A
将master的头指向当前状态
git symbolic-ref HEAD refs/heads/master
save
git commit
其他回答
我真的想避免硬重置,这就是我想到的。
A -> B -> C -> D -> HEAD
返回A(后退4步):
git pull # Get latest changes
git reset --soft HEAD~4 # Set back 4 steps
git stash # Stash the reset
git pull # Go back to head
git stash pop # Pop the reset
git commit -m "Revert" # Commit the changes
这是Jakub回答中提供的解决方案之一的扩展。
我面临的情况是,我需要回滚的提交有些复杂,其中几个提交是合并提交,我需要避免重写历史。我无法使用一系列git-restore命令,因为我最终在添加的反转更改之间遇到了冲突。我最终使用了以下步骤。
首先,检查目标提交的内容,同时将HEAD留在分支的顶端:
git checkout -f <target-commit> -- .
(--确保<targetcommit>被解释为提交而不是文件;.指的是当前目录。)
然后,确定在回滚的提交中添加了哪些文件,因此需要删除这些文件:
git diff --name-status --cached <target-commit>
添加的文件应在行的开头显示为“A”,并且不应有其他差异。现在,如果需要删除任何文件,请暂存这些文件以进行删除:
git rm <filespec>[ <filespec> ...]
最后,提交回复:
git commit -m 'revert to <target-commit>'
如果需要,请确保返回到所需状态:
git diff <target-commit> <current-commit>
应该没有区别。
扩展我在评论中写的内容
一般的规则是,你不应该重写(更改)你已经发布的历史,因为有人可能已经基于它进行了他们的工作。如果你改写(更改)历史,你会在合并他们的更改和更新他们时遇到问题。
因此,解决方案是创建一个新的提交,以恢复您想要删除的更改。您可以使用git-restore命令执行此操作。
您遇到以下情况:
A <-- B <-- C <-- D <-- master <-- HEAD
(这里的箭头指的是指针的方向:提交时的“父”引用,分支头(分支引用)时的顶部提交,head引用时的分支名称)。
您需要创建以下内容:
A <-- B <-- C <-- D <-- [(BCD)-1] <-- master <-- HEAD
其中[(BCD)^-1]表示恢复提交B、C、D中更改的提交。数学告诉我们(BCD
$ git revert --no-commit D
$ git revert --no-commit C
$ git revert --no-commit B
$ git commit -m "the commit message for all of them"
适用于除合并提交以外的所有操作。
另一种解决方案是签出提交A的内容,并提交此状态。也适用于合并提交。但是,添加的文件不会被删除。如果您有任何本地更改,请先将其保存:
$ git checkout -f A -- . # checkout that revision over the top of local files
$ git commit -a
那么您将出现以下情况:
A <-- B <-- C <-- D <-- A' <-- master <-- HEAD
提交A'的内容与提交A相同,但提交不同(提交消息、父级、提交日期)。
杰夫·费兰(Jeff Ferland)的替代解决方案,由查尔斯·贝利(Charles Bailey)修改,基于同样的想法,但使用了git重置。在这里,它被稍微修改了一下,这种方式适用于一切:
$ git reset --hard A
$ git reset --soft D # (or ORIG_HEAD or @{1} [previous location of HEAD]), all of which are D
$ git commit
我觉得有用的干净方式
git revert --no-commit HEAD~3..
git commit -m "your message regarding reverting the multiple commits"
此命令仅使用一次提交来还原最后3次提交。
也不重写历史,因此不需要强制推送。
这个帮助创建范围。意思是HEAD~3..与HEAD~3..HEAD相同
使用Git还原
也可以使用restore命令:
A <- B <- C <- D <- HEAD
假设你希望HEAD看起来和A完全一样,确保你已经找到了最新的主人。然后剪一根新树枝。
git switch -c feature/flux-capacitor # synonymous with checkout -b
git restore --source A .
git add .
git commit
git push
restore命令将所有内容(.)更改为--source提交时的内容。然后将其提交给本地分支,并将其推送到源。然后,您可以对其进行公关。
这样做的好处是不会改变其他人可能以其为基础的任何历史。它也为未来的人们留下了有用的历史。
文档:git restore