Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Comments on What is the general process for merging two git branches, reviewing edits on each branch?

Parent

What is the general process for merging two git branches, reviewing edits on each branch?

+9
−0

Suppose you have a largish git repository with many files of different types (both text and images) distributed among a number of nested directories. Parallel development has occurred on two branches, each editing, creating, and removing files at various points within the directory tree.

Now you want to merge the two branches, reviewing each of the edits to ensure that the correct information is preserved to maintain the desired content and functionality from each of the two branches.

What is the process for doing this?

History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.
Why should this post be closed?

1 comment thread

Merge or git merge? (3 comments)
Post
+9
−0

There are two major sections to this answer: the Git part and the conflict resolution part. It wasn't clear at first which one was intended by the question, but both are important for a full answer.

Git workflow

Workflow summary

  1. Make a temporary branch in case things go badly.
  2. Start the merge.
  3. Resolve conflicts.
  4. Iterate bug fixes until it works.
  5. Consolidate the merge.
  6. Merge back the changes from the temporary branch to your primary.

For a simple merge, you can get by with 2, 3, and 6. But if this is as big a merge as you imply, the extra steps can be really helpful.

Workflow details

  1. Make an integration branch from your "primary" (typically main or master) branch.

    git switch -c integration
    
  2. Merge your other branch into integration.

    git merge other-branch
    

    This will probably result in merge conflicts if what you describe is true. If it doesn't result in merge conflicts, the merge will finish right here and you can skip to Step 2.3.

    1. Deal with the merge conflicts in an appropriate merge tool.

      git mergetool
      
      • This is probably the most complicated part of the process. See the dedicated section below.
      • You may have to consult with the submitters of text and images on both branches to determine which files to keep.
      • You may even have to write new code to rectify changes from both sides.
      • You may make mistakes. That's okay! You can fix those.
    2. Commit the merge.

      git commit
      
    3. Test the code yourself.

    4. Push integration to be evaluated by your CI/CD and your testers.

      git push
      
  3. Fix any mistakes on integration.

    Use new commits for these for now. It's lots easier to comprehend your fixes when they're separate from the huge merge.

  4. Repeat Steps 2.3 to 3 until satisfied.

  5. Squash all the fixup commits on integration.

    This is not strictly necessary, but anyone using Git ReReRe will appreciate that you consolidate any extra conflict resolution directly into the merge commit. You can even share rerere solutions across a team.

    • The easiest way is to use a GUI Git client to combine the fixups with your merge commit.

    • In the absence of a GUI, this is done with an interactive rebase, which can be a little intimidating with the --rebase-merges option:

      1. git rebase -i --rebase-merges 3fe8aa^
        

        …where 3fe8aa is the merge commit's SHA. Note the ^ to get the commit before it.

      2. Your text editor will then present a list of commits in the format below.

        label onto
        
        # Branch other-branch
        reset 57a270 # Merge branch 'other-branch' into integration
        pick a27157 So many commits from...
        pick f00ba2 ...the other branch here
        label other-branch
        
        reset onto
        merge -C 3fe8aa other-branch # Merge branch 'other-branch' onto integration
        pick ed170r Fix the build
        pick de1e7e Really fix the build this time
        pick c0ffee Fix the backend
        pick dec0de Fix the UI
        
      3. Change all the pick lines in the bottom section to say fixup[1] instead of pick to fold them into the merge commit. There are instructions at the bottom of the file in a big comment, in case you forget.

  6. Test again, just to be sure.

  7. Merge integration into your primary branch.

    git switch main
    git merge integration
    

Merge conflict resolution

Congratulations! You've found one of the hardest parts of SCM. Git's pretty good at slotting in new lines or taking things out when a merge occurs. But sometimes the additions or subtractions occur in the same location in a file, and Git needs human intervention.

Types of conflict

  • Two branches changed the same part (or parts) of a file.
  • One branch edited a file, but the other branch moved or deleted that file.
  • Two branches independently added a file to the same place.

This is not quite a comprehensive list, but it covers most cases. To see all the possibilities, see the "unmerged" lines in the git status --short documentation's XY chart.

Conflict markers

In text files with conflicts, Git will add conflict markers to designate the pre-existing conditions. These are usually paired <<<<<<< and >>>>>>> separated by a =======. There is optionally a ||||||| section showing the last shared content of that section. These are labeled with the source branch or commit.

You'll see these if you open a text file in your editor that contains conflicts before that file has been resolved. Most of the time, you're using a tool that reconstructs the full file from each side of the merge and you don't see the markers, but it's worth knowing what they are in case you encounter them.

Sometimes with simple conflicts, you can identify what ought to be in a conflicted section and fix it directly with a text editor in a pinch.

Merge tools

You may have noticed that instructions on how to actually deal with conflicts is pretty sparse in Git's documentation. That's because it pawns off conflict resolution onto "mergetools," and which one is right for you or right for a certain situation is a matter of preference.

These are sometimes terminal-based programs like vimdiff,[2] or GUI programs like Kdiff3, Meld, Kaleidoscope, WinMerge, Sourcetree, Sublime Merge, and on and on. Git's documentation has a list of already-configured mergetools, though you may or may not have any particular one installed.

Git's documentation isn't going to comprehensively cover how these work or how to use them (and neither can I), but in general they have some common components. You run git mergetool, and the one configured in Git config will spawn. To pick a different one, use git mergetool --tool=winmerge or whatever. You could conceivably use one for text conflicts and another for binary conflicts.

Merge tool layout

(Optionally) List of files to be resolved

If you're working your way through a whole set of files, there may be a way to select the next one for handling.

File contents on each branch

On one side, you're going to see the code from one branch. On the other side, you're going to see the code from the other branch. The sides ("ours" and "theirs") change depending on whether you're doing a merge or a rebase, so look for the descriptive labels to know which side contains which branch.

For each set of conflicted lines, there will be a way to select the lines from the left or the right (maybe both or neither as well), to add to the output.

A mergetool may or may not be able to handle and/or render non-text files.

(Optionally) The merge base

You may have a mergetool that also shows the original file from before it diverged, for context, in case that is helpful.

The editor pane

This is where you can actually edit the outcome of the merge. If the left/right selection is insufficient for what the file should actually look like, you can tweak it directly.

Merge tool use

  • You're going to go through each text file and decide each conflicted section.

    If the other file was moved, your mergetool may be smart enough to ask you about conflicts against the file in its moved location. Or it may not.

  • For images and binary files, you're basically going to choose which whole file is appropriate.

As you "handle" each file in the mergetool, it will report back to Git what the content should be for that file. Each file has to be handled in its entirety. The mergetool reporting has a pass/fail component, but you can "fail" it and come back to (re)fix it after working on some others.

For any files that can't be handled by the mergetool(s), you need to get the files into the shape you desire and git add them to the staging area of the merge commit.

Tips

  • Don't accidentally create empty files. Sometimes a mergetool will incorrectly recreate a "deleted" file with no content. Make sure those are really deleted.

  • Whitespace differences, particularly line endings, can make merging especially difficult. It can wildly expand the "different" lines. There are options when doing a git merge that can alter treatment of whitespace, which may collapse the divergent sections to their appropriate locations.

  • Git ReReRe ("reuse recorded resolutions") is disabled by default. You may want to turn it on to record pre-image and outcome for merge resolutions. Then if it encounters those exact situations again, the conflict can be resolved automatically in the same way.

  • You also have some control over the conflict marker sections. I personally use zdiff3 as my merge.conflictstyle.


  1. You can also use squash instead of pick to include their commit messages into the merge commit. You will then have a chance to modify the merge's commit message if you want to. ↩︎

  2. I swear I will learn vimdiff someday. ↩︎

History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.

3 comment threads

Step 5 "Squash all the fixup commits on integration." is optional (2 comments)
I think an explanation is needed of what it means to "Deal with the merge conflicts in an appropriate... (6 comments)
Extra intermediate branch is worth it (1 comment)
Step 5 "Squash all the fixup commits on integration." is optional
jmathew‭ wrote 4 months ago

Great write up. It's worth mentioning that squashing your fixups (or any edits to git history) are optional and up to personal preference. Especially considering how much it increases the workload and risk for newer git users.

Michael‭ wrote 4 months ago

I'll give you that squashing is optional, but it's important if you make use of ReReRe, so that the pre-image and merge outcome are bound together. Otherwise, you have to do all those fixups again.