GitHub PR 使用什么 git 命令来显示差异

2024-03-04

我想使用命令行来生成 GitHub 提供的相同差异。帮助页面将其描述为“头部分支的尖端与头部上次与基础分支同步的提交之间的比较”(https://help.github.com/articles/about-comparing-branches-in-pull-requests https://help.github.com/articles/about-comparing-branches-in-pull-requests)

如果 PR 是将分支 a 拉入分支 b,那么 git diff 命令行是什么?

我特别想知道为什么当 a 和 b 都是在分支 m 上创建的,并且我将分支 m 上所做的后续更改合并到 a 和 b 时,该更改会出现在 PR 中。

示例:分支 m、a 和 b 的提交图(从下到上阅读)

b m a
4   5 merge branch m at commit 3 to branch a and b
|\ /| 
| 3 | commit on branch m
| | 2 create branch a off m at commit 0 and commit
1 | | create branch b off m at commit 0 and commit
 \|/
  0   start with branch m at commit 0

合并分行负责人:

git rev-parse a
5

合并基础:

git merge-base b a
3

git 命令显示提交 2 中引入的差异:

git diff b...a

但 GitHub PR 显示了提交 2 和 3 中引入的差异


Edit:我已经用本地命令和 GitHub 的实际输出对此进行了增强,现在我无法解释他们的拉取请求比较中显示的内容at all。这完全是无稽之谈,就像他们在网页上显示的许多其他内容一样。 GitHub 显示显示的提交是已经存在于目标分支中,就好像合并将进行实际上不会进行的更改一样。也就是说,对于“将分支 'a' 合并到 b”,唯一的提交将是added是那些尚未包含在“b”中的提交,但 GitHub 的显示显示了两个已包含在“b”中的提交。


TL;DR

通常(但请参阅长答案):

git diff $base...$head

where $base and $head来自下面的长答案。Edit: 嗯,他们就是这样的should展示。事实证明这不是他们想要的actually show.

使用您的示例存储库

您设置了一个存储库https://github.com/kenocrates/ex1,我克隆的:

$ git clone https://github.com/kenocrates/ex1
...
$ cd ex1

为了获得refs/pull然后,您修改了配置,使其部分内容如下:

[remote "origin"]
        url = https://github.com/kenocrates/ex1
        fetch = +refs/heads/*:refs/remotes/origin/*
        fetch = +refs/pull/*/head:refs/remotes/origin/pr/*

我也这么做了。然后:

$ git fetch origin
From https://github.com/kenocrates/ex1
 * [new ref]         refs/pull/1/head -> origin/pr/1

我现在使用的命令来查找正确的合并基础或基础,是:

$ git merge-base --all refs/remotes/origin/pr/1 refs/remotes/origin/b
587593749ee46806ed2c9fd06cf8b904bbce255a

since my通过合并拉取请求而合并的提交的全名是refs/remotes/origin/pr/1, and myGitHub 所谓的“基础分支”的全称是refs/remotes/origin/b。请注意,我们还可以使用原始哈希 ID 或更短的名称:

$ git rev-parse origin/pr/1
1cef243f9efe6e94c9926f7992efb6c093188b8c
$ git rev-parse origin/b
48728bc19480e0c1cc9e3a399634a5f389881c47

(离开了refs/remotes/,其中 - 如中所述gitrevisions 文档 https://www.kernel.org/pub/software/scm/git/docs/gitrevisions.html,将由 Git 通常用来解析名称的六步过程中的第五步假设)。

$ git merge-base --all 1cef243f9efe6e94c9926f7992efb6c093188b8c 48728bc19480e0c1cc9e3a399634a5f389881c47
587593749ee46806ed2c9fd06cf8b904bbce255a

因此,可以通过以下方式获得正确的差异(完整的,而不是一次提交一个):

$ git diff 587593749ee46806ed2c9fd06cf8b904bbce255a origin/b

或更短的:

$ git diff origin/pr/1...origin/b

其中任一输出:

diff --git a/file b/file
index 4fc2681..186222c 100644
--- a/file
+++ b/file
@@ -1,6 +1,7 @@
 Section A

 Section B
+line 1

 Section C
 line 1

这就是 GitHub 上的内容should显示如果我们接受拉取请求,它将被合并的内容以及它将产生的效果。他们实际展示的内容是不同的。 Per https://github.com/kenocrates/ex1/pull/1/commits https://github.com/kenocrates/ex1/pull/1/commits,我们看到的是四个提交,其中两个已经包含在目标分支中:

1cef243f9efe6e94c9926f7992efb6c093188b8c
587593749ee46806ed2c9fd06cf8b904bbce255a
23c2ff68c02207a2f172090566d7b2c75b6f1c16
b21d3c4067261aa295319f177ad1629b5ae12818

这是 GitHub 上存储库中的实际内容,包括拉取请求(尽管不是合并),由于我们正在使用,因此通常会进行名称更改our存储库的副本,我们还没有将我们的存储库设置为纯粹的镜像。 (制作纯镜像将使我们自己的本地存储库无法执行任何操作work in.)

$ git log --all --decorate --oneline --graph
*   48728bc (origin/b) Merge branch 'm' into b
|\  
* | f365142 added line to section B
| | *   1cef243 (HEAD -> a, origin/pr/1, origin/a, origin/HEAD) Merge branch 'm' into a
| | |\  
| | |/  
| |/|   
| * |   5875937 (origin/m) Merge branch 'p' into m
| |\ \  
|/ / /  
| * | 23c2ff6 added line to section C
|/ /  
| * b21d3c4 added line to section A
|/  
* 1ff1a3c added file

该图非常混乱且难以阅读,但是,如果我们要实际执行此提议的合并,这些是我们通过另一条腿添加的提交,这些提交尚未启用origin/a:

$ git log --decorate --oneline --graph $(git merge-base origin/pr/1 origin/b)..origin/b
* 48728bc (origin/b) Merge branch 'm' into b
* f365142 added line to section B

这就是为什么我们看到我们所看到的local差异。由于某种原因,GitHub 选择的基础不正确。

让我们再尝试一个实验——获取 GitHub 所做的实际合并提交,看看它的样子git log --all --decorate --graph --oneline:

$ git config --add remote.origin.fetch '+refs/pull/*/merge:refs/remotes/origin/pr-merge/*'
$ git fetch
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From https://github.com/kenocrates/ex1
 * [new ref]         refs/pull/1/merge -> origin/pr-merge/1

$ git log --all --decorate --graph --oneline
*   f53dc81 (origin/pr-merge/1) Merge 1cef243f9efe6e94c9926f7992efb6c093188b8c into 48728bc19480e0c1cc9e3a399634a5f389881c47
|\  
| *   1cef243 (HEAD -> a, origin/pr/1, origin/a, origin/HEAD) Merge branch 'm' into a
| |\  
| * | b21d3c4 added line to section A
* | |   48728bc (origin/b) Merge branch 'm' into b
|\ \ \  
| | |/  
| |/|   
| * |   5875937 (origin/m) Merge branch 'p' into m
| |\ \  
| | |/  
| |/|   
| | * 23c2ff6 added line to section C
| |/  
* | f365142 added line to section B
|/  
* 1ff1a3c added file

这正是我们所期望的:一个合并提交,其第一个父级origin/pr-merge/1^1 is 48728bc19480e0c1cc9e3a399634a5f389881c47 aka origin/b,以及其第二个父母origin/pr-merge/1^2 is 1cef243f9efe6e94c9926f7992efb6c093188b8c aka HEAD, a, origin/pr/1, origin/a, and origin/HEAD.

Long

答案 [edit:除非这不是 GitHub 实际使用的答案] 嵌入在短语中:

“头部分支的尖端与头部上次与基础分支同步的提交之间的比较”

为了理解(并重现)这一点,我们必须定义每个术语。

The 树枝的尖端(名称)只是分支名称解析到的提交。例如,查找分支尖端的哈希IDmaster你可以运行:

git rev-parse master

一般来说,对于大多数命令,使用分支名称与使用此分支提示哈希 ID 具有相同的效果,因此我们甚至不必费心git rev-parse这里。 (Git 中此规则有一些例外:有时名称不仅仅意味着原始哈希 ID。)

接下来我们有头支 and 基础分支。在这里,定义这些术语的是 GitHub,而不是 Git。这总行在这种情况下,是您正在执行拉取请求的分支,而基础是您所说的“进入”的分支:请将feature-X拉入master表示 head = feature-X 且 base = master;所以

如果 PR 是将分支 a 拉入分支 b...

那么“头”是a和“基地”是b,所以你可以做head=a and base=b并使用$head and $base以下。 (对于偏执狂,请获取适当的参考并使用refs/heads/$N/head或其哈希 ID,如下所述。)

最后,我们有这样一句话...上次同步的提交...。该短语部分由 GitHub 定义,因为 Git 不使用该短语,但它的真正含义是作为这两个提交的合并基础的(理想情况下单个)提交。合并基础是通过提交图定义的,因此您需要足够的图才能找到它。整个图总是足够的,因此如果您有拉取请求提交,其哈希值存储在名为的引用中refs/pull/N/head- 以及基本分支哈希,存储在refs/heads/base-跑步:

git merge-base --all refs/pull/$N/head refs/heads/$base

或者更简单地说:

git merge-base --all $head $base

将生成合并基础的哈希值。

(如果有多个,Git 中的实际合并基础将通过合并合并基础来创建,在您运行时git merge -s recursive。注意-s recursive是默认策略。 GitHub 是否也这样做,在什么条件下,我不知道。请注意,依赖于$base决心refs/heads/$base是相当可靠的,但如果你使用的话就会失火same标签和分支的名称!)

因此,差异来自合并基础——上面的哈希输出git merge-base命令——GitHub 称之为“头分支”。你可以运行git merge-base命令并验证它是否恰好生成一个散列:

hash=$(git merge-base $head $base)  # slightly sloppy
... check that $hash is just one hash ...
git diff $hash $head

or rely on the special git diff syntax using three dots: git diff A...B means:1 find the merge base(s) between A and B; pick one at random, and run git diff from that one to B.

这就是上面的简短版本的来源。如上所述,如果您有一个使用相同名称的分支和标签,$base or $head可能会错误地解析为标签而不是分支,因此如果您很偏执,请拼写出完整的引用。


1There's a long-standing but minor bug in git diff with three-dot merge syntax, when there are multiple merge bases. Multiple merge bases are pretty rare and you may not care.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

GitHub PR 使用什么 git 命令来显示差异 的相关文章

  • 致命:无法将 HEAD 解析为有效引用

    我正进入 状态fatal Failed to resolve HEAD as a valid ref 每当我尝试承诺时 我努力了 echo ref refs heads master gt git HEAD 但它不起作用 也尝试过 git
  • 按时间顺序将多个文件夹提交到 git 中

    我有数百个网站备份 每个文件夹一个 我想将它们放入 git 存储库中 每个备份作为一个版本 这些变化主要涉及图像文件和每天 2 个数据库备份 大小约为 25 GB 并且不断增加 有没有办法告诉 git 获取其中一个文件夹并将其提交到存储库中
  • 如何将 GIT 调用的输出获取到批处理脚本中的变量中?

    我有一个 git 命令来获取当前存储库的最新 SHA 如下所示 git log pretty format H n 1 我有一个 Windows 批处理脚本 我想按如下方式使用它 SET CURRENT SHA 但我不知道如何将从 git
  • 我在哪里? *(无分支)

    我已经熟悉了创建 合并和删除分支 我想知道我在哪里 这样我就不会将工作提交到错误的分支 我用git branch a看看我有哪些分支 我认为星号 显示我当前所在的分支 当我得到以下信息时 这意味着什么 no branch master or
  • 从自己的 gitlab 服务器安装节点模块

    我想从我们的 gitlab 服务器安装节点模块 这是存储库的链接 http ABCD GITLAB myGroup myNodeModule git http ABCD GITLAB myGroup myNodeModule git 根据n
  • GIT - 推送到 (GitHub) origin master 没有任何作用

    我已经分叉了某人的 GIT 存储库 https github com nippysaurus toodledo objc 将其克隆到我的本地计算机 显示带有以下信息的来源 remote origin Fetch URL https emai
  • 您的分支比“origin/master”领先 3 个提交

    我在运行时收到以下信息git status Your branch is ahead of origin master by 3 commits 我读过其他一些帖子 解决这个问题的方法是运行git pull rebase但是 rebase
  • git 如何查找分支源自的提交哈希

    假设我从主分支分支到主题分支 然后在主题分支上进行了一些提交 是否有命令告诉我主题分支源自的主分支上的提交哈希 理想情况下 我不必知道我做了多少次提交 试图避免 HEAD 5 我已经用谷歌搜索过 但似乎无法找到答案 谢谢 use git m
  • 从分叉存储库的 GitHub 操作发布评论的解决方法

    我需要在 GitHub 操作完成后向 GitHub 拉取请求发表评论 例如当 FOSS 社区成员提交 PR 时 我知道 当操作从分叉的存储库运行时 令牌没有对父存储库的写访问权限 因此它无法发布评论 人们是否为此找到了任何可行的解决方法 我
  • SSL 适用于浏览器、wget 和curl,但不适用于 git

    我有一个网站 用于托管 redmine 和几个 git 存储库 这非常适合 http 但我无法使用 https 进行克隆 即 git clone http mysite com git test git 工作正常 但是 git clone
  • 更改先前提交的作者姓名:快进推送被拒绝

    我最近在 GitHub 上打开了一个存储库 我是 Git 新手 与新人一样 我使用默认名称和电子邮件进行提交 按照最佳菜鸟传统 我发现五次提交为时已晚 现在乐趣开始了 因为我开始搜索有关如何更改这些提交的作者和提交者名称的信息 美好的 我基
  • Spring Cloud Config - 不允许使用 git-upload-pack

    我有一个在 docker 环境中运行的 spring boot 应用程序 它连接到 Git 存储库以获取应用程序的配置 我的问题是 当尝试获取 properties 文件时 应用程序有时会出错 这很奇怪 因为如果我更改用户和密码 同一个应用
  • TortoiseGit - 更改默认合并消息

    系统描述 Windows 7的 git版本2 10 1 windows 1 乌龟Git 2 3 0 0 I want 合并提交消息在不同的情况下有所不同fully自动方式 no manual amend Summary 在windows上
  • 尝试配置 GIT 时 Eclipse 没有响应

    Windows 10 专业版 64 位SSD金士顿 i5 4690Eclipse 版本 全部工作空间 空问题 每次我尝试配置 TEAM gt GIT gt 配置或尝试导入 创建本地 远程 git 时 Eclipse 都会冻结 直到我强制用任
  • 如何让 git 显示作者日期指定日期范围内的提交?

    显然this https stackoverflow com a 11189286 281545 git log all after
  • 如何获取 git 存储库中所有文件的计数?

    如何获取 git 存储库中当前所有文件的计数 您可以使用以下命令获取 git 存储库中所有跟踪文件的计数 git ls files wc l 命令分解 The git ls files命令本身打印出存储库中所有跟踪文件的列表 每行一个 Th
  • Git 中的数据完整性?

    我现在已经多次听到提到 Git 提供数据完整性 但是 这是什么意思 据我所知 git 中的所有对象都是使用 SHA 1 校验和来访问的 并且该校验和是根据文件的内容计算的 这意味着如果文件发生更改 您将得到不同的校验和 但这如何提供数据完整
  • Github 操作错误地认为变量是秘密,因此不设置输出

    我的工作流程文件中的一个步骤将返回我的 aws 账户中 EC2 实例的一些 ID 然后我将这些 ID 设置为 github 输出 以便在我的工作流程文件中的其他作业中使用 我在许多工作流程中都这样做了 步骤将返回如下内容 i 0d945b0
  • 检查 Git 中是否需要 pull

    如何检查远程存储库是否已更改并且需要拉取 现在我使用这个简单的脚本 git pull dry run grep q v Already up to date changed 1 但它比较重 有没有更好的办法 理想的解决方案是检查所有远程分支
  • 为什么cherry-pick 告诉我所有行都已更改?

    Updated 考虑文件 abc 在提交 A 和 B 中都相同 begin 123 456 789 klm end 在A中 我们重构第一行123 gt AAA并在结果之上选择 B Git 告诉我们all lines in the file

随机推荐

  • xsl:如何选择节点中的前x个字符?

    我在 XML 文档中有以下节点
  • Android,我可以使用 putExtra 传递多个值吗

    我想将两个值传递给另一个活动 我可以用 putExtra 来做到这一点 还是必须以更复杂的方式来做到这一点 从我的阅读看来 例如 这样的东西可以工作吗 public final static String ID EXTRA com fnes
  • 删除 Firefox 中的默认选择框箭头

    我必须删除 Firefox 中的默认选择框箭头 我使用了下面的代码 webkit appearance none moz appearance none background rgba 0 0 0 0 它在 Chrome 中运行良好 但它在
  • 保存照片并立即使用

    我有以下用于拍照并将其保存到相机胶卷的代码 我需要能够在保存后使用它 而不必返回图库并选择它 我还没有找到任何关于如何执行此操作的示例 IBOutlet weak var imagePicked UIImageView IBAction f
  • 为 webRTC 使用特定端口

    当使用 webRTC 创建点对点音频连接时 如果用户位于路由器后面 我们使用的 STUN 服务器将返回公共 IP 现在在 ICE 对象中 我可以看到 rport 始终介于 50000 及以上 有没有办法使用特定端口 以便用户不必打开所有这些
  • Servlet 3.1 - 多部分异步处理

    我正在测试 Servlet 3 1 API 来处理多部分请求 我对同步处理某些部分 文本字段 和异步处理其他部分 文件字段 感兴趣 乍一看 它似乎在 Servlet 3 1 中不可用 要么在异步上下文中通过 request getInput
  • 使用adapter-static时如何在sveltekit上使用获取参数?

    我在构建时收到错误消息 无法访问url searchParams在启用预渲染的页面上 如何加载和使用get参数 svelte config js import adapter from sveltejs adapter static imp
  • Twitter bootstrap - 单击时聚焦于模式内的文本区域

    刚刚开始使用 bootstrap 这真是太棒了 我正在尝试解决这个问题 我在模式窗口内有一个用于反馈的文本区域 效果很好 但我希望当您单击按钮激活模式时 焦点位于文本区域上 而且我似乎无法让它发挥作用 这是一个小提琴 http jsfidd
  • 如何更改 Grafana 中的背景颜色?

    我想修改 Grafana 中的深色主题 以便它使用 000000作为背景颜色 我见过 如何更改Grafana的默认黑色 https stackoverflow com questions 41006070 how to change def
  • 使用 msbuild 从 VS 2008 升级到 2010 时未保留构建顺序和依赖项

    我正在升级 VS 2008 解决方案以在 VS 2010 上运行我成功地在 VS 2010 中构建 我现在的下一步是配置运行 TFS 2008 的构建机器每当我开始构建时 它都会按字母顺序执行我的项目 而不考虑依赖关系 我用谷歌搜索了很多
  • 用于检查文件大小是否比之前的检查有所增加的 VB 脚本

    我需要一个 VB 脚本来检查文件大小并捕获它 并在下一次检查中将其与上一次检查进行比较 如果大小增加 则应提示文件大小增加 你可以尝试一下这个vbscript Option Explicit const bytesToKb 1024 Dim
  • 如何将画布内容转换为图像?

    from Tkinter import root Tk cv Canvas root cv create rectangle 10 10 50 50 cv pack root mainloop 我想将画布内容转换为位图或其他图像 然后执行其
  • R 中生存数据的左删失

    我想对左右删失的数据进行生存分析 Kaplan Meier 和 Cox PH 建模 我正在研究特定基因 基因 0 或 1 存在与不存在时发生心律失常 AF 的时间 然而 一些受试者在招募时被发现已经存在心律失常 因此应该进行审查 我已阅读生
  • Twisted 中的多重响应

    我正在尝试开发简单的TCP 使用 Twisted 和 Pygame 进行客户端 服务器游戏 但我在向客户端发送数据时遇到困难 Twisted 不允许我连续发送多个响应 这就是我想做的 我有方法处理玩家状态更改并将其重新发送给其他客户端 de
  • ASP.NET Core 中 Mongodb 数据存储的基于简单令牌的身份验证/授权

    我需要实现非常简单的身份验证机制 基本上有两个角色 Owners and Users 我认为拥有 Enum 就足够了 应用程序本身是SPA 通过Asp net core实现webapi 我看到文章 如何使用 EF Identity 实现它
  • 确定 MIDI 文件的时间划分

    我正在用Python编写一个脚本来解析MIDI文件 是的 我知道Python存在MIDI解析库 但对于我的用例来说 如果我从头开始制作它是最简单的 我遇到的问题之一是时间划分 标头的最后两个字节指定时间划分 但我无法确定文件的时间划分是否以
  • 正则表达式:匹配该字符串

    我无法弄清楚这一点 22 584 r n t t tl 6 579 22 我想匹配 r n t t t 并替换为一个空格 问题是数量 t r and n 波动 周围的人物也是如此 Help s s g s rnt g
  • 如何在 tkinter 中给定时间后运行函数?

    所以我在 tkinter 的画布上有一张 gif 图片 我想让这张照片变成另一张照片 但只持续三秒钟 并将其恢复到原始图片 def startTurn self newgif PhotoImage file 2h gif self left
  • UISlider 无法在原型单元中滑动

    我在故事板的视图控制器中设计了一个原型单元 但不幸的是UISlider细胞内不滑动 Note 此故事板启用了自动布局 Design 这是代码 渲染单元格UITableview UITableViewCell tableView UITabl
  • GitHub PR 使用什么 git 命令来显示差异

    我想使用命令行来生成 GitHub 提供的相同差异 帮助页面将其描述为 头部分支的尖端与头部上次与基础分支同步的提交之间的比较 https help github com articles about comparing branches