When encountering broken refs, such as a stale remote HEAD (which can
happen if the active branch was renamed in the remote), it is more
helpful to remove those refs than to exit with an error.

This fixes https://github.com/git-for-windows/git/issues/423

Signed-off-by: Johannes Schindelin <johannes.schinde...@gmx.de>
---
 builtin/prune.c | 12 +++++++++++-
 t/t6500-gc.sh   |  2 +-
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/builtin/prune.c b/builtin/prune.c
index d6f664f..1a30f65 100644
--- a/builtin/prune.c
+++ b/builtin/prune.c
@@ -6,6 +6,7 @@
 #include "reachable.h"
 #include "parse-options.h"
 #include "progress.h"
+#include "refs.h"
 
 static const char * const prune_usage[] = {
        N_("git prune [-n] [-v] [--expire <time>] [--] [<head>...]"),
@@ -100,6 +101,7 @@ static void remove_temporary_files(const char *path)
 int cmd_prune(int argc, const char **argv, const char *prefix)
 {
        struct rev_info revs;
+       struct string_list broken_refs = STRING_LIST_INIT_DUP;
        struct progress *progress = NULL;
        const struct option options[] = {
                OPT__DRY_RUN(&show_only, N_("do not remove, show only")),
@@ -110,6 +112,7 @@ int cmd_prune(int argc, const char **argv, const char 
*prefix)
                OPT_END()
        };
        char *s;
+       int i;
 
        expire = ULONG_MAX;
        save_commit_buffer = 0;
@@ -136,7 +139,14 @@ int cmd_prune(int argc, const char **argv, const char 
*prefix)
        if (show_progress)
                progress = start_progress_delay(_("Checking connectivity"), 0, 
0, 2);
 
-       mark_reachable_objects(&revs, 1, expire, progress, NULL);
+       revs.ignore_missing = 1;
+       mark_reachable_objects(&revs, 1, expire, progress, &broken_refs);
+       for (i = 0; i < broken_refs.nr; i++) {
+               char *path = broken_refs.items[i].string;
+               printf("Removing stale ref %s\n", path);
+               if (!show_only && delete_ref(path, NULL, REF_NODEREF))
+                       die("Could not remove stale ref %s", path);
+       }
        stop_progress(&progress);
        for_each_loose_file_in_objdir(get_object_directory(), prune_object,
                                      prune_cruft, prune_subdir, NULL);
diff --git a/t/t6500-gc.sh b/t/t6500-gc.sh
index b736774..0ae4271 100755
--- a/t/t6500-gc.sh
+++ b/t/t6500-gc.sh
@@ -30,7 +30,7 @@ test_expect_success 'gc -h with invalid configuration' '
        test_i18ngrep "[Uu]sage" broken/usage
 '
 
-test_expect_failure 'gc removes broken refs/remotes/<name>/HEAD' '
+test_expect_success 'gc removes broken refs/remotes/<name>/HEAD' '
        git init remote &&
        (
                cd remote &&
-- 
2.5.2.windows.2


--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to