Documentation/content/collaborating/resolve-conflicts.md

374 lines
11 KiB
Markdown
Raw Normal View History

---
eleventyNavigation:
key: ResolveConflicts
title: Resolve Conflicts
parent: Collaborating
order: 60
---
2022-07-06 23:40:17 -07:00
When collaborating with others on a big project, sometimes it occurs that someone's change conflicts with another change introduced in the meantime (e.g by another person).
2022-07-06 23:40:17 -07:00
First of all: Do not panic! You should be able to resolve merge conflicts with a little time and patience.
While it is a good idea to rebase your branch before creating a pull request, as described in the article on [Pull requests and Git flow](/collaborating/pull-requests-and-git-flow),
sometimes merge conflicts are unavoidable.
2022-07-06 23:40:17 -07:00
This article will explain what to do in case of a merge conflict, and how to resolve it using the command line.
Unfortunately, Forgejo currently does not provide a GUI to resolve conflicts.
An issue in the Gitea upstream repository of Forgejo, [#9014](https://github.com/go-gitea/gitea/issues/9014), requests this feature.
If you want to skip the setup of the examples, you can skip to the sections explaining the resolutions:
- [Resolving the conflict (in files)](#resolving-the-conflict)
- [Resolving the conflict (of deleted files)](#conflict-and-resolution)
2022-07-06 23:40:17 -07:00
## Example of a conflict, and its resolution
2022-07-06 23:40:17 -07:00
To understand the steps to be taken during the resolution of a conflict, let's actually create an example of such a conflict:
### Clone example repository
This example uses Knut's example repository. Let us create a clone of Knut's examples repository for this example:
```shell
git clone git@codeberg.org:knut/examples.git
cd examples
```
2022-07-06 23:40:17 -07:00
We will not change anything on the main branch just now.
2022-07-06 23:40:17 -07:00
### Create a branch with a change
2022-07-06 23:40:17 -07:00
Here, we're creating another branch with our first commit:
```shell
git switch -c add-link-to-readme
```
2022-07-06 23:40:17 -07:00
In the `README.md` file, we change the line
```
An example repository for Codeberg Docs.
```
to
```
An example repository for [Codeberg Docs](https://docs.codeberg.org).
```
2022-07-06 23:40:17 -07:00
Now, we'll add the change to our branch:
```shell
git add README.md
git commit -m "Added link to Codeberg docs in README"
```
2022-07-06 23:40:17 -07:00
We will leave the branch. We won't merge it into `main` just yet.
2022-07-06 23:40:17 -07:00
### Create another branch with a different change
2022-07-06 23:40:17 -07:00
Now, we'll create another branch based on `main`, and edit the `README.md` file in a different way:
```shell
git switch main
git switch -c update-last-sentence-in-readme
```
2022-07-06 23:40:17 -07:00
Again, we'll change the last line, but this time, we'll adjust the text differently, from
```
An example repository for Codeberg Docs.
```
2022-07-06 23:40:17 -07:00
to
```
An example repository to use with the Codeberg Documentation.
```
```shell
git add README.md
git commit -m "Adjusted last sentence in README"
```
We now have two branches with conflicting changes to the same line:
```shell
git switch main
git branch
add-link-to-readme
* main
update-last-sentence-in-readme
```
### Merging the first branch
2022-07-06 23:40:17 -07:00
Now, we want to merge both of the branches into the `main` branch.
2022-07-06 23:40:17 -07:00
First, we merge the branch named `add-link-to-readme`. As this is a simple change to a yet unchanged `main`-branch, there is no conflict.
```shell
git switch main
git merge add-link-to-readme
```
2022-07-06 23:40:17 -07:00
### Attempting to merge the second branch
2022-07-06 23:40:17 -07:00
Let's try to merge the second branch.
```shell
git merge update-last-sentence-in-readme
```
As expected there is a conflict:
```
$ git merge update-last-sentence-in-readme
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.
```
2022-07-06 23:40:17 -07:00
Issuing `git status` shows us that there are unmerged paths.
```
2022-07-06 23:40:17 -07:00
$ git status
On branch main
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: README.md
no changes added to commit (use "git add" and/or "git commit -a")
```
Issuing `git diff` shows the conflict:
```
diff --cc README.md
index 616dc84,088249f..0000000
--- a/README.md
+++ b/README.md
@@@ -1,3 -1,3 +1,7 @@@
![](https://docs.codeberg.org/assets/images/getting-started/knut.svg)
++<<<<<<< HEAD
+An example repository for [Codeberg Docs](https://docs.codeberg.org).
++=======
+ An example repository to use with the Codeberg Documentation.
++>>>>>>> update-last-sentence-in-readme
```
2022-07-06 23:40:17 -07:00
You have to resolve this conflict manually, as Git doesn't know how the resulting line should be.
### Resolving the conflict
2022-07-06 23:40:17 -07:00
Use your favourite text editor to open the file. The editor will show you the conflict. Git actually added the conflict description into the `README.md` file.
The end of the file now looks like this:
```
<<<<<<< HEAD
An example repository for [Codeberg Docs](https://docs.codeberg.org).
=======
An example repository to use with the Codeberg Documentation.
>>>>>>> update-last-sentence-in-readme
```
2022-07-06 23:40:17 -07:00
The conflict description starts with `<<<<<<< HEAD`.
The next line shows you that the current `HEAD` (the last commit on the `main` branch before we ran `git merge update-last-sentence-in-readme`) was:
2022-07-06 23:40:17 -07:00
```
An example repository for [Codeberg Docs](https://docs.codeberg.org).
```
2022-07-06 23:40:17 -07:00
The next line, `=======` seperates the current line from the line proposed in the branch that is to be merged.
```
An example repository to use with the Codeberg Documentation.
```
The last line `>>>>>>> update-last-sentence-in-readme` concludes the conflict description and tells you that the line(s) before are taken from the branch `update-last-sentence-in-readme`.
2022-07-06 23:40:17 -07:00
Use your editor of choice, and change the line to reflect the changes you wish to commit to the repository after the resolution of the conflict.
2022-07-06 23:40:17 -07:00
Remove all other lines, then the file should be in the form that you want to commit to the main branch.
A possible resolution of this conflict could be:
```
An example repository to use with the [Codeberg Documentation](https://docs.codeberg.org).
```
2022-07-06 23:40:17 -07:00
Calling `git diff README.md` shows the new line was added, and the two conflicting lines were removed:
```
diff --cc README.md
index 616dc84,088249f..0000000
--- a/README.md
+++ b/README.md
@@@ -1,3 -1,3 +1,3 @@@
![](https://docs.codeberg.org/assets/images/getting-started/knut.svg)
- An example repository for [Codeberg Docs](https://docs.codeberg.org).
- An example repository to use with the Codeberg Documentation.
++An example repository to use with the [Codeberg Documentation](https://docs.codeberg.org).
```
2022-07-06 23:40:17 -07:00
You can now mark the conflict as resolved, by calling `git add README.md`.
If you have more than one conflict in one or more files, repeat the resolution process until all conflicts are resolved.
2022-07-06 23:40:17 -07:00
Make sure not to leave any lines starting with `<<<<<<<`, `=======`, and `>>>>>>>`, as Git no longer knows that these are special and will treat them as normal text.
2022-07-06 23:40:17 -07:00
Issuing `git commit` without any comment will open the default editor, and lets you edit a commit message for the merge commit.
Closing the editor will complete the resolution of the merge conflict.
2022-07-06 23:40:17 -07:00
> `git log` shows you both the original commit that lead to the conflict and the merge commit.
2022-07-06 23:40:17 -07:00
For example:
```
commit c10f2c3338979149d7c6fcb815a2072743b5bde6 (HEAD -> main)
Merge: 5e2cebd 7b5bf4f
Author: Knut <knut@...>
Date: Sat May 21 19:44:43 2022 +0200
Merge branch 'update-last-sentence-in-readme' into main
commit 7b5bf4f0fe2213ded938bc9de313f4cd3d9043db (update-last-sentence-in-readme)
Author: Knut <knut@...>
Date: Sat May 21 18:38:16 2022 +0200
Adjusted last sentence in README
commit 5e2cebd523754b655d1990fb48dbb7b973f07dfa (add-link-to-readme)
Author: Knut <knut@...>
Date: Sat May 21 18:29:15 2022 +0200
Added link to Codeberg docs to README
```
2022-07-06 23:40:17 -07:00
Note the line starting with `Merge`; it includes the commit IDs of the two merged commits.
## Removed files
2022-07-06 23:40:17 -07:00
Let's create another conflict.
2022-07-06 23:40:17 -07:00
We'll start again at the `main` branch. If you didn't work through the example above, you can jumpstart the environment for this example with these commands:
```shell
git clone git@codeberg.org:knut/examples.git
cd examples
```
2022-07-06 23:40:17 -07:00
If you're still on another branch from the last example, make sure that you start this example on the `main` branch, by running `git switch main`.
### Removing a file
2022-07-06 23:40:17 -07:00
Again, we'll create a new branch.
```shell
git switch -c remove-README-file
```
2022-07-06 23:40:17 -07:00
This time, we'll remove the `README.md` file.
```shell
git rm README.md
git commit -m "removed README.md"
```
2022-07-06 23:40:17 -07:00
We won't merge this branch yet.
### Editing the file
First switch back to the main branch.
```shell
git switch main
```
On second branch we add a line to the end of the `README.md` file.
```shell
git switch -c adapt-README-file
echo "You can find this repository in the Forgejo Web GUI at https://codeberg.org/knut/examples" >> README.md
git add README.md
git commit -m "added repository url to README.md"
```
### Merging the first branch
2022-07-06 23:40:17 -07:00
Again, switch back to the main branch.
```shell
git switch main
```
2022-07-06 23:40:17 -07:00
Merging the first branch does not lead to a conflict, because the `main` branch didn't change since the branch `remove-README-file` was created.
```shell
git merge remove-README-file
```
### Conflict and resolution
2022-07-06 23:40:17 -07:00
When we try to merge the second branch `adapt-README-file`, we get a conflict because the file we are trying to change, `README.md` was removed by our previous merge.
```shell
$ git merge adapt-README-file
CONFLICT (modify/delete): README.md deleted in HEAD and modified in adapt-README-file. Version adapt-README-file of README.md left in tree.
Automatic merge failed; fix conflicts and then commit the result.
```
2022-07-06 23:40:17 -07:00
`git status` also shows the conflict:
2022-07-06 23:40:17 -07:00
```shell
$ git status
On branch main
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add/rm <file>..." as appropriate to mark resolution)
deleted by us: README.md
no changes added to commit (use "git add" and/or "git commit -a")
```
You now have two choices:
2022-07-06 23:40:17 -07:00
- Keep the current status and remove the README.md file
- Re-introduce the README.md file into the `main` branch.
To keep the current status and remove the README.md file, you must tell Git once more to remove it:
```shell
git rm README.md
```
2022-07-06 23:40:17 -07:00
To re-introduce the README.md file, simply add it again:
```shell
git add README.md
```
2022-07-06 23:40:17 -07:00
Use `git commit` if you've resolved all conflicts (in this case it was only one).
2022-07-06 23:40:17 -07:00
As with before, issuing `git commit` without any comment will open your default editor, and ask you to provide a commit message for the merge commit.
## Tips
- Try to avoid using `git push -f` on the target branch.
2022-07-06 23:40:17 -07:00
- Ensure that all branches are pushed to a remote repository before trying to resolve a conflict, as it makes it easier to start over in case you run into a problem.
- Search for `<<<<<<<`, `=======` and `>>>>>>>` in the resolved files, in order to not leave a conflict description in your files.