skip to Main Content

I did the whole thing in VSCode version control.

I have two branches, a main and b1 branch. b1 branch came from main branch. After doing some commits on b1, I merged it back into main, but main already got some conflicting commits with that merge. I resolved the conflicts then finished the merge.

I did an undo commit after that. VSCode allows me to then do more changes then press commit again, finishing the merge. This created a simple commit, not the desired merge commit in main branch.

The problem is that many commits happened since then. I want to make this commit be a merge commit.

How could I solve this problem?

An example of the problem is here: https://github.com/KijeviGombooc/merge_test

3

Answers


  1. Chosen as BEST ANSWER

    How I solved the issue:

    • Checked out the commit before the failed merge
    • merge the branch into this commit
    • run: 'git rebase --onto freshlyMergedCommit commitBeforeFailedMerge master'
    • then just do the following for each branch after: checkout that branch then run: 'rebase master'
    • then just force push (git push --force) each branch

  2. You need to play hardball every once in a while:

    git branch temp $( git commit-tree -p master~2 -p b1 -m "Here's the comment I want for the merge" master~^{tree} )
    # there you have a temp branch that is on a merge commit that has e018374be64546188 and b1 as parents and has the same content as 3457a643f9b7c7a20f15
    git checkout temp
    git cherry-pick master # now we cherry-pick that commit at the top of master
    # if you like the result, move master to the new location
    git branch -f master # assumning you didn't move from temp
    

    And now you can force-push into the remote with the new shiny master branch.

    Login or Signup to reply.
  3. Thanks for a clear example repo, it made it trivial to answer this question.
    NB All the following command assume that everything is checked in and no files are modified at the start.

    Step 0

    Start using gitk --all as your every-day version history visualization tool from today and the rest of your life. Neither vscode nor any other IDEs have anything that is remotely close to as useful as gitk.

    Step 1

    So you you have this

    initial gitk screenshot

    but would rather have this?

    final gitk screenshot

    No problem.

    Steps for the initial code setup:

    git clone https://github.com/KijeviGombooc/merge_test
    cd merge_test
    git branch b1 origin/b1
    git tag old-not-really-merge 3457a643          # Tagging just for convenience
    git branch new_master1 old-not-really-merge^   # Branch from the parent of the tag
    git branch new_master2 master
    

    which gives

    gitk screenshot 3

    (no code changes yet).

    Step 2

    Create a real merge commit.

    git switch new_master1
    git merge b1                       # This gives a merge conflict ...
    git resolve-conflict-using-kdiff3  # ... which is easy to resolve with good tools.
    git commit                         # Finishing the merge.
    

    Using KDiff3 the conflict was resolved the same way as the existing commit Merge branch ‘b1’:

    KDiff3 screenshot

    which gives the following result:

    gitk screenshot 4

    Step 3

    Now the only remaining part is to include the changes made after old-not-really-merge:

    git rebase --onto new_master1 old-not-really-merge new_master2
    git branch --delete new_master1
    

    At this point new_master2 is the result you asked for. It is a good idea to verify that the new branch is not fundamentally different:

    git diff master new_master2 
    diff --git a/test.txt b/test.txt
    index 8d069ed..d5340c7 100644
    --- a/test.txt
    +++ b/test.txt
    @@ -1,2 +1,2 @@
     this is a file
    -Line from b1
    +Line from b1
     No newline at end of file
    

    In this case there was a difference in line ending on the last line because you and I resolved the merge conflict slightly differently. You have to judge if changes like that are ok or not.

    gitk screenshot 5

    Step 4

    After you have verified that new_master2 is what you wanted you can reset the original master branch to the new branch:

    git switch master 
    git reset --hard new_master2 
    git branch -d new_master2 
    git tag -d old-not-really-merge
    git push --force origin master
    

    which then should give the same result as the second screenshot1.


    At the end now I notice that the merge commit references the branch name new_branch1 so a better approach would have been to start with renaming master to master.old and then use the name master instead of new_branch1. I’m not redoing commands and screenshots to fix that.


    1 I obviously did not push back to your origin repo, so the screenshot was taken from a "second level" local clone made with git clone merge_test merge_test2 which then has my first merge_test repo as its origin.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search