2

Edit: Thank you all for the answers. Just forcing an overwrite of remote files is what I knew would happen with git push --force but I was more caught up with not preserving the commit history of main (Again, I wanted the commit history rewritten - not necessarily have new files overwrite remote files) - but after reading through the answer, I realize what I was forgetting how the force push would overwrite the remote with my local branch, including the commit history

This all started when I noticed someone did a merge commit in the history instead of rebasing like they were supposed to do

I followed this previously answered question to fix this, that is, rewrite the commit history in a way that a rebase was done instead of a merge commit. This rewrite was just done on a local branch and I confirmed the code still builds/works as expected, and the HEAD of both my branch and main match. The only difference is the actual commit objects from commit c onwards (See picture below) - but I understand why this creates a problem, I essentially have an entirely different history on my branch now

The question is: what do I want to do now? Since I rewrote the commit history, my local branch has diverged from origin/main, which is expected. In my head I want to just take my branch and force push to main such that main has the new history that I wrote on this branch

I understand rewriting history this way is probably strongly discouraged - but is there a proper way to handle something like this if there is a desire to cleanup the history of main to not have any merge commits?

Steps I took to get here:

  1. The main branch of a local repository had a history that looked like this:
a   b   d   e   f   g   h   i   j   k
o---o---o---o---o---o---o---o---o---o
  \---o---/
      c

Where HEAD was at k and the merge commit is e - the goal was to rebase c on top of d and delete e entirely

  1. Checked out a local branch from main such that it mirrored the above commit history
  2. On my local branch, rebased back to a since that is where the divergence happened
$ git rebase -i <sha of a>
  1. In the interactive rebase, selected c for editing and dropped e entirely
  2. Resolved merge conflicts and stepped through the git rebase --continue commands until my local branch looked like the following and I was back at HEAD. Since the rebasing rewrites the history, commits after c are different objects entirely but don't actually have any different content than what is currently in the remote repository
a   b   d   c   l   m   n   o   p   q
o---o---o---o---o---o---o---o---o---o
  1. Observe the following with git status
$ git status
On branch cleanup
Your branch and 'origin/main' have diverged,
and have 6 and 7 different commits each, respectively.
  (use "git pull" to merge the remote branch into yours)

nothing to commit, working tree clean

Which again, is expected. My concern here is with how to continue, that is, force update the main branch to have the cleaner history I now have on my local branch

gregfolker
  • 29
  • 5
  • 2
    Well you've answered your own question. You would have to force update the remote main to have the same history you have on the local main (by force pushing). There isn't some magic better way unless you want to throw the whole remote away and make everyone start over (and even that is not necessarily better). – matt Jun 16 '21 at 03:24
  • Thanks for the reply. I guess I knew this would work, but I just didn't know if there was a better way to handle it. I knew a PR would be useless, because I don't want to merge my branch into `main` but rather just have my branch become `main` in a sense. Assuming I have necessary permissions, here I just need to `git push origin HEAD --force` and the commit history of `main` is rewritten for the described range of commits? – gregfolker Jun 16 '21 at 03:29

1 Answers1

2

If you want to force rewrite your history on the remote you will have to force push your changes.

  1. On your local checkout your cleaned up the main
  2. Do a git push -f origin main. This will rewrite the remote main with the one you have created on local

Pitfalls:

  1. Anyone who has cloned or has updated the repo will have a different history. They will have to fetch and hard reset their local main to a new origin/main. You will have to make sure this happens. Else if anyone else does a force push then your history will get messed up.
  2. When you force push. If any change has been pushed to remote after you had last taken the update. They will get lost.

Personal Experience: In the past, even I was obsessed with not having a merge commit and rebasing everything. Over time I have realized it was too overrated. It's not something we should spend time worrying about. Merge commits are also good (and beautiful).

Mudassir Razvi
  • 1,783
  • 12
  • 33