I have these commits in my repository. These three are exactly the same, just differ in commit message. These commits are not the latest commits. How can I delete the upper two commits?
I am working alone, no one using this repo beside myself.
I have these commits in my repository. These three are exactly the same, just differ in commit message. These commits are not the latest commits. How can I delete the upper two commits?
I am working alone, no one using this repo beside myself.
I can't be sure of this given the information above, but you may not need to delete anything.
If there is something to remove, it's not actually those commits.
First, let's note something interesting about git here: git never deletes anything.
"What, never?"
"No, never!"
"What, never?"
The secret here is that git does eventually clear away "unreferenced objects" (including commits) during its automatic "garbage collection". So this really turns out to be a question of "what does ‘reference’ mean in git?"
The short answer is that a reference is an external label—typically a branch name or a tag, but there are more—that "points to" a commit. For a good longer answer you can start here, or at the top level of the "think like a git" site.
Now, the graph fragment you posted has three starting points, all with that same one-line commit subject. All three of these starting points seem (based on the graph fragment) to point back to a common previous commit.
That's three different ways to get started when following a "line of development". It's pretty typical for graph-drawing programs, so I think the program that drew this graph found three different references to these three starting-point commits. What's not visible here is what those references are.
One of them is almost certainly your HEAD
/ current-branch. (Git's HEAD
is a special reference, kept in the file .git/HEAD
, that normally contains the name of the current branch. That's how git knows which branch you're on: git checkout master
writes the branch-name master
into the HEAD
file.)
What the other two references are, I don't know. If you can get your graph-displayer to tell you where it found those commits, that would tell you. They could be coming from the "reflog" for the current branch, though, especially if you have done some git commit --amend
or git rebase
operations. Because git does not (and literally can not) change a commit, commands like git commit --amend
and git rebase
that seem to change commits, actually just make new, slightly-different copies of commits. The old commits remain behind, remembered only by "reflog" entries that keep references so that the commits don't get garbage-collected (yet). (These reflog entries are normally invisible to command-line git, so that they don't show up like this to confuse you. Eventually, old reflog entries expire and get purged, after which the retained commits are also purged during garbage-collection.)
In any case, ultimately it's a matter of deleting, not the commits themselves, but the references. In cases like these, where the reference points to a commit that "stands alone" like the two extra copies, there's not much of a distinction to make—but in more complex cases, the reference may point to a "tip" commit that is part of a longer chain of commits, where you want to keep some (but not all) of the chain, and then it really does matter (and gets more complex, since—this is a design feature—git still can't change anything in the repository).
I suggest squash the commits, you can do it through interactive rebase interface.
Squash my last X commits together using Git
For instance, if you have 2 commits, you can squash them and make into one using interactive rebase. See below command:
$ git rebase -i HEAD~n
For example, you want to squash 2 commits:
$ git rebase -i HEAD~3
Now, you see an interactive rebase interface
, in which you can write reword/pick on your first commit and squash on rest of them. Please see this video for better understanding.