【问题标题】:How to use Git pull on file that is updated by 2 or more users如何使用 Git 拉取由 2 个或更多用户更新的文件
【发布时间】:2019-11-20 03:48:35
【问题描述】:

假设您正在与其他人一起开展一个项目。你们都更新了项目的版本。有一个名为“example.cpp”的文件。你们俩同时处理同一个文件,并在本地系统上进行多项更改。你们中的一个人将更改推送到 git。现在,当其他人拉取更改时,这不会覆盖您在系统上该文件中所做的所有事情吗?

我基本上一直在制作 git 目录的另一个副本并在那里做我的工作,因为我不知道 git pull 会对我迄今为止所做的工作做些什么。我需要澄清一下。

【问题讨论】:

  • 您所描述的通常会导致需要解决的“冲突”。在“冲突”期间,git 将为您维护这两个更改,您可以选择接受其中一个或两个或一个都不接受,或者只是编辑您自己的版本,然后提交并推回。

标签: git github git-pull


【解决方案1】:

这有点棘手,直到您意识到 Git 实际上与 文件 无关。 Git 是关于提交

提交存储文件。在每次提交中,Git 都会存储您文件的所有的完整副本。这不是提交的全部——文件是它的数据,提交也包含 元数据,例如关于谁提交的信息(姓名和电子邮件地址)、何时(日期和时间-stamp),以及为什么(他们在提交时写的日志消息)。还有更多,但我们不会在这个答案中深入探讨。

要记住的是:Git 存储 commits,每个提交都存储 每个 文件。一旦您(或任何人)做出提交,关于该提交的任何内容都无法更改。因此,只要您仍然有任何一个特定的提交,您仍然拥有 所有 文件,就像您提交该提交时的那样。所有提交始终是 100% 完全只读的。大多数提交将永远保留在您的存储库中。

(摆脱一个提交有点困难,但绝对不是不可能的。不要太担心“坏”提交会占用大量空间。每个时间都冻结的快照文件被压缩——通常是高度压缩的——因此通常比原始文件占用更少的空间,,因为它们被永久冻结,Git 可以并且确实重复使用即,假设您连续进行 100 次提交,每次只更改一个文件。这可以是每次相同的文件,也可以是每次不同的文件,您可以根据需要来回更改——这并不重要。假设这 100 次提交中的每一次都有 500 个文件。由于在您的 next 提交中只有一个文件不同,因此它重用了前一次提交中的 499 个文件!并且, 如果你更改了一个文件back,新文件与旧提交中的旧副本相同,Git 会自动重新使用旧副本。)

每个提交都有一个大而丑陋的哈希 ID,对于那个特定的提交来说是唯一的。这个哈希 ID 的神奇之处在于它不仅对 that 提交是唯一的,而且,宇宙中的每个 Git 都会同意 that commit 获取 that 哈希 ID。没有任何其他提交获得该 ID。1 因此,两个 Git 很容易判断它们是否具有相同的提交:它们只是查看彼此的哈希 ID。 (实际上获取提交需要获取他们拥有的任何文件,而你也没有,但可以快速检查你是否已经拥有它。)

考虑到这一点,答案如下:

  • 首先,我们应该注意这一点:git pull 表示 运行 git fetch,然后——如果可行的话——运行第二个 Git 命令,通常是 git merge

  • git fetch 命令让你的 Git 调用其他人的 Git,并询问他们是否有任何提交,而你没有,你的 Git 应该得到。他们给你这些提交,现在你有你的提交加上他们的提交。这对您的任何提交都没有任何影响,因此它始终是完全安全的。

  • git merge 命令不是很安全,但很安全!它首先检查以确保您已提交您的 工作。如果没有,它会抱怨并让你提交......一旦你拥有了,所有你的文件,就像你提交它们时的状态一样,在你的新文件中一直安全地冻结提交。

  • git merge 操作通过查找更改来工作。你和你的朋友/同事从一些 common 提交开始——一些提交具有相同的哈希 ID,你和他们之前通过共享获得。然后您对某些文件进行了一些更改并制作了一个新快照以永久保存您的更改(以新的整个文件的形式),他们还进行了一些更改并制作了一个新快照以保存他们的永远改变。 Merge 将 merge base 提交(你们都开始使用的那个)与您自己的最新提交进行比较,并分别与他的最新提交进行比较。

比较任何两个提交可以告诉您这两个提交的不同。所以现在 Git 知道你改变了什么,也知道他们改变了什么。合并操作合并这些更改,并将合并后的更改应用到来自基本版本的快照。

如果您和他们更改了 same 文件的 same 行,您将得到 Git 所说的 合并冲突。在这种情况下,Git 会给您留下一团糟,您必须手动清理它,也许可以借助 merge 工具。但如果 Git 认为它能够自行组合您的更改,Git 将继续提交生成的组合更改快照,作为 合并提交。此合并提交会记住您自己的紧接在前的提交 他们最后一次提交的哈希 ID,以便 Git 知道哪两个提交进入了执行合并,并可以向您显示此合并产生的历史记录。

有些人可能会建议您在git pull 之前使用git stash,而不是自己提交。您可以这样做,但我不建议这样做。原因很简单:git stash push2 所做的只是进行一些不在 any 分支上的提交。这使得git pull 更容易,因为现在当git pull 执行其获取和合并步骤时,您没有要合并的提交——它使用分支上的提交进行合并——但之后您需要使用git stash applygit stash pop撤消隐藏。

您可能会忘记立即执行此操作,并首先进行一些您尚未提交的更改,然后记住git stash apply / git stash pop 步骤。此操作使用git stash push 所做的提交来运行git merge更不安全 版本。如果这里的情况很糟糕,则很难恢复您更改但未提交的内容。因此,通过使用git stash,您只是推迟了无论如何都需要进行的合并。

一旦您对合并和其他 Git 操作有很多了解后,您可以更安全地使用 git stash pushgit stash applygit stash drop,但如果您是 Git 新手,我建议您避免使用它。


1从技术上讲,两个不同的 Git 存储库可以重复使用哈希 ID,只要您从不将这两个 Git 存储库相互介绍。有关更多信息,请参阅How does the newly found SHA-1 collision affect Git?

2现在拼写为 git stash push 在旧版本的 Git 中拼写为 git stash save。新的拼写,push,修复了选项的一些小问题并允许一些新功能,并且还有助于解释为什么poppush 的对应物。我对git stash pop 的问题——好吧,除了我一开始就非常反对使用git stash ?——如果 Git 认为应用步骤去了,Git 将放弃存储好。有时应用步骤会很糟糕,即使 Git 认为它很好,或者你应用了错误的存储,并且 已经删除了存储会很好。

(如果你藏了很多东西,你会发现有时它们很难区分。一段时间后你不知道你为了什么原因保留了哪些。诚然commits can have the same problem,但在至少在这里,您以后有更多机会再次解决问题。)

【讨论】:

    【解决方案2】:

    git pull 与远程存储库同步以进行任何更改。

    https://guide.freecodecamp.org/miscellaneous/git-pull-vs-git-fetch/

    保存未提交文件的方法是使用git stash 命令,然后使用git pull,然后使用git stash pop。如果您所拥有的内容有任何冲突,现在是您编辑它的机会:)

    更多关于 stash 的信息可以在这里找到https://git-scm.com/docs/git-stash

    【讨论】:

      【解决方案3】:

      所以,你应该合并它。 这是正常情况。如果您是 git 初学者,请使用 GitExtensions 或 SourceTree(对初学者来说会更好)或 TortoiseGit。

      系统将为您提供解决此冲突的方法。它将打开拆分为 2-3 个部分的窗口。您将看到来自一个分支和另一个分支的更改。对于每个冲突,您应该选择将哪些代码保存为结果。在底部放置的结果文件中。

      如果您对此感兴趣,请提供一些理论。您的分支有 2 个实例(例如,我将使用分支名称“master”):

      1. master(你本地版本的分支)
      2. origin\master(存储在服务中的分支版本)。

      如果有人将代码推送到 master,那么 origin\master 将与您的 master 不同,您应该合并它

      但是当 2 个人在一个分支机构工作时,这是不好的做法。当您拉动分支并开始合并时,您可以覆盖您的更改(由于缺乏经验)并丢失它。

      如果您是初学者,请在单独的分支中工作并在不合并的情况下推拉它。并在需要时创建合并提交以掌握。它会给你回滚的可能性。 如果出现问题,您可以取消更改并将分支重置为服务器版本。

      【讨论】:

        【解决方案4】:
        ** You can manage this by different ways such as **
        
        1. 通过创建一个公共分支,每个人都将在其中推送更新,接下来您应该在每次开始工作前拉出分支并合并文件

        2. 并且您可以正常获取文件并与保存最新更新的底部分支(底部分支名称是最后更新的分支)合并

        【讨论】:

          猜你喜欢
          • 2020-06-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-01-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多