push: introduce '--branches' option

The '--all' option of git-push built-in cmd support to push all branches (refs under refs/heads) to remote. Under the usage, a user can easlily work in some scenarios, for example, branches synchronization and batch upload. The '--all' was introduced for a long time, meanwhile, git supports to customize the storage location under "refs/". when a new git user see the usage like, 'git push origin --all', we might feel like we're pushing _all_ the refs instead of just branches without looking at the documents until we found the related description of it or '--mirror'. To ensure compatibility, we cannot rename '--all' to another name directly, one way is, we can try to add a new option '--heads' which be identical with the functionality of '--all' to let the user understand the meaning of representation more clearly. Actually, We've more or less named options this way already, for example, in 'git-show-ref' and 'git ls-remote'. At the same time, we fix a related issue about the wrong help information of '--all' option in code and add some test cases in t5523, t5543 and t5583. Signed-off-by: Teng Long <dyroneteng@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Teng Long committed May 6, 2023 at 19:34 UTC 425b4d7f47bd2be561ced14eac36056390862e8c
5 files changed +135 -7
Documentation/git-push.txt
+2 -1
@@ -9,7 +9,7 @@ git-push - Update remote refs along with associated objects
9 SYNOPSIS
10 --------
11 [verse]
12 -'git push' [--all | --mirror | --tags] [--follow-tags] [--atomic] [-n | --dry-run] [--receive-pack=<git-receive-pack>]
12 +'git push' [--all | --branches | --mirror | --tags] [--follow-tags] [--atomic] [-n | --dry-run] [--receive-pack=<git-receive-pack>]
13 [--repo=<repository>] [-f | --force] [-d | --delete] [--prune] [-v | --verbose]
14 [-u | --set-upstream] [-o <string> | --push-option=<string>]
15 [--[no-]signed|--signed=(true|false|if-asked)]
@@ -147,6 +147,7 @@ already exists on the remote side.
147 `tag <tag>` means the same as `refs/tags/<tag>:refs/tags/<tag>`.
148
149 --all::
150 +--branches::
151 Push all branches (i.e. refs under `refs/heads/`); cannot be
152 used with other <refspec>.
153
builtin/push.c
+4 -3
@@ -593,11 +593,12 @@ int cmd_push(int argc, const char **argv, const char *prefix)
593 struct option options[] = {
594 OPT__VERBOSITY(&verbosity),
595 OPT_STRING( 0 , "repo", &repo, N_("repository"), N_("repository")),
596 - OPT_BIT( 0 , "all", &flags, N_("push all refs"), TRANSPORT_PUSH_ALL),
596 + OPT_BIT( 0 , "all", &flags, N_("push all branches"), TRANSPORT_PUSH_ALL),
597 + OPT_ALIAS( 0 , "branches", "all"),
598 OPT_BIT( 0 , "mirror", &flags, N_("mirror all refs"),
599 (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
600 OPT_BOOL('d', "delete", &deleterefs, N_("delete refs")),
600 - OPT_BOOL( 0 , "tags", &tags, N_("push tags (can't be used with --all or --mirror)")),
601 + OPT_BOOL( 0 , "tags", &tags, N_("push tags (can't be used with --all or --branches or --mirror)")),
602 OPT_BIT('n' , "dry-run", &flags, N_("dry run"), TRANSPORT_PUSH_DRY_RUN),
603 OPT_BIT( 0, "porcelain", &flags, N_("machine-readable output"), TRANSPORT_PUSH_PORCELAIN),
604 OPT_BIT('f', "force", &flags, N_("force updates"), TRANSPORT_PUSH_FORCE),
@@ -640,7 +641,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
641 set_push_cert_flags(&flags, push_cert);
642
643 if (deleterefs && (tags || (flags & (TRANSPORT_PUSH_ALL | TRANSPORT_PUSH_MIRROR))))
643 - die(_("options '%s' and '%s' cannot be used together"), "--delete", "--all/--mirror/--tags");
644 + die(_("options '%s' and '%s' cannot be used together"), "--delete", "--all/--branches/--mirror/--tags");
645 if (deleterefs && argc < 2)
646 die(_("--delete doesn't make sense without any refs"));
647
t/t5523-push-upstream.sh
+10 -2
@@ -61,12 +61,20 @@ test_expect_success 'push -u :topic_2' '
61 check_config topic_2 upstream refs/heads/other2
62 '
63
64 -test_expect_success 'push -u --all' '
64 +test_expect_success 'push -u --all(the same behavior with--branches)' '
65 git branch all1 &&
66 git branch all2 &&
67 git push -u --all &&
68 check_config all1 upstream refs/heads/all1 &&
69 - check_config all2 upstream refs/heads/all2
69 + check_config all2 upstream refs/heads/all2 &&
70 + git config --get-regexp branch.all* > expect &&
71 + git config --remove-section branch.all1 &&
72 + git config --remove-section branch.all2 &&
73 + git push -u --branches &&
74 + check_config all1 upstream refs/heads/all1 &&
75 + check_config all2 upstream refs/heads/all2 &&
76 + git config --get-regexp branch.all* > actual &&
77 + test_cmp expect actual
78 '
79
80 test_expect_success 'push -u HEAD' '
t/t5543-atomic-push.sh
+4 -1
@@ -117,7 +117,10 @@ test_expect_success 'atomic push fails if one branch fails' '
117 test_commit five &&
118 git checkout main &&
119 test_commit six &&
120 - test_must_fail git push --atomic --all up
120 + test_must_fail git push --atomic --all up >output-all 2>&1 &&
121 + # --all and --branches have the same behavior when be combined with --atomic
122 + test_must_fail git push --atomic --branches up >output-branches 2>&1 &&
123 + test_cmp output-all output-branches
124 ) &&
125 test_refs main HEAD@{7} &&
126 test_refs second HEAD@{4}
t/t5583-push-branches.sh new
+115
@@ -0,0 +1,115 @@
1 +#!bin/sh
2 +
3 +test_description='check the consisitency of behavior of --all and --branches'
4 +
5 +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
6 +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
7 +
8 +. ./test-lib.sh
9 +
10 +delete_refs() {
11 + dir=$1
12 + shift
13 + rm -rf deletes
14 + for arg in $*
15 + do
16 + echo "delete ${arg}" >>deletes
17 + done
18 + git -C $dir update-ref --stdin < deletes
19 +}
20 +
21 +test_expect_success 'setup bare remote' '
22 + git init --bare remote-1 &&
23 + git -C remote-1 config gc.auto 0 &&
24 + test_commit one &&
25 + git push remote-1 HEAD
26 +'
27 +
28 +test_expect_success 'setup different types of references' '
29 + cat >refs <<-EOF &&
30 + update refs/heads/branch-1 HEAD
31 + update refs/heads/branch-2 HEAD
32 + EOF
33 +
34 + git tag -a -m "annotated" annotated-1 HEAD &&
35 + git tag -a -m "annotated" annotated-2 HEAD &&
36 + git update-ref --stdin < refs
37 +'
38 +
39 +test_expect_success '--all and --branches have the same behavior' '
40 + test_when_finished "delete_refs remote-1 \
41 + refs/heads/branch-1 \
42 + refs/heads/branch-2" &&
43 + git push remote-1 --all &&
44 + commit=$(git rev-parse HEAD) &&
45 + cat >expect <<-EOF &&
46 + $commit refs/heads/branch-1
47 + $commit refs/heads/branch-2
48 + $commit refs/heads/main
49 + EOF
50 +
51 + git -C remote-1 show-ref --heads >actual.all &&
52 + delete_refs remote-1 refs/heads/branch-1 refs/heads/branch-2 &&
53 + git push remote-1 --branches &&
54 + git -C remote-1 show-ref --heads >actual.branches &&
55 + test_cmp actual.all actual.branches &&
56 + test_cmp expect actual.all
57 +'
58 +
59 +test_expect_success '--all or --branches can not be combined with refspecs' '
60 + test_must_fail git push remote-1 --all main >actual.all 2>&1 &&
61 + test_must_fail git push remote-1 --branches main >actual.branches 2>&1 &&
62 + test_cmp actual.all actual.branches &&
63 + grep "be combined with refspecs" actual.all
64 +'
65 +
66 +test_expect_success '--all or --branches can not be combined with --mirror' '
67 + test_must_fail git push remote-1 --all --mirror >actual.all 2>&1 &&
68 + test_must_fail git push remote-1 --branches --mirror >actual.branches 2>&1 &&
69 + test_cmp actual.all actual.branches &&
70 + grep "cannot be used together" actual.all
71 +'
72 +
73 +test_expect_success '--all or --branches can not be combined with --tags' '
74 + test_must_fail git push remote-1 --all --tags >actual.all 2>&1 &&
75 + test_must_fail git push remote-1 --branches --tags >actual.branches 2>&1 &&
76 + test_cmp actual.all actual.branches &&
77 + grep "cannot be used together" actual.all
78 +'
79 +
80 +
81 +test_expect_success '--all or --branches can not be combined with --delete' '
82 + test_must_fail git push remote-1 --all --delete >actual.all 2>&1 &&
83 + test_must_fail git push remote-1 --branches --delete >actual.branches 2>&1 &&
84 + test_cmp actual.all actual.branches &&
85 + grep "cannot be used together" actual.all
86 +'
87 +
88 +test_expect_success '--all or --branches combines with --follow-tags have same behavior' '
89 + test_when_finished "delete_refs remote-1 \
90 + refs/heads/branch-1 \
91 + refs/heads/branch-2 \
92 + refs/tags/annotated-1 \
93 + refs/tags/annotated-2" &&
94 + git push remote-1 --all --follow-tags &&
95 + git -C remote-1 show-ref > actual.all &&
96 + cat >expect <<-EOF &&
97 + $commit refs/heads/branch-1
98 + $commit refs/heads/branch-2
99 + $commit refs/heads/main
100 + $(git rev-parse annotated-1) refs/tags/annotated-1
101 + $(git rev-parse annotated-2) refs/tags/annotated-2
102 + EOF
103 +
104 + delete_refs remote-1 \
105 + refs/heads/branch-1 \
106 + refs/heads/branch-2 \
107 + refs/tags/annotated-1 \
108 + refs/tags/annotated-2 &&
109 + git push remote-1 --branches --follow-tags &&
110 + git -C remote-1 show-ref >actual.branches &&
111 + test_cmp actual.all actual.branches &&
112 + test_cmp expect actual.all
113 +'
114 +
115 +test_done