builtin-rm.c: explain and clarify the "local change" logic
Explain the logic to check local modification a bit more in the comment, especially because the existing comment that talks about "git rm --cached" was placed in a part that was not about "--cached" at all. Also clarify "if .. else if .." structure. Signed-off-by: Junio C Hamano <gitster@pobox.com>
Junio C Hamano committed
Nov 28, 2008 at 18:41 UTC
69530cb0c0d5f08dac9bedff56c164b7370f9931
1 file changed
+42
-11
builtin-rm.c
+42
-11
@@ -31,7 +31,8 @@ static void add_list(const char *name)
31
32
static int check_local_mod(unsigned char *head, int index_only)
33
{
34
- /* items in list are already sorted in the cache order,
34
+ /*
35
+ * Items in list are already sorted in the cache order,
36
* so we could do this a lot more efficiently by using
37
* tree_desc based traversal if we wanted to, but I am
38
* lazy, and who cares if removal of files is a tad
@@ -71,25 +72,55 @@ static int check_local_mod(unsigned char *head, int index_only)
72
*/
73
continue;
74
}
75
+
76
+ /*
77
+ * "rm" of a path that has changes need to be treated
78
+ * carefully not to allow losing local changes
79
+ * accidentally. A local change could be (1) file in
80
+ * work tree is different since the index; and/or (2)
81
+ * the user staged a content that is different from
82
+ * the current commit in the index.
83
+ *
84
+ * In such a case, you would need to --force the
85
+ * removal. However, "rm --cached" (remove only from
86
+ * the index) is safe if the index matches the file in
87
+ * the work tree or the HEAD commit, as it means that
88
+ * the content being removed is available elsewhere.
89
+ */
90
+
91
+ /*
92
+ * Is the index different from the file in the work tree?
93
+ */
94
if (ce_match_stat(ce, &st, 0))
95
local_changes = 1;
96
+
97
+ /*
98
+ * Is the index different from the HEAD commit? By
99
+ * definition, before the very initial commit,
100
+ * anything staged in the index is treated by the same
101
+ * way as changed from the HEAD.
102
+ */
103
if (no_head
104
|| get_tree_entry(head, name, sha1, &mode)
105
|| ce->ce_mode != create_ce_mode(mode)
106
|| hashcmp(ce->sha1, sha1))
107
staged_changes = 1;
108
82
- if (local_changes && staged_changes &&
83
- !(index_only && is_empty_blob_sha1(ce->sha1)))
84
- errs = error("'%s' has staged content different "
85
- "from both the file and the HEAD\n"
86
- "(use -f to force removal)", name);
109
+ /*
110
+ * If the index does not match the file in the work
111
+ * tree and if it does not match the HEAD commit
112
+ * either, (1) "git rm" without --cached definitely
113
+ * will lose information; (2) "git rm --cached" will
114
+ * lose information unless it is about removing an
115
+ * "intent to add" entry.
116
+ */
117
+ if (local_changes && staged_changes) {
118
+ if (!index_only || !is_empty_blob_sha1(ce->sha1))
119
+ errs = error("'%s' has staged content different "
120
+ "from both the file and the HEAD\n"
121
+ "(use -f to force removal)", name);
122
+ }
123
else if (!index_only) {
88
- /* It's not dangerous to "git rm --cached" a
89
- * file if the index matches the file or the
90
- * HEAD, since it means the deleted content is
91
- * still available somewhere.
92
- */
124
if (staged_changes)
125
errs = error("'%s' has changes staged in the index\n"
126
"(use --cached to keep the file, "