gitmergeconflicts(7) ==================== NAME ---- gitmergeconflicts - Guide to handling merge conflicts DESCRIPTION ----------- Merge conflicts can happen during a `git merge`, `git rebase`, `git cherry-pick`, `git pull`, `git revert`, or any other command that does a merge. All of those commands use the same merge algorithm, and the process for resolving a merge conflict is always very similar. There are 3 ways to handle a merge conflict: * Resolve the conflict. (see <> below for details) * Stop the operation and return your branch to its original state with the appropriate `--abort` command, for example `git merge --abort` or `git rebase --abort`. See <> below for how to find the command to run. * Or (if you're in a multi-step operation like a rebase) skip the problematic commit with the appropriate `--skip` command. WHAT IS A MERGE CONFLICT? ------------------------- When Git merges two commits together, it looks at the changes that each side has made and combines those changes. For example, if one side edited lines 1-5 of `hello.py` and the other side edited lines 20-25 of the same file, then it can easily combine them since there's no overlap. But if both sides edited overlapping lines of the same file (for example one side edited lines 1-5 and the other edited lines 3-6), Git will not try to guess how to combine those changes. This is called a "merge conflict". When this happens, Git shows you both sides' edits and asks you to pick how to resolve them. It: * Stages all of the files which were successfully merged * For the files with conflicts, it marks them as conflicted, puts both sides' edits in the file, and leaves <> that you need to resolve. [NOTE] Even if Git successfully merges both sides with no conflicts, it's possible to end up with code that doesn't work. For example, this can happen if one side renames a function, and the other side adds a call to the old function. This is called a "semantic merge conflict". [[markers]] MERGE CONFLICT MARKERS ---------------------- When there's a merge conflict, Git will update the conflicted file to include merge conflict markers `<<<<<<<`, `=======`, and `>>>>>>>`. For example, here's a merge conflict where both sides edited a list of fruits in different ways -- one side has "cherry" and the other side has "banana": ---- FRUITS = [ "apple", <<<<<<< HEAD "cherry", ======= "banana", >>>>>>> add-fruit "mango", "orange", ] ---- The lines from one side of the merge conflict is between `<<<<<<<` and `=======`, and the lines from the other side is between `=======` and `>>>>>>>`. See <> below for a full explanation of which side is which. [[resolve]] HOW TO RESOLVE A MERGE CONFLICT ------------------------------- The process for resolving a merge conflict is: 1. Run `git status` to get a list of files with merge conflicts. 2. For each one, find the conflict markers (the `<<<<<<<`, `=======`, `>>>>>>>`) and edit the file to fix the conflict. 3. Run `git add FILENAME` for each file to mark the conflict as resolved. 4. Run the appropriate `--continue` command to continue the operation that was interrupted by the conflict, for example `git merge --continue` or `git rebase --continue`. See <> below for how to find the command to run. + Note: During a `git merge`, `git commit` and `git merge --continue` do the same thing. [[example]] EXAMPLE OF RESOLVING A MERGE CONFLICT ------------------------------------- If you see this in your code during a merge conflict: ---- FRUITS = [ "apple", <<<<<<< HEAD "cherry", ======= "banana", >>>>>>> add-fruit "mango", "orange", ] ---- Then you might edit that part of the code like this, which includes the fruits from both sides of the conflict: ---- FRUITS = [ "apple", "banana", "cherry", "mango", "orange", ] ---- [[tools]] TOOLS FOR HANDLING MERGE CONFLICTS ---------------------------------- Here are some ways to get extra context while handling a merge conflict: * There are many graphical "merge tools" for Git, which will normally show you the different versions of the code side by side. If you have a mergetool configured, `git mergetool` will launch it. See also `merge.tool` in linkgit:git-config[1] for a list of the mergetools Git supports. * You can set the configuration variable `merge.conflictstyle=diff3`. See <> below for more. * `git log --merge --patch ` will list all commits which caused the merge conflict for ``, and the diff of how they changed the file. * Look at the original files. `git show :1:filename` shows the common ancestor, `git show :2:filename` shows the "ours" version, and `git show :3:filename` shows the "theirs" version. See <> below for more on "ours" and "theirs". Here are some ways to track your progress while handling a conflict: * Use `git status` to get a list of files with conflicts * Use `git diff --check` to make sure you haven't left any merge conflict markers in a file by accident. It will print "leftover conflict marker" if it finds any. * Use `git diff AUTO_MERGE` to show what changes you've made so far to resolve the conflicts. See <> below for more. [[git_status]] EXAMPLE: GIT STATUS OUTPUT -------------------------- When you're in a merge conflict, you can find out what commands to run to handle the conflict by running `git status`. For example, this `git status` output tells you that: * `git rebase --abort` will safely bring your branch back to its original state * you should run `git rebase --continue` when you're done resolving all the conflicts * the conflicts in `fruits.py` haven't been marked as resolved ---- $ git status You are currently rebasing branch 'main' on '58a9fcc'. (fix conflicts and then run "git rebase --continue") (use "git rebase --skip" to skip this patch) (use "git rebase --abort" to check out the original branch) Unmerged paths: (use "git restore --staged ..." to unstage) (use "git add ..." to mark resolution) both modified: fruits.py ---- [[diff3]] DIFF3 ----- By default, Git doesn't include the original code when formatting a merge conflict. To include the original code, you can set the configuration option `merge.conflictstyle` to `diff3`. This extra context can make it much easier to understand what's happening in a merge conflict. Here's an example of what a merge conflict would look like when using `diff3`. There's an extra section (between `|||||||` and `=======`) with the original code. ---- FRUITS = [ "apple", <<<<<<< HEAD "cherry", "mango", ||||||| 1c22e48 "banana", "cherry", "mangoooo", ======= "banana", "mango", >>>>>>> add-fruit "orange", ] ---- With this view, you can see that both sides fixed a spelling mistake in "mango", and each removed one fruit from the list. This makes it more clear how to resolve the merge conflict: since one side removed `banana` and one side removed `cherry`, it would probably make sense to remove both from the list, like this: ---- FRUITS = [ "apple", "mango", "orange", ] ---- [NOTE] `zdiff3` is an alternative to `diff3` that makes the merge conflict shorter by making it more ambiguous. See linkgit:git-config[1] for more. [[ours]] "OURS" AND "THEIRS" ------------------- Sometimes during a merge conflict, Git will use the terms "ours" and "theirs" (or "us" and "them"). For example, `git status` might say that a file was `deleted by us`. "Ours" and "theirs" are both commits: "ours" is the current `HEAD` commit, and "theirs" is the other side being merged. The first part of a merge conflict (between `<<<<<<<` and `=======`) is from the "ours" side, and the second part (between `=======` and `>>>>>>>`) is from the "theirs" side. ---- FRUITS = [ "apple", <<<<<<< HEAD "cherry", <- ours ======= "banana", <- theirs >>>>>>> add-fruit "mango", "orange", ] ---- During a rebase, it can seem "upside down" because the "ours" commit is from the branch you're rebasing on (for instance `main` in `git rebase main`). These terms in Git all mean the same thing when dealing with a merge conflict: * "common ancestor" and "base". The files from this commit are "in stage 1". * "ours", "us", and `HEAD`. The files from this commit are "in stage 2". * "theirs", "them". The files from this commit are "in stage 3". If you're confused about what something like "deleted by us" means, it's often easiest to use some of the tools from <> above to get more context. Finding the commit that deleted the file and seeing why is usually more helpful than trying to abstractly reason through what "us" means. [[automerge]] EXAMPLE OF USING `AUTO_MERGE` ----------------------------- `git diff AUTO_MERGE` will show what changes you've made so far to resolve conflicts. `AUTO_MERGE` is a reference that Git creates during a merge. It contains the result of running the merge algorithm. For example, if we resolved the conflict by adding both "banana" and "cherry" in order, the diff would look like this: ---- FRUITS = [ "apple", -<<<<<<< HEAD - "cherry", -======= "banana", ->>>>>>> add-fruit + "cherry", "mango", "orange", ] ---- [NOTE] `AUTO_MERGE` is only set if you're using the default Git merge algorithm. SEE ALSO -------- linkgit:git-revert[1] linkgit:git-merge[1] linkgit:git-rebase[1] linkgit:git-cherry-pick[1] linkgit:git-pull[1] linkgit:git-diff[1] GIT --- Part of the linkgit:git[1] suite