Подтвердить что ты не робот

Git: Есть ли способ выяснить, откуда взялся чек?

Если я вишневый выбор из нескольких ветвей, есть ли простой способ выяснить, откуда взялся коммит (например, sha первоначальной фиксации)?

Пример:
- в мастер-ветке
- захват вишни A из ветки dev
- A становится D на главной ветке

До:

* B (master) Feature Y
| * C (dev) Feature Z
| * A Feature X
|/
* 3
* 2
* 1  

После:

* D (master) Feature X
* B Feature Y
| * C (dev) Feature Z
| * A Feature X
|/
* 3
* 2
* 1  

Можно ли вычислить, что D выбрана вишня из A (кроме поиска сообщения фиксации)?

Edit:
Хотя я поеду с лохмотьями (см. Ответ VonCs), я принял Криса Джонсена, потому что он ближе к реальному вопросу. Спасибо, ребята.

4b9b3361

Ответ 1

По умолчанию информация об исходном, "вишневом" фиксации не записывается как часть нового коммита.

Записать фиксацию источника в объявлении

Если вы можете принудительно использовать определенные рабочие процессы/параметры, git cherry-pick имеет параметр -x:

При записи фиксации добавьте к исходному сообщению фиксации примечание, указывающее, какое из этих изменений было выбрано из вишни.

Это, очевидно, бесполезно, если вы не можете полагаться на вишневых сборщиков, используя эту опцию. Кроме того, поскольку записанная информация представляет собой простой текст, а не фактическую ссылку на Git, даже если вы используете -x, вам все равно нужно предпринять шаги, чтобы убедиться, что исходная фиксация сохранена (например, является частью DAG тега или ветки без перематывания).

git вишня и Git patch-id

Если вы можете ограничить поиск двумя отдельными ветвями DAG истории, то git cherry может найти как "unpicked", так и "выбрал" вишни".

Примечание. Эта команда (и связанный с ней git патч-идентификатор) могут идентифицировать только конфликтные вишни, которые были индивидуально выбраны без дополнительных изменений. Если возник конфликт, когда вы выбираете вишню (например, вам нужно было слегка изменить его, чтобы заставить его применить), или вы использовали -n/--no-commit, чтобы выполнить дополнительные изменения (например, несколько вишней в одном коммите) или содержимое коммита было переписано после выбора, тогда вам придется полагаться на сравнение сообщений совершения (или информацию -x, если она была записана).

git Вишня не предназначена для определения происхождения собранных вишен, но мы можем немного ее использовать, чтобы идентифицировать отдельные вишневые пары.

Учитывая следующую историю DAG (как в примере с оригинальными плакатами):

1---2---3---B---D  master
         \
          A---C    dev
# D is a cherry-picked version of C

вы увидите что-то вроде этого:

% git cherry master dev
+ A
- C
% git cherry dev master
+ B
- D

(A, B, C и D - полные SHA-1 хэши в реальном выходе)

Поскольку в каждом списке мы видим одну вишню (строки -), они должны образовать вишневую пару. D была вишня, выбранная из C (или наоборот, вы не можете сказать только с помощью DAG, хотя даты фиксации могут помочь).

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

match_cherries() {
    a="$(git rev-parse --verify "$1")" &&
    b="$(git rev-parse --verify "$2")" &&
    git rev-list "$a...$b" | xargs git show | git patch-id |
    awk '
        { p[$1] = p[$1] " " $2 }
    END { 
            for (i in p) {
                l=length(p[i])
                if (l>41) print substr(p[i],2,l-1)
            }
        }'
}
match_cherries master dev

В расширенном примере, в котором есть две собранные вишни:

1---2---3---B---D---E  master
         \
          A---C        dev
# D is a cherry-picked version of C
# E is a cherry-picked version of A

Результат может выглядеть так:

match_cherries master dev
D C
E A

(A, C, D и E - полные SHA-1 хэши в реальном выходе)

Это говорит нам, что C и D представляют одно и то же изменение и что E и A представляют одно и то же изменение. Как и раньше, нет способа определить, какая из каждой пары была "первой", если вы не учитываете (например) даты фиксации каждой фиксации.

Сравнение контрольных сообщений

Если ваши вишни не были выбраны с помощью -x, или они "грязные" (имели конфликты или другие изменения, добавленные к ним (т.е. с помощью --no-commit плюс дополнительные изменения или с помощью git commit --amend или другой "истории переписывания" )), тогда вам, возможно, придется отказаться от менее надежной методики сравнения сообщений фиксации.

Этот метод работает лучше всего, если вы можете найти бит сообщения о фиксации, который, вероятно, будет уникальным для фиксации, и вряд ли изменится в фиксации, возникшей в результате выбора вишни. Бит, который будет работать лучше всего, будет зависеть от стиля сообщений фиксации, используемых в вашем проекте.

Как только вы выбрали "идентификационную часть" сообщения, вы можете использовать git log, чтобы найти коммиты (также продемонстрированные в Ответ Джефриса).

git log --grep='unique part of the commit message' dev...master

Аргумент --grep на самом деле является регулярным выражением, поэтому вам может потребоваться избежать любых метасимволов регулярного выражения ([]*?.\).

Если вы не уверены, какие ветки могут содержать исходную фиксацию и новую фиксацию, вы можете использовать --all, как показал Jefromi.

Ответ 2

Если я следую вашей диаграмме, вы хотите знать, можете ли вы определить, чем D (не B), является результатом сбора вишни A.

В теории, как показано в "Как перечислить ветки git, которые содержат заданный коммит?", вы можете искать фиксацию, если D фактически то же commit (SHA1), что и A:

git branch --contains <commit>

Но в качестве Jefromi комментариев D не может иметь тот же SHA1 в этом случае.
Это оставляет поиск общего сообщения о фиксации: см. Ответ Jefromi.


Как Кен Блум упоминает в комментариях вопроса, для такого локального набора вишни, метод скремблирования (как в monotone или mercurial) более уместен, поскольку он оставит четкий след слияния.

Дагги исправления означают использование вместо того, чтобы потерять истинное происхождение и связь между ошибками и исправлениями в графе предков.

Так как [ Git] предлагает возможность совершить фиксацию поверх любой ревизии, тем самым создавая крошечную анонимную ветку, жизнеспособная альтернатива вишневому сбору выглядит следующим образом:

  • используйте bisect, чтобы определить версию, в которой возникла ошибка;
  • проверить эту ревизию;
  • исправить ошибку;
  • и зафиксировать исправление как дочерний элемент ревизии, введший ошибку.

Это новое изменение можно легко объединить в любую ветку, у которой была исходная ошибка, без каких-либо отрывочных червей. Он использует инструмент нормального слияния и управления разрешениями для контроля версий, поэтому он намного надежнее, чем выбор вишни (реализация которого почти всегда представляет собой ряд гротескных хаков).

https://storage.googleapis.com/google-code-attachments/rainforce/issue -4/comment-5/Hg-dag-6-daggy-fix.png Hg DaggyFox

(здесь Меркуриальная диаграмма, но ее легко применить к Git)

Выполнение усталостных исправлений все время не для всех.
Не всегда так легко разработать исправление непосредственно против пересмотра, где была введена ошибка.

  • Возможно, ошибка не была обнаружена, пока какой-либо другой более поздний код не использовал ее способами, которые отображали ошибку; было бы сложно отладить и найти исправление без этого другого кода.
  • Или, возможно, важность или масштаб исправления просто не были реализованы в то время.

Смотрите также эту статью для получения дополнительной информации о daggy-fix:

Этот способ вернуться в историю, чтобы исправить ошибку, а затем объединить исправление в современные ветки, получил название "испражнения" авторов Monotone, влиятельная распределенная система контроля версий.
Исправления называются daggy, потому что они используют историю проекта, которая структурирована как направленный ациклический граф или dag.
Хотя этот подход можно использовать с Subversion, его ветки имеют большой вес по сравнению с распределенными инструментами, что делает метод daggy-fix менее практичным. Это подчеркивает мысль о том, что сильные стороны инструмента будут информировать о тех методах, которые его пользователи приносят.

Ответ 3

Никакая информация об исходном коммите не встроена во вновь созданную фиксацию, поэтому нет прямого способа рассказать. То, что вы предлагаете (поиск сообщения о фиксации), вероятно, является лучшим способом - это, безусловно, намного проще, чем поиск фиксации с тем же diff:

git log --grep="<commit subject>" --all

Если, конечно, фиксация больше не доступна из ветки... возможно, тогда вы захотите посмотреть результат git fsck.