Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Git: How to permanently delete a local commit completely from the git database

Tags:

git

I know about git reset (including --hard), but that doesn't completely remove the commit, it just adjusts the tree. I've explored git gc, but that seemingly never permanently removes a commit, either. I know about filter-branch, but that only removes files from commits, but not commits themselves.

There are a lot of stack overflow questions that circle around this topic, but I can't find a real answer to the question: How to really delete a local commit (or series of commits), so that it no longer exists anywhere in the database, as though it was never done at all? If it was a method limited to a branch tip, that would be fine.

EDIT: It was a mistake on my part. I was using gitk and used F5 to view the entire tree. But F5 does an "update" and shift-F5 does a "reload". And the deletes don't actually show up actually unless you fully reload by doing the shift-F5.

like image 458
Nairebis Avatar asked Oct 30 '25 21:10

Nairebis


2 Answers

  1. Make the commit unreachable from any ref or tag, using reset, rebase, or even filter-branch. (How to use filter-branch to remove the file from all branches).
  2. Expire the reflog so that the commit is not reachable from there. git reflog expire --expire=now --all
  3. git prune to remove unreachable objects from the database. (git gc --prune=all would also have done the trick, but git gc plain keeps loose objects that are younger than two weeks old).
  4. You can verify it's really gone by manually inspecting the git object store. A git object is stored according to its SHA1 hash. THe first two letters of the hash are a directory and the final 38 are the filename inside of that directory.

So if the SHA1 hash of your problem commit is 12345ABCDEF... then it will live at .git/objects/12/345ABCDEF...

To be really paranoid you can find out the SHA1 hash of the specific blob (file contents) that you're worried about and hash it with git hash-object <filename>, and then check the DB for that hash.

like image 110
masonk Avatar answered Nov 02 '25 13:11

masonk


If your branch looks like this:

A   <-- HEAD
|
B
|
C   <-- to be removed
|
D

and you want to remove commit C, the following command might help you:

git rebase -i D     # if you have D's sha1 handy
# OR
git rebase -i C^    # parent of C (which is the same as D in this simple example)

Once issued, an editor pops up with all the commits starting from D's children, i.e. A, B, and C in a todo list. Simply remove the line with commit C in that editor window and save the file.

like image 25
PerlDuck Avatar answered Nov 02 '25 12:11

PerlDuck