如何将git rev-list限制为特定分支和远程?

问题描述 投票:0回答:2

我希望能够搜索git rev-list特定的远程/分支组合。我对git rev-list documentation关于--branches--remotes选项感到困惑,我认为这是我想要使用的。

对于--remotes,文档说:

--remotes [=图案]

假装refs / remotes中的所有引用都在命令行中列为[commit]。如果给出[pattern],则将远程跟踪分支限制为与给定shell glob匹配的分支。如果模式缺少?,*或[,/ *最后隐含。

当它说它们在命令行中列出如“commit”时,我不明白它意味着什么。

我的困惑的一部分是,我不确定字符串--branches--remotes搜索的格式是什么,因此我不想尝试在各个地方插入通配符以查看它是否有效。我会假设分支将像“遥控器/ remote_name / branch_name”,遥控器会喜欢“remote_name”,但是当我尝试搜索时,我没有得到我期望的结果。

例如,以下是我要运行的基本查询:

 git rev-list --after='timestamp' --author="Name" --format='%h,%aI,%cI'

我使用了各种通配符配置的--branches=*remote_name/branch_name --remotes=remote_name变体,但它永远不会起作用。我的意思是,我知道在提交A存在的某些远程/分支组合上,但有时特定远程的所有分支都会找到提交A,即使它不应该,有时在非原始远程上没有分支将返回Commit A,即使我知道它存在于那里,等等。

我想如果我更好地了解如何使用--branches--remotes进行搜索,我就能将它拼凑起来。也许rev-list不打算用这两个选项进行搜索。

任何帮助将不胜感激。

谢谢。

git
2个回答
2
投票

TL;DR

git rev-list就是遍历提交图(DAG)。你给它起点。 --branches是给出各种起点的一种方式; --remotes是另一个。与git log不同,HEAD默认使用git rev-list作为起点,你必须给hg branch <name> 一些提交起点。然后列出可到达的提交:名称仅与定位图形步行的起始点相关。

Long

在Git中,你必须记住分支是什么(或不是)。如果没有这个概念,你将被误导。为了比较,让我们首先看一下Mercurial,其中分支是一个更具体的东西(虽然Git的松散和草率的分支定义现在也泄漏到Mercurial的使用中)。

在Mercurial中,您可以使用以下命令创建分支:

C

然后对它进行提交。那些提交永远都在那个分支上(好吧,直到/除非它们被剥夺,但忽略了删除提交的能力,它们永远存在)。如果提交X在分支上XX上,而不在任何其他分支上。询问哪些提交在分支C上,它将始终包括C。有道理,对吗?提交书永久钉在他们的分支机构;分支是在该分支上进行的所有提交的集合。

在Git中,情况并非如此。你在X分支上进行提交X,它在分支Y上,但在几分钟(或几天或几个月)内,它也在分支ZmasterX上。在这一点完全删除分支C,并提交Y仍然存在,仍然在分支ZmasterX。你甚至可以移动名称C,以便提交X不再在master,但仍然在A <-B <-C ... <-G <-H <--master

换句话说,在Git中,提交不会被钉在他们的分支上。提交是否在某个分支中是动态属性,将来可能会更改。存在或不存在包含它们的分支的存在。提交是重要的;分支只适用于弱小的人类。但是,提交是永久的(好的,大部分)和只读的,永远冻结。所以提交是固定的;它是移动的分支名称。

考虑到这一点,让我们画一些图表。


1Branch名称或其他引用在Git中用于其他几个目的,但最好从此开始作为您的模型。一旦掌握了这个概念,其余部分就会落实到位。


Git commit graphs

每个提交都记录其前一个或前一个或多个提交。在最简单的情况下,一个提交有一个父提交,而那个提交的父提交有一个父提交,依此类推。从链的末尾开始,我们可以轻松地向后工作:

master

分支名称(在本例中为H)存储最后一次提交的原始哈希ID,该哈希值将被视为此分支的一部分。提交G为其前任提交G存储另一个提交哈希ID。 B存储其父级的哈希ID,依此类推,返回提交B。提交A存储A的哈希ID,但A--B--C <-- master 是有史以来第一次提交,因此它没有父级。

(因为提交本身是固定的,所以不再需要将内部箭头作为箭头绘制,这有助于下一步,因为文本中的箭头绘制非常有限。所以从现在开始我将使用:

A--B--C   <-- master

例如。但是,分支名称箭头移动很多,因此将它们保持为箭头非常有用。)

在Git中向分支添加新提交是冻结源快照和创建提交对象的问题。新的提交对象记录当前提交的哈希ID,以便我们维护此向后链。然后新的提交获得自己的新唯一哈希ID,Git将新的哈希ID写入分支名称:

A--B--C--D   <-- master

变为:

develop

但我们可以添加更多分支名称。在我们再次提交新提交之前,让我们这样做:让我们创建分支名称D也指向提交A--B--C--D <-- master, develop

HEAD

现在Git需要知道要更新的分支名称,因此Git将名称A--B--C--D <-- master, develop (HEAD) 附加到一个(并且只有一个)分支名称:

E

现在当我们创建一个新的提交master时,Git更新的分支名称不再是develop,而是A--B--C--D <-- master \ E <-- develop (HEAD)

E

提交develop现在在A。提交Dmaster也都在开发并且在git checkout master。我们现在让F做一个新的提交A--B--C--D--F <-- master (HEAD) \ E <-- develop

F

承诺master现在只在E,而develop只在A-B-C-D,而A--B--C--D--F <-- master \ E--G--H <-- develop 在两者。

如果我们再开发一些提交,我们得到:

HEAD

(我已经把git checkout master && git merge develop留在了这里,因为我们无论如何都要移动它。)

现在让我们运行master。这将结合自共享提交D以来我们所有的develop更改以及自共享提交D以来我们所有的git diff --find-renames <hash-of-D> <hash-of-E> # what happened on master git diff --find-renmaes <hash-of-D> <hash-of-H> # what happened on develop 更改。也就是说,Git会运行:

D

Git将结合两组更改,将它们应用于I中的快照,并创建一个具有两个父项的新提交A--B--C--D--F------I <-- master (HEAD) \ / E--G--H <-- develop

I

承诺H回到FHG回到E,然后回到D,然后我们在C向后方向重新加入叉子,导致BA,最后master。因此所有这些提交现在都在I上。提交Fmaster仅在A-B-C-D-E-G-H,而develop在两个分支。

这是合并提交的特殊之处。现在我们有了合并提交,我们可以删除名称A--B--C--D--F------I <-- master (HEAD) \ / E--G--H

master

所有提交都保留在develop上。名字git rev-list不再存在。它曾经在那里,还是海市蜃楼? Git无论如何也不在乎。

git log and git rev-list

git loggit log都关注此提交图。这两个命令彼此非常接近 - 事实上,它们是根据相同的源文件构建的,根据您是否运行git rev-listgit log,有两个不同的入口点。两者都将遍历图形,从您指定的结束开始并向后工作。虽然git rev-list默认显示每个遍历提交,但HEAD默认只打印其哈希ID。

另一个关键区别是这个HEAD概念。 Git想要通过将名称git log附加到一个分支名称来跟踪您已检出的分支。默认情况下,HEAD命令将查找git rev-list并将其用作(单个)起点; master要求你给它一些起点。

他们都这样做“从头开始,向后工作”的事情。如果I指向提交I,如上面的示例,并且F是一个合并提交,指向提交HI,两者将首先显示提交F(或其哈希ID),然后选择一个HG来显示下一个。然后他们将展示EF(和D,如果他们还没有,在这个混合的某个地方)和and和CandB, and sinceAIA`没有父母,停在那里。

最后,两者都会显示或列出每个提交,因为每个提交都可以从给定的起始点到达,提交D。如果你给他们一个不同的起点,比如提交D,他们会告诉你C然后B然后A然后--branches=*

模式(使用*)可能很棘手,因为命令行解释器(“shell”)倾向于自己扩展echo *。如果运行echo foo*,您将看到所有文件名的列表。如果你运行foo,你将只看到以--branches=*开头的文件名。 --branches=可能会尝试扩展到名称以*开头的文件,特别是如果你有一些带有这些名字的文件。

如果你最后省略了git rev-list ... --remotes=*remote_name/branch_name ,Git会在内部提供它,这就避免了shell。


0
投票

搜索远程和分支的解决方案是使用以下选项:

--remotes

在这里使用--branches--branches=*branch_name选项都可以工作,但前提是你已经检查了有问题的分支。

说明

使用refs/heads--remotes=*remote_name中查找具有给定名称的分支,refs/remotes是一个存储有关已签出分支的信息的文件夹。这意味着它只能根据您已检出的分支搜索git修订历史记录。

使用rev-list查找具有此名称的遥控器,只要它们已添加到您的本地遥控器列表中(refs/remotes是一个存储有关所有添加的遥控器的信息的文件夹)。

如果你一起使用这两个选项,--remotes=*remote_name/branch_name可以找到你的遥控器,但除非你检查过它,否则它找不到你的分支。

但是,refs实际上存储了有关这些遥控器上所有分支的信息,因此您需要通过使用.git进行搜索。

你可以通过转到隐藏的cd .git/refs文件夹中的实际文件夹来查看qazxswpoi中的信息。从你的git文件夹,只需qazxswpoi。

© www.soinside.com 2019 - 2024. All rights reserved.