我在一个本地分支上工作,添加了许多提交.
然后我把它推到了remote staging分店.
现在我必须撤消已推送到的最后一次提交,remote staging即我本地分支的合并remote staging
我对其他答案的理解是,我必须使用还原而不是重置才能以干净的方式进行,不是吗?
所以我要做的是:
cleaning具有master父级(在分段后面)staging入清洁状态git revert {last good commit hash in staging}cleaning应该处于良好的提交状态并处于remote staging我的不良推动之前的状态,不是吗?cleaning入remote staging到具有远程分支恢复.有哪些旗帜?我对么?因为git status在第4点告诉我,我是最新的staging
bat*_*str 17
不要让它变得复杂.
首先,您需要执行a git log以找出要还原的提交ID.例如,它是提交abc123.如果您知道它是最后一个,您可以使用特殊标识符"HEAD".
然后,首先在本地"staging"分支中将其还原为本地:
git checkout staging
git revert abc123
Run Code Online (Sandbox Code Playgroud)
注意:对于您将要编写的日志中的最后一次提交git revert HEAD.
然后你更新你的远程"staging":
git push
Run Code Online (Sandbox Code Playgroud)
说明:在git中,如果你有一个遥控器,你正在处理2个不同的存储库(本地和远程).执行此操作后git checkout staging,您实际上创建了一个表示远程分支的不同本地名称.git revert实际上不会删除你的提交,但它会在顶部创建一个新的提交,撤消所有的更改(如果你添加了一个文件 - 新的提交将删除它,如果你删除了一行 - 新的提交会将其添加回来等.),即它是日志的补充,这就是推送干净的原因.
如果你想真正让它消失,那么没有人可以责怪你,你可以冒风险:
git checkout staging
git reset --hard HEAD^
git push -f
Run Code Online (Sandbox Code Playgroud)
(重置行重新定位本地"staging"分支,以便它指向最高提交之前的提交)
一般来说,强制推送是一种不好的做法,但保持无用的提交和恢复也不是很好,所以另一种解决方案是实际创建一个新的分支"staging2"并在该分支中进行测试:
git checkout staging
git checkout -b staging2
git reset --hard HEAD^
git push
Run Code Online (Sandbox Code Playgroud)
请记住,这git revert实际上意味着取消更改,而不是 恢复(即恢复)某个特定版本。可以实现恢复到/恢复,但是执行此操作的命令是git checkout和git read-tree(由于不同的原因,这两个命令都有点棘手)。请参阅如何将 Git 存储库恢复到以前的提交?并回滚到公共存储库中的旧 Git 提交(特别是jthill 的回答)。
这里唯一真正棘手的部分是“恢复合并”。这相当于在合并提交上使用git revert -m 1,这很容易运行;但这意味着之后,您无法重新合并,因为 Git 非常确定(并且正确)您已经合并了所有这些工作,并且正确的结果已经就位(确实如此,您只是稍后撤消了它)。要将其全部恢复,您可以恢复恢复。
恢复会产生一个新的提交,就像每次提交一样,只是将一个新的提交添加到当前分支。您一如既往地在自己的存储库中执行此操作。剩下的工作只是将新提交推送到其他某个Git存储库,将其添加到其他 Git 的集合中作为其分支之一的新提示。
\n\n首先,让我们备份一下,因为短语“远程分支”没有任何意义,或者更确切地说,对于太多不同的人来说意味着太多不同的事情\xe2\x80\x94无论哪种情况,它最终都会导致通信失败。
\n\nGit 确实有分支,但即使是“分支”这个词也是含糊不清的(请参阅“分支”到底是什么意思?)。我发现最好具体一些:我们有分支名称,如master和staging,在您的建议中,cleaning。Git 还具有远程跟踪名称或远程跟踪分支名称,例如origin/staging,但令人困惑的是,Git 将这些名称存储在本地,即(仅)在您自己的存储库中。当您 的Git 最后一次与他们的 Git 交谈并询问origin/staging他们有关. staging
因此,这里问题的根源是你的 Git 存储库是你的,但还有第二个 Git 存储库不是你的,而你最终想在另一个Git存储库上做一些事情。这里的限制是你的 Git 只允许你在存储库中执行这些操作,之后你最终将运行git push. 该git push步骤会将一些提交从您的 Git 存储库转移到他们的 Git 存储库。此时,你可以要求他们的Git 设置他们的名称 \xe2\x80\x94他们的 staging\xe2\x80\x94 他们会要么说是,我已经设置了(你的 Git 现在将更新你origin/staging以记住这一点),要么说否,我拒绝这样设置,原因如下:_____(在此插入原因)。
因此,您要在存储库中执行的操作是设置适当的步骤,以便他们的存储库中的 Git接受您的提交git push并更新他们的staging. 当我们执行这些步骤时,请记住这一点。有多种方法可以做到这一点,但以下是我会使用的方法。
跑步git fetch。该命令始终可以安全运行。您可以为其指定一个特定遥控器的名称,如果您有多个遥控器,但大多数人只有一个,名为origin,如果您只有一个,则无需命名。
(远程\xe2\x80\x94 \xe2\x80\x94 的名称origin主要是拼写 URL 的简写方式,您的计算机应使用该 URL 来访问其他 Git 存储库。)
这git fetch可能不会执行任何操作,或者可能会更新您的一些远程跟踪 ( origin/*) 名称。所做git fetch的就是调用另一个 Git,从中获取其所有分支的列表以及相应的提交哈希值,然后带来他们拥有但您没有的任何提交。你origin/staging现在记得他们了staging。现在您可以为此添加新的提交。
现在您的origin/stagingGit 已与其他 Git 同步staging,请根据需要创建或更新本地分支名称。此处使用的最佳名称是,但如果您愿意,staging也可以使用。cleaning因为此步骤是create 或 update,所以它有子步骤:
如果是“create”,则可以用来git checkout -b staging origin/staging创建一个staging上游为 的新对象origin/staging。
您可以将其缩短为git checkout staging,其中 \xe2\x80\x94 因为您没有自己的staging\xe2\x80\x94 将搜索您的所有origin/*名称(以及任何其他远程跟踪名称,如果您有多个远程名称)找到匹配的。然后它的行为就像您使用了更长的命令一样。(只有一个遥控器时,唯一可以匹配的名称是origin/staging。如果您同时拥有origin和xyzzy作为遥控器,则可以同时拥有origin/staging和xyzzy/staging;那么您将需要更长的命令。)
或者,如果它是“更新”,那么您已经有一个staging已origin/staging设置为上游的,因为您之前已经这样做过。在这种情况下,只需运行:
git checkout staging\ngit merge --ff-only origin/staging\nRun Code Online (Sandbox Code Playgroud)\n\n让您的舞台与origin/staging. 如果快进合并失败,则您有一些它们没有的提交,并且您将需要更复杂的东西,但我们在这里假设这会成功。
您也可以稍微缩写这些命令,但我将在此处将它们拼写出来。请注意,第一个命令与上面第一种情况的简短版本相同,您可以通过 的输出来判断发生了哪一个命令git checkout staging。(我将留下其他问题或练习的详细信息。)
我们可以在您自己的存储库中绘制您现在拥有的内容的图片,它看起来像这样:
\n\n...--o--o--o---M <-- staging (HEAD), origin/staging\n \\ /\n o--o <-- feature/whatever\nRun Code Online (Sandbox Code Playgroud)\n\n每一轮o代表一次提交。 M代表合并提交,您不喜欢其结果,但它也存在于其他 Git 的name下origin,这就是为什么您自己的 Git 的名称指向commit 。stagingorigin/stagingM
您现在想要创建一个提交来撤消错误的提交。这可能会使用git revert,但请记住,恢复意味着撤消或退出,而不是切换到旧版本。你告诉 Git 哪个提交要撤消,Git 通过弄清楚你做了什么并执行相反的操作来撤消它。
例如,如果您说要恢复的提交说“删除文件自述文件”,则更改将包括“以删除文件时的形式恢复文件自述文件”。如果您要恢复的提交说“将此行添加到 Documentation/doc.txt”,则更改将包括“从 Documentation/doc.txt 中删除该行”。如果你说要恢复的提交在第三个文件中说“将你好改为再见”,那么恢复将做的更改就是在同一行上将第三个文件中的“再见”更改为“你好”(有一些魔法可以找到如果线移动了)。
\n\n这意味着git revert可以撤消任何提交,即使它不是最新的提交。不过,要做到这一点,它必须将该提交与其直接父级进行比较。如果您尝试还原的提交是合并提交,则它有多个父级,您需要指定 Git 应使用哪个父级。
使用正确的父级并不总是显而易见的。然而,对于大多数合并,它只是“父编号 1”。这是因为 Git 特别强调合并的第一个父级:它是HEAD您运行时的提交git merge。这就是合并带来的一切,但尚未存在。
当git revert成功时,它会进行一次新的提交,以撤消合并的效果:
W <-- staging (HEAD)\n /\n...--o--o--o---M <-- origin/staging\n \\ /\n o--o <-- feature/whatever\nRun Code Online (Sandbox Code Playgroud)\n\n这里,W代表这个新的提交:它被M颠倒了。现在您所要做的就是运行git push origin staging将您自己的新提交发送W到另一个 Git:
git push origin staging:这会调用其他 Git 并为其提供提交W\xe2\x80\x94,这是我们拥有而他们没有的每个提交;他们有M和 更早的一切(向左),但没有W。
只要没有特殊限制,他们就会接受这个新的提交,并将其 staging更改为指向新的提交W。你的 Git 会记住这个改变:
W <-- staging (HEAD), origin/staging\n /\n...--o--o--o---M\n \\ /\n o--o <-- feature/whatever\nRun Code Online (Sandbox Code Playgroud)\n\n(无需继续W在单独的线上绘制,但我在此处使用复制粘贴来保持形状相同。)
如您所见,您现在已经完成了。您和他们都同意您和他们staging都应该指向W具有撤消提交效果的提交M。staging如果您愿意,现在可以安全地删除您自己的名字:
git checkout <something-else>\ngit branch -d staging\nRun Code Online (Sandbox Code Playgroud)\n\n其产生:
\n\n...--o--o--o---M--W <-- origin/staging\n \\ /\n o--o <-- feature/whatever\nRun Code Online (Sandbox Code Playgroud)\n