С одной стороны, это действительно тривиально. С другой стороны, это очень тяжело.
Вот как это тривиально:
- Есть слияние. Слияние либо сделано правильно, либо неправильно. Посмотрите на слияние и посмотрите, было ли оно правильным или неправильным. Если это не так, автор и коммиттер сообщат вам, кто это сделал (в той мере, в какой вы доверяете автору и коммиттеру1).
Вот как это очень сложно:
- Есть слияние. Это правильно?
Не существует автоматического способа найти ответ на этот вопрос.
Если у вас есть хорошие автоматические тесты, вы можете сколь угодно близко подойти к автоматическому ответу на вопрос. Хорошие автоматические тесты непросты и становятся очень сложными, если вы пытаетесь сделать их очень хорошими.
Если у вас нет автоматических тестов, но есть люди, которые умеют правильно выполнять слияния, возможно, вы можете проводить выборочные проверки: просто попросите этих хороших людей повторить слияние и сравнить их результат с предыдущим результатом. Если они одинаковые, исходное слияние выполнено правильно. Если он другой, значит, не был.
Наличие или отсутствие конфликтов слияния не является верным показателем того, правильно ли было выполнено слияние. У Git нет секретных знаний: он просто объединяет текст в соответствии с фиксированным набором правил. Тем не менее, если вы хотите выбрать для ручного тестирования те слияния, в которых были конфликты, вы можете автоматизировать эту часть. Просто повторите слияние (убедившись, что git rerere
не включен) и посмотрите, есть ли конфликты.
Повторение слияния
Выше дважды встречается фраза «повторить слияние». Вы можете задаться вопросом, как вы можете повторить слияние. В основном это тривиально.2 Сначала найдите идентификатор фиксации каждого слияния:
git rev-list --merges <start-point> [additional options if desired]
Это создает список идентификаторов кандидатов. (Вы захотите сохранить их все где-нибудь и аннотировать, какие из них вы проверили, чтобы вам не пришлось перепроверять их позже. Используйте любое специальное решение, которое вам нравится здесь.)
Затем, получив идентификатор слияния, просто извлеките его первого родителя как отдельный HEAD и запустите git merge
для оставшихся родительских идентификаторов (этот бит зависит от поведения и синтаксиса оболочки POSIX):
id=c79a113... # or whatever, from your list
set -- $(git rev-parse ${id}^@)
git checkout $1 # check out first parent
shift # now that we have $1 out, discard $1
git merge $* # (attempt to) merge the remaining commits
Обозначение rev^@
взято из gitrevisions и означает "все родителей данной ревизии». Если все ваши слияния являются стандартными слияниями с двумя родителями, вы можете использовать более четкое (но менее общее):
git checkout ${id}^1
git merge ${id}^2
(синтаксис gitrevisions
и техника оболочки set
и shift
допускают слияние осьминогов).
Поскольку это слияние выполняется на отсоединенном HEAD, результирующее слияние, если оно завершается автоматически, можно тривиально отменить, проверив любой другой коммит или имя ветки. Если git merge
не удается с конфликтом, у вас есть конфликтующее слияние с обычными результатами в индексе; вы можете завершить слияние или использовать git merge --abort
для его завершения. (Статус выхода из git merge
будет 0
, если слияние прошло успешно, и ненулевым, если нет.)
1Помните, что, за исключением передачи фиксации через push или fetch, каждая операция Git выполняется локально кем-то, кто полностью контролирует свой собственный репозиторий. Конечно, пользователь может лгать и выдавать себя за кого-то другого. Если вы вообще контролируете это, вы можете и должны сделать это на границе передачи: когда вы принимаете фиксацию от кого-то еще — будь то git fetch
с вашей стороны или git push
с их стороны — вы знаете, кто вы говорите to (через любую аутентификацию, которую вы установили: это полностью вне Git, и в наши дни обычно используется ssh или https, часто завернуто в сторонние расширения, такие как Gitolite, или предоставляется как услуга чем-то вроде GitHub ). В настоящее время у вас есть возможность выполнить любую проверку, которая вам нравится, прежде чем принимать коммиты.
В качестве альтернативы вы можете проверить «постфактум», используя, например, подписи PGP. Если кто-то подписал PGP некоторые теги и/или некоторые коммиты, и вы можете проверить эти подписи, вы можете поверить, что эти теги и/или коммиты принадлежат ему. Затем вы можете расширить это доверие (конечно, в той степени, в которой вы готовы, исходя из безопасности SHA-1 и того, насколько вы доверяете подписавшему) на предков этих коммитов и / или тегов, поскольку создание объекта, который соответствует предопределенный SHA-1 и его текст, по крайней мере, очень сложный. (Это называется второе сопротивление предварительного изображения; см., например, этот вопрос crypto.stackexchange.com а>.)
2Я говорю "в основном тривиальные", потому что параметры, предоставленные пользователем git merge
, здесь недоступны. Вы можете потребовать от пользователей, которые используют нестандартные параметры слияния, записывать их в своих коммитах или в примечаниях, прикрепленных к коммитам, но это трудно обеспечить. См. также сноску 1: вы можете применять правила принудительного исполнения только на границе передачи.
person
torek
schedule
15.11.2016