vijay
vijay

Reputation: 177

Delete and completely remove the commit from git history

I have a commits in my git history

1.commit 4930da17d8dd23d650ed38435d8b421816a0c451
  Date:   Sat Dec 5 14:34:18 2015 +0530

2.commit e1ebbbb599ee20ebec3ca92c26266d9fd16e7ccc
  Date:   Sat Dec 5 13:22:20 2015 +0530

3.commit 1c4a11a80eb054d24dafec2efed0b0282188e687
  Date:   Sat Dec 5 12:11:50 2015 +0530

4.commit b4ab3c164a3a8d93e0a71a94b5c561cb5e20ebf6
  Date:   Sat Dec 5 12:09:56 2015 +0530

5.commit 167b1d10258381f09663ce61fa88ce3bbcd404c4
  Date:   Sat Dec 5 12:09:21 2015 +0530

6.commit c61bcadac673e1c83f4c14b66d56e23b12fa3198
  Date:   Sat Dec 5 12:07:58 2015 +0530

In that 3rd and 4th commit contains a wrong code, but unknowingly I committed and pushed.

3.commit 1c4a11a80eb054d24dafec2efed0b0282188e687
  Date:   Sat Dec 5 12:11:50 2015 +0530

4.commit b4ab3c164a3a8d93e0a71a94b5c561cb5e20ebf6
  Date:   Sat Dec 5 12:09:56 2015 +0530

But 5th and 6th commits contains a correct code. I need this commit to work.

5.commit 167b1d10258381f09663ce61fa88ce3bbcd404c4
  Date:   Sat Dec 5 12:09:21 2015 +0530

6.commit c61bcadac673e1c83f4c14b66d56e23b12fa3198
  Date:   Sat Dec 5 12:07:58 2015 +0530

Now I want to Delete and Remove completely whatever I changed in 3rd and 4th commit.

I want delete 3rd and 4th commit from the git history. But not 5th and 6th.

So that my branch will be safe.

Upvotes: 14

Views: 21152

Answers (3)

Martin F Schulz
Martin F Schulz

Reputation: 9

Oh well, poor OT.

On the surface, this looks like a simple scenario. But in version control, for this type of impulses, there are no simple scenarios.

Start with thinking about what you really want:

  • at the end everything should look all right. Nobody cares what was wrongly committed yesterday if it is fixed now. You can always commit bad, good, bad, good and so on. It's the last commit that counts. [unless you are running a murder investigation or want to 'blame' someone]

With that out of the way, the OP asked specifically for the commits to be gone, even though I'd ask back: are you sure? Are you really sure?

And then it gets complicated. What do mean by 'commits be gone'? git rebase -i gives you options and not everything is what you think it is:

  1. A commit is a visible step in the version history
  2. A commit is a captured and frozen change of any number of files managed in the git repository. If you really are only interested in the visible history of commits, you do not want to use 'git rebase -i' to 'drop' or delete a line, but rather use 'squash' to make it look like it never happened. If you really are sure that all the lines you added in any file have that unmistakable smell of doom to them, then you might think the right thing to do is to delete or 'drop' the commits. Just be aware that the real pain is not over, but it starts here.

A) Dropping a commit will then lead to conflicts with subsequent commits where git tries to apply them. That is the very nature of version control, i.e. the frozen change of state of any number of files. Applying a commit where it doesn't fit will not work in many cases and the more changes, the more conflicts.

B) Did any of the responses mention branches? All your branches will still be there, with all their history. 'git rebase -i' lets you make changes to one branch (e.g. main), but will not affect your branches and branch points. Which is good, as otherwise you couldn't play with the commits that you branched from. But it is bad if you were trying to conceal the commits. They are all still there in the branches!!!

C) Are you working collaboratively with anyone? Are you aware of git push/pull? This is at the heart of git. And what you are suggesting is pulling the rug out from under your buddies feet. They are sure to want to return that favor.

Good luck.

Upvotes: -1

Ali Dehghani
Ali Dehghani

Reputation: 48193

You can use interactive rebase in order to go back in your commit history and do things differently. For using interactive rebase, just:

git rebase -i <commit_id>

<commit_id> is the parent of the last commit you want to edit. After executing this command, just put d or drop in front of commits you're gonna delete or even delete the line corresponding to that commit.

Running this command gives you a list of commits in your text editor that looks something like this:

pick f7f3f6d changed my name a bit
pick 310154e updated README formatting and added blame
pick a5f4a0d added cat-file

# Rebase 710f0f8..a5f4a0d onto 710f0f8
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

The interactive rebase gives you a script that it’s going to run. It will start at the commit you specify on the command line and replay the changes introduced in each of these commits from top to bottom. It lists the oldest at the top, rather than the newest, because that’s the first one it will replay.

But since you've pushed the branch to your upstream repository, do communicate this history rewrite to your possible colleagues, as the git documentation says:

Remember again that this is a rebasing command – every commit included in the range will be rewritten, whether you change the message or not. Don’t include any commit you’ve already pushed to a central server – doing so will confuse other developers by providing an alternate version of the same change.

Upvotes: 16

driusan
driusan

Reputation: 550

You can interactively rewrite history with git rebase -i:

git rebase HEAD~6 -i 

Will open your editor and allow you to either squash multiple commits into one, or completely remove them from history (by deleting the line for those commits in your editor.) The ~6 means rewrite the last 6 commits, the -i means do it interactively. In your case, you'll want to remove the lines that say "pick 1c4a11a" and "pick b4ab3c".

Note that the most recent commit in the editor that gets launched is the last line, not the first one, and since you're rewriting history and you've already pushed, you'll also have to "git push --force", not just "git push" in order to send your changes upstream.

Upvotes: 9

Related Questions