git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2 0/2] checkout -m: recreate conflict labels

From
PWPhillip Wood <phillip.wood123@gmail.com>
Date
Oct 5, 2026, 13:24 UTC
Message-ID
<cover.1791206658.git.phillip.wood@dunelm.org.uk>
In-Reply-To
<cover.1790761727.git.phillip.wood@dunelm.org.uk>

When "git checkout -m <path>" recreates a merge conflict, it uses the labels "base", "ours", "theirs", rather than the labels used by the original merge. This short series teaches the ort machinery to write the labels to ".git/MERGE_LABELS" when it switches to a merge result containing conflicts, so that "git checkout -m" can then read that file and use the same labels.

As "git checkout -m" is recreating the original conflict I wonder if we should remember the conflict style as well so that

    git -c merge.conflictStyle=diff3 git merge topic
    git checkout -m <unmerged-path>

would recreate diff3 style conflicts, instead of using the default config. I cannot decide if that would be convenient or confusing and am interested to hear what others think.

Changes since V1:
 - use strbuf_getline() rather than strbuf_read_file() to read labels
   so that the newline handling of the reading and writing sides match.

NB ".git/MERGE_LABELS" is still undocumented - I'm hoping to find time to add some documentation for all the MERGE_* files in a future series. Johannes suggested using an index extension to store the labels, but as we already have MERGE_MODE, MERGE_RR and MERGE_MSG I think it is easier just to add another file.

base-commit: 3bc0341126508f78f5869cbfc0005e987efdf0c7
Published-As: https://github.com/phillipwood/git/releases/tag/pw%2Fconflict-labels%2Fv2
View-Changes-At: https://github.com/phillipwood/git/compare/3bc034112...18bdf7df4
Fetch-It-Via: git fetch https://github.com/phillipwood/git pw/conflict-labels/v2
Phillip Wood (2):
  remove_branch_state: convert boolean argument to flags
  merge: remember conflict labels
 branch.c           | 17 ++++++++----
 branch.h           |  4 ++-
 builtin/checkout.c | 30 ++++++++++++++++++----
 builtin/commit.c   |  1 +
 merge-ort.c        | 19 ++++++++++++++
 merge.c            | 64 ++++++++++++++++++++++++++++++++++++++++++++++
 merge.h            |  4 +++
 path.c             |  1 +
 path.h             |  1 +
 repository.c       |  1 +
 repository.h       |  1 +
 sequencer.c        |  1 +
 t/t7201-co.sh      | 21 +++++++++++++++
 13 files changed, 154 insertions(+), 11 deletions(-)
Range-diff against v1:
1:  86ef0f848a = 1:  86ef0f848a remove_branch_state: convert boolean argument to flags
2:  fdaf3da993 ! 2:  18bdf7df49 merge: remember conflict labels
    @@ merge.c: int checkout_fast_forward(struct repository *r,
     +	return 0;
     +}
     +
    -+static int parse_merge_label_line(const char **p, char **line)
    ++static char *parse_merge_label_line(struct strbuf *buf, FILE *fp)
     +{
    -+	const char *eol = strchr(*p, '\n');
    -+
    -+	if (!eol)
    -+		return -1;
    -+
    -+	*line = xmemdupz(*p, eol - *p);
    -+	*p = eol + 1;
    -+
    -+	return 0;
    ++	if (strbuf_getline(buf, fp) == EOF)
    ++		return NULL;
    ++
    ++	return xmemdupz(buf->buf, buf->len);
     +}
     +
     +int read_merge_labels(struct repository *r,
     +		      char **pbase, char** pours, char** ptheirs)
     +{
     +	struct strbuf buf = STRBUF_INIT;
    -+	const char *p;
     +	char *base = NULL, *ours = NULL, *theirs = NULL;
     +	int ret = -1;
    ++	FILE *fp = fopen(git_path_merge_labels(r), "r");
     +
    -+	if (strbuf_read_file(&buf, git_path_merge_labels(r), 0) < 0)
    ++	if (!fp)
     +		return -1;
     +
    -+	p = buf.buf;
    -+	if (parse_merge_label_line(&p, &base))
    -+		goto out;
    -+	if (parse_merge_label_line(&p, &ours))
    -+		goto out;
    -+	if (parse_merge_label_line(&p, &theirs))
    -+		goto out;
    ++	base = parse_merge_label_line(&buf, fp);
    ++	if (!base)
    ++		goto out;
    ++
    ++	ours = parse_merge_label_line(&buf, fp);
    ++	if (!ours)
    ++		goto out;
    ++
    ++	theirs = parse_merge_label_line(&buf, fp);
    ++	if (!theirs)
    ++		goto out;
    ++
     +	ret = 0;
     +	*pbase = base;
     +	*pours = ours;
    @@ merge.c: int checkout_fast_forward(struct repository *r,
     +		free(ours);
     +		free(theirs);
     +	}
    ++	fclose(fp);
     +	strbuf_release(&buf);
     +
     +	return ret;
-- 
2.56.0.134.g299a3c16181
Previous: Phillip WoodNext: Phillip Wood
Message 11 of 27 in “checkout -m: recreate conflict labels”
  1. 0/2 checkout -m: recreate conflict labelsPhillip Wood, Sep 30, 2026
  2. 1/2 remove_branch_state: convert boolean argument to flagsPhillip Wood, Sep 30, 2026
  3. 2/2 merge: remember conflict labelsPhillip Wood, Sep 30, 2026
  4. Junio C HamanoSep 30, 2026
  5. Phillip WoodOct 1, 2026
  6. Junio C HamanoOct 1, 2026
  7. Johannes SixtSep 30, 2026
  8. Junio C HamanoSep 30, 2026
  9. Johannes SixtSep 30, 2026
  10. Phillip WoodOct 1, 2026
  11. 0/2 checkout -m: recreate conflict labelsPhillip Wood, Oct 5, 2026
  12. 1/2 remove_branch_state: convert boolean argument to flagsPhillip Wood, Oct 5, 2026
  13. 2/2 merge: remember conflict labelsPhillip Wood, Oct 5, 2026
  14. Junio C HamanoOct 5, 2026
  15. Phillip WoodOct 6, 2026
  16. Junio C HamanoOct 5, 2026
  17. Phillip WoodOct 6, 2026
  18. Junio C HamanoOct 6, 2026
  19. Phillip WoodOct 7, 2026
  20. Johannes SixtOct 5, 2026
  21. Phillip WoodOct 5, 2026
  22. Junio C HamanoOct 5, 2026
  23. 0/2 checkout -m: recreate conflict labelsPhillip Wood, Oct 9, 2026
  24. 1/2 remove_branch_state: convert boolean argument to flagsPhillip Wood, Oct 9, 2026
  25. 2/2 merge: remember conflict labelsPhillip Wood, Oct 9, 2026
  26. Junio C HamanoOct 10, 2026
  27. Junio C HamanoOct 9, 2026

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.