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?
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?
Post
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
- Make a temporary branch in case things go badly.
- Start the merge.
- Resolve conflicts.
- Iterate bug fixes until it works.
- Consolidate the merge.
- 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
-
Make an
integration
branch from your "primary" (typicallymain
ormaster
) branch.git switch -c integration
-
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.
-
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.
-
Commit the merge.
git commit
-
Test the code yourself.
-
Push
integration
to be evaluated by your CI/CD and your testers.git push
-
-
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.
-
Repeat Steps 2.3 to 3 until satisfied.
-
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:-
git rebase -i --rebase-merges 3fe8aa^
…where
3fe8aa
is the merge commit's SHA. Note the^
to get the commit before it. -
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
-
Change all the
pick
lines in the bottom section to sayfixup
[1] instead ofpick
to fold them into themerge
commit. There are instructions at the bottom of the file in a big comment, in case you forget.
-
-
-
Test again, just to be sure.
-
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 mymerge.conflictstyle
.
1 comment thread