This series adds a new command "switch" for switching branches, an
alternative for "git checkout".
v2 fixes the comments I got from v1. I think the range-diff below
summarizes it better than I do. No major changes though.
Range-diff dựa trên v1:
1: 6d550b443c ! 1: 2283204090 checkout: split part of it to new command
switch
@@ -148,24 +148,33 @@
+--------
+[verse]
+'git switch' [<options>] [--guess] <branch>
-+'git switch' [<options>] --detach [<start_point>>]
-+'git switch' [<options>] [[-c|-C|--orphan] <new_branch>] [<start_point>]
++'git switch' [<options>] --detach [<start-point>]
++'git switch' [<options>] (-c|-C|--orphan) <new-branch> [<start-point>]
+
+DESCRIPTION
+-----------
-+Switch to a specified branch and update files in the working tree to
-+match it. Optionally a new branch could be created with either `-c` or
-+`-C`, or detach from any branch with `--detach`, along with switching.
++Switch to a specified branch. The working tree and the index are
++updated to match the branch. All new commits will be added to the tip
++of this branch.
++
++Optionally a new branch could be created with either `-c` or `-C`, or
++detach the working tree from any branch with `--detach`, along with
++switching.
++
++Switching branches does not require a clean index and working tree
++(i.e. no differences compared to 'HEAD'). The operation is aborted
++however if the switch leads to loss of local changes, unless told
++otherwise.
+
+OPTIONS
+-------
+<branch>::
+ Branch to switch to.
+
-+<new_branch>::
++<new-branch>::
+ Name for the new branch.
+
-+<start_point>::
++<start-point>::
+ The name of a commit at which to switch to before creating a
+ new branch or detach from.
++
@@ -177,17 +186,27 @@
+base of `A` and `B` if there is exactly one merge base. You can leave
+out at most one of `A` and `B`, in which case it defaults to `HEAD`.
+
-+-c <new_branch>::
-+--create <new_branch>::
-+ Create a new branch named <new_branch> and start it at
-+ <start_point>; see linkgit:git-branch[1] for details.
++-c <new-branch>::
++--create <new-branch>::
++ Create a new branch named <new-branch> starting at
++ <start-point> before switching to the branch. This is a
++ convenient shortcut for:
+++
++------------
++$ git branch <new-branch>
++$ git switch <new-branch>
++------------
+
-+-C <new_branch>::
-+--force-create <new_branch>::
-+ Creates the branch <new_branch> and start it at <start_point>;
-+ if it already exists, then reset it to <start_point>. This is
-+ equivalent to running "git branch" with "-f"; see
-+ linkgit:git-branch[1] for details.
++-C <new-branch>::
++--force-create <new-branch>::
++ Similar to `--create` except that if <new-branch> already
++ exists, it will be reset to <start-point>. This is a
++ convenient shortcut for:
+++
++------------
++$ git branch -f <new-branch>
++$ git switch <new-branch>
++------------
+
+-d::
+--detach::
@@ -220,7 +239,9 @@
+-f::
+--force::
+ Proceed even if the index or the working tree differs from
-+ HEAD. This is used to throw away local changes.
++ HEAD. Both the index and working tree are restored to match
++ the switching target. This is used to throw away local
++ changes.
+
+--[no-]progress::
+ Progress status is reported on the standard error stream
@@ -270,9 +291,9 @@
+ "merge" (default) and "diff3" (in addition to what is shown by
+ "merge" style, shows the original contents).
+
-+--orphan <new_branch>::
-+ Create a new 'orphan' branch, named <new_branch>, started from
-+ <start_point> and switch to it. See explanation of the same
++--orphan <new-branch>::
++ Create a new 'orphan' branch, named <new-branch>, started from
++ <start-point> and switch to it. See explanation of the same
+ option in linkgit:git-checkout[1] for details.
+
+--ignore-other-worktrees::
2: e2f94df471 ! 2: deceb221dc switch: better names for -b and -B
@@ -61,7 +61,7 @@
+ OPT_STRING('c', "create", &opts.new_branch, N_("branch"),
+ N_("create and switch to a new branch")),
+ OPT_STRING('C', "force-create", &opts.new_branch_force,
N_("branch"),
-+ N_("create/reset and switch to a new branch")),
++ N_("create/reset and switch to a branch")),
+ OPT_END()
+ };
int ret;
3: b3d431a97f = 3: 08f28e9726 switch: remove -l
4: 26738818fa = 4: 9ee4852c8b switch: stop accepting pathspec
5: 79ebe7a68c ! 5: 0a7ea4b33b switch: reject "do nothing" case
@@ -32,7 +32,7 @@
+ !new_branch_info->name &&
+ !opts->new_branch &&
+ !opts->force_detach)
-+ die(_("nothing to do"));
++ die(_("missing branch or commit argument"));
+
if (new_branch_info->path && !opts->force_detach && !opts->new_branch &&
!opts->ignore_other_worktrees) {
6: bc36ac8510 ! 6: eedf82c72b switch: only allow explicit detached HEAD
@@ -26,7 +26,7 @@
int ignore_skipworktree;
@@
!opts->force_detach)
- die(_("nothing to do"));
+ die(_("missing branch or commit argument"));
+ if (!opts->implicit_detach &&
+ !opts->force_detach &&
7: 1a761ce8e5 = 7: 9314ff16c9 switch: add short option for --detach
8: 738c560eb9 ! 8: 9d8e461df2 switch: no implicit dwim, use --guess to dwim
@@ -143,7 +143,7 @@
@@
N_("create and switch to a new branch")),
OPT_STRING('C', "force-create", &opts.new_branch_force,
N_("branch"),
- N_("create/reset and switch to a new branch")),
+ N_("create/reset and switch to a branch")),
+ OPT_BOOL('g', "guess", &opts.dwim_new_local_branch,
+ N_("second guess 'git switch <no-such-branch>'")),
OPT_END()
9: 456e9340f1 = 9: 749665c457 switch: no worktree status unless real branch
switch happens
10: cdd132a7e2 ! 10: e4e0b397eb t: add tests for switch
@@ -51,9 +51,7 @@
+test_expect_success 'switch and create branch' '
+ test_when_finished git switch master &&
+ git switch -c temp master^ &&
-+ git rev-parse master^ >expected &&
-+ git rev-parse refs/heads/temp >actual &&
-+ test_cmp expected actual &&
++ test_cmp_rev master^ refs/heads/temp &&
+ echo refs/heads/temp >expected-branch &&
+ git symbolic-ref HEAD >actual-branch &&
+ test_cmp expected-branch actual-branch
@@ -63,9 +61,7 @@
+ test_when_finished git switch master &&
+ git switch --detach master &&
+ git switch -C temp &&
-+ git rev-parse master >expected &&
-+ git rev-parse refs/heads/temp >actual &&
-+ test_cmp expected actual &&
++ test_cmp_rev master refs/heads/temp &&
+ echo refs/heads/temp >expected-branch &&
+ git symbolic-ref HEAD >actual-branch &&
+ test_cmp expected-branch actual-branch
11: 96a97fcab4 = 11: b9a7662271 completion: support switch
12: 8d984bc684 ! 12: 7449a0c4cc doc: promote "git switch"
@@ -40,14 +40,18 @@
+
<1> This step and the next one could be combined into a single step with
@@
+ NOTES
-----
- If you are creating a branch that you want to checkout immediately, it is
+-If you are creating a branch that you want to checkout immediately, it is
-easier to use the git checkout command with its `-b` option to create
-+easier to use the "git switch" command with its `-c` option to create
- a branch and check it out with a single command.
+-a branch and check it out with a single command.
++If you are creating a branch that you want to switch to immediately,
++it is easier to use the "git switch" command with its `-c` option to
++do the same thing with a single command.
The options `--contains`, `--no-contains`, `--merged` and `--no-merged`
+ serve four related but different purposes:
diff --git a/Documentation/git-check-ref-format.txt
b/Documentation/git-check-ref-format.txt
--- a/Documentation/git-check-ref-format.txt
@@ -473,9 +477,11 @@
------------------------------------------------------
-The `git checkout` command normally expects a branch head, but will also
+-accept an arbitrary commit; for example, you can check out the commit
+-referenced by a tag:
+The `git switch` command normally expects a branch head, but will also
- accept an arbitrary commit; for example, you can check out the commit
- referenced by a tag:
++accept an arbitrary commit when invoked with --detach; for example,
++you can check out the commit referenced by a tag:
------------------------------------------------
-$ git checkout v2.6.17
@@ -628,36 +634,23 @@
{
const char *fmt =
- _("Note: checking out '%s'.\n\n"
-+ _("Note: checking out '%s'.\n"
++ _("Note: switching to '%s'.\n"
+ "\n"
"You are in 'detached HEAD' state. You can look around, make
experimental\n"
"changes and commit them, and you can discard any commits you make in
this\n"
- "state without impacting any branches by performing another
checkout.\n\n"
-+ "state without impacting any branches by performing another checkout.\n"
++ "state without impacting any branches by switching back to a branch.\n"
+ "\n"
"If you want to create a new branch to retain commits you create, you
may\n"
- "do so (now or later) by using -b with the checkout command again.
Example:\n\n"
- " git checkout -b <new-branch-name>\n\n");
-+ "do so (now or later) by using -b with the checkout command again.
Example:\n"
++ "do so (now or later) by using -c with the switch command. Example:\n"
+ "\n"
+ " git switch -c <new-branch-name>\n\n");
fprintf(stderr, fmt, new_name);
}
- diff --git a/builtin/clone.c b/builtin/clone.c
- --- a/builtin/clone.c
- +++ b/builtin/clone.c
-@@
- static const char junk_leave_repo_msg[] =
- N_("Clone succeeded, but checkout failed.\n"
- "You can inspect what was checked out with 'git status'\n"
-- "and retry the checkout with 'git checkout -f HEAD'\n");
-+ "and retry the checkout with 'git switch -f HEAD'\n");
-
- static void remove_junk(void)
- {
-
diff --git a/sha1-name.c b/sha1-name.c
--- a/sha1-name.c
+++ b/sha1-name.c
@@ -675,8 +668,20 @@
--- a/t/t2020-checkout-detach.sh
+++ b/t/t2020-checkout-detach.sh
@@
+
+ # The first detach operation is more chatty than the following ones.
+ cat >1st_detach <<-EOF &&
+- Note: checking out 'HEAD^'.
++ Note: switching to 'HEAD^'.
+
+ You are in 'detached HEAD' state. You can look around, make experimental
+ changes and commit them, and you can discard any commits you make in
this
+- state without impacting any branches by performing another checkout.
++ state without impacting any branches by switching back to a branch.
+
If you want to create a new branch to retain commits you create, you may
- do so (now or later) by using -b with the checkout command again.
Example:
+- do so (now or later) by using -b with the checkout command again.
Example:
++ do so (now or later) by using -c with the switch command. Example:
- git checkout -b <new-branch-name>
+ git switch -c <new-branch-name>
@@ -684,8 +689,20 @@
HEAD is now at \$commit three
EOF
@@
+
+ # The first detach operation is more chatty than the following ones.
+ cat >1st_detach <<-EOF &&
+- Note: checking out 'HEAD^'.
++ Note: switching to 'HEAD^'.
+
+ You are in 'detached HEAD' state. You can look around, make experimental
+ changes and commit them, and you can discard any commits you make in
this
+- state without impacting any branches by performing another checkout.
++ state without impacting any branches by switching back to a branch.
+
If you want to create a new branch to retain commits you create, you may
- do so (now or later) by using -b with the checkout command again.
Example:
+- do so (now or later) by using -b with the checkout command again.
Example:
++ do so (now or later) by using -c with the switch command. Example:
- git checkout -b <new-branch-name>
+ git switch -c <new-branch-name>
13: 91e5442069 < -: ---------- checkout: split part of it to new command
restore
14: 6bc8f87c0a < -: ---------- restore: take tree-ish from --from option
instead
15: 095a1cd3e3 < -: ---------- restore: make pathspec mandatory
16: 6eb5612187 < -: ---------- restore: disable overlay mode by default
17: cc79522047 < -: ---------- t: add tests for restore
18: ed5d7097b6 < -: ---------- completion: support restore
19: 625a4fac68 < -: ---------- doc: promote "git restore"
Nguyễn Thái Ngọc Duy (19):
git-checkout.txt: fix one syntax line
doc: document --overwrite-ignore
t: rename t2014-switch.sh to t2014-checkout-switch.sh
checkout: factor out some code in parse_branchname_arg()
checkout: make "opts" in cmd_checkout() a pointer
checkout: move 'confict_style' and 'dwim_..' to checkout_opts
checkout: split options[] array in three pieces
checkout: split part of it to new command switch
switch: better names for -b and -B
switch: remove -l
switch: stop accepting pathspec
switch: reject "do nothing" case
switch: only allow explicit detached HEAD
switch: add short option for --detach
switch: no implicit dwim, use --guess to dwim
switch: no worktree status unless real branch switch happens
t: add tests for switch
completion: support switch
doc: promote "git switch"
.gitignore | 1 +
Documentation/config/advice.txt | 13 +-
Documentation/config/branch.txt | 4 +-
Documentation/config/checkout.txt | 17 +-
Documentation/config/diff.txt | 3 +-
Documentation/git-branch.txt | 12 +-
Documentation/git-check-ref-format.txt | 3 +-
Documentation/git-checkout.txt | 48 +-
Documentation/git-format-patch.txt | 2 +-
Documentation/git-merge-base.txt | 2 +-
Documentation/git-merge.txt | 4 +
Documentation/git-rebase.txt | 2 +-
Documentation/git-remote.txt | 2 +-
Documentation/git-rerere.txt | 10 +-
Documentation/git-reset.txt | 20 +-
Documentation/git-stash.txt | 9 +-
Documentation/git-switch.txt | 257 ++++++++++
Documentation/gitattributes.txt | 3 +-
Documentation/gitcore-tutorial.txt | 18 +-
Documentation/giteveryday.txt | 24 +-
Documentation/githooks.txt | 8 +-
Documentation/gittutorial.txt | 4 +-
Documentation/revisions.txt | 2 +-
Documentation/user-manual.txt | 56 +--
Makefile | 1 +
advice.c | 11 +-
builtin.h | 1 +
builtin/checkout.c | 464 +++++++++---------
command-list.txt | 1 +
contrib/completion/git-completion.bash | 26 +
git.c | 1 +
parse-options-cb.c | 17 +
parse-options.h | 3 +-
sha1-name.c | 2 +-
t/t1090-sparse-checkout-scope.sh | 14 -
...014-switch.sh => t2014-checkout-switch.sh} | 0
t/t2020-checkout-detach.sh | 16 +-
t/t2060-switch.sh | 87 ++++
38 files changed, 796 insertions(+), 372 deletions(-)
create mode 100644 Documentation/git-switch.txt
rename t/{t2014-switch.sh => t2014-checkout-switch.sh} (100%)
create mode 100755 t/t2060-switch.sh
--
2.20.1.682.gd5861c6d90