Buckle up, because today we're talking about commits!
How many parents can a commit have?
As many or as few as you want!
A commit doesn't have to have just one parent. It can have any number of parents!
- Initial commits have 0 parents
- Normal commits have 1 parent
- Merge commits usually have 2 parents...
- But Octopus Merges can result in commits with any number of parents (the linux kernel has a commit with 66 parents, that was the result of a 66 way merge! The technical term for this is a cthlulhu merge.)
Doing an octopus merge looks just like a regular merge, just with more arguments.
Regular merge:
# merge branch1 into current branch
git merge branch1
Octopus merge:
# Merge branches 1, 2, and 3 into the current branch
git merge branch1 branch2 branch3
Why go through the horror of an octopus merge?
It can be useful if you want to merge a bunch of separate feature branches in all at once.
git switch main
git merge feature-1 feature-2 feature-3 feature-4
This looks cleaner in the history, because you only have one merge commit, as opposed to a whole bunch of merge commits in a row.
It's best used when there's a very low probability of a merge conflict.
In the case of the 66-way merge in the linux kernel, they were merging in updates to a bunch of separate drivers, so there were no conflicts between the branches.
What gets hashed in an initial commit
Basically, everything.
- The author and the author's email
- any files or directories of stuff added to the initial commit
- the commit message
This means that if you change a commit message (e.g., with git commit --amend
), you're changing the commit hash and therefore the commit appears as a different commit
Is it possible to have multiple commits without parents?
Yes! Git can do anything! There are two ways to have multiple commits without parents:
- Merge in an unrelated repository with it's own history (this has happened 3 times in the history of the linux kernel)
- Create an orphan branch (this is a branch that doesn't share history with any other branch)
You can create an orphan branch via git switch --orphan <new branch name>
, which will create an empty orphan branch.
Note: to merge it a repository with an unrelated history, just do:
# Add a separate repo as a remote
git remote add other-repo <other-repo-url>
# Fetch the contents of that repo
git fetch other-repo
# Merge the main branch of the other repo into your repo
git merge --allow-unrelated-histories other-repo/main