Мне нужно объединить более одного коммита из каждой ветки или удаленного репо в один коммит в другой ветке.
input branch#1: o--o- - -o (C1)
\
input branch#2: o--o- - -o | (C2)
: \|
input branch#N: o--o- - -o | (Cn)
\|
output branch: o--o- - -o (Cm)
Мне нужно сделать это особым образом, где исходное дерево каждый коммит слияния входной ветви является префиксом или подкаталогом в исходном дереве коммита слияния выходной ветви:
<C1> <C2> ... <Cn>
| | |
+- c1.txt +- c2.txt +- cn.txt
<Cm>
|
+- C1/c1.txt
|
+- C2/c2.txt
|
: :
|
+- Cn/cn.txt
Кроме того, мне нужно изменить некоторые параметры коммита слияния, например author date
, author email
, et c и генерирует сообщение о коммите из сообщений о коммитах всех входных ветвей, оставляя родителей коммита слияния без изменений (включая список родительских коммитов sh в коммите слияния).
Копание в inte rnet Я уже нашел наиболее универсальное решение с минимальным набором команд:
git merge --allow-unrelated-histories --no-edit --no-commit -s ours <input-branches-and-commits>
git read-tree --prefix=C1/ <C1-branch>
git read-tree --prefix=C2/ <C2-branch>
:
git read-tree --prefix=Cn/ <Cn-branch>
cat ... | git commit --no-edit --allow-empty --author="..." --date="..." -F -
Но оно работает иначе, когда выходная ветвь является сиротской ветвью. В этом случае содержимое входной ветви дополнительно сливается с root дерева исходных текстов фиксации выходной ветви:
<Cm>
|
+- C1/c1.txt
|
+- c1.txt
В основном это происходит, когда входная ветвь является единственной входной ветвью (я не не тестировать случай с несколькими входными ветвями, когда выходная ветвь является сиротской, потому что у меня еще не было этого случая, но я не исключаю этого).
Я нашел причину, по которой это случается. Поскольку заголовок еще не существует и не может существовать, включая выходную ветвь, команда merge создает его при вызове и в то же время оставляет слияние незавершенным, а выходная ветвь указывает на входную ветвь, которая фактически делает выходную ветвь родительской. к себе. Это переносит содержимое исходного дерева входной ветви в root исходного дерева коммита выходной ветви без уведомления пользователя.
Я знаю по крайней мере один подход, чтобы избежать такого поведения, например, создайте пустой коммит в выходной ветви перед слиянием, которое делает сиротскую ветвь не бесхозной и инициализирует заголовок вместе со ссылкой на выходную ветвь.
Но я не хочу этого делать, потому что Я должен каким-то образом удалить этот коммит позже, который на самом деле является обходным кодом для git.
. Существует ли какой-нибудь хорошо известный способ справиться с кишками git, чтобы все вещи работали и сливались вместе как ожидается?