我希望能够在git rev-list
中搜索特定的远程/分支组合。 git rev-list documentation对于--branches
和--remotes
选项感到困惑,我认为这是我要使用的选项。
对于--remotes
,文档显示:
-远程[=模式]
假装好像引用/远程处理中的所有引用在命令行上都列为[commit]。如果指定了[pattern],则将远程跟踪分支限制为与给定的shell glob匹配的分支。如果模式缺少末尾的?,*或[,/*。
我不明白当它说它们像“ commit”那样在命令行中列出时的含义。
我感到困惑的部分原因是我不确定字符串--branches
和--remotes
会搜索哪种格式,因此我不得不在各个地方插入通配符以查看其是否有效。我本来以为分支会像“ remote / 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,即使它不应该找到,有时在非源远程上也没有分支即使我知道它存在,也会返回“提交A”。
我认为,只要我能更好地理解如何使用--branches
和--remotes
进行搜索,我就能将它们拼凑在一起。可能不希望同时启用这两个选项来搜索rev-list
。
任何帮助将不胜感激。
谢谢。
答案 0 :(得分:2)
git rev-list
仅涉及遍历提交图(DAG)。您给它起点。 --branches
是给它各种起点的一种方法; --remotes
是另一个。与git log
(默认使用HEAD
作为起始点)不同,您必须将 some 提交起始点指定为git rev-list
。然后,它列出可达提交:这些名称仅在定位图形遍历的起点方面才有意义。
在Git中,您必须牢记什么是分支(或不是分支)。没有这个概念,您将被误入歧途。为了进行比较,让我们首先看一下Mercurial,其中 branch 是更具体的东西(尽管最近,Git对 branch 的定义松散而草率)也渗入了Mercurial的使用中。
在Mercurial中,您使用以下方法创建分支:
hg branch <name>
,然后对其进行提交。这些提交永远在该分支上 (好吧,直到/除非它们被剥离,但忽略删除提交的能力,它们就永远存在了)。如果提交C
在分支X
上,则在X
上,而不在其他任何分支上。询问哪些提交在分支X
上,它将始终包含C
。有道理吧?提交被永久装订到其分支;分支是该分支上曾经进行的所有提交的集合。
在Git中,情况并非如此。您在分支C
上进行提交X
,并且在分支X
上进行提交,但是在几分钟(或几天或几个月)内,它也在分支{{ 1}}和Y
和Z
。此时,完全删除分支master
,并提交X
仍在分支C
和Y
和Z
上。您甚至可以移动名称master
,以使X
上的提交C
不再是 ,但仍{{{ 1}}。
换句话说,在Git中,提交 not 被装订到其分支。提交是否在某个分支中是动态属性,将来可能会更改。提交的存在或不存在包含它们的分支。 commits 很重要; 1 但是,提交是永久的(很好,主要是)并且是只读的,永远冻结。因此, commits 是固定的;是分支名称。
考虑到这一点,让我们绘制一些图形。
1 分支名称或其他引用在Git中有其他用途,但是最好以此为模型。一旦掌握了这个概念,其余的将就位。
每个提交都记录其直接的前身(即 parent )提交。在最简单的情况下,一个提交有一个父级,而那个提交的父级有一个父级,依此类推。从链的末端开始,我们可以轻松地向后工作:
X
分支 name (在这种情况下为master
)存储要被视为该分支一部分的 last 提交的原始哈希ID。提交A <-B <-C ... <-G <-H <--master
为其先前的提交master
存储另一个提交哈希ID。 H
存储其父级的哈希ID,依此类推,直到提交G
。提交G
存储B
的哈希ID,但是B
是有史以来的第一个提交,因此它没有父对象。
(由于提交本身是固定的,因此不再需要将内部箭头绘制为箭头,这对下一步很有帮助,因为文本中的箭头绘制非常有限。因此,从现在开始,我将使用:< / p>
A
例如。但是,分支名称的箭头会移动很多,因此将其保留为箭头很有用。)
在Git中向分支添加 new 提交只是冻结源快照并创建提交对象。新的提交对象记录当前提交的哈希ID,以便我们维护此向后链。然后,新的提交将获得自己的新的唯一哈希ID,Git将新的哈希ID写入分支名称:
A
成为:
A--B--C <-- master
但是我们可以添加更多的分支名称。在进行另一个新提交之前,我们要这样做:让分支名称A--B--C <-- master
也指向提交A--B--C--D <-- master
:
develop
现在Git需要知道要更新的 分支名称,因此Git将名称D
附加到一个(并且只有一个)分支名称:
A--B--C--D <-- master, develop
现在,当我们进行新的提交HEAD
时,Git更新的分支名称不再是A--B--C--D <-- master, develop (HEAD)
,而是E
:
master
提交develop
现在在A--B--C--D <-- master
\
E <-- develop (HEAD)
上。提交E
和develop
都在开发上,而在A
上。现在D
,然后重新提交master
:
git checkout master
提交F
在A--B--C--D--F <-- master (HEAD)
\
E <-- develop
上仅 ,而F
在master
和<{ {1}}都在这两者上。
如果我们在开发上再提交一些承诺,我们将得到:
E
(由于我们仍然要移动它,因此我在这里省略了develop
。)
现在让我们运行A-B-C-D
。这将合并自共享提交A--B--C--D--F <-- master
\
E--G--H <-- develop
起的所有HEAD
更改与自共享提交git checkout master && git merge develop
以来的所有master
更改。也就是说,Git将运行:
D
Git将结合两组更改,将它们应用于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
提交D
返回到两者 I
和 A--B--C--D--F------I <-- master (HEAD)
\ /
E--G--H <-- develop
,I
回到{{ 1}},然后到达H
,然后我们制作的叉子在F
处向后重新接合,从而导致H
和G
,最后是{{1} }。因此,所有这些提交现在位于E
上。 {{1}上的D
和C
都是 ,而两个分支上的B
都是。
这是关于合并提交的特殊之处。现在我们有了合并提交,我们可以删除名称A
:
master
所有提交都保留在I
上。名称F
不再存在。曾经在那里吗?还是那海市mi楼? Git不在乎这两种方式。
master
和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 log
默认为仅显示其哈希ID。
另一个关键区别是这个git rev-list
概念。 Git希望通过将名称git log
附加到一个分支名称来跟踪您已签出的分支。默认情况下,git log
命令将查找git rev-list
并将其用作其(单个)起点; git log
要求您提供一些起点。
他们两个都这样做“从头开始并向后工作”。如果git rev-list
指向上面的示例中的提交HEAD
,并且HEAD
是指向提交git log
和HEAD
的合并提交,则两者都将首先显示您提交了git rev-list
(或其哈希ID),然后选择master
和I
中的一个进行下一步显示。然后,他们将显示I
和F
(如果尚未混合,则显示H
,如果混合,则显示I
和C F
B {{ 1}} A H
A`没有父母,就停在那里。
最后,由于每次提交都可以从给定的起点到达,因此,两次提交都将显示或列出每次提交,因此提交G
。如果您给他们一个不同的起点,例如提交E
,他们将向您显示F
然后是D
然后是and
然后是and
。
模式(带有, and since
)可能很棘手,因为命令行解释器(“ shell”)往往会自己扩展I
。如果运行D
,将看到所有文件名的列表。如果运行D
,则只会看到以C
开头的文件名。 B
可能会尝试扩展到名称以A
开头的文件,尤其是当您有一些使用这些名称的文件时。
如果您在末尾省略了--branches=*
,则Git会在内部提供它,从而避免使用shell。
答案 1 :(得分:0)
解决方案
同时搜索远程分支和分支的解决方案是使用以下选项:
git rev-list ... --remotes=*remote_name/branch_name
在此处同时使用--remotes
和--branches
选项可以,但前提是您已经签出了相关分支。
说明
使用--branches=*branch_name
在refs/heads
中查找具有给定名称的分支,该文件夹是存储有关已签出分支的信息的文件夹。这意味着它只能根据已经签出的分支仅搜索git修订历史。
只要已将--remotes=*remote_name
添加到您的本地远程列表中,就使用refs/remotes
查找具有此名称的遥控器(rev-list
是一个文件夹,用于存储有关所有已添加的遥控器的信息)。
如果同时使用这两个选项,refs/remotes
可以找到您的遥控器,但是除非您已将其签出,否则它找不到您的分支。。
但是,--remotes=*remote_name/branch_name
实际上将有关 all 分支的信息存储在这些远程服务器上,因此您只需使用refs
进行搜索即可。
通过转到隐藏的.git
文件夹中的实际文件夹,可以查看cd .git/refs
中的信息。在您的git文件夹中,只需Eigen::NaturalOrdering
。