Может ли git commit иметь более 2 родителей?

48

В этой документации упоминается

У объекта коммита может быть любое количество родителей.

Но, насколько я понимаю, единственный случай, когда коммит будет иметь более одного родителя, - это когда произошло слияние, и в этом случае будет только два родителя. Итак, мой вопрос, может ли коммит иметь более 2 родителей? Если да, то когда?

Не могу сказать
источник
11
github.com/torvalds/linux/commit/… - я не думаю, что Github знает, как отобразить 27-сторонний дифференциал, но вы можете свободно клонировать репозиторий и просмотреть его самостоятельно.
user253751

Ответы:

43

Вы можете использовать git merge для объединения более одного коммита в вашу текущую ветку. От man git-merge(или git help merge):

git-merge - объединяет две или более истории разработки вместе

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

Дэвид Хаммен
источник
33
Слияние более чем одной ветви (т. Е. Коммит с более чем двумя родителями) в разговорной речи называется «слияние осьминога». Это также источник вдохновения для логотипа и талисмана GitHub, восьминогой кошки: первоначально она называлась Octopuss, но была переименована в более корпоративный Octocat.
Йорг Миттаг
4
Каковы преимущества слияния трех или более ветвей в одном коммите вместо серии коммитов?
Тор Клингберг
2
@TorKlingberg Очистите историю, но обязательно протестируйте конечный продукт, прежде чем отправлять его в удаленный репозиторий.
Ferrybig
5
@KasunSiyambalapitiya - В одном конкретном репозитории github есть несколько примеров . Один из множества слияния осьминогов в этом репо, в котором участвуют 27 родителей .
Дэвид
1
@ JörgWMittag Буквально ничего из этого не является правдой. Источник: работал в GitHub пять лет.
Гьторикян
5

Да как насчет 100к родителей?

Вот живой пример GitHub со слиянием 100 000 коммитов: https://github.com/cirosantilli/test-octopus-100k, созданный с помощью этого скрипта .

пустяки

Линус не любит коммиты с более чем 60 родителями: https://www.destroyallsoftware.com/blog/2017/the-biggest-and-weirdest-commits-in-linux-kernel-git-history

Это тянет, и это хорошо, но есть четкий баланс между «слияния осьминога в порядке» и «Христос, это не осьминог, это слияние Ктулху».

Посмотрите на формат для объекта коммита Git

https://stackoverflow.com/questions/22968856/what-is-the-file-format-of-a-git-commit-object/37438460#37438460

Из этого анализа мы можем видеть, что список родителей является произвольным разделенным символом новой строки списком типа:

parent {parent_1_sha}
parent {parent_2_sha}
...
parent {parent_N_sha}

и поэтому разрешено произвольное количество родителей.

Минимальный пример

Автор сценария:

#!/usr/bin/env bash
set -eu

mkdir tmp
cd tmp
git init

touch root
git add .
git commit -m root
sha_root="$(git log -1 --format="%H")"

touch 1
git add .
git commit -m 1
sha1="$(git log -1 --format="%H")"

git reset --hard "$sha_root"
touch 2
git add .
git commit -m 2
sha2="$(git log -1 --format="%H")"

git reset --hard "$sha_root"
touch 3
git add .
git commit -m 3
sha3="$(git log -1 --format="%H")"

git merge -m merge "$sha1" "$sha2"

Выход:

*-.   2d2a6c2 (HEAD -> master) merge
|\ \  
| | * 2300c18 2
| * | 7e096cb 1
| |/  
* | 50aa125 3
|/  
* a1e94fd root
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
источник
Я не уверен, что GitHub просто не может обработать слияние такого масштаба или вы оставили его как частный репозиторий. Или если у GitHub просто какая-то не связанная проблема. Но независимо от того, ссылка для слияния 100 Кб является для меня ошибкой 500.
8bittree
@ 8bittree, с которым он не может справиться, частное репо будет 400 :-) github.com/isaacs/github/issues/1344
Чиро Сантилли 新疆 改造 中心 法轮功 六四 事件
Какова эта связь между защитниками FOSS в бородатых сандалиях и Лавкрафтом, которые я неоднократно встречал?
Нейтрино
3

Вы можете указать более одной ветви при объединении.

Например:

git merge branch_A branch_B branch_C [...]

Тогда коммит имеет больше родителей.

simhumileco
источник