git@vger.kernel.org list mirror (unofficial, one of many)
 help / color / Atom feed
From: Thomas Gummerer <t.gummerer@gmail.com>
To: Duy Nguyen <pclouds@gmail.com>
Cc: "Ævar Arnfjörð Bjarmason" <avarab@gmail.com>,
	"Junio C Hamano" <gitster@pobox.com>,
	"Git Mailing List" <git@vger.kernel.org>
Subject: Re: [RFC] Introduce two new commands, switch-branch and restore-paths
Date: Sun, 25 Nov 2018 22:20:21 +0000
Message-ID: <20181125222021.GL4883@hank.intra.tgummerer.com> (raw)
In-Reply-To: <20181120174554.GA29910@duynguyen.home>

On 11/20, Duy Nguyen wrote:
> On Mon, Nov 19, 2018 at 04:19:53PM +0100, Duy Nguyen wrote:
> > I promise to come back with something better (at least it still
> > sounds better in my mind). If that idea does not work out, we can
> > come back and see if we can improve this.
> 
> So this is it. The patch isn't pretty, mostly as a proof of
> concept. Just look at the three functions at the bottom of checkout.c,
> which is the main thing.
> 
> This patch tries to split "git checkout" command in two new ones:
> 
> - git switch-branch is all about switching branches
> - git restore-paths (maybe restore-file is better) for checking out
>   paths
> 
> The main idea is these two commands will co-exist with the good old
> 'git checkout', which will NOT be deprecated. Old timers will still
> use "git checkout". But new people should be introduced to the new two
> instead. And the new ones are just as capable as "git checkout".
> 
> Since the three commands will co-exist (with duplicate functionality),
> maintenance cost must be kept to minimum. The way I did this is simply
> split the command line options into three pieces: common,
> switch-branch and checkout-paths. "git checkout" has all three, the
> other two have common and another piece.
>
> With this, a new option added to git checkout will be automatically
> available in either switch-branch or checkout-paths. Bug fixes apply
> to all relevant commands.
> 
> Later on, we could start to add a bit more stuff in, e.g. some form of
> disambiguation is no longer needed when running as switch-branch, or
> restore-paths.
> 
> So, what do you think?

I like the idea of splitting those commands up, in fact it is
something I've been considering working on myself.  I do think we
should consider if we want to change the behaviour of those new
commands in any way compared to 'git checkout', since we're starting
with a clean slate.

One thing in particular that I have in mind is something I'm currently
working on, namely adding a --index flag to 'git checkout', which
would make 'git checkout' work in non-overlay mode (for more
discussion on that see also [*1*].  I got something working, that
needs to be polished a bit and am hoping to send that to the list
sometime soon.

I wonder if such the --index behaviour could be the default in
restore-paths command?

Most of the underlying machinery for 'checkout' could and should of
course still be shared between the commands.

*1*: <xmqq4loqplou.fsf@gitster.mtv.corp.google.com>

> -- 8< --
> diff --git a/builtin.h b/builtin.h
> index 6538932e99..6e321ec8a4 100644
> --- a/builtin.h
> +++ b/builtin.h
> @@ -214,6 +214,7 @@ extern int cmd_remote_fd(int argc, const char **argv, const char *prefix);
>  extern int cmd_repack(int argc, const char **argv, const char *prefix);
>  extern int cmd_rerere(int argc, const char **argv, const char *prefix);
>  extern int cmd_reset(int argc, const char **argv, const char *prefix);
> +extern int cmd_restore_paths(int argc, const char **argv, const char *prefix);
>  extern int cmd_rev_list(int argc, const char **argv, const char *prefix);
>  extern int cmd_rev_parse(int argc, const char **argv, const char *prefix);
>  extern int cmd_revert(int argc, const char **argv, const char *prefix);
> @@ -227,6 +228,7 @@ extern int cmd_show_index(int argc, const char **argv, const char *prefix);
>  extern int cmd_status(int argc, const char **argv, const char *prefix);
>  extern int cmd_stripspace(int argc, const char **argv, const char *prefix);
>  extern int cmd_submodule__helper(int argc, const char **argv, const char *prefix);
> +extern int cmd_switch_branch(int argc, const char **argv, const char *prefix);
>  extern int cmd_symbolic_ref(int argc, const char **argv, const char *prefix);
>  extern int cmd_tag(int argc, const char **argv, const char *prefix);
>  extern int cmd_tar_tree(int argc, const char **argv, const char *prefix);
> diff --git a/builtin/checkout.c b/builtin/checkout.c
> index acdafc6e4c..868ca3c223 100644
> --- a/builtin/checkout.c
> +++ b/builtin/checkout.c
> @@ -33,6 +33,16 @@ static const char * const checkout_usage[] = {
>  	NULL,
>  };
>  
> +static const char * const switch_branch_usage[] = {
> +	N_("git switch-branch [<options>] <branch>"),
> +	NULL,
> +};
> +
> +static const char * const restore_paths_usage[] = {
> +	N_("git restore-paths [<options>] [<branch>] -- <file>..."),
> +	NULL,
> +};
> +
>  struct checkout_opts {
>  	int patch_mode;
>  	int quiet;
> @@ -44,6 +54,7 @@ struct checkout_opts {
>  	int ignore_skipworktree;
>  	int ignore_other_worktrees;
>  	int show_progress;
> +	int dwim_new_local_branch;
>  	/*
>  	 * If new checkout options are added, skip_merge_working_tree
>  	 * should be updated accordingly.
> @@ -55,6 +66,7 @@ struct checkout_opts {
>  	int new_branch_log;
>  	enum branch_track track;
>  	struct diff_options diff_options;
> +	char *conflict_style;
>  
>  	int branch_exists;
>  	const char *prefix;
> @@ -1223,78 +1235,105 @@ static int checkout_branch(struct checkout_opts *opts,
>  	return switch_branches(opts, new_branch_info);
>  }
>  
> -int cmd_checkout(int argc, const char **argv, const char *prefix)
> +static struct option *add_common_options(struct checkout_opts *opts,
> +					 struct option *prevopts)
>  {
> -	struct checkout_opts opts;
> -	struct branch_info new_branch_info;
> -	char *conflict_style = NULL;
> -	int dwim_new_local_branch = 1;
> -	int dwim_remotes_matched = 0;
>  	struct option options[] = {
> -		OPT__QUIET(&opts.quiet, N_("suppress progress reporting")),
> -		OPT_STRING('b', NULL, &opts.new_branch, N_("branch"),
> +		OPT__QUIET(&opts->quiet, N_("suppress progress reporting")),
> +		OPT_BOOL(0, "ignore-skip-worktree-bits", &opts->ignore_skipworktree,
> +			 N_("do not limit pathspecs to sparse entries only")),
> +		{ OPTION_CALLBACK, 0, "recurse-submodules", NULL,
> +			    "checkout", "control recursive updating of submodules",
> +			    PARSE_OPT_OPTARG, option_parse_recurse_submodules_worktree_updater },
> +		OPT_BOOL(0, "progress", &opts->show_progress, N_("force progress reporting")),
> +		OPT__FORCE(&opts->force, N_("force checkout (throw away local modifications)"),
> +			   PARSE_OPT_NOCOMPLETE),
> +		OPT_STRING(0, "conflict", &opts->conflict_style, N_("style"),
> +			   N_("conflict style (merge or diff3)")),
> +		OPT_END()
> +	};
> +	struct option *newopts = parse_options_concat(prevopts, options);
> +	free(prevopts);
> +	return newopts;
> +}
> +
> +static struct option *add_switch_branch_options(struct checkout_opts *opts,
> +						struct option *prevopts)
> +{
> +	struct option options[] = {
> +		OPT_STRING('b', NULL, &opts->new_branch, N_("branch"),
>  			   N_("create and checkout a new branch")),
> -		OPT_STRING('B', NULL, &opts.new_branch_force, N_("branch"),
> +		OPT_STRING('B', NULL, &opts->new_branch_force, N_("branch"),
>  			   N_("create/reset and checkout a branch")),
> -		OPT_BOOL('l', NULL, &opts.new_branch_log, N_("create reflog for new branch")),
> -		OPT_BOOL(0, "detach", &opts.force_detach, N_("detach HEAD at named commit")),
> -		OPT_SET_INT('t', "track",  &opts.track, N_("set upstream info for new branch"),
> +		OPT_BOOL('l', NULL, &opts->new_branch_log, N_("create reflog for new branch")),
> +		OPT_BOOL(0, "detach", &opts->force_detach, N_("detach HEAD at named commit")),
> +		OPT_SET_INT('t', "track",  &opts->track, N_("set upstream info for new branch"),
>  			BRANCH_TRACK_EXPLICIT),
> -		OPT_STRING(0, "orphan", &opts.new_orphan_branch, N_("new-branch"), N_("new unparented branch")),
> -		OPT_SET_INT_F('2', "ours", &opts.writeout_stage,
> +		OPT_STRING(0, "orphan", &opts->new_orphan_branch, N_("new-branch"), N_("new unparented branch")),
> +		OPT_BOOL('m', "merge", &opts->merge, N_("perform a 3-way merge with the new branch")),
> +		OPT_HIDDEN_BOOL(0, "guess", &opts->dwim_new_local_branch,
> +				N_("second guess 'git checkout <no-such-branch>'")),
> +		OPT_BOOL(0, "ignore-other-worktrees", &opts->ignore_other_worktrees,
> +			 N_("do not check if another worktree is holding the given ref")),
> +		OPT_END()
> +	};
> +	struct option *newopts = parse_options_concat(prevopts, options);
> +	free(prevopts);
> +	return newopts;
> +}
> +
> +static struct option *add_checkout_path_options(struct checkout_opts *opts,
> +						struct option *prevopts)
> +{
> +	struct option options[] = {
> +		OPT_SET_INT_F('2', "ours", &opts->writeout_stage,
>  			      N_("checkout our version for unmerged files"),
>  			      2, PARSE_OPT_NONEG),
> -		OPT_SET_INT_F('3', "theirs", &opts.writeout_stage,
> +		OPT_SET_INT_F('3', "theirs", &opts->writeout_stage,
>  			      N_("checkout their version for unmerged files"),
>  			      3, PARSE_OPT_NONEG),
> -		OPT__FORCE(&opts.force, N_("force checkout (throw away local modifications)"),
> -			   PARSE_OPT_NOCOMPLETE),
> -		OPT_BOOL('m', "merge", &opts.merge, N_("perform a 3-way merge with the new branch")),
> -		OPT_BOOL_F(0, "overwrite-ignore", &opts.overwrite_ignore,
> -			   N_("update ignored files (default)"),
> -			   PARSE_OPT_NOCOMPLETE),
> -		OPT_STRING(0, "conflict", &conflict_style, N_("style"),
> -			   N_("conflict style (merge or diff3)")),
> -		OPT_BOOL('p', "patch", &opts.patch_mode, N_("select hunks interactively")),
> -		OPT_BOOL(0, "ignore-skip-worktree-bits", &opts.ignore_skipworktree,
> -			 N_("do not limit pathspecs to sparse entries only")),
> -		OPT_HIDDEN_BOOL(0, "guess", &dwim_new_local_branch,
> -				N_("second guess 'git checkout <no-such-branch>'")),
> -		OPT_BOOL(0, "ignore-other-worktrees", &opts.ignore_other_worktrees,
> -			 N_("do not check if another worktree is holding the given ref")),
> -		{ OPTION_CALLBACK, 0, "recurse-submodules", NULL,
> -			    "checkout", "control recursive updating of submodules",
> -			    PARSE_OPT_OPTARG, option_parse_recurse_submodules_worktree_updater },
> -		OPT_BOOL(0, "progress", &opts.show_progress, N_("force progress reporting")),
> -		OPT_END(),
> +		OPT_BOOL('p', "patch", &opts->patch_mode, N_("select hunks interactively")),
> +		OPT_END()
>  	};
> +	struct option *newopts = parse_options_concat(prevopts, options);
> +	free(prevopts);
> +	return newopts;
> +}
>  
> -	memset(&opts, 0, sizeof(opts));
> +static int checkout_main(int argc, const char **argv, const char *prefix,
> +			 struct checkout_opts *opts, struct option *options,
> +			 const char * const usagestr[])
> +{
> +	struct branch_info new_branch_info;
> +	int dwim_remotes_matched = 0;
> +
> +	memset(opts, 0, sizeof(*opts));
> +	opts->dwim_new_local_branch = 1;
>  	memset(&new_branch_info, 0, sizeof(new_branch_info));
> -	opts.overwrite_ignore = 1;
> -	opts.prefix = prefix;
> -	opts.show_progress = -1;
> +	opts->overwrite_ignore = 1;
> +	opts->prefix = prefix;
> +	opts->show_progress = -1;
>  
> -	git_config(git_checkout_config, &opts);
> +	git_config(git_checkout_config, opts);
>  
> -	opts.track = BRANCH_TRACK_UNSPECIFIED;
> +	opts->track = BRANCH_TRACK_UNSPECIFIED;
>  
> -	argc = parse_options(argc, argv, prefix, options, checkout_usage,
> +	argc = parse_options(argc, argv, prefix, options, usagestr,
>  			     PARSE_OPT_KEEP_DASHDASH);
>  
> -	if (opts.show_progress < 0) {
> -		if (opts.quiet)
> -			opts.show_progress = 0;
> +	if (opts->show_progress < 0) {
> +		if (opts->quiet)
> +			opts->show_progress = 0;
>  		else
> -			opts.show_progress = isatty(2);
> +			opts->show_progress = isatty(2);
>  	}
>  
> -	if (conflict_style) {
> -		opts.merge = 1; /* implied */
> -		git_xmerge_config("merge.conflictstyle", conflict_style, NULL);
> +	if (opts->conflict_style) {
> +		opts->merge = 1; /* implied */
> +		git_xmerge_config("merge.conflictstyle", opts->conflict_style, NULL);
>  	}
>  
> -	if ((!!opts.new_branch + !!opts.new_branch_force + !!opts.new_orphan_branch) > 1)
> +	if ((!!opts->new_branch + !!opts->new_branch_force + !!opts->new_orphan_branch) > 1)
>  		die(_("-b, -B and --orphan are mutually exclusive"));
>  
>  	/*
> @@ -1302,14 +1341,14 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
>  	 * and new_branch_force and new_orphan_branch will tell us which one of
>  	 * -b/-B/--orphan is being used.
>  	 */
> -	if (opts.new_branch_force)
> -		opts.new_branch = opts.new_branch_force;
> +	if (opts->new_branch_force)
> +		opts->new_branch = opts->new_branch_force;
>  
> -	if (opts.new_orphan_branch)
> -		opts.new_branch = opts.new_orphan_branch;
> +	if (opts->new_orphan_branch)
> +		opts->new_branch = opts->new_orphan_branch;
>  
>  	/* --track without -b/-B/--orphan should DWIM */
> -	if (opts.track != BRANCH_TRACK_UNSPECIFIED && !opts.new_branch) {
> +	if (opts->track != BRANCH_TRACK_UNSPECIFIED && !opts->new_branch) {
>  		const char *argv0 = argv[0];
>  		if (!argc || !strcmp(argv0, "--"))
>  			die(_("--track needs a branch name"));
> @@ -1318,7 +1357,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
>  		argv0 = strchr(argv0, '/');
>  		if (!argv0 || !argv0[1])
>  			die(_("missing branch name; try -b"));
> -		opts.new_branch = argv0 + 1;
> +		opts->new_branch = argv0 + 1;
>  	}
>  
>  	/*
> @@ -1337,56 +1376,56 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
>  	if (argc) {
>  		struct object_id rev;
>  		int dwim_ok =
> -			!opts.patch_mode &&
> -			dwim_new_local_branch &&
> -			opts.track == BRANCH_TRACK_UNSPECIFIED &&
> -			!opts.new_branch;
> +			!opts->patch_mode &&
> +			opts->dwim_new_local_branch &&
> +			opts->track == BRANCH_TRACK_UNSPECIFIED &&
> +			!opts->new_branch;
>  		int n = parse_branchname_arg(argc, argv, dwim_ok,
> -					     &new_branch_info, &opts, &rev,
> +					     &new_branch_info, opts, &rev,
>  					     &dwim_remotes_matched);
>  		argv += n;
>  		argc -= n;
>  	}
>  
>  	if (argc) {
> -		parse_pathspec(&opts.pathspec, 0,
> -			       opts.patch_mode ? PATHSPEC_PREFIX_ORIGIN : 0,
> +		parse_pathspec(&opts->pathspec, 0,
> +			       opts->patch_mode ? PATHSPEC_PREFIX_ORIGIN : 0,
>  			       prefix, argv);
>  
> -		if (!opts.pathspec.nr)
> +		if (!opts->pathspec.nr)
>  			die(_("invalid path specification"));
>  
>  		/*
>  		 * Try to give more helpful suggestion.
>  		 * new_branch && argc > 1 will be caught later.
>  		 */
> -		if (opts.new_branch && argc == 1)
> +		if (opts->new_branch && argc == 1)
>  			die(_("'%s' is not a commit and a branch '%s' cannot be created from it"),
> -				argv[0], opts.new_branch);
> +				argv[0], opts->new_branch);
>  
> -		if (opts.force_detach)
> +		if (opts->force_detach)
>  			die(_("git checkout: --detach does not take a path argument '%s'"),
>  			    argv[0]);
>  
> -		if (1 < !!opts.writeout_stage + !!opts.force + !!opts.merge)
> +		if (1 < !!opts->writeout_stage + !!opts->force + !!opts->merge)
>  			die(_("git checkout: --ours/--theirs, --force and --merge are incompatible when\n"
>  			      "checking out of the index."));
>  	}
>  
> -	if (opts.new_branch) {
> +	if (opts->new_branch) {
>  		struct strbuf buf = STRBUF_INIT;
>  
> -		if (opts.new_branch_force)
> -			opts.branch_exists = validate_branchname(opts.new_branch, &buf);
> +		if (opts->new_branch_force)
> +			opts->branch_exists = validate_branchname(opts->new_branch, &buf);
>  		else
> -			opts.branch_exists =
> -				validate_new_branchname(opts.new_branch, &buf, 0);
> +			opts->branch_exists =
> +				validate_new_branchname(opts->new_branch, &buf, 0);
>  		strbuf_release(&buf);
>  	}
>  
>  	UNLEAK(opts);
> -	if (opts.patch_mode || opts.pathspec.nr) {
> -		int ret = checkout_paths(&opts, new_branch_info.name);
> +	if (opts->patch_mode || opts->pathspec.nr) {
> +		int ret = checkout_paths(opts, new_branch_info.name);
>  		if (ret && dwim_remotes_matched > 1 &&
>  		    advice_checkout_ambiguous_remote_branch_name)
>  			advise(_("'%s' matched more than one remote tracking branch.\n"
> @@ -1405,6 +1444,49 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
>  			       dwim_remotes_matched);
>  		return ret;
>  	} else {
> -		return checkout_branch(&opts, &new_branch_info);
> +		return checkout_branch(opts, &new_branch_info);
>  	}
>  }
> +
> +int cmd_checkout(int argc, const char **argv, const char *prefix)
> +{
> +	struct checkout_opts opts;
> +	struct option *options = NULL;
> +	int ret;
> +
> +	options = add_common_options(&opts, options);
> +	options = add_switch_branch_options(&opts, options);
> +	options = add_checkout_path_options(&opts, options);
> +	ret = checkout_main(argc, argv, prefix, &opts,
> +			    options, checkout_usage);
> +	FREE_AND_NULL(options);
> +	return ret;
> +}
> +
> +int cmd_switch_branch(int argc, const char **argv, const char *prefix)
> +{
> +	struct checkout_opts opts;
> +	struct option *options = NULL;
> +	int ret;
> +
> +	options = add_common_options(&opts, options);
> +	options = add_switch_branch_options(&opts, options);
> +	ret = checkout_main(argc, argv, prefix, &opts,
> +			    options, switch_branch_usage);
> +	FREE_AND_NULL(options);
> +	return ret;
> +}
> +
> +int cmd_restore_paths(int argc, const char **argv, const char *prefix)
> +{
> +	struct checkout_opts opts;
> +	struct option *options = NULL;
> +	int ret;
> +
> +	options = add_common_options(&opts, options);
> +	options = add_checkout_path_options(&opts, options);
> +	ret = checkout_main(argc, argv, prefix, &opts,
> +			    options, restore_paths_usage);
> +	FREE_AND_NULL(options);
> +	return ret;
> +}
> diff --git a/git.c b/git.c
> index 2f604a41ea..e8a76a99da 100644
> --- a/git.c
> +++ b/git.c
> @@ -542,6 +542,7 @@ static struct cmd_struct commands[] = {
>  	{ "replace", cmd_replace, RUN_SETUP },
>  	{ "rerere", cmd_rerere, RUN_SETUP },
>  	{ "reset", cmd_reset, RUN_SETUP },
> +	{ "restore-paths", cmd_restore_paths, RUN_SETUP | NEED_WORK_TREE },
>  	{ "rev-list", cmd_rev_list, RUN_SETUP | NO_PARSEOPT },
>  	{ "rev-parse", cmd_rev_parse, NO_PARSEOPT },
>  	{ "revert", cmd_revert, RUN_SETUP | NEED_WORK_TREE },
> @@ -557,6 +558,7 @@ static struct cmd_struct commands[] = {
>  	{ "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
>  	{ "stripspace", cmd_stripspace },
>  	{ "submodule--helper", cmd_submodule__helper, RUN_SETUP | SUPPORT_SUPER_PREFIX | NO_PARSEOPT },
> +	{ "switch-branch", cmd_switch_branch, RUN_SETUP | NEED_WORK_TREE },
>  	{ "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
>  	{ "tag", cmd_tag, RUN_SETUP | DELAY_PAGER_CONFIG },
>  	{ "unpack-file", cmd_unpack_file, RUN_SETUP | NO_PARSEOPT },
> diff --git a/parse-options-cb.c b/parse-options-cb.c
> index 8c9edce52f..c609d52926 100644
> --- a/parse-options-cb.c
> +++ b/parse-options-cb.c
> @@ -126,7 +126,7 @@ struct option *parse_options_concat(struct option *a, struct option *b)
>  	struct option *ret;
>  	size_t i, a_len = 0, b_len = 0;
>  
> -	for (i = 0; a[i].type != OPTION_END; i++)
> +	for (i = 0; a && a[i].type != OPTION_END; i++)
>  		a_len++;
>  	for (i = 0; b[i].type != OPTION_END; i++)
>  		b_len++;
> -- 8< --

  reply index

Thread overview: 110+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-11-10 13:35 [PATCH/RFC] checkout: print something when checking out paths Nguyễn Thái Ngọc Duy
2018-11-12  6:21 ` Junio C Hamano
2018-11-12 16:27   ` Duy Nguyen
2018-11-12 20:15     ` Junio C Hamano
2018-11-19 13:08     ` Ævar Arnfjörð Bjarmason
2018-11-19 15:19       ` Duy Nguyen
2018-11-20  2:53         ` Junio C Hamano
2018-11-20 17:45         ` [RFC] Introduce two new commands, switch-branch and restore-paths Duy Nguyen
2018-11-25 22:20           ` Thomas Gummerer [this message]
2018-11-26  3:03             ` Junio C Hamano
2018-11-26 15:37               ` Duy Nguyen
2018-11-26 16:00           ` Ævar Arnfjörð Bjarmason
2018-11-26 16:08             ` Duy Nguyen
2018-11-26 23:10             ` Stefan Beller
2018-11-27  0:34               ` Junio C Hamano
2018-11-27 16:52           ` [PATCH/RFC v2 0/7] Introduce new commands switch-branch and checkout-files Nguyễn Thái Ngọc Duy
2018-11-27 16:52             ` [PATCH v2 1/7] parse-options: allow parse_options_concat(NULL, options) Nguyễn Thái Ngọc Duy
2018-11-27 19:43               ` Stefan Beller
2018-11-28 15:22                 ` Duy Nguyen
2018-11-28  4:47               ` Junio C Hamano
2018-11-27 16:52             ` [PATCH v2 2/7] checkout: make "opts" in cmd_checkout() a pointer Nguyễn Thái Ngọc Duy
2018-11-27 16:52             ` [PATCH v2 3/7] checkout: move 'confict_style' to checkout_opts Nguyễn Thái Ngọc Duy
2018-11-27 19:50               ` Stefan Beller
2018-11-27 16:52             ` [PATCH v2 4/7] checkout: move dwim_new_local_branch " Nguyễn Thái Ngọc Duy
2018-11-27 19:52               ` Stefan Beller
2018-11-27 16:52             ` [PATCH v2 5/7] checkout: split options[] array in three pieces Nguyễn Thái Ngọc Duy
2018-11-29  6:29               ` Junio C Hamano
2018-11-27 16:52             ` [PATCH v2 6/7] checkout: split into switch-branch and checkout-files Nguyễn Thái Ngọc Duy
2018-11-28  6:03               ` Junio C Hamano
2018-11-28 15:30                 ` Duy Nguyen
2018-11-28 19:08                   ` Stefan Beller
2018-11-28 19:18                     ` Duy Nguyen
2018-11-29  5:55                     ` Junio C Hamano
2018-11-28 23:22                   ` Stefan Xenos
2018-11-28 23:26                     ` Stefan Xenos
2018-11-28 23:37                       ` Stefan Xenos
2018-11-29  5:59                       ` Junio C Hamano
2018-11-29 15:36                         ` Duy Nguyen
2018-11-29 15:46                     ` Duy Nguyen
2018-11-29 18:14                       ` Stefan Beller
2018-11-29 18:30                         ` Duy Nguyen
2018-11-29 19:29                       ` Stefan Xenos
2018-11-27 16:52             ` [PATCH v2 7/7] Suggest other commands instead of "git checkout" Nguyễn Thái Ngọc Duy
2018-11-28  6:04               ` Junio C Hamano
2018-11-28 15:33                 ` Duy Nguyen
2018-11-29  6:05                   ` Junio C Hamano
2018-11-28 20:01             ` [PATCH/RFC v2 0/7] Introduce new commands switch-branch and checkout-files Duy Nguyen
2018-11-28 20:09               ` Duy Nguyen
2018-11-28 20:30                 ` Stefan Beller
2018-11-29 15:33                   ` Duy Nguyen
2018-12-03 21:42                     ` Stefan Beller
2018-11-30  1:47                 ` Junio C Hamano
     [not found]               ` <CAPL8Ziuj7Ffmdvz6NZWSJ+vzAtxFQhO1cfY2wmXm16J_8sY5fw@mail.gmail.com>
2018-11-28 22:53                 ` Stefan Xenos
2018-11-29  6:14                   ` Junio C Hamano
2018-11-29 21:58             ` [PATCH/RFC v3 00/14] Introduce new commands switch-branch and restore-files Nguyễn Thái Ngọc Duy
2018-11-29 21:58               ` [PATCH v3 01/14] git-checkout.txt: fix one syntax line Nguyễn Thái Ngọc Duy
2018-11-29 21:58               ` [PATCH v3 02/14] git-checkout.txt: split detached head section out Nguyễn Thái Ngọc Duy
2018-11-29 21:58               ` [PATCH v3 03/14] checkout: factor out some code in parse_branchname_arg() Nguyễn Thái Ngọc Duy
2018-11-29 21:58               ` [PATCH v3 04/14] checkout: make "opts" in cmd_checkout() a pointer Nguyễn Thái Ngọc Duy
2018-11-29 21:58               ` [PATCH v3 05/14] checkout: move 'confict_style' and 'dwim_..' to checkout_opts Nguyễn Thái Ngọc Duy
2018-11-29 21:58               ` [PATCH v3 06/14] checkout: split options[] array in three pieces Nguyễn Thái Ngọc Duy
2018-11-29 21:58               ` [PATCH v3 07/14] checkout: split into switch-branch and restore-files Nguyễn Thái Ngọc Duy
2018-12-04  0:45                 ` Elijah Newren
2018-12-04  3:33                   ` Junio C Hamano
2018-12-04 16:21                   ` Duy Nguyen
2018-12-04 17:43                     ` Elijah Newren
2018-12-04 18:17                       ` Duy Nguyen
2018-12-05  2:25                         ` Junio C Hamano
2018-12-05  4:45                           ` Elijah Newren
2018-12-05  6:56                             ` Junio C Hamano
2018-12-05  2:14                     ` Junio C Hamano
2018-12-05  4:22                       ` Elijah Newren
2018-11-29 21:58               ` [PATCH v3 08/14] switch-branch: better names for -b and -B Nguyễn Thái Ngọc Duy
2018-11-29 21:58               ` [PATCH v3 09/14] switch-branch: stop accepting pathspec Nguyễn Thái Ngọc Duy
2018-11-29 21:58               ` [PATCH v3 10/14] switch-branch: reject "do nothing" case Nguyễn Thái Ngọc Duy
2018-11-29 21:58               ` [PATCH v3 11/14] switch-branch: only allow explicit detached HEAD Nguyễn Thái Ngọc Duy
2019-03-10 19:32                 ` Eckhard Maaß
2019-03-11 14:27                   ` Duy Nguyen
2018-11-29 21:58               ` [PATCH v3 12/14] restore-files: take tree-ish from --from option instead Nguyễn Thái Ngọc Duy
2018-11-29 21:58               ` [PATCH v3 13/14] restore-files: make pathspec mandatory Nguyễn Thái Ngọc Duy
2018-11-29 21:58               ` [PATCH v3 14/14] doc: promote "git switch-branch" and "git restore-files" Nguyễn Thái Ngọc Duy
2018-11-29 23:05               ` [PATCH/RFC v3 00/14] Introduce new commands switch-branch and restore-files Ævar Arnfjörð Bjarmason
2018-11-29 23:18                 ` Ævar Arnfjörð Bjarmason
2018-11-29 23:37                 ` Dan Fabulich
2018-11-30  0:16                 ` Dan Fabulich
2018-11-30  6:49                   ` Duy Nguyen
2018-11-30  5:37                 ` Duy Nguyen
2018-11-30  6:47                   ` Junio C Hamano
2018-11-30 11:29                   ` Ævar Arnfjörð Bjarmason
2018-11-30 12:10                     ` Duy Nguyen
2018-11-30  2:16               ` Junio C Hamano
2018-11-30  5:41                 ` Duy Nguyen
2018-11-30  6:46                   ` Junio C Hamano
2018-12-02 18:58                 ` Thomas Gummerer
2018-12-02 19:46                   ` Junio C Hamano
2018-12-04  1:28               ` Elijah Newren
2018-12-04 16:27                 ` Duy Nguyen
2018-12-04 17:45                   ` Elijah Newren
2018-12-04 18:22                     ` Duy Nguyen
2018-12-04 18:31                       ` Elijah Newren
2018-12-04 18:39                         ` Duy Nguyen
2018-12-04 21:18                   ` Eric Sunshine
2018-11-13 18:28 ` [PATCH v2] checkout: print something when checking out paths Nguyễn Thái Ngọc Duy
2018-11-14 10:12   ` Junio C Hamano
2018-11-14 15:31     ` Duy Nguyen
2019-01-28 21:58   ` Junio C Hamano
2019-01-29  1:26     ` Duy Nguyen
2019-02-06  2:51     ` [PATCH 0/2] nd/checkout-noisy updates Nguyễn Thái Ngọc Duy
2019-02-06  2:51       ` [PATCH 1/2] checkout: update count-checkouts messages Nguyễn Thái Ngọc Duy
2019-02-06  2:51       ` [PATCH 2/2] checkout: count and print -m paths separately Nguyễn Thái Ngọc Duy

Reply instructions:

You may reply publicly 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=20181125222021.GL4883@hank.intra.tgummerer.com \
    --to=t.gummerer@gmail.com \
    --cc=avarab@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=pclouds@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

Example config snippet for mirrors

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.io/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.git