Простой ответ заключается в том, что вы можете сказать Github, чтобы он запрещал прямые удары мастеру.Это автоматизирует вашу работу.Все обязательства перед мастером должны исходить от пиара.https://help.github.com/articles/about-protected-branches/
Вы также можете потребовать, чтобы определенные автоматические проверки состояния прошли до объединения PR, например, автоматический просмотр кода и CI.https://help.github.com/articles/about-required-status-checks/
Более сложный ответ ...
В PR нет ничего явно отличного от любого другого коммита.Но в зависимости от того, как вы объединяете свои PR и просматриваете ваши коммиты, будет много подсказок.
git log
и история коммитов Github вам лгут.История Git взаимосвязана с коммитами с фактическими ветками, выглядящими примерно так:
A - B - F - G - H - I [master]
\ /
----C - D
Каждая буква является коммитом.Они связаны друг с другом.Репо начинается с A. [master]
- это «метка ветви», но на самом деле это просто метка, указывающая на коммит I. Мы можем видеть, что C, D и E были сделаны как часть ветки, а H - это коммит, который объединилэто в мастер.
Все это можно увидеть в истории даже после того, как ветвь «удалена», потому что это просто удаляет метку.Историю еще можно увидеть, если ты умеешь смотреть.git log --graph --decorate --all
и другие различные инструменты просмотра репозитория раскрывают истинную историю.
$ git log --graph --decorate --all --oneline
* f164d0e (HEAD -> master) Merge branch 'feature'
|\
| * ae7b325 feature 2
| * 562cb51 feature 1
* | 2504fb9 master 4
* | a3e73ae master 3
|/
* e8bd7c4 commit 2
* 46edb1d commit 1
Мы ясно видим точку слияния и то, что зафиксировано в ветви.Когда вы объединяете PR, Github добавит дополнительную информацию к сообщению коммита слияния, например, PR #, чтобы его можно было проследить до его источника.Это НЕОБХОДИМОЕ использование людьми позже.
К сожалению, Github и git log
(по умолчанию) составляют линейную историю, которая аккуратна, легко читаема и неправильна.Это является источником большой путаницы с Git.
$ git log --all --oneline
f164d0e (HEAD -> master) Merge branch 'feature'
2504fb9 master 4
a3e73ae master 3
ae7b325 feature 2
562cb51 feature 1
e8bd7c4 commit 2
46edb1d commit 1
Помимо сообщений фиксации, все указания ветвей и слияний теряются.Поэтому обязательно посмотрите на настоящую историю.
Другой способ потерять историю - это способ объединения ваших PR.Сквош, перебазировка и ускоренная перемотка слияния потеряют историю ветки.
Сквош
Это худшее.Он берет все коммиты в ветке и разбивает их в один коммит.Если у вас есть ветка с тщательно продуманными коммитами и сообщениями, образующими четкое объяснение того, почему было внесено каждое изменение, все они будут перемешаны вместе.
Before squash
* eb54d0d (feature) feature 2
* 218a926 feature 1
| * 2504fb9 (HEAD -> master) master 4
| * a3e73ae master 3
|/
* e8bd7c4 commit 2
* 46edb1d commit 1
After squash
* d6054cf (HEAD -> master) Squashed commit of the following:
* 2504fb9 master 4
* a3e73ae master 3
* e8bd7c4 commit 2
* 46edb1d commit 1
Хотя это может быть очень удобно для лица, выполняющего слияниеЭто ужасно для тех, кто позже пытается выяснить, что было сделано в этой ветке и почему.
Rebase
Существует много, много хороших применений для rebase.Например, обновление ветки функций лучше выполнять с помощью перебазирования, чтобы избежать ненужных слияний бухгалтерии в истории.Но когда ветка завершена, она должна быть объединена, а не перебазирована.Перебазировка исключает существование ветви.
Before rebase
* eb54d0d (feature) feature 2
* 218a926 feature 1
| * 2504fb9 (HEAD -> master) master 4
| * a3e73ae master 3
|/
* e8bd7c4 commit 2
* 46edb1d commit 1
After rebase
* aff85f0 (HEAD -> master) feature 2
* aa8bc45 feature 1
* 2504fb9 master 4
* a3e73ae master 3
* e8bd7c4 commit 2
* 46edb1d commit 1
По крайней мере, отдельные коммиты все еще существуют, но топологические доказательства того, что они были выполнены как единое целое как часть ветви для устранения проблемы, пропали.
Fast Forward
Аналогично перебазированию, если Git не нужно объединять, он не будет.Это просто переместит метку ветки вперед.Это происходит, если на master
не было сделано никакой работы с момента создания ветки.Например.
Before
* eb54d0d (feature) feature 2
* 218a926 feature 1
* e8bd7c4 (HEAD -> master) commit 2
* 46edb1d commit 1
After fast forward
$ git merge feature
* eb54d0d (HEAD -> master, feature) feature 2
* 218a926 feature 1
* e8bd7c4 commit 2
* 46edb1d commit 1