Как git rebase работает между слияниями? - PullRequest
0 голосов
/ 29 августа 2018

У меня есть функция и основная ветка, например, как это (где мастер был дважды объединен с функцией):

*   27e89b5 (HEAD -> feature) f4
|\  
| * 6849a63 (master) 3
* | 3b78807 f3
* |   e84e33f f2
|\ \  
| |/  
| * 90e6f74 2
* | 4e4025b f1
|/  
* e4e0759 (tag: initial) 1

Вы можете перестроить этот MWE с помощью следующих команд:

git init
f() {   echo "$1" > README.md && git add README.md && git commit -m "$1"; }
f 1
git tag initial
git checkout -b feature
f f1
git checkout master
f 2
git checkout feature
git merge master
f f2
f f3
git checkout master
f 3
git checkout feature
git merge master
f f4

Когда я включаю функцию, я бы хотел git rebase -i initial раздавить некоторые из коммитов ветви функций. Git показывает это:

pick 4e4025b f1
pick 90e6f74 2
pick 3b78807 f3
pick 6849a63 3

squash только "f3" дает следующий график.

* be4387c (HEAD -> feature) 3
* a90d504 2
* 2afe0a4 f1
| * c447c7f (master) 3
| * efec11d 2
|/  
* 661d8fc (tag: initial) 1

Вопросы:

  • Почему Git не предлагает раздавить "f2"?
  • Могу ли я только раздавить "f3" без дальнейших изменений всей структуры ветви?

1 Ответ

0 голосов
/ 29 августа 2018

Почему Git не предлагает раздавить "f2"?

Потому что f2 - это коммит слияния, и вы не просили сохранять слияния. По умолчанию git rebase линеаризует историю и устраняет слияния. Это просто укладка коммитов поверх базы, как если бы они были свежими патчами.

Вы можете сохранить слияния с помощью -p, и тогда вы получите все коммиты.

$ git rebase -i initial
pick bde29dc f1
pick c9a9c74 2
pick e5565c5 f2
pick 7f18c18 f3
pick ffdd62c 3
pick 35d8ae9 f4

# Rebase aa61de7..35d8ae9 onto aa61de7 (6 commands)

Могу ли я только раздавить "f3" без дальнейших изменений всей структуры ветви?

Да, но тогда как до того, как вы раздавили f3 в 2, если вы хотите сохранить структуру, вы должны раздавить f3 в f2, поскольку это топологически предшествующий коммит.

pick bde29dc f1
pick c9a9c74 2
pick e5565c5 f2
squash 7f18c18 f3
pick ffdd62c 3
pick 35d8ae9 f4

Вы получите это.

*  (HEAD -> feature) f4
|\  
| *  (master) 3
* |  f2
|\ \  
| |/  
| *  2
* |  f1
|/  
* (tag: initial) 1

Хотя нет смысла раздавливать коммит в коммит слияния.

Если вы вместо этого переупорядочите коммиты, чтобы вы могли раздавить f3 в 2 ...

pick bde29dc f1
pick c9a9c74 2
squash 7f18c18 f3
pick e5565c5 f2
pick ffdd62c 3
pick 35d8ae9 f4

... вы получите ... что-то странное.

*   (HEAD -> feature) f4
|\  
| * 3
|/  
* f3
* 2
* (tag: initial) 1

Попытка переместить коммиты между ветвями с git rebase -i -p может сбить с толку, потому что git rebase -i представляет вам линейное представление нелинейной истории. Притворство о том, что нелинейная история линейна, - вот где Git сбивает с толку.


Но вам, вероятно, не стоит беспокоиться о сохранении всего этого. Сохранение истории Git в основном линейным делает все намного проще Вот как это сделать.

Ваша история, вероятно, является результатом обновления feature с git merge master. Вот лучший способ увидеть это.

1 -- 2 ------- 3 [master]
 \    \         \
  f1 - f2 - f3 - f4 [feature]

f2 и f4 не имеют реальной ценности; это обновления от master и не содержат интересного контента Они просто запутывают историю. Только f1 и f3 содержат фактическое содержание. Было бы лучше исключить эти обновления с помощью git rebase master и получить линейную историю.

$ git rebase master

1 - 2 - 3 [master]
         \
         f1 - f3 [feature]

Тогда все ясно и просто. Продолжайте сохранять свою историю простой, обновляя ветки с git rebase master вместо git merge master.

# After more updates with `git rebase master`
1 - 2 - 3 - 4 - 5 [master]
                 \
                  f1 - f3 - f5 - f6 [feature]

Когда вы будете готовы к слиянию feature в master, это когда вы хотите сделать коммит слияния. Используйте git merge --no-ff feature для принудительной фиксации слияния, а затем удалите feature.

$ git merge --no-ff feature
$ git branch -d feature

1 - 2 - 3 - 4 - 5 ------------------ 6 [master]
                 \                 /
                  f1 - f3 - f5 - f6

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...