Как найти обратное слияние в Git? - PullRequest
1 голос
/ 08 октября 2019

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

    A---F----------M------ V.1
     \ / \        /           
      E   H------L            

Изменения были добавлены в E, H и L перед объединением с веткой выпуска V.1.

Если мы работаемна V.2 в то же время любые изменения в V.1 также должны быть «объединены» с V.2:

          C--D                
         /    \               
        B---G--J---K---N-- V.2
       /   / \    /   /       
      /   /   I--'   /        
     /   /          /         
    A---F----------M------ V.1
     \ / \        /           
      E   H------L            

Это гарантирует, что любые исправления, которые применяются к V.1,переносится в V.2.

Время от времени разработчик случайно сливается с неверной веткой выпуска. Допустим, что коммит 'I', который был ответвлен от V.2, вместо этого был слит обратно в V.1:

          C--D                
         /    \               
        B---G--J-------N-- V.2
       /   / \        /       
      /   /   I      /        
     /   /     \    /         
    A---F-------K--M------ V.1
     \ / \        /           
      E   H------L            

В этом случае мы называем K "обратным слиянием". Это вызывает объединение всех новых функций V.2 с V.1, что очень плохо.

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

Как мы можем найти обратное слияние K программно?

1 Ответ

1 голос
/ 08 октября 2019

Поскольку эта идея "обратного слияния" не является чем-то, о чем git ничего не знает, вам нужно будет выполнить несколько пользовательских сценариев. (Самая близкая вещь, которую я могу придумать, чтобы действительно помочь здесь, это git bisect - но это не совсем сработает, потому что он думает, что ищет индивидуальный коммит, который ввел какое-то поведение, тогда как вы хотите найти, где какое-то поведение (я)объединены в определенную ветвь.)

Итак ...

Первый тонкий элемент, который вам нужен, - это способ проверить, что коммит содержит изменения с v2. Вы можете проверить самый ранний v2 коммит (B в вашем примере графика) и создать там тег

git tag v2-root

Затем вы можете проверить коммит, чтобы увидеть, является ли v2-root "достижимым";Есть несколько способов, но самый прямой - это, вероятно,

git merge-base --is-ancestor v2-root <some-commit>

Далее вам нужен список коммитов для тестирования. Вы можете использовать git rev-list. При нормальных обстоятельствах вы можете использовать

git rev-list --first-parent v1.0

. Предполагается, что для каждого слияния, добавляемого в ветку релиза, первый родительский элемент - это предыдущий коммит ветки релиза, что обычно имеет значение true. Есть способы создания слияний, где это не так. (Самое простое - объединить V1.0 в другую ветвь, а затем перенести V1.0 на объединение.)

Если вас беспокоит то, что происходит, тогда выпришлось бы опустить опцию --first-parent, и тогда вашему сценарию нужен способ сортировки топологии ветвей. Сейчас я предполагаю, что в этом нет необходимости.

Так что теперь вам просто нужен скрипт, чтобы пройти по списку коммитов, запуская тест (git merge-base ...) для каждого коммита, пока он не найдет тот, гдетест возвращает ложь. Если первая (самая последняя) фиксация возвращает false, обратного слияния не происходит;в противном случае последний коммит, возвращающий true, является обратным слиянием.

...