Основная проблема в том, что вопрос некорректен:
... перечислите все файлы, измененные в PR вместе со статусом
Пулзапрос, по сути, является запросом формы: Пожалуйста, измените имя ветви B
, чтобы вместо указания на то, на что он указывает в то время, когда вы пытаетесь его изменить, оно указывает на принятие C
вместо.Делайте это так, как вам нравится, но, возможно, сделав свой собственный коммит слияния. Эта вещь с запросом на получение запроса может или не может быть - трудно сказать, так как запросы на выборку не являются частью самого Git, а скореенадстройки, предоставляемые различными веб-сервисами, и каждый веб-сервис может реализовать это, однако они похожи - включают информацию в форме: И, кстати, когда я попросил вас изменить значениеимя B
для идентификатора хеша C
, значение было идентификатор хеша O
.
Предположим на данный момент, что он предоставляет все три элемента: имя ветвиB
, старый хэш-идентификатор фиксации O
и запрошенный хэш-идентификатор фиксации C
.Также давайте заявим, что фактическое значение хеша B
в настоящее время A
.Может быть A
= O
, а может и нет.(Если O
не включен в запрос на извлечение, это на самом деле не фатально, но вам нужно найти подходящую замену и определить, как все это работает и т. Д.)
Что нужно знать о коммитах
Теперь, первое, что касается хеш-идентификатора коммита, это то, что он обозначает один конкретный коммит , и каждый коммит представляет собой полный снимоквсе файлы .Это не набор изменений вообще!Это просто состояние, подобное объявлению, что температура снаружи сегодня составляет 68 ° F (20 ° C).Само по себе это ничего не говорит о том, что было вчера или на прошлой неделе.Чтобы превратить состояние в изменение , вы должны выбрать другое состояние для сравнения.Если вчера было 77 ° F (25 ° C), изменение равно 9 ° F (5 ° C).
Мы делаем то же самое с коммитами в Git: мы выбираем одинсостояние - например, C
- и сравните его с некоторым предыдущим состоянием.Но мы только что сказали, что фактическое предыдущее состояние - A
, в то время как записанное предыдущее состояние - O
.Если вы сравните C
против O
, вы получите ответ, отличный от сравнения C
против A
, если, конечно, A
= O
.
Но это не единственное в коммите.Каждый коммит также записывает ноль или более родительских хеш-идентификаторов коммитов - обычно ровно 1, а следующий наиболее распространенный - 2 для коммитов слияния.(Нулевые родители означают, что коммит является корневым коммитом; обычно это только один из них на репозиторий для самого первого коммита. Три или более - это слияние осьминога .) РодителиC
- это каждый коммит по своему праву, который также имеет родителей и так далее.Если принять во внимание родителей, то, что мы действительно имеем, может быть примерно таким:
...--D--E--F--O--A <-- B
\ \
G--H--C <-- (pull requested at C)
Или может быть проще:
...--D--E--F--A <-- B
\
G--C <-- (pull requested at C)
, где A
и O
тот же коммит.Или это может быть даже запрос на удаление некоторых коммитов, хотя некоторые веб-сервисы не позволяют этого или не предпринимают никаких действий, если вы используете их интерфейс «принять запрос», но давайте просто нарисуем его:
...--C--O--A <-- B
(при запросе на сумму , пожалуйста, "перемотайте" B, чтобы зафиксировать A
и O
vanish ).
Что, если будет вызвано другое слияние-for?
Давайте снова посмотрим на этот график:
...--D--E--F--O--A <-- B
\ \
G--H--C <-- (pull requested at C)
На GitHub,по крайней мере, если вы используете тип по умолчанию «запрос на слияние», GitHub будет добавлять новый коммит - назовем его M
- чей снимок формируетсязапуск new git merge
(на GitHub), 1 , хотя сам C
является коммитом слияния.Снимок в M
будет получен путем объединения изменений.Конечным продуктом будет:
...--D--E--F--O--A--M <-- B
\ \ __/
G--H--C
Но GitHub также предлагает два других способа принять этот пул-запрос, каждый из которых делает что-то свое.Если коммиты G
, H
и C
еще не находятся в вашем хранилище, опция rebase и merge создает вместо этого график:
...--D--E--F--O--A--G'-H' <-- B
, тогда как опция squash and merge выдает:
...--D--E--F--O--A--S <-- B
, где S
имеет содержимое , которое M
будет иметь, если бы GitHub сделал M
.
1 GitHub выполняет слияние не с помощью git merge
, по крайней мере, не в буквальном смысле, поскольку нет способа обработки конфликтов.GitHub даже не предложит сделать M
, если возникнут конфликты слияния.Но эффект , как если бы GitHub управлял литералом git merge
, так что вы можете использовать это как ментальную модель, по крайней мере.
Простейший случай: A = O,потенциал для ускоренной перемотки вперед
Предположим, что график действительно выглядит следующим образом:
...--D--E--F--A <-- B
\
G--C <-- (pull requested at C)
, так что current value B
то же самое, что old значение B
в то время, когда лицо, сделавшее запрос на удаление, сделало это.То есть у нас есть A
= O
.Если вы используете стандартную кнопку «слияния» на GitHub, вы получите следующее:
...--D--E--F--A------M <-- B
\ /
G--C
, но содержимое коммита M
будет соответствовать содержимому совершить C
точно, что помогает несколькими способами.
Если вы используете режим rebase и слияние кнопки слияния, вы получите это:
...--D--E--F--A--G'-C' <-- B
где коммиты G'
и C'
являются копиями коммитов G
и C
запрашивающей стороны: моментальные снимки совпадают, и даже идентификатор родительского коммита G'
совпадает с идентификаторомG
;что отличается от хеш-идентификаторов: GitHub сделал копии как G
, так и C
, даже если нет смысла делать такие копии.(Я, например, хотел бы, чтобы GitHub вообще не делал эти копии. Возможно, что другие службы этого не делают.) Оригинальные коммиты не входят;вместо этого идут копии.
Если вы используете кнопку сквош и объединить , вы получите следующее:
...--D--E--F--A--S <-- B
где родитель S
равно A
, в то время как содержимое из S
точно совпадает с C
.Снова, коммиты G
и C
сами по себе не входят в репозиторий: только содержимое C
входит (как новый снимок в "squash" commit S
).
Определение того, что выхотите
Теперь вы знаете, что запрос на удаление - это действительно запрос переместить имя ветки из того места, где оно сейчас (A
), в нечто, полученное из запрошенного коммита(C
), возможно, добавив новый коммит слияния M
, возможно, добавив новый сквош-слияние (обычный одиночный родительский коммит без слияния) S
, или, возможно, скопировав некоторые или все их коммиты.
Что на самом деле произойдет, если вы примете их запрос на извлечение, зависит от того, какую кнопку вы нажимаете на GitHub, или если вы используете что-то еще (Bitbucket? GitLab? Что бы это ни было), что бы эта система не обеспечивала,Вам решать, что на самом деле произойдет .
Затем, зная, что на самом деле произойдет, вам еще раз предстоит выяснить, как сравнить коммиты, которые войдет в ваш репозиторий - коммиты, которые еще не могут существовать! - с коммитами, которые уже в вашем хранилище.Хотите сравнить содержимое C
с содержимым A
?Вы хотите сравнить C
с содержимым O
, предполагая, что доступен хеш-код O
?Или вы хотите внимательно посмотреть, что бы каждый новый коммит делал по сравнению с его родителем (-ями), даже если ни один из этих коммитов на самом деле еще не существует?
Последний, очевидно,самое сложное: но создание этих новых коммитов следует четко определенному процессу, поэтому, чтобы узнать, что они будут содержать, как только они появятся, вы можете просто создать их самостоятельно, в своем собственном хранилище, точно так же, как ваш веб-сервис.создаст их завтра, если вы примете запросПредостережение заключается в том, что если вы делаете делаете это - если вы проецируете то, что они сделают завтра - и затем соглашаетесь, что вы нажмете кнопку завтра, что произойдет, если завтра ветвь B
укажет на какое-тоФиксация, отличная от A
?
Если вы выберете этот последний вариант, то есть от принятия на основе того, что произойдет , вам нужно будет построить какой-то процесс вокруг всей операции, чтобы сделатьУбедитесь, что то, что произойдет , останется таким же, как то, что произойдет.Есть также много способов достичь этого, но ни один из них не совершенен.
Достижение того, что вы хотите
Как только вы определите 1288 *, что вы хотите, вам все равно придется достичь это.Это относительно просто для GitHub.(Я не уверен, что вы будете делать для Bitbucket или других систем.) Вы начнете с использования git fetch
для получения в свой собственный клон вашего репозитория копий коммитов C
и любых родительских коммитов, которые у вас есть, что выне хватает.
Предположим, что origin
- это имя репозитория GitHub, а запрос на получение - # 123.Затем:
git fetch origin # update everything so that we have origin/B pointing to A, etc
git fetch origin refs/pull/123/head:refs/heads/pr123
Теперь у вас есть ветвь с именем pr123
, в которой коммит коммита является коммитом C
вместе с вашим именем удаленного отслеживания origin/B
, указывающим на коммит A
.
Теперь легко определить, является ли A
предком C
, т. Е. Действует ли простейший случай.Этот конкретный тест выполняется в bash следующим образом (не уверен насчет PowerShell):
if git merge-base --is-ancestor refs/remotes/origin/B refs/heads/pr123; then
echo "it's the simple case, yay"
else
echo "it's the merge case, boo"
fi
В простом случае, независимо от того, какой метод вы используете для принятия запроса на извлечение, содержимое финального коммита для какого origin/B
пунктов в конце будут соответствовать содержимому коммита C
, как указано прямо сейчас refs/heads/pr123
. 2 Если вы решили, что вы хотите протестировать - это общее суммарное изменение , то есть с A
до C
, без рассмотрения каких-либо промежуточных фиксаций, - файлы, которые будут изменены, перечислены в:
git diff-tree -r --name-status [options] refs/remotes/origin/B refs/heads/pr123
Но если вы хотите проверить и промежуточные коммиты, у вас есть больше работы.
Если вы находитесь в случае слияния , все становится еще сложнее, так как- даже если вы просто собираетесь сравнить конечный результат с одним коммитом - теперь вы должны решить, будет ли сравниваться коммит A
, O
или что-то еще целиком, например, текущая база слияния A
и C
, всеr коммит, который может быть.
Если вы do хотите использовать фактическую базу слияния, то здесь синтаксис из трех точек может быть полезен.Однако из-за незначительных ошибок в старых версиях Git я бы посоветовал запустить здесь git merge-base --all refs/heads/B refs/heads/pr123
и собрать его вывод.Это перечислит некоторое количество хеш-идентификаторов, в идеале только один: если вы получите только один, это будет фиксация базы слияния.Если вы получаете более одного, они являются всеми кандидатами в базы слияния, и стратегия по умолчанию git merge -s recursive
сначала объединит все базы слияния, а затем использует полученный коммит в качестве базы слияния для слияний.
(Это частоСамый мудрый или, по крайней мере, самый простой - просто отклонить сложные запросы на извлечение, заявив, кто бы их ни написал, они должны переработать свой запрос на извлечение, чтобы он не требовал какого-либо особого / необычного слияния.)
2 Как правило, если у вас есть имя для удаленного отслеживания origin/B
и имя-ветви pr123
, указывающее на нужные коммиты, вы можете просто использовать эти имена.Однако метод, который Git использует для превращения имени в хеш-идентификатор, состоит из шести этапов, описанных в документации gitrevisions , а "использовать в качестве имени ветви" на шаге четыре., после «использовать как имя тега»;имя «использовать как удаленное отслеживание» - шаг пять .На практике это означает, что если у вас есть branch pr123
и tag pr123
, имя pr123
относится к тегу, а не к ветви.Для сценариев, которые будут запускаться без предупреждений о мониторинге человеком, целесообразно указать полные имена: refs/remotes/origin/B
и refs/heads/pr123
.Вы можете даже разрешить их один раз, чтобы хэшировать идентификаторы, а затем везде использовать хеш-идентификаторы, поскольку хеш-идентификаторы никогда не меняются.