我希望能够搜索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 rev-list
就是遍历提交图(DAG)。你给它起点。 --branches
是给出各种起点的一种方式; --remotes
是另一个。与git log
不同,HEAD
默认使用git rev-list
作为起点,你必须给hg branch <name>
一些提交起点。然后列出可到达的提交:名称仅与定位图形步行的起始点相关。
在Git中,你必须记住分支是什么(或不是)。如果没有这个概念,你将被误导。为了比较,让我们首先看一下Mercurial,其中分支是一个更具体的东西(虽然Git的松散和草率的分支定义现在也泄漏到Mercurial的使用中)。
在Mercurial中,您可以使用以下命令创建分支:
C
然后对它进行提交。那些提交永远都在那个分支上(好吧,直到/除非它们被剥夺,但忽略了删除提交的能力,它们永远存在)。如果提交X
在分支上X
在X
上,而不在任何其他分支上。询问哪些提交在分支C
上,它将始终包括C
。有道理,对吗?提交书永久钉在他们的分支机构;分支是在该分支上进行的所有提交的集合。
在Git中,情况并非如此。你在X
分支上进行提交X
,它在分支Y
上,但在几分钟(或几天或几个月)内,它也在分支Z
和master
和X
上。在这一点完全删除分支C
,并提交Y
仍然存在,仍然在分支Z
和master
和X
。你甚至可以移动名称C
,以便提交X
不再在master
,但仍然在A <-B <-C ... <-G <-H <--master
。
换句话说,在Git中,提交不会被钉在他们的分支上。提交是否在某个分支中是动态属性,将来可能会更改。存在或不存在包含它们的分支的存在。提交是重要的;分支只适用于弱小的人类。但是,提交是永久的(好的,大部分)和只读的,永远冻结。所以提交是固定的;它是移动的分支名称。
考虑到这一点,让我们画一些图表。
1Branch名称或其他引用在Git中用于其他几个目的,但最好从此开始作为您的模型。一旦掌握了这个概念,其余部分就会落实到位。
每个提交都记录其前一个或前一个或多个提交。在最简单的情况下,一个提交有一个父提交,而那个提交的父提交有一个父提交,依此类推。从链的末尾开始,我们可以轻松地向后工作:
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
。提交D
和master
也都在开发并且在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
回到F
和H
,G
回到E
,然后回到D
,然后我们在C
向后方向重新加入叉子,导致B
和A
,最后master
。因此所有这些提交现在都在I
上。提交F
和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无论如何也不在乎。
git log
and git rev-list
git log
和git log
都关注此提交图。这两个命令彼此非常接近 - 事实上,它们是根据相同的源文件构建的,根据您是否运行git rev-list
或git log
,有两个不同的入口点。两者都将遍历图形,从您指定的结束开始并向后工作。虽然git rev-list
默认显示每个遍历提交,但HEAD
默认只打印其哈希ID。
另一个关键区别是这个HEAD
概念。 Git想要通过将名称git log
附加到一个分支名称来跟踪您已检出的分支。默认情况下,HEAD
命令将查找git rev-list
并将其用作(单个)起点; master
要求你给它一些起点。
他们都这样做“从头开始,向后工作”的事情。如果I
指向提交I
,如上面的示例,并且F
是一个合并提交,指向提交H
和I
,两者将首先显示提交F
(或其哈希ID),然后选择一个H
和G
来显示下一个。然后他们将展示E
和F
(和D
,如果他们还没有,在这个混合的某个地方)和and
和Cand
B, and since
AI
A`没有父母,停在那里。
最后,两者都会显示或列出每个提交,因为每个提交都可以从给定的起始点到达,提交D
。如果你给他们一个不同的起点,比如提交D
,他们会告诉你C
然后B
然后A
然后--branches=*
。
模式(使用*
)可能很棘手,因为命令行解释器(“shell”)倾向于自己扩展echo *
。如果运行echo foo*
,您将看到所有文件名的列表。如果你运行foo
,你将只看到以--branches=*
开头的文件名。 --branches=
可能会尝试扩展到名称以*
开头的文件,特别是如果你有一些带有这些名字的文件。
如果你最后省略了git rev-list ... --remotes=*remote_name/branch_name
,Git会在内部提供它,这就避免了shell。
解
搜索远程和分支的解决方案是使用以下选项:
--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。