【问题标题】:Need clarity with git workflow involving git pull and pull requests需要明确涉及 git pull 和 pull requests 的 git 工作流程
【发布时间】:2022-01-23 10:51:21
【问题描述】:

上图让我们很好地了解了 git pull 和 git pull --rebase。 我在这里对一件事感到困惑。让我详细说明-

1.案例 1 -> git pull --rebase origin master

命令后我的本地主分支 - A B C X Y D' E'

命令后我的远程主分支 - A B C X Y

如果我现在执行 git push origin master:master,我的远程 master 分支将看起来像 - A B C X Y D' E'

2。案例 2 -> git pull origin master

命令后我的本地主分支 - A B C D E F

命令后我的远程主分支 - A B C X Y

git push origin master:master 在这种情况下会如何表现?我不明白为什么在任何情况下我们都想在没有 --rebase 的情况下使用 git pull?

【问题讨论】:

  • 大多数时候我们只是做一个 git pull,rebase 就像一个脏合并(不像合并那样跟踪所有的更改历史),但更容易保持分支同步。我是一个 rebase 粉丝,但有些公司不喜欢它,如果合并噪音真的是一个问题,那么我们使用 git flow 并创建本地功能分支,这样每个开发人员都可以在自己的分支中工作,不再有噪音!,我不t 认为(不是 100%)它会做任何事情来掌握,因为您在本地重新调整更改并从与您推送到的同一分支中提取。

标签: git rebase pull merge-conflict-resolution


【解决方案1】:

我认为,避免git pull 可以很好地解释你所缺少的。尽管如此,让我们假设git pull 有一个假设的--merge 选项,因此我们可以说您正在运行git pull --merge origin master。 (您已经获得了合并;如果它是显式选项,则此选项将是默认选项。)也就是说,您的 git pull origin master 运行相当于:

  1. git fetch origin;那么
  2. git merge -m "merge branch master of <url>" origin/master。

这会产生图表,他们将其绘制为:

A--B--C--D--E--F   <-- master
       \      /
        X----Y

(我在这里把它转过来了。旋转 90˚ ccw 以匹配。)

我现在想建议像这样重绘它:

        D--E
       /    \
A--B--C      F   <-- master
       \    /
        X--Y

现在我已经以 this 的方式绘制了图表,哪些提交是“on”分支master?如果你选了A-B-C-D-E-F,那你为什么不选X-Y呢?如果你选A-B-C-X-Y-F,为什么不选D-E?

事实上,所有八个提交,包括D-E 和 X-Y,都是“on”分支master。 名称 master 标识提交F,但提交F 是一个合并提交。它返回到两个不同的提交:E 和 Y。这两个不同的提交分别返回到D 和X,这两个不同的提交返回到一个共同的共享起点C。

Commit C 是两个 tip 提交的 合并基础,当时您通过 git pull 让 Git 运行 git merge。因此,Git 通过运行提交C 和E 中的快照之间的差异,找出了你在C-to-E 上所做的事情。然后 Git 通过运行 C 和 Y 之间的差异,在 C-to-Y 分支上找到了他们所做的事情。然后 Git 获取两个差异并将它们组合,将组合结果应用到来自提交 C 的共享快照,并使用它来进行新的合并提交 F。

合并提交F 有一个快照,就像其他所有提交一样。它与其他提交的不同之处在于它有 两个 父级,E 和 Y。所以你可以问 Git:*从 E 到 F 的变化是什么,你会得到由于合并的较低(在我的绘图中)腿而带来的变化;或者您可以询问从Y 到F 发生了什么变化,您会看到由于合并的上半部分带来了哪些变化。

无论如何,这是合并的工作(和要点):合并工作,记录合并工作的事实。您现在可以确切地看到发生了什么:您在他们工作的时候做了一些事情,他们在您工作的时候做了一些事情,然后您一次将它们组合在一起。

使用 rebase 可以创建“更清晰”的历史记录:看起来他们做了某事,您等待他们完成,然后您开始执行您的任务,知道他们做了什么,完成了您的工作并提交了它。这并不是真正发生的事情,但也许它同样好。也许它更好,因为对于未来的你、他们或任何人来说,它更简单:它不需要弄清楚在工作组合过程中是否出了问题。但是,如果某事确实出了问题,它可能会隐藏某事的本来面目,让未来的你/他们/任何人更糟。 p>

这就是为什么你有一个选择:一个可能比另一个更好,或者不是。

[编辑:]git push 做了什么

当你运行时:

git push origin master

或其等效但更明确的变体:

git push origin master:master

您的 Git 将:

  • 使用名称origin 查找此git push 操作的URL(git config --get remote.origin.pushurl;如果未设置,则为git config --get remote.origin.url);
  • 调用任何响应此 URL 的内容:应该是另一个 Git 软件,连接到另一个存储库;
  • 提议通过其哈希 ID 向他们发送您最新的 master 提交;和
  • 从那里继续。

首先假设您使用了rebase,因此您最新的master 提交哈希ID 是提交E' 的哈希ID。你的 Git 提议将此提交发送到他们的 Git。他们从未听说过这个哈希 ID,所以他们说是的,请发送那个,然后告诉我它的父代。然后你的 Git 告诉他们提交 D' 的哈希 ID;他们也没有听说过那个,所以你的 Git 告诉他们D's parent Y。此时他们对你的 Git 说:啊,我已经提交 Y,你现在可以停止发送东西了;打包我所要求的提交所需的内容,知道我已经提交 Y以及之前的每个提交。

或者,让我们暂时假设您使用了git merge。你的 Git 将提供提交F(通过哈希 ID)。他们的 Git 会对那个人说 yes,所以你的 Git 现在会提供发送 both 父母 E 和 Y。他们会对Y 说不,谢谢,因为他们已经有了那个,但是是的,请 对E,所以你的Git 会提供D;他们也会同意那个,然后你的 Git 要么提供C,要么意识到他们有C,因为他们有Y:如果你的Git 确实提供C,他们会说他们没有'不需要它,所以这两种方法都是一样的(如果你的 Git 更聪明,它会更有效)。

既然您的 Git 知道要发送哪些提交,以及他们已经拥有哪些提交,您的 Git 会创建一个相当小的精简包——这在技术上取决于所选的推送协议,但每个人都应该使用这些天来的“智能”协议——包含必要的提交和对象,知道另一个 Git 存储库已经拥有与他们已经拥有的所有提交相关的所有对象。然后,您的 Git 会将这个“精简包”发送给他们,如果一切顺利,他们会将其保存起来以备进一步使用。

最后,您的 Git 会发送以下形式的礼貌请求:如果没问题,请将您的分支名称 master 设置为 ________。如果没问题,请告诉我。 你的 Git 用你自己的 master 的哈希 ID 填充空白。然后,他们的 Git 会检查新提交是否添加到他们自己的 master 分支,而不会从他们的 master 中删除他们之前的任何提交。

这两种情况——你要求他们添加F,或者你要求他们添加E'——都添加,将他们现有的提交Y保留在他们的分支中,所以他们可能会接受你的礼貌请求。

请注意,他们从不知道或关心您使用什么分支名称来查找这些提交。他们只关心 他们 被要求设置什么分支名称、哈希 ID 以及其中涉及的各种提交。

【讨论】:

  • 所以基本上你的意思是说,F 包含来自 X 和 Y 的所有东西?以及合并冲突解决的东西?
  • 与每个提交一样,合并提交包含一个快照。根据定义,F 中的快照是合并的正确结果(无论如何,就 Git 而言!——如果它是错误的,则由人来解决这个问题)。默认的合并算法(这是git pull 将在此处使用的)尝试从“双方”保留工作,是的。
  • 如果在 git pull origin master 之后,我们执行 git push origin master:master 怎么办?你能用这个输出更新你的答案吗?
  • 在origin 上的Git 中,他们的master 指向提交F,合并。所以他们的master 名称指向您的名称master 在您的存储库中指向的同一个提交,这意味着他们和您的存储库同意master 由提交F 组成,然后是合并的子分支,然后是常见的共享提交。这与重新定位链的成功git push 后相同:您和他们有相同的提交,通过相同的名称master 找到。 (如果origin 接受你的git push,你的Git 会更新你自己对他们的master 的记忆——即你的origin/master——以匹配。)
  • 理解这一切的真正关键是 commits 被共享。您的存储库中的名称和它们的名称不需要匹配:名称仅用于查找提交,而那些是您需要匹配的。但是人类也喜欢有匹配的名字,所以这通常是计划。 :-)
猜你喜欢
  • 2011-01-26
  • 2017-11-23
  • 2020-03-25
  • 2012-10-30
  • 2012-09-10
  • 2021-11-17
  • 2014-10-15
  • 1970-01-01
  • 2011-02-22
相关资源
最近更新 更多