【问题标题】:How to sync two different Git repos without making a commit?如何在不提交的情况下同步两个不同的 Git 存储库?
【发布时间】:2023-04-05 20:35:01
【问题描述】:

我能够使用 'fetch' 和 'checkout' 将文件从一个 RepoA 同步到 RepoB 到我的主人并处理冲突(如果有的话)。但是这种方法使我在 RepoB 上进行了“合并提交”。

有没有办法在生成提交 ID 的情况下做到这一点? 我想安排所有提交,然后通过 chron-task 定期同步。

我还研究了 git-daemon 和 post-commit 钩子。如果可以,请举个例子。

Repos 的初始状态:

应用合并后:

重置为上次提交后(创建 File02.txt):

【问题讨论】:

  • “处理冲突”是指创建有关如何解决冲突的数据。这些数据必须存储在某处,而该某处就是合并提交。即使没有冲突,合并提交也是使两个分歧的分支再次汇聚以合并两个变更集的原因。因此,在一般情况下,您无法避免合并提交。
  • 能否rebase 帮助更改提交历史,以便以最后一次提交而不是最终合并提交结束?
  • @PratyushRaizada 是的,最简单的方法是简单地使用git pull --rebase,有关详细信息,请参阅my answer
  • 这两个“初始提交”是否有不同的哈希值?然后观察到的行为是可以预期的,但是这个comment space is too narrow to explain ;)
  • 两个“初始提交”(AB)确实具有不同的哈希值,所以 git 必须 进行合并

标签: git github


【解决方案1】:

由于 git 存储和寻址数据的方式,给定的提交 ID 可能只能存储一个特定的树 - 也就是说,一组目录具有一组文件,每个文件中具有一组特定的内容。

(从技术上讲,您可以争辩说这不是真的,但实际上永远不会发生具有不同树的两个提交具有相同的提交哈希。)

因此,当您合并时,无论您是否解决冲突,除非合并的结果与原始提交之一完全相同(这通常仅在一个提交是另一个提交的祖先并且快进时发生是允许的),必须创建一个新的提交。

因此,当您同步两个 repo 时,如果其中包括同步分支,其中每个 repo 包含另一个尚未看到的更改,则无法避免创建新的提交。

更新 - 在 cmets 中,提出了一个后续问题:“可以 rebase 帮助改变提交历史,以便以最后一次提交而不是最终合并结束 -提交?”

虽然这个问题可以用几种方式来解释,但无论如何答案都是“否”。如果涉及的任何存储库与其他用户共享,则将有关使用 rebase 的警告放在一边,它不会按照您的要求执行。

首先,了解 rebase 不会改变提交的顺序。不可能改变提交的顺序。当您执行交互式变基并更改待办事项列表的顺序时,会发生 全新的 个提交(每个提交都有一个新的提交 ID),以便应用以不同的顺序进行相同的更改

事实上,默认情况下,您可能不会注意到这一点,但原始提交仍保留在变基之前的位置。 (尝试在执行这种类型的变基之前标记 HEAD,然后运行 ​​gitk --all 之类的内容以查看结果。)

您无法重新排序提交的原因与您无法在未创建新提交 ID 的情况下合并更改的原因类似。 关于提交的所有内容都编码在提交 ID 中。这包括我之前提到的它的树;它还包括父提交的 ID(因此,传递到当前提交的整个提交谱系)。

一般来说:

  • 如果您有一个 repo,并且您将以前没有的新更改合并到其中,那么反映这些更改的每个提交都会有一个以前在 repo 中没有看到的新 ID。

    李> 1234563 .

【讨论】:

  • 能否rebase 帮助更改提交历史,以便以最后一次提交而不是最终合并提交结束?
  • 简短回答:不。我会用长答案更新。
  • 我提供了一个更新来尝试解决这个问题。如果您想了解更多细节或认为我误解了这个问题,我建议您尝试以下方法:绘制一个图表,显示合并前每个 repo 的内容,以及一个图表,显示您希望最终 repo 的样子。把那个贴出来,我们可以直接说明是否可行,如果可以怎么做,如果不可以,为什么不可以。
  • 谢谢,我会尽快发帖
  • 嗨,马克!我找到了解决提交删除的方法,通过将存储库恢复到最后一个作者提交,我现在可以使用命令“git reset --hard fb62ef635b07afaf719ba15841579ed12e1224b0”忽略合并提交
【解决方案2】:

合并 repo 后,可以通过简单地将 Repo 的状态恢复到父 repo 的最后一次提交来删除最后一次合并提交。

使用命令:

git log --format="%H" -n 1 ---> 从父 repo 获取最后一次提交 id

git reset --hard fb62ef635b07afaf719ba15841579ed12e1224b0 将 Repo 的状态恢复到之前的状态

fb62ef635b07afaf719ba15841579ed12e1224b0 是前一个状态的提交 ID

【讨论】:

  • 您可以使用HEAD^ 代替固定的提交ID,或者使用例如。 HEAD~4 用于提交 4 次之前的提交。但是硬重置通常是一个危险的过程,会让你失去所有未提交的更改;您可能要考虑使用rebase。或者先使用git stash
  • 我想过考虑 HEAD^ 但如果没有提交,一个真正的提交将被删除。感谢您介绍“git stash”!
  • 不客气-但请注意,您的回答不仅意味着失去合并提交,还意味着自上次拉取以来您自己的所有提交!幸运的是,git 确实保留了一个 reflog,因此如果您尽快采取行动,您可以再次找到这些提交。
【解决方案3】:

您可以使用git pull --rebase,它将您的本地提交重新定位在远程头之上。您当然可能会遇到必须修复的其他冲突,但您仍然不会有任何额外的合并提交。您也可以git config pull.rebase true 以始终通过git pull 实现此目的。请注意rebase 的后果,例如你以前不应该有 pushed 任何东西 rebased。

相关的 SO 问题:

【讨论】:

  • 嗯...我想我对这个问题的理解不同,但取决于你真正想要完成的事情,这可能是一个很好的解决方案。
  • @MarkAdelsberger 是的,不幸的是,如果没有一些示例历史,这个问题并不完全清楚。希望我们的答案对其他人有用:)
  • @TobiasKienzler 我上传了一些图片作为示例来说明问题。你可以在马克的回答中找到它。希望它澄清。 (我是使用这个平台的新手,否则我可以在问题本身中发布它)
  • @PratyushRaizada 您可以编辑您的问题,还有一个图片上传功能 - 哦,我明白了,您首先需要一些代表,别担心很快就会发生。我会为你编辑它。
猜你喜欢
  • 2011-02-11
  • 2011-06-19
  • 2021-11-03
  • 2019-09-16
  • 2014-08-18
  • 2013-07-21
  • 1970-01-01
  • 2019-04-15
  • 2015-06-19
相关资源
最近更新 更多