发现路径下有变化的分支



我计划将 GitHub 存储库中的某个文件夹路径提取到新存储库。 例如:

- repository/
- src/
- primaryCode/
- codeToExtract/
- ci/
- ...

我要codeToExtract迁移到新的存储库。

有没有办法找到对该文件夹有更改的分支? 这是一个团队项目,因此手动检查它们不是一种选择。

git for-each-ref --format='%(refname)' refs/heads/ |
while read branch; do
if test -n "`git rev-list -n1 $branch -- $path`"; then
echo $branch
fi
done

解释:

git for-each-ref --format='%(refname)' refs/heads/ — list all branches
while read branch — run the loop over every branch
git rev-list -n1 $branch -- $path — find a commit in the branch
that touches the $path
if test -n … echo $branch — if at least one commit found print the branch name.

这个问题格式不正确,但是一旦形式固定,答案可能是肯定的。 但是哪个是,你想要哪个答案,取决于你真正的意思。

每个提交都包含一个快照。 没有提交保留更改,就像如果您有几张照片(可能是不同年龄的自己)一样,没有一张照片包含任何更改。 但也许你在一张照片中的头发比另一张照片长(或更多),所以通过比较两张照片,你可以观察到变化。

正如您现在可能看到的那样,问题在于您必须选择两个快照。 你关心哪两个? 你可以选择任意两个,但只能选择两个,或者一次只能选择两个。

Git关心的是各种提交。 正如我们刚才所说,每个都包含一个快照——但它也包含更多。 例如,它包含制作快照的人的姓名和电子邮件地址。 它带有日期和时间戳。 (实际上,它既有作者又有提交者,给出了两个名称,电子邮件地址和时间戳。 它有一个日志消息,由做出提交的人编写,告诉您他们为什么进行提交。 并且,每个提交都存储其提交(在合并提交的情况下或提交)的哈希 ID。 这些额外的内容是提交的元数据,主要数据是源快照。

每个提交都有自己唯一的哈希 ID。 这个哈希 ID 似乎是随机的,实际上只是该提交内容(数据 + 元数据)的加密校验和。 该哈希 ID 是 Git 实际查找提交的方式,即它如何从 Git 存储的主数据库中检索提交的内容(数据 + 元数据)。 你已经在git log输出中看到过这些哈希 ID,以及到处都是缩写版本——Git 迫切需要它们,因为它们是内部 Git 对象的实际名称,所以 Git 不可避免地会向你展示其中的一些。 例如,它们看起来像b5101f929789889c2e536d915698f58d5c5c6b7a。 不过,它们对人类来说毫无用处:它们太难记住了;我必须剪切和粘贴它们才能使它们正确。

给定任何一个特定的提交哈希 ID,Git 可以找出提交及其元数据。 该元数据包括提交的父提交哈希 ID,因此 Git 现在也可以捞出父提交哈希 ID。 然后 Git 可以比较两个提交,这就是你所看到的,例如,git log -p输出:这个比较的结果。 与此提交的父提交相比git loggit show都将完整快照减少为一组更改。 这就是两个快照的来源。

现在,由于提交具有其父级的哈希 ID,而父级具有另一个哈希 ID,依此类推,我们可以将提交绘制为一长串向后指向的节点,每个节点表示提交,从该节点出来的箭头作为父节点的哈希 ID:

... <-o <-o <-o ...

但是要开始这个过程,我们必须知道一些起始(结束?)点哈希ID。 我们可以写下那些丑陋的大哈希ID,或者剪切和粘贴它们,但我们有一台电脑。 为什么不让计算机为我们保存哈希 ID? 这就是分支名称的用武之地。

实际上,分支名称是存储一 (1) 个哈希 ID 的地方。 我们将上次提交的哈希 ID 存储在分支上:

...--F--G--H   <-- master (HEAD)

(在这里,我使用像H这样的大写字母代替实际的哈希值,只是为了更容易谈论它们。 为了进行新的提交,我们在工作树中摆弄源代码,使用git add告诉 Git 更新其准备好快照的文件副本,然后使用git commit收集元数据并制作新快照。 这将获得一个新的、不可预测的哈希 ID。 请记住,其中一个输入是时间,因此即使我们预测源以及我们的名称和日志消息等,我们也不会知道哈希 ID 是什么,直到我们按 Enter 或单击"提交"按钮或其他什么。

无论如何,我们都会得到一个带有新哈希 ID 的新提交,我们可以将其调用I

...--F--G--H   <-- master (HEAD)

I

I的父母是H。 现在来了一个偷偷摸摸但精湛的技巧:Git 将提交I的实际哈希 ID 写入当前分支名称master。 我们可以像现在一样理顺我们的图纸:

...--F--G--H--I   <-- master (HEAD)

我们有一个新的快照,其父级是旧快照。

如果我们现在创建一个新分支,我们会得到两个指向提交I的名称:

...--F--G--H--I   <-- feature, master (HEAD)

请注意,所有提交都在两个分支上。我们可以使用以下git checkout feature切换哪个分支附加了HEAD

...--F--G--H--I   <-- feature (HEAD), master

现在,如果我们进行新的提交J它将仅在feature

...--F--G--H--I   <-- master

J   <-- feature

您现在拥有回答自己问题所需的大部分内容

我要将代码提取迁移到新的存储库。

大概你的意思是你打算从一些提交中取出名称位于该目录/文件夹中的文件,并将它们放在一个新的存储库中。 目前为止,一切都好。

有没有办法找到对该文件夹有更改的分支?

如您现在所知,分支和提交都没有更改,但分支确实允许您查找提交,如果您选择任何两个特定的快照(提交),则可以比较它们。

请记住,某些提交可能位于许多分支上。 如果有的话,这取决于你想用这个做什么。 您还需要决定是否将检查的每个提交与其父级进行比较,还是与某个固定的起点或终点提交快照进行比较。 例如,您可能有一个图表,其中部分包括:

o--o--*--K
/          
...--o--*--o--*--L---M--o   <-- br1

o--*--o--o   <-- br2

与父文件夹相比,每个*提交在相关文件夹中的文件存在一些差异。

您还需要决定如何处理合并提交。 这些是具有多个父级的提交。 我在字母M上方给出了一个有趣的合并提交,并给它的两个父级中的每一个都提供了字母KL(尽管实际上它们都只有大丑陋的哈希ID)。 合并提交M具有快照,就像任何其他提交一样。 但是很难将它与它的父级进行比较,因为它没有一个父级,它有两个父级。

由您来弄清楚该怎么做。 如果您决定分别从KL的父级*提交中获取(文件),您可能还希望从中获取(文件)提交M即使这些文件与K和/或L中的文件匹配。

您可能不关心这些:也许您只想查看每个分支的提示提交,并将每个分支与所有其他此类提示提交进行比较,以确定您想要的一个文件夹中文件的哪个版本。 如果这是您想要的,您可以使用git diff进行这些比较:git diff提供两个提交哈希 ID,它将比较这两个提交中的快照。 给它两个分支名称,如masterfeature,或br1br2,它将比较由这些名称标识的两个提交的快照,而不做任何父链接跟踪。

一旦你弄清楚你想要什么答案——或者你想回答什么问题——你可以用它来得到你想要的。

与其单独搜索,不如这样做:

git clone -ns . ../extract
cd $_
git filter-branch 
--subdirectory-filter src/codeToExtract 
-- --all -- src/codeToExtract

上面的第二组参数(在第一个--之后)是你想玩的分支,第三组(在第二个--之后)是你关心的路径。

然后(一如既往,Git 不关心存储库边界或名称本身,它们很方便,只有历史记录很重要)将您想要的任何结果历史记录推送/获取到您想要的任何存储库中,以您想要的任何名称。

最新更新