push: fix local refs update if already up-to-date

git push normally updates local refs only after a successful push. If the
remote already has the updates -- pushed indirectly through another repository,
for example -- we forget to update local tracking refs.

Signed-off-by: Clemens Buchacher <drizzd@aon.at>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Clemens Buchacher 2008-11-05 21:55:54 +01:00 committed by Junio C Hamano
parent 5bdd8d4a30
commit 16ed2f48be
2 changed files with 39 additions and 14 deletions

View file

@ -222,7 +222,7 @@ static void update_tracking_ref(struct remote *remote, struct ref *ref)
{ {
struct refspec rs; struct refspec rs;
if (ref->status != REF_STATUS_OK) if (ref->status != REF_STATUS_OK && ref->status != REF_STATUS_UPTODATE)
return; return;
rs.src = ref->name; rs.src = ref->name;
@ -424,24 +424,19 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
*/ */
new_refs = 0; new_refs = 0;
for (ref = remote_refs; ref; ref = ref->next) { for (ref = remote_refs; ref; ref = ref->next) {
const unsigned char *new_sha1;
if (!ref->peer_ref) { if (ref->peer_ref)
if (!args.send_mirror) hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
else if (!args.send_mirror)
continue; continue;
new_sha1 = null_sha1;
}
else
new_sha1 = ref->peer_ref->new_sha1;
ref->deletion = is_null_sha1(ref->new_sha1);
ref->deletion = is_null_sha1(new_sha1);
if (ref->deletion && !allow_deleting_refs) { if (ref->deletion && !allow_deleting_refs) {
ref->status = REF_STATUS_REJECT_NODELETE; ref->status = REF_STATUS_REJECT_NODELETE;
continue; continue;
} }
if (!ref->deletion && if (!ref->deletion &&
!hashcmp(ref->old_sha1, new_sha1)) { !hashcmp(ref->old_sha1, ref->new_sha1)) {
ref->status = REF_STATUS_UPTODATE; ref->status = REF_STATUS_UPTODATE;
continue; continue;
} }
@ -469,14 +464,13 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
!ref->deletion && !ref->deletion &&
!is_null_sha1(ref->old_sha1) && !is_null_sha1(ref->old_sha1) &&
(!has_sha1_file(ref->old_sha1) (!has_sha1_file(ref->old_sha1)
|| !ref_newer(new_sha1, ref->old_sha1)); || !ref_newer(ref->new_sha1, ref->old_sha1));
if (ref->nonfastforward && !ref->force && !args.force_update) { if (ref->nonfastforward && !ref->force && !args.force_update) {
ref->status = REF_STATUS_REJECT_NONFASTFORWARD; ref->status = REF_STATUS_REJECT_NONFASTFORWARD;
continue; continue;
} }
hashcpy(ref->new_sha1, new_sha1);
if (!ref->deletion) if (!ref->deletion)
new_refs++; new_refs++;

View file

@ -437,6 +437,37 @@ test_expect_success 'push updates local refs' '
' '
test_expect_success 'push updates up-to-date local refs' '
rm -rf parent child &&
mkdir parent &&
(cd parent && git init &&
echo one >foo && git add foo && git commit -m one) &&
git clone parent child1 &&
git clone parent child2 &&
(cd child1 &&
echo two >foo && git commit -a -m two &&
git push) &&
(cd child2 &&
git pull ../child1 master &&
git push &&
test $(git rev-parse master) = $(git rev-parse remotes/origin/master))
'
test_expect_success 'push preserves up-to-date packed refs' '
rm -rf parent child &&
mkdir parent &&
(cd parent && git init &&
echo one >foo && git add foo && git commit -m one) &&
git clone parent child &&
(cd child &&
git push &&
! test -f .git/refs/remotes/origin/master)
'
test_expect_success 'push does not update local refs on failure' ' test_expect_success 'push does not update local refs on failure' '
rm -rf parent child && rm -rf parent child &&