summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandre Julliard <julliard@winehq.org>2008-11-08 12:03:59 (GMT)
committerJunio C Hamano <gitster@pobox.com>2008-11-09 18:11:39 (GMT)
commit323e00fd46afb9293b25ee85f061ce11a2f95ca6 (patch)
tree42c867205627ef8cc70a306ad2fcfde9b0c17f5d
parent7c181d627c136cbc67ef0f722e74e34017e662f0 (diff)
downloadgit-323e00fd46afb9293b25ee85f061ce11a2f95ca6.zip
git-323e00fd46afb9293b25ee85f061ce11a2f95ca6.tar.gz
git-323e00fd46afb9293b25ee85f061ce11a2f95ca6.tar.bz2
checkout: Don't crash when switching away from an invalid branch.
When using alternates, it is possible for HEAD to end up pointing to an invalid commit. git checkout should be able to recover from that situation without crashing. Signed-off-by: Alexandre Julliard <julliard@winehq.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--builtin-checkout.c8
-rwxr-xr-xt/t2011-checkout-invalid-head.sh18
2 files changed, 22 insertions, 4 deletions
diff --git a/builtin-checkout.c b/builtin-checkout.c
index 1deda92..05eee4e 100644
--- a/builtin-checkout.c
+++ b/builtin-checkout.c
@@ -32,7 +32,7 @@ static int post_checkout_hook(struct commit *old, struct commit *new,
memset(&proc, 0, sizeof(proc));
argv[0] = name;
- argv[1] = xstrdup(sha1_to_hex(old->object.sha1));
+ argv[1] = xstrdup(sha1_to_hex(old ? old->object.sha1 : null_sha1));
argv[2] = xstrdup(sha1_to_hex(new->object.sha1));
argv[3] = changed ? "1" : "0";
argv[4] = NULL;
@@ -360,10 +360,10 @@ static void update_refs_for_switch(struct checkout_opts *opts,
strbuf_init(&msg, 0);
old_desc = old->name;
- if (!old_desc)
+ if (!old_desc && old->commit)
old_desc = sha1_to_hex(old->commit->object.sha1);
strbuf_addf(&msg, "checkout: moving from %s to %s",
- old_desc, new->name);
+ old_desc ? old_desc : "(invalid)", new->name);
if (new->path) {
create_symref("HEAD", new->path, msg.buf);
@@ -419,7 +419,7 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
* a new commit, we want to mention the old commit once more
* to remind the user that it might be lost.
*/
- if (!opts->quiet && !old.path && new->commit != old.commit)
+ if (!opts->quiet && !old.path && old.commit && new->commit != old.commit)
describe_detached_head("Previous HEAD position was", old.commit);
if (!old.commit) {
diff --git a/t/t2011-checkout-invalid-head.sh b/t/t2011-checkout-invalid-head.sh
new file mode 100755
index 0000000..764bb0a
--- /dev/null
+++ b/t/t2011-checkout-invalid-head.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+test_description='checkout switching away from an invalid branch'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ echo hello >world &&
+ git add world &&
+ git commit -m initial
+'
+
+test_expect_success 'checkout master from invalid HEAD' '
+ echo 0000000000000000000000000000000000000000 >.git/HEAD &&
+ git checkout master --
+'
+
+test_done