0

我需要获取提交列表,例如,在“task/105”分支中推送。

我的意思是,我需要将提交推送到“task/105”分支,范围从“task/105”分支中的第一次提交到最后一次。

我尝试执行以下操作:

git /dir/project
git checkout task/105
git log task/105

但这无济于事。它向我展示了对另一个分支和“测试”分支的提交。

我读过,我需要做这样的事情:

git log TASK_105_FIRST_COMMITE..task/105

但是我不知道,如何获得我阅读的 task/105 的第一次提交,它可以提供什么帮助:

git merge-base master task/105
git log as65g76s5dgsd5gsd6sd65g4s...task/105

但是我被“大师”这个词弄糊涂了。如果在推送任务/105 中的提交后推送主中的提交怎么办?

最后,我真的不知道该怎么办......对不起英语不好

4

1 回答 1

3

(我不确定您所说的“第一次提交”是什么意思,“推送”让我认为您可能正在考虑更受限制的情况。)

通常,要使用名称标记特定提交,应该使用 git 的“标签”,或者“行为类似于”标签的引用。

这里有一些基本的必要背景:

  • git 存储库中的每个提交都充当充满文件的目录树的“快照”。此快照具有关联的日期、作者/提交者和消息。1
  • 每个提交也有一组独特的“父提交”(根提交没有,普通提交有 1 个父提交,合并提交有 2 个,有时甚至更多)。
  • 每个提交(以及存储在存储库中的其他三种对象)都有一个唯一的“真实名称”,即 SHA-1 ID,通常表示为 40 个字符的十六进制字符串bd5d3781a8e32d3627bb1de70dc6b105dc9d77a0(通常缩短为前 7 个字符)。
  • 这些“真名”笨拙,不利于人类使用,因此 git 添加了“引用”,例如“分支”和“标签”。这些是对用户更友好的名称,例如refs/heads/masterrefs/tags/v1.3。您通常也可以省略refs/heads/andrefs/tags/部分。

分支或标签名称实际上只是指定 SHA-1 的一种方式,但还有一个例外:

  • refs/heads/“本地”分支(位于命名空间中的引用)会在需要时自动移动。(当你从远程时,一个“远程”分支refs/remotes/也会移动fetch。更一般的想法是“分支移动但标签不移动”。)

添加一个新的提交,git commit -m 'fix some bug'查找当前分支——可能是master,或者可能是task/105,或者任何其他有效的分支名称字符串;如果它以通常不可见的部分为前缀,则它是一个分支refs/heads/。找到当前分支(及其对应的 SHA-1 值)后,该git commit命令将新提交写入 repo,其父级是当时的当前 SHA-1。新提交有一个新的唯一 SHA-1 值,git commit然后更改分支名称以指向新提交,人们称之为“向前移动分支”。

Git 没有2在这里记录分支的“旧值”。它只是更改了分支名称 -> SHA-1 映射。那么你怎么知道这个分支曾经指向哪个提交呢?答案是你不能,不能 100% 可靠(见脚注 2)。

如果您需要用名称标记提交,这就是“标签”的用途。有两种标签:“注释”标签(实际上位于 git 存储库中,必要时可以进行身份​​验证)和“轻量级”标签。

轻量级标签由位于命名空间中的外部名称组成refs/tags/,指向提交,就像分支一样,只是它不会自动移动。(您可以使用“强制”标志手动移动它。)

一个带注释的标签由一个外部(轻量级)标签组成,它指向一个“标签”类型的 git 存储库对象,它携带的信息很像 git 提交对象:日期、作者等。但是,提交对象“指向”树,而标记对象“指向”提交对象(然后指向树)。3

考虑到所有这些,人们所说的“分支”通常是提交图的一部分。提交图是通过获取所有外部引用的提交(具有分支和标签名称的提交,以及一些其他特殊情况)并沿着父引用“向后工作”以查找更多提交而形成的。这可以写成或画成这样:

          o--o--o
         /       \
...--o--o--o--o---o--o   <-- refs/heads/master
         \
          o              <-- refs/tags/v0.9
           \
            o--o         <-- refs/heads/devel

这里的小os 描绘了提交节点,<--箭头显示了外部引用的提交。

因此,如果您有一个存储库(例如在您的开发机器上)并且想知道哪些提交发生在“点之后X”和“通过名称指向的分支的尖端Y”,您必须保存(某处)“ “点”的真实姓名”(SHA-1)X。假设X在我们制作标签时,“点”是早些时候被捕获的v0.9,而“点Y”实际上是“分支devel”。然后:

v0.9..devel

是标准的 git 修订字符串简写,意思是“所有可以从 name 访问的devel提交,不包括所有可以从 name 访问的提交v0.9”。由于v0.9是一个有效的标签,这将使您只获得最底部的两个o--o提交。

要求master..devel将让您“从 可访问的提交devel,不包括从可访问的提交master”。是否有可到达的提交从master无法到达并不重要devel:您可以将其视为采用彩色标记并从 中“向后”绘制refs/heads/master,通过在绘图中向左移动可以到达的所有提交着色(但是永远不会向右移动)。然后你在所有提交中使用第二个不同的颜色和颜色,refs/heads/devel但不要重新着色任何已经着色的提交。所以在这种情况下,master..devel得到三个提交:一个由 命名的提交refs/tags/v0.9,加上底部的两个提交。

现在,你一直提到“推”,它带来了一个新的和不同的皱纹。当你运行 时git push origin branch,涉及到两个存储库:你的,用你的refs/heads/branch名字,和“起源”(在其他一些 URL),用他的 refs/heads/branch名字。

如果推送成功更新(而不是“创建”)他的refs/heads/branch,这意味着他有一些以前的 SHA-1 标识refs/heads/branch,一旦推送完成,他有一些新的和不同的 SHA-1 标识,特别是你刚刚推送成功。

如果您想知道“在我更改之前refs/heads/branch他的观点是什么”,那么,他是唯一知道这一点的人。最好的方法是问他。您可以使用来执行此操作,或. 一般来说,无论如何你都应该在推送之前获取,所以这可能是合适的选择。但是这里有一个问题,因为当你问 (或) 时他告诉你的内容与你最终得到-ing 时他所拥有的内容之间存在竞争。即使您工作得非常快,在您的查询和您的查询之间的几毫秒内,其他人也可能潜入并做不同的事情git ls-remotegit fetchls-remotefetchgit pushpushpush并改变事物。因此,找出“在他身边”更新了什么的最好方法是让他告诉你,通常是通过“接收后挂钩”。(这个钩子得到“old-SHA-1, new-SHA-1, ref-name”三元组。)


1实际上,有两个单独的日期和用户名,一个用于“作者”,一个用于“提交者”。尝试git cat-file -p HEAD查看提交中的(大部分)原始数据。

2实际上,git确实在“reflog”中记录了旧值……但 reflog 不是永久性的。如果您需要恢复被遗忘的 SHA-1,在到期时间内,它就在那里;但是如果你想要它作为一个更永久的项目,那不是 reflog 的目的,那样使用它会很尴尬。

3事实上,标签可以指向更多(带注释的)标签,这被认为是正常使用。物理上也可以将任何引用指向存储库内的“树”或“blob”,但这些不是refs/heads/refs/tags/引用的正常用途。

于 2013-11-12T03:53:45.577 回答