2

we are working on a git repo with several branches. The system only allows to deploy changes onto the live system, if all commits have feature-ids as the beginning of the commit comment that must be approved by the company for this project.

We have a typo in one commit that is more than 100 commits back in the past (several people working on this repo), that leads to the feature-id being wrong (and therefore not approved for this project). So now we are not able to push our changes into the live system because of this one commit.

Therefore I need to change the commit message of this one commit to solve my problem.

I researched and came across this solution using git rebase. I'm aware of the fact that I would change git history here and I'm aware of the implications. That would be fine so far. Now my problem is that (to my understanding), git rebase takes all the ~140 commits, deletes them from the history and tries to apply them again. This works well if you don't have any merges in your commits. But boy do we have a lot of merges. There were many merge conflicts, that have all been resolved (obviously).

But when the rebase is done, the information on how to resolve the conflicts seems to be lost and git asks me to merge everything again. That is not a viable option because re-doing merges for ~140 commits would take about four weeks or more (also information on how to merge might not be available any more).

So we need to make git resolve these conflicts automatically, using the information given in the repo.

I can't figure out how to do that. I read about the git rerere command (see here), but to my understanding I should have enabled that option before resolving all the conflicts and while doing so, git would have recorded the necessary information for later.

What are my options to get this one commit renamed? Seems like a simple tasks, but I'm out of ideas.

Thanks a lot for any help!

Community
  • 1
  • 1
Mathias Bader
  • 3,585
  • 7
  • 39
  • 61

2 Answers2

2

You can use git amend to change the commit message. Then replace your current commit with new commit in all branch.

$ git branch backup                                 # backup your branch just for safety

$ git checkout <commit-hash>                        # checkout the commit trying to modify
$ git commit --amend -m 'Change message here'       # change the author name and mail

$ git log                                           # copy the new-commit-hash
$ git replace <old-commit-hash> <new-commit-hash>   # replace the old commit by new one
$ git filter-branch -- --all ^<old-commit-hash>     # note '^' before hash, rewrite all futures commits based on the replacement                   

$ git replace -d <old-commit-hash>                  # remove the replacement for cleanliness 

$ git checkout <branch>                             # go to branch HEAD and see if the commit is changed perfectly

$ git push -f origin HEAD                           # force push as history is changed.
Sajib Khan
  • 22,878
  • 9
  • 63
  • 73
  • 1
    This is the way to go. I will add that it is possible to do this with a single `--msg-filter` filter-branch (without the amend and replace steps), but that's a lot trickier to get right. You can speed up the filtering by adding `^` after `--all` in the filter-branch, where `` is the replaced commit (we don't need to copy earlier commits, only later ones). – torek Feb 15 '17 at 19:13
  • "+1 I agree". Thanks for `--msg-filter` idea (may be more tricky as `regex` may be needed to match commit message). I edited post adding `^`. – Sajib Khan Feb 15 '17 at 19:45
  • I was thinking `^` but `^` should work too. You wouldn't need a regex, you would need to test `$GIT_COMMIT` for the old hash ID. – torek Feb 15 '17 at 20:43
1

Try using --preserve-merges on your rebase

git rebase --preserve-merges HEAD~100

It should try to recreate the merge commits and might help you out. If using with -i just make sure you don't change the order of the commits or it might mess things up.

Pedro Nascimento
  • 13,136
  • 4
  • 36
  • 64
  • The OP noted that those merges had merge conflicts. Since `rebase -p` has to *re-create* the merges, this method is usually not suitable. Using `filter-branch` (as in sajib khan's answer) is the way to go, although using filter-branch is painful. – torek Feb 15 '17 at 19:10
  • Tried that one - leads to merge conflicts :-/ – Mathias Bader Feb 16 '17 at 08:47