Почему 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
были разработаны для одной функции.