I am really presenting an XY problem here, I know.
Let’s imagine that the last 4 commits represents a change that I want to create a no-ff
merge into the original state to preserve the individual commits explaining why they themselves made a good change, but have the merge commit message describe what the feature is about, and what benefit it provides to users.
I could execute the following:
git reset HEAD~4 --hard # Reset HEAD to the commit before the feature
git merge --no-ff HEAD@{1} # HEAD@{1} is not the prev. commit, thus my features.
The first command changes my working tree, but the end state is identical to where I started. The changing of work tree can have some unfortunate consequences, e.g. tsserver
, the TypeScript/JavaScript language server can sometimes go into 100% CPU if files are moved/removed. It could also trigger automatic test runs, which could have side effects I didn’t want.
So I wanted to see if I could perform that operation without changes to the working folder.
After reading the documentation for True merge, and inspecting the intermediate state when performing the --no-ff
merge (while it is waiting for a commit message), I tried:
# reset to the commit I want to merge _to_, but keep working dir
git reset HEAD~4
git update-ref MERGE_HEAD HEAD@{1} # Gathered from merge documentation
git update-ref ORIG_HEAD HEAD # Not in doc, but `no-ff` updates this ref
echo "no-ff" > .git/MERGE_MODE # Not in doc, but `no-ff` creates this file
git add . # Gathered from merge documentation
git merge --continue
While it creates the commit, the commit only has one parent, not 2.
I also notice that no-ff
adds an AUTO_MERGE
file pointing to a commit root tree object.
I tried to add (just using the hardcoded tree object id valid in this particular case).
git update-ref AUTO_MERGE f9e3c4cb... # just for this particular case
But that didn’t have any effect. The new commit still has only one parent, not two.
How can I manually create a commit with two parents?
And what goes on behind the scenes in the git commit --no-ff <ref>
that I was unable to detect when inspecting the intermediate state?