On Fri, Feb 08, 2008 at 09:46:36PM -0500, Jeff King wrote: > > The local side has the remote refs if the client has fetched recently, > > so it might be able to tell in some cases. Not with authority (things > > may have changed on the server side...) but the client might be able > > to say something less alarming. > > This is actually not that hard to do in the case that we can. Patch will > follow in a second, though I am not sure it is a good idea (because it > silently ignores pushing rewinds). And here it is. Again, I don't think this is the right default behavior. I'm not even sure it is a good idea as configurable behavior. But it's here for comment and for playing with, nonetheless. -- >8 -- send-pack: treat strict rewinds specially If you try to push an out-of-date version of a branch, it will generally be rejected as a non-fastforward. This can clutter up the status output of git-push if you have many such branches. Instead, let's check explicitly whether what we are pushing is a strict subset of what the remote already has. We treat this as a non-error, and don't even print any status unless "verbose" is given. If the push is "forced", then we will push as usual. Note that we cannot always perform this check accurately; it relies on us having the commit object that the remote claims to have. In the case that we don't, we treat it like an ordinary non-fastforward and reject. --- diff --git a/cache.h b/cache.h index 920e731..78fee0b 100644 --- a/cache.h +++ b/cache.h @@ -596,6 +596,7 @@ struct ref { REF_STATUS_UPTODATE, REF_STATUS_REMOTE_REJECT, REF_STATUS_EXPECTING_REPORT, + REF_STATUS_REJECT_REWIND, } status; char *remote_status; struct ref *peer_ref; /* when renaming */ diff --git a/builtin-send-pack.c b/builtin-send-pack.c index 454ad8f..9f82b83 100644 --- a/builtin-send-pack.c +++ b/builtin-send-pack.c @@ -315,6 +315,7 @@ static int print_one_push_status(struct ref *ref, const char *dest, int count) ref->peer_ref, NULL); break; case REF_STATUS_REJECT_NONFASTFORWARD: + case REF_STATUS_REJECT_REWIND: print_ref_status('!', "[rejected]", ref, ref->peer_ref, "non-fast forward"); break; @@ -343,7 +344,8 @@ static void print_push_status(const char *dest, struct ref *refs) if (args.verbose) { for (ref = refs; ref; ref = ref->next) - if (ref->status == REF_STATUS_UPTODATE) + if (ref->status == REF_STATUS_UPTODATE || + ref->status == REF_STATUS_REJECT_REWIND) n += print_one_push_status(ref, dest, n); } @@ -354,7 +356,8 @@ static void print_push_status(const char *dest, struct ref *refs) for (ref = refs; ref; ref = ref->next) { if (ref->status != REF_STATUS_NONE && ref->status != REF_STATUS_UPTODATE && - ref->status != REF_STATUS_OK) + ref->status != REF_STATUS_OK && + ref->status != REF_STATUS_REJECT_REWIND) n += print_one_push_status(ref, dest, n); } } @@ -365,6 +368,7 @@ static int refs_pushed(struct ref *ref) switch(ref->status) { case REF_STATUS_NONE: case REF_STATUS_UPTODATE: + case REF_STATUS_REJECT_REWIND: break; default: return 1; @@ -463,8 +467,12 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest (!has_sha1_file(ref->old_sha1) || !ref_newer(new_sha1, ref->old_sha1)); + if (ref->nonfastforward && !ref->force && !args.force_update) { - ref->status = REF_STATUS_REJECT_NONFASTFORWARD; + if (ref_newer(ref->old_sha1, new_sha1)) + ref->status = REF_STATUS_REJECT_REWIND; + else + ref->status = REF_STATUS_REJECT_NONFASTFORWARD; continue; } @@ -522,6 +530,7 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest case REF_STATUS_NONE: case REF_STATUS_UPTODATE: case REF_STATUS_OK: + case REF_STATUS_REJECT_REWIND: break; default: return -1; - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html