git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [PATCH v2 0/1] teach format.useAutoBase "whenAble" option
@ 2020-10-01 21:46 Jacob Keller
  2020-10-01 21:46 ` [PATCH v2 1/1] format-patch: " Jacob Keller
  2020-10-01 22:21 ` [PATCH v2 0/1] " Junio C Hamano
  0 siblings, 2 replies; 3+ messages in thread
From: Jacob Keller @ 2020-10-01 21:46 UTC (permalink / raw)
  To: git; +Cc: Jacob Keller

From: Jacob Keller <jacob.keller@gmail.com>

This is a v2 of [1] to address comments on the mailing list. Primarily the
change is to remove the option for --base=if-able, since it is not as useful
as the configuration option. If we think it is desirable, adding back a
whenable or whenAble option is easy enough.

Here's the range diff since the v1.

1:  3c7f89213158 !  1:  cb24cf3fe8b5 format-patch: teach format.useAutoBase "whenAble" option
    @@ Commit message
         Teach format.useAutoBase a new mode, "whenAble". This mode will cause
         format-patch to attempt to include a base commit when it can. However,
         if no valid base commit can be found, then format-patch will continue
    -    formatting the patch without a base commit. --base also learns the same
    -    mode using the term "if-able".
    +    formatting the patch without a base commit.
    +
    +    In order to avoid making yet another branch name unusable with --base,
    +    do not teach --base=whenAble or --base=whenable.
    +
    +    Instead, refactor the base_commit option to use a callback, and rely on
    +    the global configuration variable auto_base.
    +
    +    This does mean that a user cannot request this optional base commit
    +    generation from the command line. However, this is likely not too
    +    valuable. If the user requests base information manually, they will be
    +    immediately informed of the failure to acquire a suitable base commit.
    +    This allows the user to make an informed choice about whether to
    +    continue the format.
     
         Add tests to cover the new mode of operation for --base.
     
         Signed-off-by: Jacob Keller <jacob.keller@gmail.com>
    -    Signed-off-by: Junio C Hamano <gitster@pobox.com>
     
      ## Documentation/config/format.txt ##
     @@ Documentation/config/format.txt: format.outputDirectory::
    @@ Documentation/config/format.txt: format.outputDirectory::
      format.useAutoBase::
      	A boolean value which lets you enable the `--base=auto` option of
     -	format-patch by default.
    -+	format-patch by default. Can also be set to "whenAble" to set
    -+	`--base=if-able`. This causes format-patch to include the base
    -+	commit information if it can be determined, but skip it otherwise
    -+	without dying.
    ++	format-patch by default. Can also be set to "whenAble" to allow
    ++	enabling `--base=auto` if a suitable base is available, but to skip
    ++	adding base info otherwise without the format dying.
      
      format.notes::
      	Provides the default value for the `--notes` option to
     
    - ## Documentation/git-format-patch.txt ##
    -@@ Documentation/git-format-patch.txt: you can use `--suffix=-patch` to get `0001-description-of-my-change-patch`.
    - 	Record the base tree information to identify the state the
    - 	patch series applies to.  See the BASE TREE INFORMATION section
    - 	below for details. If <commit> is "auto", a base commit is
    --	automatically chosen. The `--no-base` option overrides a
    -+	automatically chosen. If <commit> is "if-able", a base commit is
    -+	included if available, however format-patch won't die if it cannot
    -+	find a valid base commit. The `--no-base` option overrides a
    - 	`format.useAutoBase` configuration.
    - 
    - --root::
    -
      ## builtin/log.c ##
     @@ builtin/log.c: enum cover_from_description {
      	COVER_FROM_AUTO
    @@ builtin/log.c: static int git_format_config(const char *var, const char *value,
      		return 0;
      	}
      	if (!strcmp(var, "format.from")) {
    +@@ builtin/log.c: static int from_callback(const struct option *opt, const char *arg, int unset)
    + 	return 0;
    + }
    + 
    ++static int base_callback(const struct option *opt, const char *arg, int unset)
    ++{
    ++	const char **base_commit = opt->value;
    ++
    ++	if (unset) {
    ++		auto_base = AUTO_BASE_NEVER;
    ++		*base_commit = NULL;
    ++	} else if (!strcmp(arg, "auto")) {
    ++		auto_base = AUTO_BASE_ALWAYS;
    ++		*base_commit = NULL;
    ++	} else {
    ++		auto_base = AUTO_BASE_NEVER;
    ++		*base_commit = arg;
    ++	}
    ++	return 0;
    ++}
    ++
    + struct base_tree_info {
    + 	struct object_id base_commit;
    + 	int nr_patch_id, alloc_patch_id;
     @@ builtin/log.c: static struct commit *get_base_commit(const char *base_commit,
      {
      	struct commit *base = NULL;
    @@ builtin/log.c: static struct commit *get_base_commit(const char *base_commit,
     +	int i = 0, rev_nr = 0, auto_select, die_on_failure;
      
     -	if (base_commit && strcmp(base_commit, "auto")) {
    -+	if (!strcmp(base_commit, "auto")) {
    -+		auto_select = 1;
    -+		die_on_failure = 1;
    -+	} else if (!strcmp(base_commit, "if-able")) {
    -+		auto_select = 1;
    -+		die_on_failure = 0;
    -+	} else {
    -+		auto_select = 0;
    -+		die_on_failure = 1;
    ++	switch (auto_base) {
    ++	case AUTO_BASE_NEVER:
    ++		if (base_commit) {
    ++			auto_select = 0;
    ++			die_on_failure = 1;
    ++		} else {
    ++			/* no base information is requested */
    ++			return NULL;
    ++		}
    ++		break;
    ++	case AUTO_BASE_ALWAYS:
    ++	case AUTO_BASE_WHEN_ABLE:
    ++		if (base_commit) {
    ++			BUG("requested automatic base selection but a commit was provided");
    ++		} else {
    ++			auto_select = 1;
    ++			die_on_failure = auto_base == AUTO_BASE_ALWAYS;
    ++		}
    ++		break;
    ++	default:
    ++		BUG("unexpected automatic base selection method");
     +	}
     +
     +	if (!auto_select) {
    @@ builtin/log.c: static struct commit *get_base_commit(const char *base_commit,
      	}
      
      	free(rev);
    +@@ builtin/log.c: int cmd_format_patch(int argc, const char **argv, const char *prefix)
    + 	char *branch_name = NULL;
    + 	char *base_commit = NULL;
    + 	struct base_tree_info bases;
    ++	struct commit *base;
    + 	int show_progress = 0;
    + 	struct progress *progress = NULL;
    + 	struct oid_array idiff_prev = OID_ARRAY_INIT;
    +@@ builtin/log.c: int cmd_format_patch(int argc, const char **argv, const char *prefix)
    + 			    PARSE_OPT_OPTARG, thread_callback),
    + 		OPT_STRING(0, "signature", &signature, N_("signature"),
    + 			    N_("add a signature")),
    +-		OPT_STRING(0, "base", &base_commit, N_("base-commit"),
    +-			   N_("add prerequisite tree info to the patch series")),
    ++		OPT_CALLBACK_F(0, "base", &base_commit, N_("base-commit"),
    ++			       N_("add prerequisite tree info to the patch series"),
    ++			       0, base_callback),
    + 		OPT_FILENAME(0, "signature-file", &signature_file,
    + 				N_("add a signature from a file")),
    + 		OPT__QUIET(&quiet, N_("don't print the patch filenames")),
     @@ builtin/log.c: int cmd_format_patch(int argc, const char **argv, const char *prefix)
      	s_r_opt.def = "HEAD";
      	s_r_opt.revarg_opt = REVARG_COMMITTISH;
      
     -	if (base_auto)
    -+	if (auto_base == AUTO_BASE_ALWAYS)
    - 		base_commit = "auto";
    -+	else if (auto_base == AUTO_BASE_WHEN_ABLE)
    -+		base_commit = "if-able";
    - 
    +-		base_commit = "auto";
    +-
      	if (default_attach) {
      		rev.mime_boundary = default_attach;
    + 		rev.no_inline = 1;
     @@ builtin/log.c: int cmd_format_patch(int argc, const char **argv, const char *prefix)
    - 	memset(&bases, 0, sizeof(bases));
    - 	if (base_commit) {
    - 		struct commit *base = get_base_commit(base_commit, list, nr);
    --		reset_revision_walk();
    --		clear_object_flags(UNINTERESTING);
    --		prepare_bases(&bases, base, list, nr);
    -+		if (base) {
    -+			reset_revision_walk();
    -+			clear_object_flags(UNINTERESTING);
    -+			prepare_bases(&bases, base, list, nr);
    -+		}
      	}
      
    - 	if (in_reply_to || thread || cover_letter)
    + 	memset(&bases, 0, sizeof(bases));
    +-	if (base_commit) {
    +-		struct commit *base = get_base_commit(base_commit, list, nr);
    ++	base = get_base_commit(base_commit, list, nr);
    ++	if (base) {
    + 		reset_revision_walk();
    + 		clear_object_flags(UNINTERESTING);
    + 		prepare_bases(&bases, base, list, nr);
     
      ## t/t4014-format-patch.sh ##
     @@ t/t4014-format-patch.sh: test_expect_success 'format-patch errors out when history involves criss-cross'
      	test_must_fail 	git format-patch --base=auto -1
      '
      
    -+test_expect_success 'format-patch disable base=if-able when history involves criss-cross' '
    -+	git format-patch --base=if-able -1 >patch &&
    -+	! grep "^base-commit:" patch
    -+'
    -+
     +test_expect_success 'format-patch format.useAutoBase whenAble history involves criss-cross' '
     +	test_config format.useAutoBase whenAble &&
     +	git format-patch -1 >patch &&

Jacob Keller (1):
  format-patch: teach format.useAutoBase "whenAble" option

 Documentation/config/format.txt |   4 +-
 builtin/log.c                   | 130 ++++++++++++++++++++++++++------
 t/t4014-format-patch.sh         |  22 ++++++
 3 files changed, 130 insertions(+), 26 deletions(-)

-- 
2.28.0.497.g54e85e7af1ac


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH v2 1/1] format-patch: teach format.useAutoBase "whenAble" option
  2020-10-01 21:46 [PATCH v2 0/1] teach format.useAutoBase "whenAble" option Jacob Keller
@ 2020-10-01 21:46 ` Jacob Keller
  2020-10-01 22:21 ` [PATCH v2 0/1] " Junio C Hamano
  1 sibling, 0 replies; 3+ messages in thread
From: Jacob Keller @ 2020-10-01 21:46 UTC (permalink / raw)
  To: git; +Cc: Jacob Keller

From: Jacob Keller <jacob.keller@gmail.com>

The format.useAutoBase configuration option exists to allow users to
enable '--base=auto' for format-patch by default.

This can sometimes lead to poor workflow, due to unexpected failures
when attempting to format an ancient patch:

    $ git format-patch -1 <an old commit>
    fatal: base commit shouldn't be in revision list

This can be very confusing, as it is not necessarily immediately obvious
that the user requested a --base (since this was in the configuration,
not on the command line).

We do want --base=auto to fail when it cannot provide a suitable base,
as it would be equally confusing if a formatted patch did not include
the base information when it was requested.

Teach format.useAutoBase a new mode, "whenAble". This mode will cause
format-patch to attempt to include a base commit when it can. However,
if no valid base commit can be found, then format-patch will continue
formatting the patch without a base commit.

In order to avoid making yet another branch name unusable with --base,
do not teach --base=whenAble or --base=whenable.

Instead, refactor the base_commit option to use a callback, and rely on
the global configuration variable auto_base.

This does mean that a user cannot request this optional base commit
generation from the command line. However, this is likely not too
valuable. If the user requests base information manually, they will be
immediately informed of the failure to acquire a suitable base commit.
This allows the user to make an informed choice about whether to
continue the format.

Add tests to cover the new mode of operation for --base.

Signed-off-by: Jacob Keller <jacob.keller@gmail.com>
---
 Documentation/config/format.txt |   4 +-
 builtin/log.c                   | 130 ++++++++++++++++++++++++++------
 t/t4014-format-patch.sh         |  22 ++++++
 3 files changed, 130 insertions(+), 26 deletions(-)

diff --git a/Documentation/config/format.txt b/Documentation/config/format.txt
index 564e8091ba5c..c2efd8758a58 100644
--- a/Documentation/config/format.txt
+++ b/Documentation/config/format.txt
@@ -96,7 +96,9 @@ format.outputDirectory::
 
 format.useAutoBase::
 	A boolean value which lets you enable the `--base=auto` option of
-	format-patch by default.
+	format-patch by default. Can also be set to "whenAble" to allow
+	enabling `--base=auto` if a suitable base is available, but to skip
+	adding base info otherwise without the format dying.
 
 format.notes::
 	Provides the default value for the `--notes` option to
diff --git a/builtin/log.c b/builtin/log.c
index b8824d898f49..55a4fd9eafeb 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -805,9 +805,15 @@ enum cover_from_description {
 	COVER_FROM_AUTO
 };
 
+enum auto_base_setting {
+	AUTO_BASE_NEVER,
+	AUTO_BASE_ALWAYS,
+	AUTO_BASE_WHEN_ABLE
+};
+
 static enum thread_level thread;
 static int do_signoff;
-static int base_auto;
+static enum auto_base_setting auto_base;
 static char *from;
 static const char *signature = git_version_string;
 static const char *signature_file;
@@ -906,7 +912,11 @@ static int git_format_config(const char *var, const char *value, void *cb)
 	if (!strcmp(var, "format.outputdirectory"))
 		return git_config_string(&config_output_directory, var, value);
 	if (!strcmp(var, "format.useautobase")) {
-		base_auto = git_config_bool(var, value);
+		if (value && !strcasecmp(value, "whenAble")) {
+			auto_base = AUTO_BASE_WHEN_ABLE;
+			return 0;
+		}
+		auto_base = git_config_bool(var, value) ? AUTO_BASE_ALWAYS : AUTO_BASE_NEVER;
 		return 0;
 	}
 	if (!strcmp(var, "format.from")) {
@@ -1424,6 +1434,23 @@ static int from_callback(const struct option *opt, const char *arg, int unset)
 	return 0;
 }
 
+static int base_callback(const struct option *opt, const char *arg, int unset)
+{
+	const char **base_commit = opt->value;
+
+	if (unset) {
+		auto_base = AUTO_BASE_NEVER;
+		*base_commit = NULL;
+	} else if (!strcmp(arg, "auto")) {
+		auto_base = AUTO_BASE_ALWAYS;
+		*base_commit = NULL;
+	} else {
+		auto_base = AUTO_BASE_NEVER;
+		*base_commit = arg;
+	}
+	return 0;
+}
+
 struct base_tree_info {
 	struct object_id base_commit;
 	int nr_patch_id, alloc_patch_id;
@@ -1436,13 +1463,36 @@ static struct commit *get_base_commit(const char *base_commit,
 {
 	struct commit *base = NULL;
 	struct commit **rev;
-	int i = 0, rev_nr = 0;
+	int i = 0, rev_nr = 0, auto_select, die_on_failure;
 
-	if (base_commit && strcmp(base_commit, "auto")) {
+	switch (auto_base) {
+	case AUTO_BASE_NEVER:
+		if (base_commit) {
+			auto_select = 0;
+			die_on_failure = 1;
+		} else {
+			/* no base information is requested */
+			return NULL;
+		}
+		break;
+	case AUTO_BASE_ALWAYS:
+	case AUTO_BASE_WHEN_ABLE:
+		if (base_commit) {
+			BUG("requested automatic base selection but a commit was provided");
+		} else {
+			auto_select = 1;
+			die_on_failure = auto_base == AUTO_BASE_ALWAYS;
+		}
+		break;
+	default:
+		BUG("unexpected automatic base selection method");
+	}
+
+	if (!auto_select) {
 		base = lookup_commit_reference_by_name(base_commit);
 		if (!base)
 			die(_("unknown commit %s"), base_commit);
-	} else if ((base_commit && !strcmp(base_commit, "auto"))) {
+	} else {
 		struct branch *curr_branch = branch_get(NULL);
 		const char *upstream = branch_get_upstream(curr_branch, NULL);
 		if (upstream) {
@@ -1450,19 +1500,32 @@ static struct commit *get_base_commit(const char *base_commit,
 			struct commit *commit;
 			struct object_id oid;
 
-			if (get_oid(upstream, &oid))
-				die(_("failed to resolve '%s' as a valid ref"), upstream);
+			if (get_oid(upstream, &oid)) {
+				if (die_on_failure)
+					die(_("failed to resolve '%s' as a valid ref"), upstream);
+				else
+					return NULL;
+			}
 			commit = lookup_commit_or_die(&oid, "upstream base");
 			base_list = get_merge_bases_many(commit, total, list);
 			/* There should be one and only one merge base. */
-			if (!base_list || base_list->next)
-				die(_("could not find exact merge base"));
+			if (!base_list || base_list->next) {
+				if (die_on_failure) {
+					die(_("could not find exact merge base"));
+				} else {
+					free_commit_list(base_list);
+					return NULL;
+				}
+			}
 			base = base_list->item;
 			free_commit_list(base_list);
 		} else {
-			die(_("failed to get upstream, if you want to record base commit automatically,\n"
-			      "please use git branch --set-upstream-to to track a remote branch.\n"
-			      "Or you could specify base commit by --base=<base-commit-id> manually"));
+			if (die_on_failure)
+				die(_("failed to get upstream, if you want to record base commit automatically,\n"
+				      "please use git branch --set-upstream-to to track a remote branch.\n"
+				      "Or you could specify base commit by --base=<base-commit-id> manually"));
+			else
+				return NULL;
 		}
 	}
 
@@ -1479,8 +1542,14 @@ static struct commit *get_base_commit(const char *base_commit,
 		for (i = 0; i < rev_nr / 2; i++) {
 			struct commit_list *merge_base;
 			merge_base = get_merge_bases(rev[2 * i], rev[2 * i + 1]);
-			if (!merge_base || merge_base->next)
-				die(_("failed to find exact merge base"));
+			if (!merge_base || merge_base->next) {
+				if (die_on_failure) {
+					die(_("failed to find exact merge base"));
+				} else {
+					free(rev);
+					return NULL;
+				}
+			}
 
 			rev[i] = merge_base->item;
 		}
@@ -1490,12 +1559,24 @@ static struct commit *get_base_commit(const char *base_commit,
 		rev_nr = DIV_ROUND_UP(rev_nr, 2);
 	}
 
-	if (!in_merge_bases(base, rev[0]))
-		die(_("base commit should be the ancestor of revision list"));
+	if (!in_merge_bases(base, rev[0])) {
+		if (die_on_failure) {
+			die(_("base commit should be the ancestor of revision list"));
+		} else {
+			free(rev);
+			return NULL;
+		}
+	}
 
 	for (i = 0; i < total; i++) {
-		if (base == list[i])
-			die(_("base commit shouldn't be in revision list"));
+		if (base == list[i]) {
+			if (die_on_failure) {
+				die(_("base commit shouldn't be in revision list"));
+			} else {
+				free(rev);
+				return NULL;
+			}
+		}
 	}
 
 	free(rev);
@@ -1638,6 +1719,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 	char *branch_name = NULL;
 	char *base_commit = NULL;
 	struct base_tree_info bases;
+	struct commit *base;
 	int show_progress = 0;
 	struct progress *progress = NULL;
 	struct oid_array idiff_prev = OID_ARRAY_INIT;
@@ -1714,8 +1796,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 			    PARSE_OPT_OPTARG, thread_callback),
 		OPT_STRING(0, "signature", &signature, N_("signature"),
 			    N_("add a signature")),
-		OPT_STRING(0, "base", &base_commit, N_("base-commit"),
-			   N_("add prerequisite tree info to the patch series")),
+		OPT_CALLBACK_F(0, "base", &base_commit, N_("base-commit"),
+			       N_("add prerequisite tree info to the patch series"),
+			       0, base_callback),
 		OPT_FILENAME(0, "signature-file", &signature_file,
 				N_("add a signature from a file")),
 		OPT__QUIET(&quiet, N_("don't print the patch filenames")),
@@ -1752,9 +1835,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 	s_r_opt.def = "HEAD";
 	s_r_opt.revarg_opt = REVARG_COMMITTISH;
 
-	if (base_auto)
-		base_commit = "auto";
-
 	if (default_attach) {
 		rev.mime_boundary = default_attach;
 		rev.no_inline = 1;
@@ -2018,8 +2098,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 	}
 
 	memset(&bases, 0, sizeof(bases));
-	if (base_commit) {
-		struct commit *base = get_base_commit(base_commit, list, nr);
+	base = get_base_commit(base_commit, list, nr);
+	if (base) {
 		reset_revision_walk();
 		clear_object_flags(UNINTERESTING);
 		prepare_bases(&bases, base, list, nr);
diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh
index 958c2da56ec6..294e76c860cf 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.sh
@@ -2037,6 +2037,12 @@ test_expect_success 'format-patch errors out when history involves criss-cross'
 	test_must_fail 	git format-patch --base=auto -1
 '
 
+test_expect_success 'format-patch format.useAutoBase whenAble history involves criss-cross' '
+	test_config format.useAutoBase whenAble &&
+	git format-patch -1 >patch &&
+	! grep "^base-commit:" patch
+'
+
 test_expect_success 'format-patch format.useAutoBase option' '
 	git checkout local &&
 	test_config format.useAutoBase true &&
@@ -2047,6 +2053,16 @@ test_expect_success 'format-patch format.useAutoBase option' '
 	test_cmp expect actual
 '
 
+test_expect_success 'format-patch format.useAutoBase option with whenAble' '
+	git checkout local &&
+	test_config format.useAutoBase whenAble &&
+	git format-patch --stdout -1 >patch &&
+	grep "^base-commit:" patch >actual &&
+	git rev-parse upstream >commit-id-base &&
+	echo "base-commit: $(cat commit-id-base)" >expect &&
+	test_cmp expect actual
+'
+
 test_expect_success 'format-patch --base overrides format.useAutoBase' '
 	test_config format.useAutoBase true &&
 	git format-patch --stdout --base=HEAD~1 -1 >patch &&
@@ -2062,6 +2078,12 @@ test_expect_success 'format-patch --no-base overrides format.useAutoBase' '
 	! grep "^base-commit:" patch
 '
 
+test_expect_success 'format-patch --no-base overrides format.useAutoBase whenAble' '
+	test_config format.useAutoBase whenAble &&
+	git format-patch --stdout --no-base -1 >patch &&
+	! grep "^base-commit:" patch
+'
+
 test_expect_success 'format-patch --base with --attach' '
 	git format-patch --attach=mimemime --stdout --base=HEAD~ -1 >patch &&
 	sed -n -e "/^base-commit:/s/.*/1/p" -e "/^---*mimemime--$/s/.*/2/p" \
-- 
2.28.0.497.g54e85e7af1ac


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v2 0/1] teach format.useAutoBase "whenAble" option
  2020-10-01 21:46 [PATCH v2 0/1] teach format.useAutoBase "whenAble" option Jacob Keller
  2020-10-01 21:46 ` [PATCH v2 1/1] format-patch: " Jacob Keller
@ 2020-10-01 22:21 ` Junio C Hamano
  1 sibling, 0 replies; 3+ messages in thread
From: Junio C Hamano @ 2020-10-01 22:21 UTC (permalink / raw)
  To: Jacob Keller; +Cc: git, Jacob Keller

Jacob Keller <jacob.e.keller@intel.com> writes:

> From: Jacob Keller <jacob.keller@gmail.com>
>
> This is a v2 of [1] to address comments on the mailing list. Primarily the
> change is to remove the option for --base=if-able, since it is not as useful
> as the configuration option. If we think it is desirable, adding back a
> whenable or whenAble option is easy enough.

The simplification is a great thing to do, and I agree with the
rationale you wrote ...

>     +    This does mean that a user cannot request this optional base commit
>     +    generation from the command line. However, this is likely not too
>     +    valuable. If the user requests base information manually, they will be
>     +    immediately informed of the failure to acquire a suitable base commit.
>     +    This allows the user to make an informed choice about whether to
>     +    continue the format.

... which is sensible.

Thanks, will queue.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2020-10-01 22:22 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-01 21:46 [PATCH v2 0/1] teach format.useAutoBase "whenAble" option Jacob Keller
2020-10-01 21:46 ` [PATCH v2 1/1] format-patch: " Jacob Keller
2020-10-01 22:21 ` [PATCH v2 0/1] " Junio C Hamano

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).