简体   繁体   English

获取合并分支分支的提交(中间合并)

[英]Get commit where merged branch forked from (with intermediate merge)

Lets use the latest available git 2.16.2 and tig 2.3.3. 让我们使用最新的git 2.16.2和tig 2.3.3。

cd /tmp && mkdir fit && cd fit

git init
touch m1 && git add m1 && git commit -m "master 1"
touch m2 && git add m2 && git commit -m "master 2"
git checkout -b develop
touch d1 && git add d1 && git commit -m "develop 1"
git checkout master
touch m3 && git add m3 && git commit -m "master 3"
git checkout develop
git merge master --no-edit
touch d2 && git add d2 && git commit -m "develop 2"
touch d3 && git add d3 && git commit -m "develop 3"
git checkout master
git merge develop --no-edit
touch m4 && git add m4 && git commit -m "master 4"

git reflog expire --expire=now --all && git gc --prune=now --aggressive

TIG 在此处输入图片说明

It is so easy to retrieve the last commit in develop branch: 检索develop分支中的最后一个提交非常容易:

git --no-pager show -s --format=%B $(git rev-parse develop)

develop 3 发展3

But I couldn't retrieve the first commit in develop branch. 但是我无法在develop分支中检索到第一次提交 So I couldn't find the commit where branch forked from. 所以我找不到分支从哪里分支的提交。

git merge-base --fork-point develop
git rev-list develop..master
git rev-list develop master
git rev-list master develop
git rev-list ^develop master

Results are useless. 结果没有用。

I've found a solution for question How to get commit where merged branch forked from 我找到了一个问题的解决方案, 如何从合并分支分支的地方获得提交

git oldest-ancestor master develop
git oldest-ancestor develop master

Results are useless too. 结果也没有用。

But tig and git log --graph are still able to see that develop 1 was the first commit of the develop branch and this branch were forked from master 2 commit in master . 但是, tiggit log --graph仍然能够看到develop 1是第一个提交的develop分支,这个分支从分叉master 2在提交master

Is it possible to retrieve master 2 with current git console tools? 是否可以使用当前的git控制台工具检索master 2

 git --no-pager show -s --format=%B $(git rev-parse develop) 

Even simpler: 更简单:

git --no-pager show -s --format=%B develop

or: 要么:

git --no-pager log --no-walk --format=%B develop

( show -s and log --no-walk are nearly the same thing; the key item here is to drop the unnecessary git rev-parse ). show -slog --no-walk几乎是同一件事;这里的关键项是删除不必要的git rev-parse )。

But I couldn't retrieve the first commit in develop branch 但是我无法在develop分支中检索到第一次提交

The first commit in that branch is master 1 , or 27ee6b8 in your image (the hash ID will vary with the time that the commit is made). 该分支中的第一个提交是master 127ee6b8中的27ee6b8 (哈希ID随提交时间的不同而不同)。 This is also the first commit in branch master . 这也是分支master的第一次提交。

The problem here is that branches do not have "starting points". 这里的问题是分支没有“起点”。 Branches are , in one sense, the structure—the graph fragment—that one reaches by starting at the ending point and working back to the beginning. 从某种意义上说,分支结构(即图形片段),它是通过从终点开始然后再回到起点而到达的。 This means that some commits are on many branches; 这意味着某些提交在许多分支上; typically, the root commit, the first commit you make in a repository, is on every branch (though in a repository with multiple roots, some roots may not be on some branches). 通常, 提交是您在存储库中进行的第一次提交,位于每个分支上(尽管在具有多个根的存储库中,某些根可能不在某些分支上)。

A branch name is, in general—there are some exceptions—synonymous with the tip commit on that branch, which is why you don't need an explicit git rev-parse . 通常,分支名称 (有些例外)与该分支上的tip commit同义词,这就是为什么您不需要显式的git rev-parse The key feature of a branch name, however, is that it moves over time, so that it always names the tip commit of the branch. 但是,分支名称的主要特征是它随着时间的推移而移动 ,因此它总是命名分支的尖端提交。

See also What exactly do we mean by "branch"? 另请参见“分支”到底是什么意思?

If you wish to mark some particular commit, in order to remember it later, the usual tool for this is a Git tag. 如果您希望标记某些特定的提交,以便以后记住它,通常的工具是Git标签。 A tag is very much like a branch name, in that it identifies one specific commit. 标签非常类似于分支名称,因为它标识一个特定的提交。 Unlike a branch name, however, a tag is never supposed to move, and Git won't move it automatically. 但是,与分支名称不同,永远不要移动标签,并且Git不会自动移动标签。

 git reflog expire --expire=now --all 

Reflogs exist specifically to be able to observe the movement (over time) of references. 专门存在引用日志是为了能够观察引用的移动(随时间变化)。 The reflog for a branch name like develop retains, for 30 or 90 days by default, 1 the hash IDs that develop used to identify. 一个分支名状的引用日志develop保留,默认情况下为30天或90天,1散列ID的develop 用于识别。 By expiring them, you've removed your ability to go back in time and look at develop@1 , develop@2 , and so on. 通过使它们过期,您已经失去了回到过去并查看develop@1develop@2等的功能。 If you had retained them, you could look for the oldest develop that exists. 如果保留了它们,则可以寻找现有的最古老的develop That might be when it was born, and you can often tell: 可能是它诞生的时候,您通常可以说:

05d0c47 master@{37}: clone: from ...

(indicating that master was born at this point). (表明此刻master已出生)。

Unfortunately, reflogs do expire, so this is not completely reliable. 不幸的是,刷新日志确实会过期,因此这不是完全可靠的。 The tag is reliable, but may be annoying since git log will decorate commits with their tags. 标签是可靠的,但可能会令人讨厌,因为git log会用其标签装饰提交。 If there's a procedure for finding the interesting commit, you can use that. 如果有寻找有趣的提交程序 ,你可以使用。 In this case, there is such a procedure: you want the commit(s) that was or were the merge base(s) of the merge. 在这种情况下,有一个这样的过程:您想要的合并曾经是或曾经是合并的提交。

To find the merge base, find the merge itself, then find its parents: 要找到合并基础,请找到合并本身,然后找到其父级:

m=11c63bc  # this is the merge
p1=$(git rev-parse ${m}^1)
p2=$(git rev-parse ${m}^2)

Now $p1 and $p2 are the two parents of this merge. 现在$p1$p2是此合并的两个父级。 (A merge can have more than two parents, but most merges have only two.) The common point where these two branches were last merged is the merge base of the two parents: (一个合并可以有两个以上的父级,但是大多数合并只有两个。)最后两个合并这两个分支的共同点是两个父级的合并基础:

git merge-base --all $p1 $p2

Since there is only one merge base, this prints just the one commit hash. 由于只有一个合并基础,因此只打印一个提交哈希。 If there were several, it would print all of them because we used --all . 如果有几个,它将打印所有的,因为我们使用了--all Leaving out --all , we would get one chosen at (apparently) random (the actual one chosen depends on the algorithm used to find the merge bases). 省略--all ,我们将(显然)随机地选择一个(实际选择的一个取决于用于查找合并基础的算法)。

As before, one does not need a lot of temporary variables—we could do: 和以前一样,不需要很多临时变量,我们可以这样做:

mbases=$(git merge-base --all ${m}^1 ${m}^2)

since git merge-base takes the same commit-specifier syntax as git rev-parse : the ^1 and ^2 suffixes work the same there (and indeed work the same in most Git commands). 因为git merge-base采用与git rev-parse相同的commit-specifier语法: ^1^2后缀在那里工作相同(并且实际上在大多数Git命令中工作)。


1 The expiration times are configurable. 1到期时间是可配置的。 The shorter time, 30 days by default, is for hash IDs that are not reachable from the current value of the reference; 较短的时间(默认为30天)用于从引用的当前值无法访问的哈希ID。 the longer 90-day default is for hash IDs that are reachable from the current value of the reference. 90天的默认较长时间是从引用的当前值可访问的哈希ID。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何获得合并分支分支的提交 - How to get commit where merged branch forked from 合并分支但没有合并提交 - Merged a branch but there is no merge commit 如何合并从另一个分支分叉的分支? (为了从原始分支获取最新提交) - How to merge a branch which has been forked from another into it ? (in order to get the latest commit from original branch) “合并提交”是否应该合并回 dev 分支? - Should “merge commit” be merged back into the dev branch? 从功能分支中的功能分支中删除合并提交的影响,这两个功能分支都将合并到 - Affects of removing a merge commit from a feature branch in a feature branch that will both be merged in 确定哪个合并提交导致特定提交合并到我的分支中 - determining which merge commit caused a specific commit to be merged into my branch 检查提交是否合并到另一个分支,如果是,那么合并提交是什么? - Check if a commit is merged to another branch, and if so, what is the merge commit? Git 在将要合并的同一分支的手动更新/提交之上自动合并 - Git automatic merge on top of maual update/commit from the same branch which is going to be merged 如何找到提交来自的合并分支? - How to find merged branch a commit came from? 如何从分支 B 合并到 A 时从分支 A 获取最新提交? - How to get the lastest commit from branch A that was the leave when branch B was merged into A?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM