Subject: On undoing a forced push

From: Duy Nguyen <[email-masked]>
Date: Tue, 9 Jun 2015 19:12:21 +0700

>>From a thread on Hacker News. It seems that if a user does not have
access to the remote's reflog and accidentally forces a push to a ref,
how does he recover it? In order to force push again to revert it
back, he would need to know the remote's old SHA-1. Local reflog does
not help because remote refs are not updated during a push.

This patch prints the latest SHA-1 before the forced push in full. He
then can do

    git push <remote> +<old-sha1>:<ref>

He does not even need to have the objects that <old-sha1> refers
to. We could simply push an empty pack and the the remote will happily
accept the force, assuming garbage collection has not happened. But
that's another and a little more complex patch.

Is there any other way to undo a forced push?

-- 8< --
diff --git a/transport.c b/transport.c
index f080e93..6bd6a64 100644
--- a/transport.c
+++ b/transport.c
@@ -657,16 +657,17 @@ static void print_ok_ref_status(struct ref *ref, int porcelain)
 			"[new branch]"),
 			ref, ref->peer_ref, NULL, porcelain);
 	else {
-		char quickref[84];
+		char quickref[104];
 		char type;
 		const char *msg;
 
-		strcpy(quickref, status_abbrev(ref->old_sha1));
 		if (ref->forced_update) {
+			strcpy(quickref, sha1_to_hex(ref->old_sha1));
 			strcat(quickref, "...");
 			type = '+';
 			msg = "forced update";
 		} else {
+			strcpy(quickref, status_abbrev(ref->old_sha1));
 			strcat(quickref, "..");
 			type = ' ';
 			msg = NULL;
-- 8< --