git-commit(1) is the high-level command that you want to use almost all
of the time. git-commit-tree(1) is a lower-level command which is not a
daily-use command.
git-commit(1) is used when you commit new changes interactively. But I
guess I don’t have to elaborate on that.
git-commit-tree(1) is useful when you:
- Want to explicitly pick the parents of a commit
- You already have a tree for the commit
Say that I want to effectively “squash” all the commits in the repo down
to a single commit. But “squash” is a rebase operation which is
excessive since it combines changes, and I don’t need to combine any
changes since I already know what snapshot I want—the current
one. So:[1] [2]
$ git commit-tree -m Init HEAD^{tree}
1a875b50b508c70e44a4e6300fd80f580aed3d99
(That becomes a parentless commit since I didn’t specify any parents with
-p
.)
That’s the SHA1 of the commit. I better put it on a
branch so that the garbage collector won’t collect it a few months from
now.
$ git branch new-start 1a875b50b508c70e44a4e6300fd80f580aed3d99
Another thing you can do is create whatever history you want using
existing commits and their trees. Say for example that I want to make a
history of the Git repository which only consists of versions v1.0.0
,
v2.0.0
, and v2.40.0
and call the branch small-git
:
git clone https://github.com/git/git/ git-repo
cd git-repo
first=$(git commit-tree -m v1 v1.0.0^{tree})
second=$(git commit-tree -p $first -m v2 v2.0.0^{tree})
third=$(git commit-tree -p $second -m v2.40.0 v2.40.0^{tree})
git branch small-git $third
You can verify with this (all diffs should be empty):
$ # While on `small-git`
$ git diff v2.40.0
$ git diff @^ v2.0.0
$ git diff @^^ v1.0.0
Notes
- See
man gitrevisions
for the ^{tree}
syntax
- This can be accomplished by way of other means, like e.g.
git checkout --orphan new-start && git commit -m Init
. So it’s not like
you need this command to do it.