Reputation: 345
I have commits A, B, C and D and I need to just keep the most recent one which is D.
I see that one way is by using git rebase -i --root
as you can pick and squash commits.
Although I don't understand the difference between pick and squash that much, it made my wondering that since the commits are incremental thus commit D includes all changes in between, why do you have to go through git rebase
for keeping the most recent commit and not just delete the rest of the commits?
Or am I missing something fundamental about git? Can you have commits that are unrelated between each other? i.e someday use commit B and in another situation use the most recent commit D?
Upvotes: 1
Views: 1100
Reputation: 154926
git commits aren't really incremental, each commit contains the entire tree. It is only the user interface that presents a commit in terms of differences from its parent. In that sense, you don't have to go through git rebase
to keep the most recent commit and discard the rest, you can also use the git commit-tree
plumbing command to create the commit. The full equivalent of the rebase would be a line like this:
git reset --hard $(git commit-tree HEAD: -m message)
That dense line does the following:
HEAD:
refers to the tree object contained in the current head commit.
git commit-tree TREE -m MESSAGE
creates a new parentless commit that contains the specified tree, in our case the tree of HEAD
. Its output is the SHA1 of the newly created commit.
git reset --hard COMMIT
resets the current branch and the working tree to the specified commit, in this case the newly created root commit.
Creating commits without history is discouraged by git because such commits make it hard for git to operate on the data. Commands like git annotate
and git merge
rely heavily on history being available, and without those git is a much less useful tool.
Upvotes: 6