Cauchy
Cauchy

Reputation: 248

How to remove some past duplicate git commits?

In my office, I found that I had committed a sensitive file to github. So I used BFG Repo-Cleaner to remove the file from past commits. So it was deleted and I was happy. I guess that the commit hashes were changed at that time.

I went to home and opened a github desktop. It said I need to pull from origin and I did. There were no problems until then.

But then github desktop said I have to push 3 commits. It was weird but I was curious so I agreed to push. I shouldn't have done this. Now all commits have duplicates.

It's like this (recent commit on top):

5 min ago : Merge branch 'master' of https:....
3 hrs ago : commit 3
22 hrs ago : commit 2
22 hrs ago : commit 2
00 days ago : commit 1
00 days ago : commit 1
00 days ago : initial commit

'commit 1' and 'commit 2' have duplicates. Also one commit of 'commit 1's, one commit of 'commit 2's and 'Merge branch ...' have the sensitive file which I deleted. It was re-uploaded from github desktop right now.

I need to remove three commits without touching other commits.

Upvotes: 1

Views: 1909

Answers (3)

cmbuckley
cmbuckley

Reputation: 42458

In this case, your local branch was most likely in the original (pre-cleaned) state, and the remote branch was in the altered state. After rewriting the history, you should delete any local copies, or reset the local branch to the remote one. However, now you'll need to do some cleanup yourself.

My local was clean, the remote was not

If you cleaned your local branch, you ended up like this:

M─┐ eeeee Merge branch 'master' of ...
│ o ddddd Original Commit 2
│ o ccccc Original Commit 1
o │ bbbbb Commit 3
o │ aaaaa Cleaned Commit 2
o │ 99999 Cleaned Commit 1
o─┘ 88888 Previous Commit

Here, you need to get rid of 99999 and aaaaa. You could do this with an interactive rebase as with nitishagar's answer, or you can do it by resetting your branch:

git reset --hard bbbbb
git push --force origin master

The remote was clean, my local was not

If you cleaned up the remote, your history probably looks like this:

M─┐ eeeee Merge branch 'master' of ...
│ o ddddd Commit 3
│ o ccccc Original Commit 2
│ o bbbbb Original Commit 1
o │ aaaaa Cleaned Commit 2
o │ 99999 Cleaned Commit 1
o─┘ 88888 Previous Commit

In this case, aaaaa was the previous origin/master, and ddddd was your local branch. What you want to end up with is:

  o ddddd Commit 3
o─┘ aaaaa Cleaned Commit 2
o   99999 Cleaned Commit 1
o   88888 Previous Commit

You can do this with a single rebase (you can even add -i to confirm it's doing what you expect):

 git checkout master
 git rebase --onto aaaaa ddddd^
 git push --force origin master

This can be used no matter how many commits you've put on top of your local branch; you can refer to ccccc directly (the most recent local commit you want to remove), or ddddd^ (the parent commit of the first commit you want to keep).

Warning - force push to master

Be aware that you're rewriting history to master branch again. Given that your original commits contain the sensitive file, and you were previously happy to rewrite master's history to get rid of this, it's presumably OK for you to do it again. Just make sure to let any other users of this repository know the situation.

Upvotes: 1

Taylor Holloway
Taylor Holloway

Reputation: 21

I think this may be exactly what you're looking for here:"recently made duplicate commits help"

EDITED: I think the above link is better for your situation since your commit_ID's may be the same. If the ID's arent though, I dont see why this wouldnt work.

also this may be something of use: Githubs help on undoing a commit

maybe running the prompts listed here could undo the commits you'd like to get rid of.

Running this: "git revert {commit_id}", and using the commits ID you'd like to get rid of may work. Howeve

There is also a section on undoing your last commit, but it sounds like you need to undo 3. Be sure to have a backup just in case!

Upvotes: 1

nitishagar
nitishagar

Reputation: 9403

The best one I can think of is to use rebase here to rewrite the history and the do a push force. Following are some of the steps which can help here:

$> git rebase -i HEAD~6 // takes in 6 commits you want to edit

// Update the ones which you want to drop
drop xxxxxx initial commit
pick xxxxxx commit 1
drop xxxxxx commit 1
pick xxxxxx commit 2
drop xxxxxx commit 2
pick xxxxxx commit 3
drop xxxxxx Merge branch 'master' of https:....

Note: The commits are listed in the opposite order than you normally see them using the log command.

More detailed instructions here.

Upvotes: 2

Related Questions