git@vger.kernel.org list mirror (unofficial, one of many)
 help / color / Atom feed
From: Johannes Schindelin <Johannes.Schindelin@gmx.de>
To: Thomas Gummerer <t.gummerer@gmail.com>
Cc: Johannes Schindelin via GitGitGadget <gitgitgadget@gmail.com>,
	git@vger.kernel.org, Junio C Hamano <gitster@pobox.com>
Subject: Re: [PATCH v4 03/21] range-diff: first rudimentary implementation
Date: Mon, 30 Jul 2018 18:21:29 +0200 (DST)
Message-ID: <nycvar.QRO.7.76.6.1807301759340.10478@tvgsbejvaqbjf.bet> (raw)
In-Reply-To: <20180729183629.GC2734@hank.intra.tgummerer.com>

Hi Thomas,

On Sun, 29 Jul 2018, Thomas Gummerer wrote:

> On 07/21, Johannes Schindelin via GitGitGadget wrote:
> > From: Johannes Schindelin <johannes.schindelin@gmx.de>
> > 
> > At this stage, `git range-diff` can determine corresponding commits
> > of two related commit ranges. This makes use of the recently introduced
> > implementation of the linear assignment algorithm.
> > 
> > The core of this patch is a straight port of the ideas of tbdiff, the
> > apparently dormant project at https://github.com/trast/tbdiff.
> > 
> > The output does not at all match `tbdiff`'s output yet, as this patch
> > really concentrates on getting the patch matching part right.
> > 
> > Note: due to differences in the diff algorithm (`tbdiff` uses the Python
> > module `difflib`, Git uses its xdiff fork), the cost matrix calculated
> > by `range-diff` is different (but very similar) to the one calculated
> > by `tbdiff`. Therefore, it is possible that they find different matching
> > commits in corner cases (e.g. when a patch was split into two patches of
> > roughly equal length).
> > 
> > Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> > ---
> >  Makefile             |   1 +
> >  builtin/range-diff.c |  43 +++++-
> >  range-diff.c         | 311 +++++++++++++++++++++++++++++++++++++++++++
> >  range-diff.h         |   7 +
> >  4 files changed, 361 insertions(+), 1 deletion(-)
> >  create mode 100644 range-diff.c
> >  create mode 100644 range-diff.h
> >
> > [...]
> > 
> > diff --git a/range-diff.c b/range-diff.c
> > new file mode 100644
> > index 000000000..15d418afa
> > --- /dev/null
> > +++ b/range-diff.c
> > @@ -0,0 +1,311 @@
> > +#include "cache.h"
> > +#include "range-diff.h"
> > +#include "string-list.h"
> > +#include "run-command.h"
> > +#include "argv-array.h"
> > +#include "hashmap.h"
> > +#include "xdiff-interface.h"
> > +#include "linear-assignment.h"
> > +
> > +struct patch_util {
> > +	/* For the search for an exact match */
> > +	struct hashmap_entry e;
> > +	const char *diff, *patch;
> > +
> > +	int i;
> > +	int diffsize;
> > +	size_t diff_offset;
> > +	/* the index of the matching item in the other branch, or -1 */
> > +	int matching;
> > +	struct object_id oid;
> > +};
> > +
> > +/*
> > + * Reads the patches into a string list, with the `util` field being populated
> > + * as struct object_id (will need to be free()d).
> > + */
> > +static int read_patches(const char *range, struct string_list *list)
> > +{
> > +	struct child_process cp = CHILD_PROCESS_INIT;
> > +	FILE *in;
> > +	struct strbuf buf = STRBUF_INIT, line = STRBUF_INIT;
> > +	struct patch_util *util = NULL;
> > +	int in_header = 1;
> > +
> > +	argv_array_pushl(&cp.args, "log", "--no-color", "-p", "--no-merges",
> > +			"--reverse", "--date-order", "--decorate=no",
> > +			"--no-abbrev-commit", range,
> > +			NULL);
> 
> Compared to tbdiff, add "--decorate=no", and "--no-abbrev-commit".  I
> see we're abbreviating the commit hashes later.  We don't want ref
> names here, so "--decorate=no" makes sense as well.

Indeed. Compare also to https://github.com/trast/tbdiff/pull/8

> > +	cp.out = -1;
> > +	cp.no_stdin = 1;
> > +	cp.git_cmd = 1;
> > +
> > +	if (start_command(&cp))
> > +		return error_errno(_("could not start `log`"));
> > +	in = fdopen(cp.out, "r");
> > +	if (!in) {
> > +		error_errno(_("could not read `log` output"));
> > +		finish_command(&cp);
> > +		return -1;
> > +	}
> > +
> > +	while (strbuf_getline(&line, in) != EOF) {
> > +		const char *p;
> > +
> > +		if (skip_prefix(line.buf, "commit ", &p)) {
> > +			if (util) {
> > +				string_list_append(list, buf.buf)->util = util;
> > +				strbuf_reset(&buf);
> > +			}
> > +			util = xcalloc(sizeof(*util), 1);
> > +			if (get_oid(p, &util->oid)) {
> > +				error(_("could not parse commit '%s'"), p);
> > +				free(util);
> > +				string_list_clear(list, 1);
> > +				strbuf_release(&buf);
> > +				strbuf_release(&line);
> > +				fclose(in);
> > +				finish_command(&cp);
> > +				return -1;
> > +			}
> > +			util->matching = -1;
> > +			in_header = 1;
> > +			continue;
> > +		}
> > +
> > +		if (starts_with(line.buf, "diff --git")) {
> > +			in_header = 0;
> > +			strbuf_addch(&buf, '\n');
> > +			if (!util->diff_offset)
> > +				util->diff_offset = buf.len;
> > +			strbuf_addbuf(&buf, &line);
> > +		} else if (in_header) {
> > +			if (starts_with(line.buf, "Author: ")) {
> > +				strbuf_addbuf(&buf, &line);
> > +				strbuf_addstr(&buf, "\n\n");
> > +			} else if (starts_with(line.buf, "    ")) {
> > +				strbuf_addbuf(&buf, &line);
> > +				strbuf_addch(&buf, '\n');
> > +			}
> > +			continue;
> > +		} else if (starts_with(line.buf, "@@ "))
> > +			strbuf_addstr(&buf, "@@");
> > +		else if (!line.buf[0] || starts_with(line.buf, "index "))
> > +			/*
> > +			 * A completely blank (not ' \n', which is context)
> > +			 * line is not valid in a diff.  We skip it
> > +			 * silently, because this neatly handles the blank
> > +			 * separator line between commits in git-log
> > +			 * output.
> > +			 *
> > +			 * We also want to ignore the diff's `index` lines
> > +			 * because they contain exact blob hashes in which
> > +			 * we are not interested.
> > +			 */
> > +			continue;
> > +		else
> > +			strbuf_addbuf(&buf, &line);
> > +
> > +		strbuf_addch(&buf, '\n');
> > +		util->diffsize++;
> > +	}
> 
> This seems to differ from tbdiff in the number of newlines we're
> adding in various places, however I think as long as it's consistent
> in itself, and with the way we're printing the output the differences
> shouldn't matter.

Right.

> > +	fclose(in);
> > +	strbuf_release(&line);
> > +
> > +	if (util)
> > +		string_list_append(list, buf.buf)->util = util;
> > +	strbuf_release(&buf);
> > +
> > +	if (finish_command(&cp))
> > +		return -1;
> > +
> > +	return 0;
> > +}
> > +
> > +static int patch_util_cmp(const void *dummy, const struct patch_util *a,
> > +		     const struct patch_util *b, const char *keydata)
> > +{
> > +	return strcmp(a->diff, keydata ? keydata : b->diff);
> > +}
> > +
> > +static void find_exact_matches(struct string_list *a, struct string_list *b)
> > +{
> > +	struct hashmap map;
> > +	int i;
> > +
> > +	hashmap_init(&map, (hashmap_cmp_fn)patch_util_cmp, NULL, 0);
> > +
> > +	/* First, add the patches of a to a hash map */
> > +	for (i = 0; i < a->nr; i++) {
> > +		struct patch_util *util = a->items[i].util;
> > +
> > +		util->i = i;
> > +		util->patch = a->items[i].string;
> > +		util->diff = util->patch + util->diff_offset;
> > +		hashmap_entry_init(util, strhash(util->diff));
> > +		hashmap_add(&map, util);
> > +	}
> > +
> > +	/* Now try to find exact matches in b */
> > +	for (i = 0; i < b->nr; i++) {
> > +		struct patch_util *util = b->items[i].util, *other;
> > +
> > +		util->i = i;
> > +		util->patch = b->items[i].string;
> > +		util->diff = util->patch + util->diff_offset;
> > +		hashmap_entry_init(util, strhash(util->diff));
> > +		other = hashmap_remove(&map, util, NULL);
> > +		if (other) {
> > +			if (other->matching >= 0)
> > +				BUG("already assigned!");
> > +
> > +			other->matching = i;
> > +			util->matching = other->i;
> > +		}
> > +	}
> 
> One possibly interesting corner case here is what happens when there
> are two patches that have the exact same diff, for example in the
> pathological case of commit A doing something, commit B reverting
> commit A, and then commit C reverting commit B, so it ends up with the
> same diff.
> 
> Having those same commits unchanged in both ranges (e.g. if a commit
> earlier in the range has been changed, and range B has been rebased on
> top of that), we'd get the following mapping from range A to range B
> for the commits in question:
> 
> A -> C
> B -> B
> C -> A
> 
> Which is not quite what I would expect as the user (even though it is
> a valid mapping, and it probably doesn't matter too much for the end
> result of the range diff, as nothing has changed between the commits
> anyway).  So I'm not sure it's worth fixing this, as it is a
> pathological case, and nothing really breaks.

Indeed. As far as I am concerned, this falls squarely into the "let's
cross that bridge when, or if, we reach it" category.

> > +
> > +	hashmap_free(&map, 0);
> > +}
> > +
> > +static void diffsize_consume(void *data, char *line, unsigned long len)
> > +{
> > +	(*(int *)data)++;
> > +}
> > +
> > +static int diffsize(const char *a, const char *b)
> > +{
> > +	xpparam_t pp = { 0 };
> > +	xdemitconf_t cfg = { 0 };
> > +	mmfile_t mf1, mf2;
> > +	int count = 0;
> > +
> > +	mf1.ptr = (char *)a;
> > +	mf1.size = strlen(a);
> > +	mf2.ptr = (char *)b;
> > +	mf2.size = strlen(b);
> > +
> > +	cfg.ctxlen = 3;
> > +	if (!xdi_diff_outf(&mf1, &mf2, diffsize_consume, &count, &pp, &cfg))
> > +		return count;
> > +
> > +	error(_("failed to generate diff"));
> > +	return COST_MAX;
> > +}
> > +
> > +static void get_correspondences(struct string_list *a, struct string_list *b,
> > +				int creation_factor)
> > +{
> > +	int n = a->nr + b->nr;
> > +	int *cost, c, *a2b, *b2a;
> > +	int i, j;
> > +
> > +	ALLOC_ARRAY(cost, st_mult(n, n));
> > +	ALLOC_ARRAY(a2b, n);
> > +	ALLOC_ARRAY(b2a, n);
> > +
> > +	for (i = 0; i < a->nr; i++) {
> > +		struct patch_util *a_util = a->items[i].util;
> > +
> > +		for (j = 0; j < b->nr; j++) {
> > +			struct patch_util *b_util = b->items[j].util;
> > +
> > +			if (a_util->matching == j)
> > +				c = 0;
> > +			else if (a_util->matching < 0 && b_util->matching < 0)
> > +				c = diffsize(a_util->diff, b_util->diff);
> > +			else
> > +				c = COST_MAX;
> > +			cost[i + n * j] = c;
> > +		}
> > +
> > +		c = a_util->matching < 0 ?
> > +			a_util->diffsize * creation_factor / 100 : COST_MAX;
> > +		for (j = b->nr; j < n; j++)
> > +			cost[i + n * j] = c;
> > +	}
> > +
> > +	for (j = 0; j < b->nr; j++) {
> > +		struct patch_util *util = b->items[j].util;
> > +
> > +		c = util->matching < 0 ?
> > +			util->diffsize * creation_factor / 100 : COST_MAX;
> > +		for (i = a->nr; i < n; i++)
> > +			cost[i + n * j] = c;
> > +	}
> > +
> > +	for (i = a->nr; i < n; i++)
> > +		for (j = b->nr; j < n; j++)
> > +			cost[i + n * j] = 0;
> > +
> > +	compute_assignment(n, n, cost, a2b, b2a);
> > +
> > +	for (i = 0; i < a->nr; i++)
> > +		if (a2b[i] >= 0 && a2b[i] < b->nr) {
> > +			struct patch_util *a_util = a->items[i].util;
> > +			struct patch_util *b_util = b->items[a2b[i]].util;
> > +
> > +			a_util->matching = a2b[i];
> > +			b_util->matching = i;
> 
> So here we re-assign 'matching' in the struct regardless of whether it
> was assigned before while searching for exact matches or not.

If `matching` were assigned here, it would indicate a bug in the code, I
think. Before this loop, all of the `matching` fields should be `NULL`,
and the `compute_assignment()` function is expected to populate `a2b` and
`b2a` appropriately, i.e. no "double booking".

> Shouldn't diffsize for matching patches also be 0?  So are we doing
> the 'find_exact_matches()' bit only as an optimization, or am I
> missing some other reason why that is beneficial?

An optimization.

Remember, the linear assignment algorithm runs in O(n^3). That's not a
laughing matter by any stretch of imagination. The more stuff we can get
out of the way, as quickly as possible, the less it hurts to have a cubic
runtime complexity.

> > +		}
> > +
> > +	free(cost);
> > +	free(a2b);
> > +	free(b2a);
> > +}
> > +
> > +static const char *short_oid(struct patch_util *util)
> > +{
> > +	return find_unique_abbrev(&util->oid, DEFAULT_ABBREV);
> > +}
> > +
> > +static void output(struct string_list *a, struct string_list *b)
> > +{
> > +	int i;
> > +
> > +	for (i = 0; i < b->nr; i++) {
> > +		struct patch_util *util = b->items[i].util, *prev;
> > +
> > +		if (util->matching < 0)
> > +			printf("-: -------- > %d: %s\n",
> > +					i + 1, short_oid(util));
> > +		else {
> > +			prev = a->items[util->matching].util;
> > +			printf("%d: %s ! %d: %s\n",
> > +			       util->matching + 1, short_oid(prev),
> > +			       i + 1, short_oid(util));
> > +		}
> > +	}
> > +
> > +	for (i = 0; i < a->nr; i++) {
> > +		struct patch_util *util = a->items[i].util;
> > +
> > +		if (util->matching < 0)
> > +			printf("%d: %s < -: --------\n",
> > +			       i + 1, short_oid(util));
> > +	}
> > +}
> > +
> > +int show_range_diff(const char *range1, const char *range2,
> > +		    int creation_factor)
> > +{
> > +	int res = 0;
> > +
> > +	struct string_list branch1 = STRING_LIST_INIT_DUP;
> > +	struct string_list branch2 = STRING_LIST_INIT_DUP;
> > +
> > +	if (read_patches(range1, &branch1))
> > +		res = error(_("could not parse log for '%s'"), range1);
> > +	if (!res && read_patches(range2, &branch2))
> > +		res = error(_("could not parse log for '%s'"), range2);
> > +
> > +	if (!res) {
> > +		find_exact_matches(&branch1, &branch2);
> 
> Note to self: here we assign the matching member of struct patch_util
> for each patch in both ranges to a patch number in the other range if
> it is an exact match.
> 
> We also assign the patch and diff members, and number the patches
> using the 'i' member of struct patch_util.  Let's see if that
> numbering is still useful later.
> 
> > +		get_correspondences(&branch1, &branch2, creation_factor);
> 
> And here we use the linear assignment algorithm to match the rest of
> the commits.
> 
> > +		output(&branch1, &branch2);
> 
> And finally we print the output.  We don't seem to use the util->i
> that's assigned for range b (or range 2) anywhere at the moment, which
> I was wondering about earlier, so I assume it's there mainly for
> symmetry, but it doesn't really hurt other than me wondering what it
> was for.

It's there because it would require extra care to do it only for one side.

> > +	}
> > +
> > +	string_list_clear(&branch1, 1);
> > +	string_list_clear(&branch2, 1);
> > +
> > +	return res;
> > +}
> > diff --git a/range-diff.h b/range-diff.h
> > new file mode 100644
> > index 000000000..dd30449c4
> > --- /dev/null
> > +++ b/range-diff.h
> > @@ -0,0 +1,7 @@
> > +#ifndef BRANCH_DIFF_H
> > +#define BRANCH_DIFF_H
> 
> s/BRANCH/RANGE/ above?

Good eyes.

Thank you for your review. It is nice to see that you can follow the code
and come to the same conclusions as I. Can I always have you as reviewer?

Ciao,
Dscho

> > +int show_range_diff(const char *range1, const char *range2,
> > +		    int creation_factor);
> > +
> > +#endif
> > -- 
> > gitgitgadget
> > 
> 

  reply index

Thread overview: 387+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-05-03 15:30 [PATCH 00/18] Add `branch-diff`, a `tbdiff` lookalike Johannes Schindelin
2018-05-03 15:30 ` [PATCH 01/18] Add a function to solve least-cost assignment problems Johannes Schindelin
2018-05-13 18:19   ` Duy Nguyen
2018-05-21  9:52     ` Johannes Schindelin
2018-05-03 15:30 ` [PATCH 02/18] Add a new builtin: branch-diff Johannes Schindelin
2018-05-03 16:10   ` Ramsay Jones
2018-05-03 20:25     ` Johannes Schindelin
2018-05-03 23:20       ` Ramsay Jones
2018-05-04  6:40         ` Johannes Schindelin
2018-05-04 15:37           ` Ramsay Jones
2018-05-05 19:41             ` Johannes Schindelin
2018-05-09 16:24               ` Ramsay Jones
2018-06-01  8:23                 ` Johannes Schindelin
2018-05-04 16:34           ` Elijah Newren
2018-05-05 20:24             ` Johannes Schindelin
2018-05-03 16:41   ` Duy Nguyen
2018-05-03 20:30     ` Johannes Schindelin
2018-05-03 20:32       ` Johannes Schindelin
2018-05-04  5:15         ` Duy Nguyen
2018-05-04  7:23           ` Johannes Schindelin
2018-05-04 14:44             ` Duy Nguyen
2018-05-04 15:17               ` Duy Nguyen
2018-05-04 15:23               ` Johannes Schindelin
2018-05-04 15:29                 ` Duy Nguyen
2018-05-03 16:43   ` Stefan Beller
2018-05-03 20:42     ` Johannes Schindelin
2018-05-03 21:12       ` Stefan Beller
2018-05-03 21:49         ` Johannes Schindelin
2018-05-04  3:23           ` Junio C Hamano
2018-05-04  2:35   ` Eric Sunshine
2018-05-04  6:52     ` Johannes Schindelin
2018-05-04  7:27       ` Eric Sunshine
2018-05-03 15:30 ` [PATCH 03/18] branch-diff: first rudimentary implementation Johannes Schindelin
2018-05-03 16:30   ` Ramsay Jones
2018-05-03 20:44     ` Johannes Schindelin
2018-05-03 17:06   ` Stefan Beller
2018-05-03 21:01     ` Johannes Schindelin
2018-05-03 21:19       ` Stefan Beller
2018-05-03 22:00         ` Johannes Schindelin
2018-05-04  2:35   ` Eric Sunshine
2018-05-04  7:03     ` Johannes Schindelin
2018-05-04  4:56   ` Junio C Hamano
2018-05-04  7:18     ` Johannes Schindelin
2018-05-03 15:30 ` [PATCH 04/18] branch-diff: improve the order of the shown commits Johannes Schindelin
2018-05-03 15:30 ` [PATCH 05/18] branch-diff: also show the diff between patches Johannes Schindelin
2018-05-04  2:51   ` Eric Sunshine
2018-05-04  3:15     ` Eric Sunshine
2018-05-04  7:15     ` Johannes Schindelin
2018-05-03 15:30 ` [PATCH 06/18] branch-diff: right-trim commit messages Johannes Schindelin
2018-05-03 15:30 ` [PATCH 07/18] branch-diff: indent the diffs just like tbdiff Johannes Schindelin
2018-05-03 15:30 ` [PATCH 08/18] branch-diff: suppress the diff headers Johannes Schindelin
2018-05-03 15:30 ` [PATCH 09/18] branch-diff: adjust the output of the commit pairs Johannes Schindelin
2018-05-03 15:30 ` [PATCH 10/18] branch-diff: do not show "function names" in hunk headers Johannes Schindelin
2018-05-03 15:30 ` [PATCH 11/18] branch-diff: add tests Johannes Schindelin
2018-05-03 16:56   ` Ævar Arnfjörð Bjarmason
2018-05-03 21:03     ` Johannes Schindelin
2018-05-03 17:11   ` Stefan Beller
2018-05-03 21:05     ` Johannes Schindelin
2018-05-03 23:27   ` Philip Oakley
2018-05-04  6:42     ` Johannes Schindelin
2018-05-03 15:30 ` [PATCH 12/18] branch-diff: use color for the commit pairs Johannes Schindelin
2018-05-03 15:30 ` [PATCH 13/18] color: provide inverted colors, too Johannes Schindelin
2018-05-03 15:30 ` [PATCH 14/18] diff: add an internal option to dual-color diffs of diffs Johannes Schindelin
2018-05-03 15:31 ` [PATCH 15/18] branch-diff: offer to dual-color the diffs Johannes Schindelin
2018-05-03 15:31 ` [PATCH 16/18] branch-diff --dual-color: work around bogus white-space warning Johannes Schindelin
2018-05-03 15:31 ` [PATCH 17/18] branch-diff: add a man page Johannes Schindelin
2018-05-04  3:27   ` Eric Sunshine
2018-05-04  7:17     ` Johannes Schindelin
2018-05-03 15:31 ` [PATCH 18/18] completion: support branch-diff Johannes Schindelin
2018-05-03 18:05 ` [PATCH 00/18] Add `branch-diff`, a `tbdiff` lookalike Ævar Arnfjörð Bjarmason
2018-05-03 21:07   ` Johannes Schindelin
2018-05-03 21:50   ` Jacob Keller
2018-05-04  5:24 ` Junio C Hamano
2018-05-04  7:24   ` Johannes Schindelin
2018-05-04 15:34 ` [PATCH v2 " Johannes Schindelin
2018-05-04 15:34   ` [PATCH v2 01/18] Add a function to solve least-cost assignment problems Johannes Schindelin
2018-05-05 18:24     ` Jeff King
2018-05-05 21:55       ` Johannes Schindelin
2018-05-30 13:55     ` SZEDER Gábor
2018-05-30 16:14       ` Stefan Beller
2018-05-30 23:28         ` brian m. carlson
2018-05-31 12:19           ` Johannes Schindelin
2018-05-04 15:34   ` [PATCH v2 02/18] Add a new builtin: branch-diff Johannes Schindelin
2018-05-05 18:26     ` Jeff King
2018-05-05 21:57       ` Johannes Schindelin
2018-05-06  0:25         ` Todd Zullinger
2018-05-06  0:38           ` Todd Zullinger
2018-05-06 12:04             ` Johannes Schindelin
2018-05-06  1:05         ` Igor Djordjevic
2018-05-06  4:53           ` Jacob Keller
2018-05-06  8:32             ` Duy Nguyen
2018-05-06 12:08               ` Johannes Schindelin
2018-05-06 12:10           ` Johannes Schindelin
2018-05-06 13:37             ` Igor Djordjevic
2018-05-07  1:34               ` Johannes Schindelin
2018-05-07 22:05                 ` Igor Djordjevic
2018-05-07 22:24                   ` Stefan Beller
2018-05-07 23:39                     ` Igor Djordjevic
2018-05-08  3:44                     ` Jeff King
2018-05-08  3:48                       ` Jeff King
2018-05-22 11:38                       ` Ævar Arnfjörð Bjarmason
2018-05-25 22:06                         ` Stefan Beller
     [not found]                           ` <CAA8fPEkNjy+ETz4Mx+C2kUfLjLzR9uuOmO3GfN48ZH1SwyfE1A@mail.gmail.com>
2018-05-26  6:15                             ` Fwd: " Øyvind Rønningstad
2018-06-01  8:15                             ` Johannes Schindelin
2018-05-06  2:33         ` Junio C Hamano
2018-05-06 12:21           ` Johannes Schindelin
2018-05-06 20:51             ` Eric Sunshine
2018-05-07  2:04               ` Johannes Schindelin
2018-05-07  7:48                 ` Jeff King
2018-05-07 21:33                   ` Igor Djordjevic
2018-05-21 10:33                     ` Johannes Schindelin
2018-05-21 17:56                       ` Stefan Beller
2018-05-21 20:24                         ` Jeff King
2018-05-21 21:40                           ` Brandon Williams
2018-05-21 21:48                             ` Stefan Beller
2018-05-21 21:52                             ` Jeff King
2018-05-22  2:08                               ` Junio C Hamano
2018-05-08  0:30                   ` Junio C Hamano
2018-05-07  1:45             ` Junio C Hamano
2018-05-07  5:39               ` Johannes Schindelin
2018-05-07 15:12                 ` Junio C Hamano
2018-05-21 10:41                   ` Johannes Schindelin
2018-05-07  7:50         ` Jeff King
2018-05-07 15:28           ` Duy Nguyen
2018-05-07 19:58             ` Stefan Beller
2018-05-04 15:34   ` [PATCH v2 03/18] branch-diff: first rudimentary implementation Johannes Schindelin
2018-05-04 15:34   ` [PATCH v2 04/18] branch-diff: improve the order of the shown commits Johannes Schindelin
2018-05-04 15:34   ` [PATCH v2 05/18] branch-diff: also show the diff between patches Johannes Schindelin
2018-05-06  1:14     ` Igor Djordjevic
2018-05-06 12:18       ` Johannes Schindelin
2018-05-04 15:34   ` [PATCH v2 06/18] branch-diff: right-trim commit messages Johannes Schindelin
2018-05-04 15:34   ` [PATCH v2 07/18] branch-diff: indent the diffs just like tbdiff Johannes Schindelin
2018-05-06 14:15     ` Martin Ågren
2018-05-07  1:54       ` Johannes Schindelin
2018-05-04 15:34   ` [PATCH v2 08/18] branch-diff: suppress the diff headers Johannes Schindelin
2018-05-04 15:34   ` [PATCH v2 09/18] branch-diff: adjust the output of the commit pairs Johannes Schindelin
2018-05-04 16:25     ` Elijah Newren
2018-05-04 15:34   ` [PATCH v2 10/18] branch-diff: do not show "function names" in hunk headers Johannes Schindelin
2018-05-04 15:34   ` [PATCH v2 11/18] branch-diff: add tests Johannes Schindelin
2018-05-04 15:34   ` [PATCH v2 12/18] branch-diff: use color for the commit pairs Johannes Schindelin
2018-05-05 23:48     ` Todd Zullinger
2018-05-07  1:52       ` Johannes Schindelin
2018-05-08  2:10         ` Todd Zullinger
2018-06-01  8:17           ` Johannes Schindelin
2018-05-04 15:34   ` [PATCH v2 13/18] color: provide inverted colors, too Johannes Schindelin
2018-05-05 18:29     ` Jeff King
2018-05-05 22:03       ` Johannes Schindelin
2018-05-06  6:35         ` Jeff King
2018-05-06  6:41           ` Jeff King
2018-05-07  1:20             ` Johannes Schindelin
2018-05-07  7:37               ` Jeff King
2018-05-07  1:35             ` Junio C Hamano
2018-05-07  5:38               ` Johannes Schindelin
2018-05-07  7:40               ` Jeff King
2018-05-04 15:34   ` [PATCH v2 14/18] diff: add an internal option to dual-color diffs of diffs Johannes Schindelin
2018-05-04 15:35   ` [PATCH v2 15/18] branch-diff: offer to dual-color the diffs Johannes Schindelin
2018-05-04 15:35   ` [PATCH v2 16/18] branch-diff --dual-color: work around bogus white-space warning Johannes Schindelin
2018-05-04 15:35   ` [PATCH v2 17/18] branch-diff: add a man page Johannes Schindelin
2018-05-04 15:35   ` [PATCH v2 18/18] completion: support branch-diff Johannes Schindelin
2018-05-06  8:24     ` Duy Nguyen
2018-05-07  1:23       ` Johannes Schindelin
2018-05-04 16:21   ` [PATCH v2 00/18] Add `branch-diff`, a `tbdiff` lookalike Elijah Newren
2018-05-04 16:30     ` Elijah Newren
2018-05-05 20:03     ` Johannes Schindelin
2018-05-07 17:07       ` Elijah Newren
2018-05-07 17:50         ` SZEDER Gábor
2018-05-07 18:38           ` Elijah Newren
2018-05-06  5:22   ` Junio C Hamano
2018-05-06 12:23     ` Johannes Schindelin
2018-05-06 22:56   ` brian m. carlson
2018-05-07  2:05     ` Johannes Schindelin
2018-07-03 11:26   ` [PATCH v3 00/20] Add `range-diff`, " Johannes Schindelin via GitGitGadget
2018-04-30 21:54     ` [PATCH v3 01/20] linear-assignment: a function to solve least-cost assignment problems Johannes Schindelin via GitGitGadget
2018-07-06 22:43       ` Junio C Hamano
2018-07-07 11:34         ` Johannes Schindelin
2018-07-07 16:34           ` Junio C Hamano
2018-07-07 19:27             ` Johannes Schindelin
2018-07-07 22:23               ` Johannes Schindelin
2018-07-09 22:08                 ` refs/notes/amlog problems, was " Johannes Schindelin
2018-07-11 16:12                   ` Junio C Hamano
2018-07-12 15:23                     ` Johannes Schindelin
2018-07-12 16:59                       ` Junio C Hamano
2018-07-19 17:06                         ` Junio C Hamano
2018-07-20 18:51                           ` Johannes Schindelin
2018-07-20 19:34                             ` Junio C Hamano
2018-07-20 21:20                               ` Stefan Beller
2018-07-20 21:24                                 ` Junio C Hamano
     [not found]                                   ` <CAPc5daW-KoyUX3i7M5YbdQC2mFKAmVBS42-XT84hpm30VFcZ1g@mail.gmail.com>
2018-07-20 21:30                                     ` Stefan Beller
2018-07-21 22:02                                       ` Johannes Schindelin
2018-07-21 21:56                               ` Johannes Schindelin
2018-07-23  1:25                                 ` Jeff King
2018-07-24  1:50                                   ` Junio C Hamano
2018-07-24  9:45                                     ` Jeff King
2018-07-09 22:23                 ` Junio C Hamano
2018-07-10 10:47                   ` refs/notes/amlog woes, was " Johannes Schindelin
2018-07-11 10:07       ` SZEDER Gábor
2018-07-12 15:11         ` Johannes Schindelin
2018-05-01 19:42     ` [PATCH v3 02/20] Introduce `range-diff` to compare iterations of a topic branch Johannes Schindelin via GitGitGadget
2018-05-02  0:34     ` [PATCH v3 03/20] range-diff: first rudimentary implementation Johannes Schindelin via GitGitGadget
2018-07-16  6:55       ` Eric Sunshine
2018-07-17  9:53         ` Johannes Schindelin
2018-05-02 10:22     ` [PATCH v3 04/20] range-diff: improve the order of the shown commits Johannes Schindelin via GitGitGadget
2018-05-02 14:49     ` [PATCH v3 06/20] range-diff: right-trim commit messages Johannes Schindelin via GitGitGadget
2018-05-02 14:52     ` [PATCH v3 07/20] range-diff: indent the diffs just like tbdiff Johannes Schindelin via GitGitGadget
2018-05-02 14:53     ` [PATCH v3 08/20] range-diff: suppress the diff headers Johannes Schindelin via GitGitGadget
2018-05-02 15:19     ` [PATCH v3 11/20] range-diff: add tests Thomas Rast via GitGitGadget
2018-07-16  7:28       ` Eric Sunshine
2018-07-17 16:28         ` Johannes Schindelin
2018-05-02 21:35     ` [PATCH v3 09/20] range-diff: adjust the output of the commit pairs Johannes Schindelin via GitGitGadget
2018-07-16  7:21       ` Eric Sunshine
2018-07-17 16:24         ` Johannes Schindelin
2018-07-17 17:47           ` Stefan Beller
2018-07-20 18:57             ` Johannes Schindelin
2018-07-20 19:16               ` Stefan Beller
2018-07-21 22:07                 ` Johannes Schindelin
2018-05-02 23:32     ` [PATCH v3 12/20] range-diff: use color for " Johannes Schindelin via GitGitGadget
2018-05-03  0:14     ` [PATCH v3 13/20] color: add the meta color GIT_COLOR_REVERSE Johannes Schindelin via GitGitGadget
2018-05-03  0:17     ` [PATCH v3 14/20] diff: add an internal option to dual-color diffs of diffs Johannes Schindelin via GitGitGadget
2018-07-09 19:29       ` Stefan Beller
2018-07-10 17:45         ` [PATCH 0/2] " Stefan Beller
2018-07-10 17:45           ` [PATCH 1/2] diff.c: convert emit_line_ws_markup to take string for sign Stefan Beller
2018-07-10 17:45           ` [PATCH 2/2] WIP diff.c: clarify emit_line_0 Stefan Beller
2018-07-10 19:58             ` [PATCH 1/2] diff.c: convert emit_line_ws_markup to take string for sign Stefan Beller
2018-07-10 19:59             ` [PATCH] diff.c: clarify emit_line_0 Stefan Beller
2018-07-10 21:54               ` [PATCH] ws: do not reset and set color twice Stefan Beller
2018-07-21 21:13           ` [PATCH 0/2] Re: [PATCH v3 14/20] diff: add an internal option to dual-color diffs of diffs Johannes Schindelin
2018-05-03  1:01     ` [PATCH v3 15/20] range-diff: offer to dual-color the diffs Johannes Schindelin via GitGitGadget
2018-05-03  1:11     ` [PATCH v3 16/20] range-diff --dual-color: work around bogus white-space warning Johannes Schindelin via GitGitGadget
2018-07-09 19:34       ` Stefan Beller
2018-07-09 21:02         ` Junio C Hamano
2018-07-10 10:08           ` Johannes Schindelin
2018-07-10 15:50             ` Junio C Hamano
2018-07-10 16:32             ` Stefan Beller
2018-07-21 21:44               ` Johannes Schindelin
2018-05-03 13:50     ` [PATCH v3 17/20] range-diff: add a man page Johannes Schindelin via GitGitGadget
2018-07-09 18:20       ` Stefan Beller
2018-07-09 20:00         ` Johannes Schindelin
2018-07-09 20:25           ` Stefan Beller
2018-07-09 20:38             ` Johannes Schindelin
2018-07-16  8:01       ` Eric Sunshine
2018-07-17 16:39         ` Johannes Schindelin
2018-05-03 14:44     ` [PATCH v3 18/20] completion: support `git range-diff` Johannes Schindelin via GitGitGadget
2018-07-06 22:46       ` Junio C Hamano
2018-07-07 11:38         ` Johannes Schindelin
2018-05-05 19:52     ` [PATCH v3 19/20] range-diff: left-pad patch numbers Johannes Schindelin via GitGitGadget
2018-05-06 15:26     ` [PATCH v3 05/20] range-diff: also show the diff between patches Johannes Schindelin via GitGitGadget
2018-05-06 15:35     ` [PATCH v3 10/20] range-diff: do not show "function names" in hunk headers Johannes Schindelin via GitGitGadget
2018-06-30 20:41     ` [PATCH v3 20/20] range-diff: make --dual-color the default mode Johannes Schindelin via GitGitGadget
2018-07-16  8:06       ` Eric Sunshine
2018-07-17 16:40         ` Johannes Schindelin
2018-07-21 22:04     ` [PATCH v4 00/21] Add `range-diff`, a `tbdiff` lookalike Johannes Schindelin via GitGitGadget
2018-07-21 22:04       ` [PATCH v4 01/21] linear-assignment: a function to solve least-cost assignment problems Johannes Schindelin via GitGitGadget
2018-07-28  8:46         ` Thomas Gummerer
2018-07-30 15:59           ` Johannes Schindelin
2018-07-21 22:04       ` [PATCH v4 02/21] Introduce `range-diff` to compare iterations of a topic branch Johannes Schindelin via GitGitGadget
2018-07-21 22:04       ` [PATCH v4 03/21] range-diff: first rudimentary implementation Johannes Schindelin via GitGitGadget
2018-07-29 18:36         ` Thomas Gummerer
2018-07-30 16:21           ` Johannes Schindelin [this message]
2018-07-30 21:16             ` Thomas Gummerer
2018-08-10 20:50               ` Johannes Schindelin
2018-07-21 22:04       ` [PATCH v4 04/21] range-diff: improve the order of the shown commits Johannes Schindelin via GitGitGadget
2018-07-21 22:04       ` [PATCH v4 05/21] range-diff: also show the diff between patches Johannes Schindelin via GitGitGadget
2018-07-29 19:03         ` Thomas Gummerer
2018-07-29 19:22           ` Eric Sunshine
2018-07-29 21:45             ` Thomas Gummerer
2018-07-30 16:28               ` Johannes Schindelin
2018-07-30 21:26                 ` Thomas Gummerer
2018-07-30 21:51                   ` Eric Sunshine
2018-08-10 21:12                     ` Johannes Schindelin
2018-08-10 21:31                       ` Eric Sunshine
2018-08-10 22:02                         ` Johannes Schindelin
2018-08-10 20:36                   ` Johannes Schindelin
2018-07-21 22:04       ` [PATCH v4 06/21] range-diff: right-trim commit messages Johannes Schindelin via GitGitGadget
2018-07-21 22:04       ` [PATCH v4 07/21] range-diff: indent the diffs just like tbdiff Johannes Schindelin via GitGitGadget
2018-07-21 22:04       ` [PATCH v4 08/21] range-diff: suppress the diff headers Johannes Schindelin via GitGitGadget
2018-07-21 22:04       ` [PATCH v4 09/21] range-diff: adjust the output of the commit pairs Johannes Schindelin via GitGitGadget
2018-07-29 19:38         ` Thomas Gummerer
2018-08-10 21:01           ` Johannes Schindelin
2018-07-29 21:28         ` Thomas Gummerer
2018-07-21 22:04       ` [PATCH v4 10/21] range-diff: do not show "function names" in hunk headers Johannes Schindelin via GitGitGadget
2018-07-29 20:52         ` Thomas Gummerer
2018-08-10 21:03           ` Johannes Schindelin
2018-07-21 22:05       ` [PATCH v4 11/21] range-diff: add tests Thomas Rast via GitGitGadget
2018-07-22  5:04         ` Eric Sunshine
2018-07-30 16:30           ` Johannes Schindelin
2018-07-30 20:18             ` Junio C Hamano
2018-07-30 23:40               ` Stefan Beller
2018-07-31 15:19                 ` Junio C Hamano
2018-07-23 21:25         ` Stefan Beller
2018-07-21 22:05       ` [PATCH v4 12/21] range-diff: use color for the commit pairs Johannes Schindelin via GitGitGadget
2018-07-21 22:05       ` [PATCH v4 13/21] color: add the meta color GIT_COLOR_REVERSE Johannes Schindelin via GitGitGadget
2018-07-21 22:05       ` [PATCH v4 14/21] diff: add an internal option to dual-color diffs of diffs Johannes Schindelin via GitGitGadget
2018-07-23 22:27         ` Junio C Hamano
2018-07-23 22:48           ` Stefan Beller
2018-07-21 22:05       ` [PATCH v4 15/21] range-diff: offer to dual-color the diffs Johannes Schindelin via GitGitGadget
2018-07-21 22:05       ` [PATCH v4 16/21] range-diff --dual-color: fix bogus white-space warning Johannes Schindelin via GitGitGadget
2018-07-23 22:20         ` Stefan Beller
2018-08-10 21:05           ` Johannes Schindelin
2018-07-23 22:39         ` Junio C Hamano
2018-07-24  1:27           ` Junio C Hamano
2018-07-21 22:05       ` [PATCH v4 17/21] range-diff: populate the man page Johannes Schindelin via GitGitGadget
2018-07-29 21:23         ` Thomas Gummerer
2018-08-10 21:06           ` Johannes Schindelin
2018-07-21 22:05       ` [PATCH v4 18/21] completion: support `git range-diff` Johannes Schindelin via GitGitGadget
2018-07-22  5:49         ` Eric Sunshine
2018-08-10 20:24           ` Johannes Schindelin
2018-07-21 22:05       ` [PATCH v4 19/21] range-diff: left-pad patch numbers Johannes Schindelin via GitGitGadget
2018-07-21 22:05       ` [PATCH v4 20/21] range-diff: make --dual-color the default mode Johannes Schindelin via GitGitGadget
2018-07-29 21:33         ` Thomas Gummerer
2018-08-10 21:07           ` Johannes Schindelin
2018-07-21 22:05       ` [PATCH v4 21/21] range-diff: use dim/bold cues to improve dual color mode Johannes Schindelin via GitGitGadget
2018-07-23 21:03       ` [PATCH v4 00/21] Add `range-diff`, a `tbdiff` lookalike Stefan Beller
2018-07-23 21:49         ` Junio C Hamano
2018-07-25 17:44           ` Stefan Beller
2018-07-26  9:47         ` Johannes Schindelin
2018-08-08 13:05         ` Johannes Schindelin
2018-08-08 17:33           ` Stefan Beller
2018-08-10 21:18             ` Johannes Schindelin
2018-08-10 21:31               ` Junio C Hamano
2018-08-10 22:00                 ` Johannes Schindelin
2018-07-29 21:50       ` Thomas Gummerer
2018-08-10 22:14       ` [PATCH v5 00/21] Add range-diff, a tbdiff lookalike Johannes Schindelin via GitGitGadget
2018-08-10 22:14         ` [PATCH v5 01/21] linear-assignment: a function to solve least-cost assignment problems Johannes Schindelin via GitGitGadget
2018-08-10 22:14         ` [PATCH v5 02/21] Introduce `range-diff` to compare iterations of a topic branch Johannes Schindelin via GitGitGadget
2018-08-10 22:14         ` [PATCH v5 03/21] range-diff: first rudimentary implementation Johannes Schindelin via GitGitGadget
2018-08-10 22:14         ` [PATCH v5 04/21] range-diff: improve the order of the shown commits Johannes Schindelin via GitGitGadget
2018-08-10 22:14         ` [PATCH v5 05/21] range-diff: also show the diff between patches Johannes Schindelin via GitGitGadget
2018-08-12 21:47           ` Thomas Gummerer
2018-08-13  9:46             ` Johannes Schindelin
2018-08-13 18:01               ` Thomas Gummerer
2018-08-10 22:14         ` [PATCH v5 06/21] range-diff: right-trim commit messages Johannes Schindelin via GitGitGadget
2018-08-10 22:14         ` [PATCH v5 07/21] range-diff: indent the diffs just like tbdiff Johannes Schindelin via GitGitGadget
2018-08-10 22:14         ` [PATCH v5 08/21] range-diff: suppress the diff headers Johannes Schindelin via GitGitGadget
2018-08-10 22:14         ` [PATCH v5 09/21] range-diff: adjust the output of the commit pairs Johannes Schindelin via GitGitGadget
2018-08-10 22:14         ` [PATCH v5 10/21] range-diff: do not show "function names" in hunk headers Johannes Schindelin via GitGitGadget
2018-08-10 22:14         ` [PATCH v5 11/21] range-diff: add tests Thomas Rast via GitGitGadget
2018-08-10 22:14         ` [PATCH v5 12/21] range-diff: use color for the commit pairs Johannes Schindelin via GitGitGadget
2018-08-10 22:14         ` [PATCH v5 13/21] color: add the meta color GIT_COLOR_REVERSE Johannes Schindelin via GitGitGadget
2018-08-10 22:14         ` [PATCH v5 14/21] diff: add an internal option to dual-color diffs of diffs Johannes Schindelin via GitGitGadget
2018-08-10 22:14         ` [PATCH v5 15/21] range-diff: offer to dual-color the diffs Johannes Schindelin via GitGitGadget
2018-08-10 22:14         ` [PATCH v5 16/21] range-diff --dual-color: skip white-space warnings Johannes Schindelin via GitGitGadget
2018-08-10 22:14         ` [PATCH v5 17/21] range-diff: populate the man page Johannes Schindelin via GitGitGadget
2018-08-10 22:14         ` [PATCH v5 18/21] completion: support `git range-diff` Johannes Schindelin via GitGitGadget
2018-08-10 22:14         ` [PATCH v5 19/21] range-diff: left-pad patch numbers Johannes Schindelin via GitGitGadget
2018-08-10 22:14         ` [PATCH v5 20/21] range-diff: make --dual-color the default mode Johannes Schindelin via GitGitGadget
2018-08-10 22:14         ` [PATCH v5 21/21] range-diff: use dim/bold cues to improve dual color mode Johannes Schindelin via GitGitGadget
2018-08-13 11:32         ` [PATCH v6 00/21] Add range-diff, a tbdiff lookalike Johannes Schindelin via GitGitGadget
2018-08-13 11:33           ` [PATCH v6 01/21] linear-assignment: a function to solve least-cost assignment problems Johannes Schindelin via GitGitGadget
2018-08-13 11:33           ` [PATCH v6 02/21] Introduce `range-diff` to compare iterations of a topic branch Johannes Schindelin via GitGitGadget
2018-08-13 11:33           ` [PATCH v6 03/21] range-diff: first rudimentary implementation Johannes Schindelin via GitGitGadget
2019-03-05  6:29             ` Junio C Hamano
2018-08-13 11:33           ` [PATCH v6 04/21] range-diff: improve the order of the shown commits Johannes Schindelin via GitGitGadget
2018-08-13 11:33           ` [PATCH v6 05/21] range-diff: also show the diff between patches Johannes Schindelin via GitGitGadget
2018-08-13 11:33           ` [PATCH v6 06/21] range-diff: right-trim commit messages Johannes Schindelin via GitGitGadget
2018-08-13 11:33           ` [PATCH v6 07/21] range-diff: indent the diffs just like tbdiff Johannes Schindelin via GitGitGadget
2018-08-13 11:33           ` [PATCH v6 08/21] range-diff: suppress the diff headers Johannes Schindelin via GitGitGadget
2018-08-13 11:33           ` [PATCH v6 09/21] range-diff: adjust the output of the commit pairs Johannes Schindelin via GitGitGadget
2018-08-13 11:33           ` [PATCH v6 10/21] range-diff: do not show "function names" in hunk headers Johannes Schindelin via GitGitGadget
2018-08-13 11:33           ` [PATCH v6 11/21] range-diff: add tests Thomas Rast via GitGitGadget
2018-08-13 18:35             ` Thomas Gummerer
2018-08-14 14:53               ` Johannes Schindelin
2018-08-14 15:03                 ` Jeff King
2018-08-14 15:06                   ` Jeff King
2018-08-14 15:18                 ` Junio C Hamano
2018-08-13 11:33           ` [PATCH v6 12/21] range-diff: use color for the commit pairs Johannes Schindelin via GitGitGadget
2018-08-13 11:33           ` [PATCH v6 13/21] color: add the meta color GIT_COLOR_REVERSE Johannes Schindelin via GitGitGadget
2018-08-13 11:33           ` [PATCH v6 14/21] diff: add an internal option to dual-color diffs of diffs Johannes Schindelin via GitGitGadget
2018-08-13 11:33           ` [PATCH v6 15/21] range-diff: offer to dual-color the diffs Johannes Schindelin via GitGitGadget
2018-08-13 11:33           ` [PATCH v6 16/21] range-diff --dual-color: skip white-space warnings Johannes Schindelin via GitGitGadget
2018-08-13 17:48             ` Junio C Hamano
2018-08-13 11:33           ` [PATCH v6 17/21] range-diff: populate the man page Johannes Schindelin via GitGitGadget
2018-09-09 11:14             ` Ævar Arnfjörð Bjarmason
2018-09-09 16:54               ` SZEDER Gábor
2018-09-09 17:19                 ` Ævar Arnfjörð Bjarmason
2018-09-10 13:37                   ` Jeff King
2018-10-02 15:06                     ` Johannes Schindelin
2018-09-10 17:17                   ` Junio C Hamano
2018-08-13 11:33           ` [PATCH v6 18/21] completion: support `git range-diff` Johannes Schindelin via GitGitGadget
2018-08-13 11:33           ` [PATCH v6 19/21] range-diff: left-pad patch numbers Johannes Schindelin via GitGitGadget
2018-08-13 11:33           ` [PATCH v6 20/21] range-diff: make --dual-color the default mode Johannes Schindelin via GitGitGadget
2018-08-13 11:33           ` [PATCH v6 21/21] range-diff: use dim/bold cues to improve dual color mode Johannes Schindelin via GitGitGadget
2018-08-13 11:38           ` [PATCH v6 00/21] Add range-diff, a tbdiff lookalike Johannes Schindelin
2018-08-13 20:47             ` Thomas Gummerer
2018-05-21  4:48 ` [PATCH 00/18] Add `branch-diff`, a `tbdiff` lookalike Junio C Hamano
2018-05-21  9:51   ` Johannes Schindelin
2018-05-22  1:42     ` Junio C Hamano
2018-06-01  8:28       ` Johannes Schindelin

Reply instructions:

You may reply publically to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=nycvar.QRO.7.76.6.1807301759340.10478@tvgsbejvaqbjf.bet \
    --to=johannes.schindelin@gmx.de \
    --cc=git@vger.kernel.org \
    --cc=gitgitgadget@gmail.com \
    --cc=gitster@pobox.com \
    --cc=t.gummerer@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

git@vger.kernel.org list mirror (unofficial, one of many)

Archives are clonable:
	git clone --mirror https://public-inbox.org/git
	git clone --mirror http://ou63pmih66umazou.onion/git
	git clone --mirror http://czquwvybam4bgbro.onion/git
	git clone --mirror http://hjrcffqmbrq6wope.onion/git

Newsgroups are available over NNTP:
	nntp://news.public-inbox.org/inbox.comp.version-control.git
	nntp://ou63pmih66umazou.onion/inbox.comp.version-control.git
	nntp://czquwvybam4bgbro.onion/inbox.comp.version-control.git
	nntp://hjrcffqmbrq6wope.onion/inbox.comp.version-control.git
	nntp://news.gmane.org/gmane.comp.version-control.git

 note: .onion URLs require Tor: https://www.torproject.org/

AGPL code for this site: git clone https://public-inbox.org/ public-inbox