Simon 'corecode' Schubert [off-list ref] writes:
I don't say "Push needs to behave like a fast forward pull",
because that's wrong. You can't just change the workdir,
possibly due to permissions problems. But push has to abort
if you try to forward HEAD on the remote, except if it is
bare, of course.
You can tweak receive-pack.c::update() to do that, perhaps along
the lines of this.
---
diff --git a/receive-pack.c b/receive-pack.c
index 7311c82..ccd48e4 100644
--- a/receive-pack.c
+++ b/receive-pack.c
@@ -9,6 +9,7 @@
static const char receive_pack_usage[] = "git-receive-pack <git-dir>";
+static char *current_branch;
static int deny_non_fast_forwards = 0;
static int receive_unpack_limit = -1;
static int transfer_unpack_limit = -1;
@@ -115,6 +116,18 @@ static int update(struct command *cmd)
name);
}
+ if (!is_bare_repository()) {
+ /*
+ * Pusing into a live repository. updating .git/HEAD
+ * or the current branch is a no-no...
+ */
+ if (strncmp(name, "refs/", 5) ||
+ (current_branch && !strcmp(name, current_branch))) {
+ cmd->error_string = "update current";
+ return error("refusing to update the current branch '%s' in a live repository", name);
+ }
+ }
+
strcpy(new_hex, sha1_to_hex(new_sha1));
strcpy(old_hex, sha1_to_hex(old_sha1));
@@ -436,6 +449,13 @@ int main(int argc, char **argv)
else if (0 <= receive_unpack_limit)
unpack_limit = receive_unpack_limit;
+ if (!is_bare_repository()) {
+ unsigned char h[20];
+ const char *head = resolve_ref("HEAD", h, 0, NULL);
+ if (head && strcmp("HEAD", head))
+ current_branch = xstrdup(head);
+ }
+
write_head_info();
/* EOF */