From: Steffen Prohaska <prohaska@zib.de>
To: git@vger.kernel.org
Cc: Steffen Prohaska <prohaska@zib.de>
Subject: [PATCH 10/10] push: teach push to be quiet if local ref is strict subset of remote ref
Date: Sun, 28 Oct 2007 18:46:21 +0100 [thread overview]
Message-ID: <11935935821192-git-send-email-prohaska@zib.de> (raw)
In-Reply-To: <11935935823496-git-send-email-prohaska@zib.de>
git push reports errors if a remote ref is not a strict subset
of a local ref. The push wouldn't be a fast-forward and is
therefore refused. This is in general a good idea.
But these messages can be annoying if you work with a shared
remote repository. Branches at the remote may have advanced and
you haven't pulled to all of your local branches. In this
situation, local branches may be strict subsets of the remote
heads. Pushing such branches wouldn't add any information to the
remote. It would only reset the remote to an ancestor. A merge
between the remote and the local branch is not very interested
either because it would just be a fast forward of the local
branch. In these cases you're not interested in the error
message.
This commit teaches git push to be quiet for local refs that are
strict subsets of the matching remote refs and no refspec is
specified on the command line. If the --verbose flag is used a
"note" is printed instead of silently ignoring the refs.
If no notes have been printed the number of ignored refs will
be reported in the final summary.
If refs are ignored their matching remote tracking refs will not
be changed.
git push now allows you pushing a couple of branches that have
advanced, while ignoring all branches that have no local changes,
but are lagging behind their matching remote refs. This is done
without reporting errors.
Thanks to Junio C. Hamano <gitster@pobox.com> for suggesting to
report in the summary that refs have been ignored.
Signed-off-by: Steffen Prohaska <prohaska@zib.de>
---
send-pack.c | 68 +++++++++++++++++++++++++++++++---------
t/t5516-fetch-push.sh | 84 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 137 insertions(+), 15 deletions(-)
diff --git a/send-pack.c b/send-pack.c
index 77acae1..68a4692 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -187,6 +187,7 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha
int ask_for_status_report = 0;
int allow_deleting_refs = 0;
int expect_status_report = 0;
+ int ignored_refs = 0;
/* No funny business with the matcher */
remote_tail = get_remote_heads(in, &remote_refs, 0, NULL, REF_NORMAL);
@@ -259,24 +260,56 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha
!will_delete_ref &&
!is_null_sha1(ref->old_sha1) &&
!ref->force) {
- if (!has_sha1_file(ref->old_sha1) ||
- !ref_newer(ref->peer_ref->new_sha1,
- ref->old_sha1)) {
- /* We do not have the remote ref, or
- * we know that the remote ref is not
- * an ancestor of what we are trying to
- * push. Either way this can be losing
- * commits at the remote end and likely
- * we were not up to date to begin with.
+ if (!has_sha1_file(ref->old_sha1)) {
+ /* We do not have the remote ref.
+ * This can be losing commits at
+ * the remote end.
*/
- error("remote '%s' is not a strict "
- "subset of local ref '%s'. "
- "maybe you are not up-to-date and "
- "need to pull first?",
- ref->name,
- ref->peer_ref->name);
+ error("You don't have the commit"
+ "for the remote ref '%s'."
+ "This may cause losing commits"
+ "that cannot be recovered.",
+ ref->name);
ret = -2;
continue;
+ } else if (!ref_newer(ref->peer_ref->new_sha1,
+ ref->old_sha1)) {
+ /* We know that the remote ref is not
+ * an ancestor of what we are trying to
+ * push. This can be losing commits at
+ * the remote end and likely we were not
+ * up to date to begin with.
+ *
+ * Therefore, we don't push.
+ *
+ * If no explicit refspec was passed on the
+ * commandline, then we only report an error
+ * if the local is not a strict subset of the
+ * remote. If the local is a strict subset we
+ * don't have new commits for the remote.
+ * Pulling and pushing wouldn't add anything to
+ * the remote.
+ *
+ */
+ if (nr_refspec ||
+ !ref_newer(ref->old_sha1, ref->peer_ref->new_sha1)) {
+ error("remote '%s' is not a strict "
+ "subset of local ref '%s'. "
+ "maybe you are not up-to-date and "
+ "need to pull first?",
+ ref->name,
+ ref->peer_ref->name);
+ ret = -2;
+ } else if (verbose) {
+ fprintf(stderr,
+ "note: ignoring local ref '%s' "
+ "because it is a strict "
+ "subset of remote '%s'.\n",
+ ref->peer_ref->name,
+ ref->name);
+ } else
+ ignored_refs++;
+ continue;
}
}
hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
@@ -335,6 +368,11 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha
ret = -4;
}
+ if (ignored_refs)
+ fprintf(stderr,
+ "Ignored %d local refs that are strict subsets of matching remote ref. "
+ "Use --verbose for more details.\n",
+ ignored_refs);
if (!new_refs && ret == 0)
fprintf(stderr, "Everything up-to-date\n");
return ret;
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 6708ec1..1f740b2 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -56,6 +56,22 @@ check_push_result () {
)
}
+check_local_result () {
+ (
+ it="$1" &&
+ shift
+ for ref in "$@"
+ do
+ r=$(git show-ref -s --verify refs/$ref) &&
+ test "z$r" = "z$it" || {
+ echo "Oops, refs/$ref is wrong"
+ exit 1
+ }
+ done &&
+ git fsck --full
+ )
+}
+
test_expect_success setup '
: >path1 &&
@@ -345,4 +361,72 @@ test_expect_success 'push with dry-run' '
check_push_result $old_commit heads/master
'
+test_expect_success 'push with local is strict subset (must not report error)' '
+
+ mk_test heads/foo &&
+ git push testrepo $the_commit:refs/heads/foo &&
+ git branch -f foo $old_commit &&
+ if git push testrepo 2>&1 | grep ^error
+ then
+ echo "Oops, should not report error"
+ false
+ else
+ check_push_result $the_commit heads/foo
+ fi
+
+'
+
+test_expect_success 'push with local is strict subset (must not update remotes)' '
+
+ mk_test heads/foo &&
+ git push testrepo $the_commit:refs/heads/foo &&
+ git branch -f foo $old_commit &&
+ git fetch test &&
+ check_local_result $the_commit remotes/test/foo &&
+ if git push test 2>&1 | grep ^error
+ then
+ echo "Oops, should not report error"
+ false
+ else
+ check_push_result $the_commit heads/foo &&
+ check_local_result $the_commit remotes/test/foo
+ fi
+
+'
+
+test_expect_success 'push with explicit refname, local is strict subset (must report error)' '
+
+ mk_test heads/foo &&
+ git push testrepo $the_commit:refs/heads/foo &&
+ git branch -f foo $old_commit &&
+ if ! git push testrepo foo 2>&1 | grep ^error
+ then
+ echo "Oops, should have reported error"
+ false
+ else
+ check_push_result $the_commit heads/foo
+ fi
+
+'
+
+test_expect_success 'push with neither local nor remote is strict subset (must report error)' '
+
+ mk_test heads/foo &&
+ git push testrepo $the_commit:refs/heads/foo &&
+ git branch -f foo $old_commit &&
+ git checkout foo &&
+ : >path3 &&
+ git add path3 &&
+ test_tick &&
+ git commit -a -m branched &&
+ if ! git push testrepo 2>&1 | grep ^error
+ then
+ echo "Oops, should have reported error"
+ false
+ else
+ check_push_result $the_commit heads/foo
+ fi
+
+'
+
test_done
--
1.5.3.4.439.ge8b49
next prev parent reply other threads:[~2007-10-28 17:50 UTC|newest]
Thread overview: 53+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-10-28 17:46 [PATCH 0/10 v3] improve refspec handling in push Steffen Prohaska
2007-10-28 17:46 ` [PATCH 01/10] push: change push to fail if short refname does not exist Steffen Prohaska
2007-10-28 17:46 ` [PATCH 02/10] push: teach push new flag --create Steffen Prohaska
2007-10-28 17:46 ` [PATCH 03/10] push: support pushing HEAD to real branch name Steffen Prohaska
2007-10-28 17:46 ` [PATCH 04/10] push: add "git push HEAD" shorthand for 'push current branch to default repo' Steffen Prohaska
2007-10-28 17:46 ` [PATCH 05/10] rename ref_matches_abbrev() to ref_abbrev_matches_full_with_fetch_rules() Steffen Prohaska
2007-10-28 17:46 ` [PATCH 06/10] add ref_abbrev_matches_full_with_rev_parse_rules() comparing abbrev with full ref name Steffen Prohaska
2007-10-28 17:46 ` [PATCH 07/10] push: use same rules as git-rev-parse to resolve refspecs Steffen Prohaska
2007-10-28 17:46 ` [PATCH 08/10] push: teach push to accept --verbose option Steffen Prohaska
2007-10-28 17:46 ` [PATCH 09/10] push: teach push to pass --verbose option to transport layer Steffen Prohaska
2007-10-28 17:46 ` Steffen Prohaska [this message]
2007-10-30 8:29 ` [PATCH 10/10] push: teach push to be quiet if local ref is strict subset of remote ref Junio C Hamano
2007-10-30 10:15 ` Steffen Prohaska
2007-10-30 10:26 ` Andreas Ericsson
2007-10-30 10:53 ` Steffen Prohaska
2007-10-30 19:19 ` Junio C Hamano
2007-10-31 7:53 ` Steffen Prohaska
2007-10-31 8:45 ` Junio C Hamano
[not found] ` <B3C76DB8-076D-4C43-AC28-99119A05325C@z ib.de>
2007-10-31 9:14 ` Junio C Hamano
2007-10-31 10:50 ` Steffen Prohaska
2007-10-31 18:51 ` Junio C Hamano
2007-10-31 21:09 ` Steffen Prohaska
2007-10-31 21:31 ` Junio C Hamano
2007-11-01 7:03 ` Steffen Prohaska
2007-11-01 9:11 ` Andreas Ericsson
2007-11-01 16:43 ` Steffen Prohaska
2007-11-01 20:18 ` Junio C Hamano
2007-11-02 7:21 ` Steffen Prohaska
2007-11-02 7:52 ` Junio C Hamano
2007-11-02 10:03 ` Steffen Prohaska
2007-11-02 10:44 ` Junio C Hamano
2007-11-02 11:40 ` Steffen Prohaska
2007-11-02 10:03 ` Andreas Ericsson
2007-11-02 13:24 ` Tom Prince
2007-11-02 13:52 ` Andreas Ericsson
2007-11-02 14:49 ` Steffen Prohaska
2007-11-02 19:42 ` Junio C Hamano
2007-11-02 20:19 ` Junio C Hamano
2007-11-01 8:18 ` Andreas Ericsson
2007-11-01 8:36 ` Steffen Prohaska
2007-11-01 9:29 ` Andreas Ericsson
2007-11-02 8:18 ` Wincent Colaiuta
2007-11-02 12:14 ` Johannes Schindelin
2007-11-02 12:48 ` Steffen Prohaska
2007-11-02 13:11 ` Wincent Colaiuta
2007-10-30 18:00 ` Daniel Barkalow
2007-10-30 8:28 ` [PATCH 07/10] push: use same rules as git-rev-parse to resolve refspecs Junio C Hamano
2007-10-30 8:49 ` Steffen Prohaska
2007-10-30 8:28 ` [PATCH 04/10] push: add "git push HEAD" shorthand for 'push current branch to default repo' Junio C Hamano
2007-10-30 8:28 ` [PATCH 03/10] push: support pushing HEAD to real branch name Junio C Hamano
2007-10-30 8:29 ` [PATCH 01/10] push: change push to fail if short refname does not exist Junio C Hamano
2007-10-30 8:56 ` Steffen Prohaska
2007-10-30 9:22 ` Junio C Hamano
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
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=11935935821192-git-send-email-prohaska@zib.de \
--to=prohaska@zib.de \
--cc=git@vger.kernel.org \
/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
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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 NNTP newsgroup(s).