2

There is a commit on master branch which I need to make some changes to.

Here's some history of what happened:

  • I was working on some code, and merged this to master
  • I created a new branch
  • Someone else branched from master themselves, made changes and then merged to master
  • In doing so, they have modified parts of the code which they should not have done. This is the core of the problem.
  • Part of the work they committed should be on master (most of it in fact) however a small number of the changes should not have been merged.
  • I continued working
  • Now: I cannot merge to master myself, because not only will my code break in doing so, but some of my work will be lost, because the other person who has committed their changes has undone some of my work in the process.
  • In theory, I could merge to master, and manually revert their changes by comparing code side-by-side as it was before they committed, or by inspecting the changes made during their commit.
  • However, I believe there might be a better way. If I was able to edit the history of master (which for obvious reasons I cannot - at least not without upsetting a lot of people) then I would do an interactive rebase, focusing on this commit. But I can't do this.
  • The "guilty commit" is now several commits down in the commit stack on master, as other people have committed work since this time.

What is the best approach here? I have never been in this situation before because I never worked in an environment where anyone could commit work without having it approved first.

I am of course aware that whatever I do here, I will have to do some level of manual work to make all of the new commits compile. It seems the longer I leave the situation the worse it will be to fix.

Martin Heralecký
  • 5,649
  • 3
  • 27
  • 65
FreelanceConsultant
  • 13,167
  • 27
  • 115
  • 225
  • Just merge to master, resolve conflicts, fix whatever breaks and push. I don't think there's any other way. Merging shouldn't discard your work - you'll get a conflict, which you'll have to resolve. – Martin Heralecký May 22 '23 at 17:28
  • I think judicious use of [git-diff](https://git-scm.com/docs/git-diff), [git-blame](https://git-scm.com/docs/git-blame), and [git-cherry-pick](https://git-scm.com/docs/git-cherry-pick) will stand you in good stead – code_monk May 22 '23 at 17:35
  • I would just as easily create a new branch off the _broken_ commit, correct the code there, merge fix into `master`. – eftshift0 May 22 '23 at 18:50
  • @MartinHeralecký That will only happen if I make changes to the same files and lines. Otherwise, Git will just accept the newer changes of other person as there is no conflict. – FreelanceConsultant May 22 '23 at 19:09

3 Answers3

1

I think your best bet in this situation is to first fix master by doing a partial revert of the offending commit. After that, you should be able to merge your feature branch in properly.

Note there isn't anything special about git revert, it's basically a convenience feature that reverses all the changes brought in by a commit. A "partial" revert is simply a regular revert that you modify before committing, typically by unstaging the portions of the original commit that you wish to keep.

As for where to start, as suggested by eftshift0 you could branch off of the offending commit in master, or you could use the current tip of master (and probably anywhere in between if you wish). It doesn't make much difference which of those you start from unless you will have conflicts. If conflicts are inevitable, then if you branch off of the offending commit, the revert won't have conflicts but the merge into master will. If you start from master, you'll have conflicts at the revert but not when you merge into master. Choose whichever you're more comfortable with. Note if master were protected and you must use a PR to merge in your change, I'd start from master, but that doesn't appear to be the case here.

TTT
  • 22,611
  • 8
  • 63
  • 69
0

I think that the best approach is to isolate the fix, especially considering that newer commits do not modify the problematic files. The flow would be something like this:

  1. Create a new branch from the latest published master.
  2. Use git revert to undo the the "guilty" commit(s).
  3. In case the commits include changes which should be kept, "redo" only these changes for each reverted commit with a new commit.
  4. Test everything, and fix anything that might have broken due to the reverts and redos.
  5. In case some required "fixes" (for the previous step) were already added to new work, you can cherry-pick these commits to this branch. Using cherry-pick will ease any future merge or rebase actions.
  6. Notify your colleagues of the issue, and this resolution.
  7. Push this branch to master (DO NOT force-push).

Now, for any newer (unmerged) branch, it can be rebased over master, have master merged into itself, or be merged to master as-is. Further conflicts should only be an issue in case newer work has modified the "guilty contents" (sounds like a song title by Eminem?, #sorry) - but that's what you probably want. Additionally, if there was a practical reason for keeping the current master, having this as a separate branch would isolate any judgement calls from affecting newer, unrelated work.

While this method should play nice with most future git actions (whether rebasing or merging), it has one major drawback - any new work based on the "guilty contents" is bound to silently break (i.e. no merge conflict). For example, say you modified a function to accept an additional argument, and the "guilty" code modified it back to remove that argument. Newer code which assumes the original function arguments will still pass locally for your colleagues, but may break when merged to master. This is why it is important to notify your colleagues, at the very least to let them know they should merge/rebase their work with the latest master.

Finally, as your mission is to not upset lots of people, I hope the person who "modified what they shouldn't have" is one of them. I suggest discussing this issue with that person directly, and perhaps even have them sign-off on the fixing branch, or work with them towards a new solution. "Undoing" someone else's work might be perceived as offensive (both for you and for them), and there could actually be a good reason for that you're not aware of. Communication is key for a healthy collaboration, and may prove extremely beneficial in the long run.

micromoses
  • 6,747
  • 2
  • 20
  • 29
-1

git merge and resolve conflicts. It won't favor their changes over yours; you'll just have to look through it and resolve each conflict. If you decide you didn't want to merge after all, git reset --hard HEAD will will take you back just before you started merging.

Caleb
  • 205
  • 1
  • 8
  • There won't be conflicts in all cases. In the majority of cases, there will be no conflicts. What has happened here is they have gone and modified code which I was no longer working on, and have not worked on since. So I don't have changes in the same files, or same lines in those files. – FreelanceConsultant May 22 '23 at 21:13