@matheusbsbs / matheus-bagliano / commits / 69530cb0c0
Fork 0

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, "