summaryrefslogtreecommitdiff
path: root/builtin-rm.c
diff options
context:
space:
mode:
authorMatthieu Moy <Matthieu.Moy@imag.fr>2007-07-13 19:41:38 +0200
committerJunio C Hamano <gitster@pobox.com>2007-07-13 23:52:46 -0700
commitbdecd9d41b3528e17aea2290344c584412e2424e (patch)
treee452049ca2a9cd38462831f73ea7a19fdff760e0 /builtin-rm.c
parent1701872fc2cfc48c740175848c1ef6fc10eb0e10 (diff)
downloadgit-bdecd9d41b3528e17aea2290344c584412e2424e.tar.gz
More permissive "git-rm --cached" behavior without -f.
In the previous behavior, "git-rm --cached" (without -f) had the same restriction as "git-rm". This forced the user to use the -f flag in situations which weren't actually dangerous, like: $ git add foo # oops, I didn't want this $ git rm --cached foo # back to initial situation Previously, the index had to match the file *and* the HEAD. With --cached, the index must now match the file *or* the HEAD. The behavior without --cached is unchanged, but provides better error messages. Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'builtin-rm.c')
-rw-r--r--builtin-rm.c32
1 files changed, 26 insertions, 6 deletions
diff --git a/builtin-rm.c b/builtin-rm.c
index 4a0bd93c8b..9a808c1bf9 100644
--- a/builtin-rm.c
+++ b/builtin-rm.c
@@ -46,7 +46,7 @@ static int remove_file(const char *name)
return ret;
}
-static int check_local_mod(unsigned char *head)
+static int check_local_mod(unsigned char *head, int index_only)
{
/* items in list are already sorted in the cache order,
* so we could do this a lot more efficiently by using
@@ -65,6 +65,8 @@ static int check_local_mod(unsigned char *head)
const char *name = list.name[i];
unsigned char sha1[20];
unsigned mode;
+ int local_changes = 0;
+ int staged_changes = 0;
pos = cache_name_pos(name, strlen(name));
if (pos < 0)
@@ -87,14 +89,32 @@ static int check_local_mod(unsigned char *head)
continue;
}
if (ce_match_stat(ce, &st, 0))
- errs = error("'%s' has local modifications "
- "(hint: try -f)", ce->name);
+ local_changes = 1;
if (no_head
|| get_tree_entry(head, name, sha1, &mode)
|| ce->ce_mode != create_ce_mode(mode)
|| hashcmp(ce->sha1, sha1))
- errs = error("'%s' has changes staged in the index "
- "(hint: try -f)", name);
+ staged_changes = 1;
+
+ if (local_changes && staged_changes)
+ errs = error("'%s' has staged content different "
+ "from both the file and the HEAD\n"
+ "(use -f to force removal)", name);
+ else if (!index_only) {
+ /* It's not dangerous to git-rm --cached a
+ * file if the index matches the file or the
+ * HEAD, since it means the deleted content is
+ * still available somewhere.
+ */
+ if (staged_changes)
+ errs = error("'%s' has changes staged in the index\n"
+ "(use --cached to keep the file, "
+ "or -f to force removal)", name);
+ if (local_changes)
+ errs = error("'%s' has local modifications\n"
+ "(use --cached to keep the file, "
+ "or -f to force removal)", name);
+ }
}
return errs;
}
@@ -192,7 +212,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
unsigned char sha1[20];
if (get_sha1("HEAD", sha1))
hashclr(sha1);
- if (check_local_mod(sha1))
+ if (check_local_mod(sha1, index_only))
exit(1);
}