Skip to content
Valentin Hilbig edited this page Jun 11, 2022 · 13 revisions

If you have any ideas, create an issue or pull request. Thanks.

WTF why?

It is good practice to start your git repository empty. This way, all real commits get a parent commit, and all branches can share a common (empty) parent commit.

Quite often you have more than one single thing in a repository. Like here on GitHub, you can have a gh-pages branch in parallel to your source code branch. This works well, however the output of some tools (like git log --graph --oneline --decorate --all) looks quite confusing when you have more than one branch with no common parent.

This repository tries to give you several variants of the "empty" repository to start with. Just choose the right $VARIANT (branch name) and then follow something like following recipe:

git init newrepo
cd newrepo
git fetch https://github.com/hilbix/empty.git $VARIANT
git reset FETCH_HEAD
git commit --amend --reset-author --allow-empty --reuse-message=HEAD
git branch empty
  • Please note that the commit --amend fails if VARIANT is (not given), master or gitignore, because an empty message is only supported on plumbing. You will see Aborting commit due to empty commit message. instead. This is not a bug of this repository.

Empties:

  • master: Date 0. Empty author. Empty committer. Empty message. Empty tree.
  • empty: Message "empty"
  • root: Message "root"
  • rc: Message "root commit"
  • er: Message "empty root"
  • erc: Message "empty root commit"

Not so empty:

  • gitignore: Empty .gitignore file
  • g: Empty .gitignore file, Message ".gitignore"
  • eg: Empty .gitignore file, Message "empty .gitignore"
  • gr: Empty .gitignore file, Message "root"
  • grc: Empty .gitignore file, Message "root commit"

Other uses

You want to rebase your project onto an empty commit:

git fetch https://github.com/hilbix/empty.git $VARIANT
git rebase --onto FETCH_HEAD --root
  • Use git rebase --onto FETCH_HEAD --keep-empty --preserve-merges --root if you want to keep everything. However this does not play very well with empty authors which are used in empty.git. As rebase may have many sideffects, it probably is best to not use --keep-empty. Instead conserve your previous TIP until you are sure, all important commit messages are still there and the new history looks good.

How was this done?

Here is a snippet

for a in "" root "root commit" ".gitignore" "empty .gitignore"
do
  git branch -f "g-${a// /-}" $(GIT_AUTHOR_NAME=. GIT_AUTHOR_EMAIL= GIT_AUTHOR_DATE='1 Jan 0:0:0 1970 UTC' GIT_COMMITTER_NAME=. GIT_COMMITTER_EMAIL= GIT_COMMITTER_DATE="1 Jan 0:0:0 1970 UTC" git commit-tree 82e3a754b6a0fcb238b03c0e47d05219fbf9cf89 <<<"$a")
done
  • This then was adapted accordingly.
  • The SHA was taken from git write-tree.
  • The objects were manually verified with something like git cat-file -p gitignore

Remarks

Can we get this into git like git branch --empty variant [--message "message"] BRANCH or similar? Variant names need not be compatible to this here, of course!

Update 2022-06-11

Today I learned, that git commit-tree of git 2.30.2 no more allows empty names as shown above. So the documentation above no more works to get following:

$ git cat-file -p HEAD
tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904
author  <> 0 +0000
committer  <> 0 +0000


$

I am not decided if this is good or bad. However this is no fault of this documentation at all.

Just use an old git version to archive this again. Sorry, but I do not know which one.

Looking after this I found a way to create a truly empty empty git commit:

git hash-object -t commit --stdin -w <<<$'tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904\n'

This leads to a bug at above lines:

Shell redirection <<<'' does add a $'\n' to the input argument, hence we see the two LFs above.

Which actually is a bug as this could have been left away.

Anyway, it is as it is, so I leave it as-is. Note that there is not much of a problem, as it is the tree which is important for the commit, everything else just is decoration.

Clone this wiki locally