just playing with tangled
1# First-class conflicts
2
3
4## Introduction
5
6Conflicts happen when Jujutsu can't figure out how to merge different changes
7made to the same file. For instance, this can happen if two people are working
8on the same file and make different changes to the same part of the file, and
9then their commits are merged together with `jj new` (or one is rebased onto the
10other with `jj rebase`).
11
12Unlike most other VCSs, Jujutsu can record conflicted states in commits. For
13example, if you rebase a commit and it results in a conflict, the conflict will
14be recorded in the rebased commit and the rebase operation will succeed. You can
15then resolve the conflict whenever you want. Conflicted states can be further
16rebased, merged, or backed out. Note that what's stored in the commit is a
17logical representation of the conflict, not conflict *markers*; rebasing a
18conflict doesn't result in a nested conflict markers (see
19[technical doc](technical/conflicts.md) for how this works).
20
21
22## Advantages
23
24The deeper understanding of conflicts has many advantages:
25
26* Removes the need for things like
27 `git rebase/merge/cherry-pick/etc --continue`. Instead, you get a single
28 workflow for resolving conflicts: check out the conflicted commit, resolve
29 conflicts, and amend.
30* Enables the "auto-rebase" feature, where descendants of rewritten commits
31 automatically get rewritten. This feature mostly replaces Mercurial's
32 [Changeset Evolution](https://www.mercurial-scm.org/wiki/ChangesetEvolution).
33* Lets us define the change in a merge commit as being compared to the merged
34 parents. That way, we can rebase merge commits correctly (unlike both Git and
35 Mercurial). That includes conflict resolutions done in the merge commit,
36 addressing a common use case for
37 [git rerere](https://git-scm.com/docs/git-rerere).
38 Since the changes in a merge commit are displayed and rebased as expected,
39 [evil merges](https://git-scm.com/docs/gitglossary/2.22.0#Documentation/gitglossary.txt-aiddefevilmergeaevilmerge)
40 are arguably not as evil anymore.
41* Allows you to postpone conflict resolution until you're ready for it. You
42 can easily keep all your work-in-progress commits rebased onto upstream's head
43 if you like.
44* [Criss-cross merges](https://stackoverflow.com/questions/26370185/how-do-criss-cross-merges-arise-in-git)
45 and [octopus merges](https://git-scm.com/docs/git-merge#Documentation/git-merge.txt-octopus)
46 become trivial (implementation-wise); some cases that Git can't currently
47 handle, or that would result in nested conflict markers, can be automatically
48 resolved.
49* Enables collaborative conflict resolution. (This assumes that you can share
50 the conflicts with others, which you probably shouldn't do if some people
51 interact with your project using Git.)
52
53For information about how conflicts are handled in the working copy, see
54[here](working-copy.md#conflicts).
55
56
57## Conflict markers
58
59Conflicts are "materialized" using *conflict markers* in various contexts. For
60example, when you run `jj new` or `jj edit` on a commit with a conflict, it will
61be materialized in the working copy. Conflicts are also materialized when they
62are part of diff output (e.g. `jj show` on a commit that introduces or resolves
63a conflict).
64
65As an example, imagine that you have a file which contains the following text,
66all in lowercase:
67
68```text
69apple
70grape
71orange
72```
73
74One person replaces the word "grape" with "grapefruit" in commit A, while
75another person changes every line to uppercase in commit B. If you merge the
76changes together with `jj new A B`, the resulting commit will have a conflict
77since Jujutsu can't figure out how to combine these changes. Therefore, Jujutsu
78will materialize the conflict in the working copy using conflict markers, which
79would look like this:
80
81```text
82<<<<<<< Conflict 1 of 1
83%%%%%%% Changes from base to side #1
84 apple
85-grape
86+grapefruit
87 orange
88+++++++ Contents of side #2
89APPLE
90GRAPE
91ORANGE
92>>>>>>> Conflict 1 of 1 ends
93```
94
95The markers `<<<<<<<` and `>>>>>>>` indicate the start and end of a conflict
96respectively. The marker `+++++++` indicates the start of a snapshot, while the
97marker `%%%%%%%` indicates the start of a diff to apply to the snapshot.
98Therefore, to resolve this conflict, you would apply the diff (changing "grape"
99to "grapefruit") to the snapshot (the side with every line in uppercase),
100editing the file to look like this:
101
102```text
103APPLE
104GRAPEFRUIT
105ORANGE
106```
107
108In practice, conflicts are usually 2-sided, meaning that there's only 2
109conflicting changes being merged together at a time, but Jujutsu supports
110conflicts with arbitrarily many sides, which can happen when merging 3 or more
111commits at once. In that case, you would see a single snapshot section and
112multiple diff sections.
113
114Compared to just showing the content of each side of the conflict, the main
115benefit of Jujutsu's style of conflict markers is that you don't need to spend
116time manually comparing the sides to spot the differences between them. This is
117especially beneficial for many-sided conflicts, since resolving them just
118requires applying each diff to the snapshot one-by-one.
119
120## Alternative conflict marker styles
121
122If you prefer to just see the contents of each side of the conflict without the
123diff, Jujutsu also supports a "snapshot" style, which can be enabled by setting
124the `ui.conflict-marker-style` config option to "snapshot":
125
126```text
127<<<<<<< Conflict 1 of 1
128+++++++ Contents of side #1
129apple
130grapefruit
131orange
132------- Contents of base
133apple
134grape
135orange
136+++++++ Contents of side #2
137APPLE
138GRAPE
139ORANGE
140>>>>>>> Conflict 1 of 1 ends
141```
142
143Some tools expect Git-style conflict markers, so Jujutsu also supports [Git's
144"diff3" style](https://git-scm.com/docs/git-merge#_how_conflicts_are_presented)
145conflict markers by setting the `ui.conflict-marker-style` config option to
146"git":
147
148```text
149<<<<<<< Side #1 (Conflict 1 of 1)
150apple
151grapefruit
152orange
153||||||| Base
154apple
155grape
156orange
157=======
158APPLE
159GRAPE
160ORANGE
161>>>>>>> Side #2 (Conflict 1 of 1 ends)
162```
163
164This conflict marker style only supports 2-sided conflicts though, so it falls
165back to the similar "snapshot" conflict markers if there are more than 2 sides
166to the conflict.
167
168## Long conflict markers
169
170Some files may contain lines which could be confused for conflict markers. For
171instance, a line could start with `=======`, which looks like a Git-style
172conflict marker. To ensure that it's always unambiguous which lines are conflict
173markers and which are just part of the file contents, `jj` sometimes uses
174conflict markers which are longer than normal:
175
176```text
177<<<<<<<<<<<<<<< Conflict 1 of 1
178%%%%%%%%%%%%%%% Changes from base to side #1
179-Heading
180+HEADING
181 =======
182+++++++++++++++ Contents of side #2
183New Heading
184===========
185>>>>>>>>>>>>>>> Conflict 1 of 1 ends
186```
187
188## Conflicts with missing terminating newline
189
190When materializing conflicts, `jj` outputs them in a line-based format. This
191format is easiest to interpret for text files that consist of a series of lines,
192with each line terminated by a newline character (`\n`). This means that a text
193file should either be empty, or it should end with a newline character.
194
195While most text files follow this convention, some do not. When `jj` encounters
196a missing terminating newline character in a conflict, it will add a comment to
197the conflict markers to make the conflict easier to interpret. If you don't care
198about whether your file ends with a terminating newline character, you can
199generally ignore this comment and resolve the conflict normally.
200
201For instance, if a file originally contained `grape` with no terminating newline
202character, and one person changed `grape` to `grapefruit`, while another person
203added the missing newline character to make `grape\n`, the resulting conflict
204would look like this:
205
206```text
207<<<<<<< Conflict 1 of 1
208+++++++ Contents of side #1 (no terminating newline)
209grapefruit
210%%%%%%% Changes from base to side #2 (adds terminating newline)
211-grape
212+grape
213>>>>>>> Conflict 1 of 1 ends
214```
215
216Therefore, a resolution of this conflict could be `grapefruit\n`, with the
217terminating newline character added.