I need a merge more than 1 commit each from a branch or a remote repo into a single commit in another branch.
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)
I need to do it in a special way where the source tree of each input branch merge commit is a prefix or subdirectory in the source tree of the output branch merge commit:
<C1> <C2> ... <Cn>
| | |
+- c1.txt +- c2.txt +- cn.txt
<Cm>
|
+- C1/c1.txt
|
+- C2/c2.txt
|
: :
|
+- Cn/cn.txt
Additionally, I need to change some parameters of the merge commit, like author date
, author email
, etc and generate a commit message from commit messages of all input branches leave the parents of a merge commit as is without any changes (including parent commit hash list in a merge commit).
Digging in the internet I have already found the most universal solution with the minimal set of commands:
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 -
But it does work differently when the output branch is an orphan branch. In that case the content of an input branch merges additionally into the root of the source tree of the output branch commit:
<Cm>
|
+- C1/c1.txt
|
+- c1.txt
Basically it happens when the input branch is the only input branch (I didn't test the case with the multiple input branches when the output branch is an orphan branch because I didn't have that case yet, but I don't exclude that).
I have found the reason why that happens. Because the head does not exist yet and can not exist including the output branch then the merge command creates it upon the call and in the same time leaves the merge incomplete with the output branch pointing to an input branch which actually makes the output branch the parent to itself. This brings the content of the source tree of an input branch into the root of the source tree of the output branch commit without a notice from the user.
I know at least one approach to avoid that behavior, for example, create an empty commit in the output branch before the merge which makes the orphan branch not orphan and initializes the head together with the reference to the output branch.
But I don't want that to do because I have to somehow remove that commit later which is actually workaround code to the git.
Does out there exist a good known way to deal with the git guts to make all things work and merge together as expected?