5

After some playing with remotes I ended up with all my commits being doubled. E.g. instead of

C3107
..
C3
C2
C1

I got

C3107
C3107
..
C3
C3
C2
C2
C1
C1

where doubled commits has same names but different hashes. The problem is I noticed it too late and not I added a good bunch of commits on top of it.

Is there a way to remove duplicate commits and not not loose ones I added over?

P.S.: If it will help I have a copy of a repository before my experiments with remotes.

Thanks a lot in advance.

UPDATE As many of you asked here is how ended up like this: I have a repo R1 then I created another one R2. At my local copy which was up to date with R1 I changed origins to R2 and tried to push but some large files were rejected by github. So I did git filter-branch --index-filter 'git rm --cached --ignore-unmatch filename' which made git think repositories are different. Then I pushed all to R2 made some commits and decided to switch back to R1 changed origin again and pushed. Then I added some more commits to R1.

user487772
  • 8,800
  • 5
  • 47
  • 72
  • By default Git doesn't allow truly duplicate commits, i.e. commits with the same tree and the previous one. Did you pass `--allow-empty` to `git commit`? – Magnus Bäck Jan 30 '14 at 22:42
  • Updated my question with details about how I screwed my repo. – user487772 Jan 31 '14 at 08:46
  • I have the same problem. I suspect it was caused by an automated merge commit. I use the following commands to solve it (get rid of the merge commit and retain commits before and after it, but Committer and Commit Date will be updated due to creating new commits): `git checkout -b tmpBranchBeforeErrorMerge oldHashBeforeErrorMerge; git rebase --onto tmpBranchBeforeErrorMerge oldHashBeforeErrorMerge headLastestHash; git branch -b new_master; git branch -d master; git branch -D tmpBranchBeforeErrorMerge; git branch -m new_master master; git push -v --set-upstream origin master:master -f` – samm Dec 27 '17 at 08:09

3 Answers3

7

With a bit of shell magic, grepping and a lot of confidence, then the answer is probably "yes". But I'd be too leery of completely messing things up to squash over 3000 commits with a single command!

However, you can do it (moderately) interactively by using interactive rebasing. It's a bit laborious, but you have good control over what's happening and you get good feedback from git.

Paul Hicks
  • 13,289
  • 5
  • 51
  • 78
  • It really isn't that hard. People squash commits all the time. It's how you keep the commit log from saying "safety checkin" over and over again when people are doing frequent commits for backup reasons. – joel3000 Jan 31 '14 at 00:14
  • That's a different question. But since you're here.. I suggest either `git add` (and use the staging area for this), or `git commit --amend`. Resist the temptation to push your "backup" commits to a central repository. It's just not needed. – Paul Hicks Jan 31 '14 at 01:00
5

You can run the following command:

git rebase -i <commit id where you want to start squashing>

This will bring up an interactive session. Switch everything but the first commit on the stack to fixup or squash.

pick 07520cd Caught file exists issue. # this is last commit
fixup 3b71b9f Added README.            # fixup will squash the commit

# Rebase b041966..3b71b9f onto b041966
#
# 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

I have a git koan (koan 8) that walks you through git rebase -i.

KyleMit
  • 30,350
  • 66
  • 462
  • 664
joel3000
  • 1,249
  • 11
  • 22
1

An the end I decided in favour of cherrypicking.

user487772
  • 8,800
  • 5
  • 47
  • 72
  • this is the best solution for this issue. i got duplicate commits while rebasing with remote master branch and just did the following. - cherry picked the commit I want to have as HEAD -> git cherrypick - pushed those changes to the remote branch by force with lease -> git push origin --force-with-lease HEAD: – Vivek22 May 16 '20 at 02:32