我的问题很简单。
我需要放弃任何代码更改并将代码恢复为之前的更改日志。 例如我想丢弃T2,T3和T4并返回tu T1。
在谷歌上搜索我只资助这个命令:
git reset --hard T1
但是当我尝试推送时,它说我的分支落后了,迫使我合并 T2、T3 和 T4。 我只想从之前的提交重新开始。
运行:
git reset --hard T1
git push --force-with-lease
git 中的提交像链表一样被链接起来。每个提交都指向之前的提交,除了具有空父级的第一个提交之外。 (旁注:合并提交有两个父级。)
git 中的分支只是指针。 git 中有一个特殊的指针,叫做
HEAD
。它指向您当前所处的位置。
master
|
v
T1 <- T2 <- T3
^
|
HEAD
这里,
master
分支位于T3
。 HEAD
指向 T3
,与分支指向的位置相同,这意味着您当前正处于 T3
提交。
Git 存储库旨在以去中心化的方式工作。我的意思是,您可以在本地使用您的存储库,而无需联系服务器。您的本地存储库和服务器存储库是副本。它们与
fetch
和 push
等命令同步。这是您的本地和服务器存储库的图示。
master (origin/master) master
| |
v v
T1 <- T2 <- T3 T1 <- T2 <- T3
^ ^
| |
HEAD HEAD
LOCAL REPO SERVER/ORIGIN
本地计算机上的 git 使用 origin/master
从服务器角度标记 master 分支指向的位置。当您运行
git reset --hard T3
时,它会将
HEAD
和当前分支(本例中为
master
)重新定位到
T3
。
master origin/master master
| | |
v v v
T1 <- T2 <- T3 T1 <- T2 <- T3
^ ^
| |
HEAD HEAD
LOCAL REPO SERVER/ORIGIN
请注意,HEAD
和
master
已重新定位,但
origin/master
仍然指向服务器指向的位置。现在,当您推送时,git 会拒绝,因为它认为您位于服务器
后面,并且您应该在分支上获得其余的提交master
。要告诉 git 你知道你在做什么,你可以使用
--force-with-lease
选项:
git push --force-with-lease
.它告诉 git,只要你知道服务器的变化,你就知道自己在做什么。比
git push --force
更好用;因为如果您的本地存储库实际上落后于服务器存储库,则会导致推送失败,从而避免破坏其他人的工作。
更新被拒绝,因为当前分支的尖端位于其远程对应分支的后面。在再次推送之前集成远程更改(例如“git pull ...”)。
由于您重置了本地历史记录,但其中一些更改之前已推送,Git 会阻止您丢失上一条消息的提交。 Git 无法区分您只是落后的情况或您决定将本地历史记录恢复到之前的点的情况。在这种情况下,正如 @eftshift0 已经在评论中所说,您应该使用
git push --force <remote> <branch>
强制推送到远程。像这样,您告诉 Git 您确定要推送的历史记录并覆盖该远程分支上当前的内容。但是,只有当您“绝对确定”团队中没有其他人已经将他们的工作基于这些提交时,您才应该执行此类操作。否则,他们的提交历史记录将从您的分支中无法到达的点分支出来,从而使协调变得非常混乱,并且绝对无法通过简单的
git merge
来完成。
在需要撤消某些提交引入的更改的情况下,更可行的替代方案是
git revert
。 命令
基本上引入了与给定提交的更改相反的内容。在你的情况下,它会像
git revert T4..T2
。但是,从您的帖子来看,我想说您已经重置了本地分支,此时 git push --force
可能是最简单的继续方法。
但是,如果您遇到其他开发人员已经将他们的工作基于这些提交的情况,您可以通过
git reflog
将本地分支带回 T4。该命令通常被描述为 Git 的时间机器,允许您了解 HEAD 引用指向的提交。通过这种方式,您可以重建哪个 SHA1 对应于 T4 并将您的本地分支带到该状态。此时,您可以启动 git revert HEAD..HEAD~2
并使本地分支达到与 T1 完全相同的状态,而无需更改分支的历史记录。这将使您能够毫无问题地推动并避免打扰同事的工作。