Home > Software engineering >  If part of a commit is its parent, how do initial commits work?
If part of a commit is its parent, how do initial commits work?

Time:11-04

Title, basically. This seems to be the go-to resource for what a commit is built from. I couldn't find an article describing this subject in the official book, so do point me that way if I missed it.

My question is about commits without parents, i.e. initial commits. Specifically, what gets hashed in the case of no parent commit existing? And, when are parent commits required? Is it possible to have multiple commits without parents?

In my experimentation, I see that before the first commit, no branches exist; which makes sense considering branches are refs to commits, and none exist yet.

CodePudding user response:

Buckle up, bxtches, 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
  •  Tags:  
  • git
  • Related