Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

receive-pack: allow deletion of corrupt refs

Occasionally, in some setups (*cough* forks on repo.or.cz *cough*) some
refs go stale, e.g. when the forkee rebased and lost some objects needed
by the fork.  The quick & dirty way to deal with those refs is to delete
them and push them again.

However, git-push first would first fetch the current commit name for the
ref, would receive a null sha1 since the ref does not point to a valid
object, then tell receive-pack that it should delete the ref with this
commit name.  delete_ref() would be subsequently be called, and check that
resolve_ref() (which does _not_ check for validity of the object) returns
the same commit name.  Which would fail.

The proper fix is to avoid corrupting repositories, but in the meantime
this is a good fix in any case.

Incidentally, some instances of "cd .." in the test cases were fixed, so
that subsequent test cases run in t/trash/ irrespective of the outcome of
the previous test cases.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information...
commit 28391a80a94d2b59d1d21f8264fe5dab91d77249 1 parent 346d203
dscho authored November 29, 2007 gitster committed November 30, 2007
4  receive-pack.c
@@ -200,6 +200,10 @@ static const char *update(struct command *cmd)
200 200
 	}
201 201
 
202 202
 	if (is_null_sha1(new_sha1)) {
  203
+		if (!parse_object(old_sha1)) {
  204
+			warning ("Allowing deletion of corrupt ref.");
  205
+			old_sha1 = NULL;
  206
+		}
203 207
 		if (delete_ref(name, old_sha1)) {
204 208
 			error("failed to delete %s", name);
205 209
 			return "failed to delete";
45  t/t5516-fetch-push.sh
@@ -247,11 +247,50 @@ test_expect_success 'push with colon-less refspec (4)' '
247 247
 test_expect_success 'push with dry-run' '
248 248
 
249 249
 	mk_test heads/master &&
250  
-	cd testrepo &&
251  
-	old_commit=$(git show-ref -s --verify refs/heads/master) &&
252  
-	cd .. &&
  250
+	(cd testrepo &&
  251
+	 old_commit=$(git show-ref -s --verify refs/heads/master)) &&
253 252
 	git push --dry-run testrepo &&
254 253
 	check_push_result $old_commit heads/master
255 254
 '
256 255
 
  256
+test_expect_success 'push updates local refs' '
  257
+
  258
+	rm -rf parent child &&
  259
+	mkdir parent &&
  260
+	(cd parent && git init &&
  261
+		echo one >foo && git add foo && git commit -m one) &&
  262
+	git clone parent child &&
  263
+	(cd child &&
  264
+		echo two >foo && git commit -a -m two &&
  265
+		git push &&
  266
+	test $(git rev-parse master) = $(git rev-parse remotes/origin/master))
  267
+
  268
+'
  269
+
  270
+test_expect_success 'push does not update local refs on failure' '
  271
+
  272
+	rm -rf parent child &&
  273
+	mkdir parent &&
  274
+	(cd parent && git init &&
  275
+		echo one >foo && git add foo && git commit -m one &&
  276
+		echo exit 1 >.git/hooks/pre-receive &&
  277
+		chmod +x .git/hooks/pre-receive) &&
  278
+	git clone parent child &&
  279
+	(cd child &&
  280
+		echo two >foo && git commit -a -m two &&
  281
+		! git push &&
  282
+		test $(git rev-parse master) != \
  283
+			$(git rev-parse remotes/origin/master))
  284
+
  285
+'
  286
+
  287
+test_expect_success 'allow deleting an invalid remote ref' '
  288
+
  289
+	pwd &&
  290
+	rm -f testrepo/.git/objects/??/* &&
  291
+	git push testrepo :refs/heads/master &&
  292
+	(cd testrepo && ! git rev-parse --verify refs/heads/master)
  293
+
  294
+'
  295
+
257 296
 test_done

0 notes on commit 28391a8

Please sign in to comment.
Something went wrong with that request. Please try again.