You should probably use 3-way conflict style for Git
Preface
I'd like to preface that this takes references from the excellent tutorial from Ted Felix called Git Conflict Resolution; I highly recommend reading through the tutorial if you want to go even deeper.
This article is more of a condensed version that helped me address problems I encountered when working with a huge codebase.
Since Git is constantly evolving and improving, the commands in this article require at least version 2.17.1
$ git --version
git version 2.17.1
The problem
Cherry-picking a set of 10-plus commits, unfortunately for me, the files that those commits were touching also were being worked on by me, so downloading a patch and doing git apply <patch_file>
would error out due to the limited conflict resolution abilities of this command. Also, for some reason, my muscle memory likes to default to this command, even though this is only recommended when working with files that do not belong to the same Git repository you're working with; in other words, I had skill issues. From the manual, we have one particular line that just doesn't seem to stick to my brain:
This command applies the patch but does not create a commit. Use git-am(1) to create commits from patches generated by git-format-patch(1) and/or received by email.
The solution
git-am
creates commits, allowing me to resolve conflicts when applying a patch file. And since I wanted to experience the 3-way merge before committing to use the diff3
conflict style in my git config file, I can run git am <patch_file> --3way
and start resolving conflicts should they appear; also, git am
will generate non-merge commits if the patch uses the mailbox UNIX form from git-format-patch
; from the docs, we have
Splits mail messages in a mailbox into commit log messages, authorship information, and patches and applies them to the current branch. You could think of it as a reverse operation of git-format-patch(1) run on a branch with a straight history without merges.
Platforms like GitLab and GitHub provide these patches from their Merge Requests/Pull Requests.
Additional notes
What does a diff3 look like? Again, thanks to Ted Felix for the tutorial and the examples of 3-way diffs
diff --cc hello.txt
index 5eb9649,379bd44..0000000
--- a/hello.txt
+++ b/hello.txt
@@@ -1,1 -1,1 +1,7 @@@
++<<<<<<< HEAD
+Hello, main change.
++||||||| merged common ancestors
++Hello, Original.
++=======
+ Hello, branch b1 change.
++>>>>>>> b1
You have a common ancestor followed by the main
branch and the branch that wants to apply the patches. The process is similar to the 2-way diff but with additional context for easier "grokking" with visual tools.
git mergetool
can help visualize these diffs in more detail. Tools like P4Merge are among my favorites; Ted recommends kdiff3, but I haven't tried it yet.
git-am
is similar to git rebase
, meaning that to resolve conflicts, we have to issue --continue
to keep applying the additional commits that come from the patch file after a resolution has been completed, unlike git-merge
where to continue we have issue git commit
to finish the conflict resolution process.
Similar commands in behavior to git-am
git rebase
git cherry-pick
git stash pop