【问题标题】:How to re-merge deleted folder in GitHub?如何重新合并 GitHub 中已删除的文件夹?
【发布时间】:2022-01-18 19:24:24
【问题描述】:

假设我有 3 个分支:main、dev 和 release dev 分支是使用主分支创建的,并且在主分支之前。 dev 分支有一个新文件夹,里面有一些新文件。

在 GitHub 中,我错误地从 dev 分支直接合并到 release 分支,而 dev 必须先合并到 main 分支,只有 main 分支必须与 release 分支合并。此时,在 dev 分支中的新文件夹在 release 分支中创建。

我立即恢复了发布分支中的合并。由于还原,新文件夹在发布分支中被删除。

接下来我将 dev 分支与 main 分支合并(这是我首先应该做的),然后将 main 分支与 release 分支合并。

但是,dev 分支中的新文件夹现在仅存在于主分支中,并且该文件夹及其文件不会在 release 分支中重新创建,因为该文件夹由于还原而被删除第一次合并。

如果我尝试创建一个从 main 到 release 分支的新合并请求,GitHub 会显示 release 分支是最新的,包含来自 main 的所有提交,并且 release 领先于 main。

main 合并到 release 的解决方案是什么,以便从 dev 分支到 main 的新文件夹在 release 分支中重新创建?

编辑 1:

无论我从 dev 合并到 release 都是正确的代码,但我不应该直接从 dev 合并到 release 作为练习。

【问题讨论】:

  • git 不太关心文件;它更不关心文件夹。这里实际发生的是,您还原的 commits 没有被合并到发布分支,因为就 git 而言 您已经合并了它们。所以现在你需要“revert the revert”——见stackoverflow.com/questions/8728093/…stackoverflow.com/questions/5354682/…,可能还有很多其他类似的问题。
  • 在上面的帖子中,我并不清楚,还原还原如何启用从主分支到发布分支的全新合并,并创建文件夹/文件。引擎盖下发生了什么/是什么使它起作用?我不想在不了解的情况下在生产 repo 上尝试一些东西。
  • 如果我们回滚revert,Git如何理解那些来自主分支的提交不再合并到发布分支中?
  • 我的问题也与其他帖子略有不同,因为我从 dev 合并到 release 的任何内容都是正确的代码,但我不应该直接从 dev 合并到 release 作为策略。跨度>
  • 至于政策方面,为什么你会陷入这种境地并不重要,事实是你情况:你已经恢复了一些东西,现在你想要它回来。只有两种方法可以做到这一点:1)重写历史(做对很棘手,做错很危险); 2)创建一个新的提交重新引入恢复的更改。这就是 git 的工作原理。

标签: git github merge version-control


【解决方案1】:

git 不太关心文件;它更不关心文件夹。这里实际发生的是你有一些 git 认为不需要合并的提交。这是因为,就 git 而言,您已经合并了它们

这里的关键点是,reverts 不会记录他们正在恢复的提交;每次运行git revert 时,它只会创建一个新提交,就像原始提交的镜像一样。假设您创建了提交 abc123,然后运行 ​​git revert abc123: 创建一个新提交 def456,它撤消 abc123 的更改;但它不会撤消该分支历史中提交 abc123 的存在。

假设您的原始更改是提交 b1b1b1,而您将 abc123 合并为发布;你的历史现在可能看起来像这样:

                                       release
                                          |
                                          v
               +---------<* abc123 <- def456
              /          /
... <- 000aaa           /
             \         /
              <- b1b1b1
                   ^        
                   |        
               my_branch

现在,每当您尝试将“my_branch”合并到“release”中时,git 都会查找 该分支上尚不存在的提交。提交 abc123 仍然是分支的一部分,并且由于将 b1b1b1 记录为其父级,因此 b1b1b1 也是分支的一部分。因此,合并只会跳过该提交 - 它不知道您后来恢复了更改。

因此,您需要“还原还原” - 请参阅 How do I "un-revert" a reverted Git commit?How can I fix a reverted git commit? 以及可能许多其他类似问题。

在这种情况下,如果您运行 git revert def456,您将创建第三个提交 789aaa,它会撤消撤消操作 - 换句话说,它会重新创建来自提交 abc123 的原始更改。如果您将还原视为镜像,那么还原还原就是镜像的镜像 - 与原始图像相同。

鉴于上图,我们可能首先将“release”合并到“my_branch”,这样 abc213 和 def456 就在那个分支上。这样,我们就可以在某个地方放置我们的“revert of the revert”,而无需直接提交“release”。那么当我们还原def456的时候,结果是这样的:

                                       release
                                          |
                                          v
               +---------<* abc123 <- def456
              /          /                 \
... <- 000aaa           /                   \
             \         /                     \
              <- b1b1b1 ---------------------<* c2c2c2 <- 789aaa
                                                            ^        
                                                            |        
                                                        my_branch

现在,如果我们要求 git 将“my_branch”合并到“release”中,它会再次查找目标分支上尚不存在的提交。在这种情况下,它会找到提交 c2c2c2(没有更改的合并提交)和 789aaa(reverted revert)。

                                                                  release
                                                                    |
                                                                    v
               +---------<* abc123 <- def456 -------------------*> 999fff
              /          /                 \                   /
... <- 000aaa           /                   \                 /
             \         /                     \               /
              <- b1b1b1 ---------------------<* c2c2c2 <- 789aaa
                                                            ^        
                                                            |        
                                                        my_branch

在所有这些中,git 应用的是一个更改:创建一个文件是一个更改,它的镜像是删除文件;在文件中添加一行也将是一个更改,并且镜像将删除该行。没有办法简单地“提醒 git 一个文件存在”——如果你试图对“丢失”的文件进行更改并合并它,你会遇到冲突,因为没有地方可以进行更改。

底线是:要在发布分支上重新创建文件,您需要创建一个新的提交来创建这些文件

该提交需要位于文件尚不存在的分支上,因此在您的情况下,我认为您需要:

  • 将“release”合并到“main”中:由于意外提交以及您恢复它的提交,它目前领先于“main”。
  • 完成后,文件将在“main”上删除。要让它们恢复原状,您需要revert the revert
  • 这实际上将创建原始更改的新副本,重新创建文件。
  • 现在将“main”合并到“release”中会根据需要创建文件。

【讨论】:

  • 在您的解释中,我不明白提交 b1b1b1 是如何在执行还原后合并到发布分支中的。即使是 revert 的 revert 也不会从发布分支的历史记录中删除 b1b1b1,对吧?
  • @AllSolutions 不,如图所示,提交 b1b1b1 仍然存在于完全相同的位置;它已经在 my_branch 和 release 的历史中。但是现在我们有了一个新的提交,789aaa,它再次添​​加了文件。 那个提交将被合并到发布分支。
  • 只是为了理解,如果我不将发布合并回 my_branch,我只是在发布分支中还原还原并说这个提交是 789aaa,现在我尝试将 my_branch 合并到发布, 那么 my_branch 仍将位于原始提交 b1b1b1 上,该提交已在发布分支的历史记录中,因此仅对 revert 进行还原将不允许从 my_branch 合并到发布分支,但在这种情况下它可能没问题,因为两个分支(在还原之后)具有相同的文件集。
  • 如果我在发布分支中还原了还原,然后我在 my_branch 中添加了更多提交,假设没有其他提交被添加到发布分支中,这些提交将直接合并到发布分支中同时,这种理解正确吗?
  • 感谢您的所有时间。我无意冒犯你。我在这里总结一下:如果我将提交 c1 直接从 dev 推送到 release,而我的意图是将它从 dev 推送到 main 再到 release,则无需还原。我也可以简单地将相同的提交 c1 推送到 main 。但是,既然我已经完成了 revert (c2),最好将 revert (c3) 还原并将其合并回 main,以便 main 和 release 具有相同的提交 c3,并且将来对 main 的任何提交都将是可合并的释放而不会产生冲突,因为两者都将具有相同的祖先 c3
猜你喜欢
  • 1970-01-01
  • 2020-04-24
  • 1970-01-01
  • 2012-01-14
  • 2014-09-06
  • 1970-01-01
  • 2018-07-31
  • 1970-01-01
相关资源
最近更新 更多