Получить фиксацию, из которой разветвляется объединенная ветка (с промежуточным слиянием)

Давайте использовать последние доступные версии 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 введите здесь описание изображения

Так просто получить последний коммит в ветке develop:

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

разработать 3

Но я не смог получить первую фиксацию в ветке develop. Поэтому я не смог найти фиксацию, из которой разветвляется ветка.

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

Результаты бесполезны.

Я нашел решение для вопроса Как получить фиксацию при слиянии ответвление от

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

Результаты тоже бесполезны.

Но tig и git log --graph по-прежнему могут видеть, что develop 1 был первым коммитом ветки develop, и эта ветка была разветвлена ​​из коммита master 2 в master.

Можно ли получить master 2 с помощью текущих инструментов консоли git?


person puchu    schedule 15.03.2018    source источник
comment
Результаты бесполезны. . . . пожалуйста, будьте конкретны: какое использование вы намерены?   -  person jthill    schedule 16.03.2018


Ответы (1)


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

Еще проще:

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

or:

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

(show -s и log --no-walk почти одно и то же; ключевой момент здесь — отбросить ненужные git rev-parse).

Но я не смог получить первую фиксацию в ветке develop

Первый коммит в этой ветке — master 1 или 27ee6b8 в вашем образе (идентификатор хэша будет меняться в зависимости от времени совершения коммита). Это также первый коммит в ветке master.

Проблема здесь в том, что ветки не имеют «отправных точек». Ветви являются, в некотором смысле, структурой — фрагментом графа, — до которого можно добраться, начав с конечной точки и вернувшись к началу. Это означает, что некоторые коммиты находятся во многих ветках; как правило, коммит root, первый коммит, который вы делаете в репозитории, находится в каждой ветке (хотя в репозитории с несколькими корнями некоторые корни могут не находиться в некоторых ветках ).

имя ветки, как правило, за некоторыми исключениями, является синонимом концевого коммита в этой ветке, поэтому вам не нужен явный git rev-parse. Однако ключевой особенностью имени ветки является то, что оно перемещается с течением времени, так что оно всегда называет окончательную фиксацию ветки.

См. также Что именно мы подразумеваем под ветвью?

Если вы хотите пометить какой-то конкретный коммит, чтобы запомнить его позже, обычным инструментом для этого является тег Git. Тег очень похож на имя ветки, поскольку он идентифицирует один конкретный коммит. Однако, в отличие от имени ветки, тег никогда не должен перемещаться, и Git не будет перемещать его автоматически.

git reflog expire --expire=now --all

Reflogs существуют специально для того, чтобы иметь возможность наблюдать за движением (с течением времени) ссылок. Журнал ссылок для ветки с таким названием, как develop, по умолчанию сохраняет в течение 30 или 90 дней1 хэш-идентификаторы, которые develop использовались для идентификации. По истечении срока их действия вы лишаетесь возможности вернуться в прошлое и посмотреть на develop@1, develop@2 и так далее. Если бы вы сохранили их, вы могли бы поискать самые старые develop из существующих. Это может быть, когда он родился, и вы часто можете сказать:

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

(указывая, что master родился в этот момент).

К сожалению, срок действия журналов ссылок действителен, поэтому это не совсем надежно. Тег надежен, но может раздражать, так как git log будет украшать коммиты своими тегами. Если есть процедура для поиска интересного коммита, вы можете использовать ее. В этом случае существует есть такая процедура: вам нужны коммиты, которые были или были базами слияния слияния.

Чтобы найти базу слияния, найдите само слияние, затем найдите его родителей:

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

Теперь $p1 и $p2 являются двумя родителями этого слияния. (Слияние может иметь более двух родителей, но большинство слияний имеют только два.) Общая точка, где эти две ветви были объединены в последний раз, является базой слияния двух родителей:

git merge-base --all $p1 $p2

Поскольку существует только одна база слияния, это печатает только один хэш коммита. Если бы их было несколько, он напечатал бы их все, потому что мы использовали --all. Опуская --all, мы получим один, выбранный (очевидно) случайным образом (фактический выбор зависит от алгоритма, используемого для поиска баз слияния).

Как и прежде, не нужно много временных переменных — можно было бы сделать:

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

поскольку git merge-base использует тот же синтаксис спецификатора фиксации, что и git rev-parse: суффиксы ^1 и ^2 работают там одинаково (и действительно работают одинаково в большинстве команд Git).


1Срок действия можно настроить. Более короткое время, 30 дней по умолчанию, предназначено для хэш-идентификаторов, которые недоступны из текущего значения ссылки; более длинный 90-дневный срок по умолчанию предназначен для хэш-идентификаторов, которые доступны из текущего значения ссылки.

person torek    schedule 15.03.2018
comment
Таким образом, промежуточное слияние основного в develop сделает мои ветки анонимными, и я не мог пройти develop коммитов, потому что только reflog знает, как разделить develop и master коммиты перед этим слиянием. - person puchu; 16.03.2018
comment
Довольно много, да. Обратите внимание, что слияния do имеют строгий порядок родительских элементов: первым родительским элементом слияния является фиксация, которая была HEAD при выполнении слияния. Настоящая проблема заключается в операциях быстрой перемотки вперед, которые не являются слияниями, но обновляют хеш-значения имени ветки, а также любую команду git reset, которая вносит любое произвольное (заданное пользователем) изменение в хэш-значение имени ветки. - person torek; 16.03.2018