[PATCH] optionally disable overwriting of ignored files
From: Clemens Buchacher <hidden>
Date: 2016-06-15 22:49:20
Subsystem:
documentation, the rest · Maintainers:
Jonathan Corbet, Linus Torvalds
Possibly related (same subject, not in this thread)
- 2016-06-15 · Re: Re: [PATCH] optionally disable overwriting of ignored files · Heiko Voigt <hidden>
- 2016-06-15 · Re: [PATCH] optionally disable overwriting of ignored files · Matthieu Moy <hidden>
- 2016-06-15 · Re: [PATCH] optionally disable overwriting of ignored files · Matthieu Moy <hidden>
- 2016-06-15 · Re: [PATCH] optionally disable overwriting of ignored files · Holger Hellmuth <hidden>
- 2016-06-15 · Re: [PATCH] optionally disable overwriting of ignored files · Clemens Buchacher <hidden>
By default, checkout and fast-forward merge will overwrite ignored files. Make this behavior configurable. If overwriting ignored files is disabled, it can still be enabled on the command line by passing -i to merge or checkout. Signed-off-by: Clemens Buchacher <redacted> --- Hi, On Tue, Aug 17, 2010 at 12:33:25PM -0700, Junio C Hamano wrote:
Ancient git didn't honor gitignore and considered no files trashable, which caused a lot of trouble to users. It may be illuminating to check discussions in the list archive during the period the following commits were made. f8a9d42 (read-tree: further loosen "working file will be lost" check., 2006-12-04), ed93b44 (merge: loosen overcautious "working file will be lost" check., 2006-10-08), c819353 (Fix switching to a branch with D/F when current branch has file D., 2007-03-15).
I am not convinced this is something that most users want. The fact that adding a file to .gitignore also marks it as trashable to git is quite surprising to me. This is something that the gitignore manpage should warn about loudly. Instead, I think this behavior is completely undocumented. As far as I can tell from the code, only fast-forward merge and checkout overwrite ignored files by default. A regular merge will complain about untracked files that would be overwritten (ignored or not). I am quite familiar with that behavior and I think it's useful to be reminded of those untracked files rather than having them overwritten. I thought that by extension, other git commands would behave in the same way. Here is a patch to optionally disable overwriting of ignored files. But I think we should even disable it by default. Clemens Documentation/config.txt | 6 ++++++ builtin/checkout.c | 7 +++++++ builtin/merge.c | 9 +++++++++ cache.h | 1 + config.c | 3 +++ environment.c | 1 + 6 files changed, 27 insertions(+), 0 deletions(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index f81fb91..eb9bb43 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt@@ -450,6 +450,12 @@ core.excludesfile:: to the value of `$HOME` and "{tilde}user/" to the specified user's home directory. See linkgit:gitignore[5]. +core.overwriteignored:: + Untracked files can get in the way of merge or checkout. If + overwriteignored is enabled, such files will be overwritten + to let fast-forward merges and checkouts succeed. Enabled + by default. + core.editor:: Commands such as `commit` and `tag` that lets you edit messages by launching an editor uses the value of this
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 5affb6f..121a6a3 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c@@ -389,6 +389,11 @@ static int merge_working_tree(struct checkout_opts *opts, topts.gently = opts->merge && old->commit; topts.verbose_update = !opts->quiet; topts.fn = twoway_merge; + if (overwrite_ignored) { + topts.dir = xcalloc(1, sizeof(*topts.dir)); + topts.dir->flags |= DIR_SHOW_IGNORED; + topts.dir->exclude_per_dir = ".gitignore"; + } tree = parse_tree_indirect(old->commit ? old->commit->object.sha1 : (unsigned char *)EMPTY_TREE_SHA1_BIN);
@@ -664,6 +669,8 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) OPT_SET_INT('3', "theirs", &opts.writeout_stage, "stage", 3), OPT_BOOLEAN('f', "force", &opts.force, "force"), + OPT_BOOLEAN('i', "overwrite-ignored", &overwrite_ignored, + "allow explicitly ignored files to be overwritten"), OPT_BOOLEAN('m', "merge", &opts.merge, "merge"), OPT_STRING(0, "conflict", &conflict_style, "style", "conflict style (merge or diff3)"),
diff --git a/builtin/merge.c b/builtin/merge.c
index 4d31e09..47b12ba 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c@@ -185,6 +185,8 @@ static struct option builtin_merge_options[] = { "allow fast-forward (default)"), OPT_BOOLEAN(0, "ff-only", &fast_forward_only, "abort if fast-forward is not possible"), + OPT_BOOLEAN('i', "overwrite-ignored", &overwrite_ignored, + "allow explicitly ignored files to be overwritten"), OPT_RERERE_AUTOUPDATE(&allow_rerere_auto), OPT_CALLBACK('s', "strategy", &use_strategies, "strategy", "merge strategy to use", option_parse_strategy),
@@ -682,6 +684,7 @@ int checkout_fast_forward(const unsigned char *head, const unsigned char *remote struct unpack_trees_options opts; struct tree_desc t[MAX_UNPACK_TREES]; int i, fd, nr_trees = 0; + struct dir_struct dir; struct lock_file *lock_file = xcalloc(1, sizeof(struct lock_file)); refresh_cache(REFRESH_QUIET);
@@ -691,6 +694,12 @@ int checkout_fast_forward(const unsigned char *head, const unsigned char *remote memset(&trees, 0, sizeof(trees)); memset(&opts, 0, sizeof(opts)); memset(&t, 0, sizeof(t)); + memset(&dir, 0, sizeof(dir)); + if (overwrite_ignored) { + dir.flags |= DIR_SHOW_IGNORED; + dir.exclude_per_dir = ".gitignore"; + opts.dir = &dir; + } opts.head_idx = 1; opts.src_index = &the_index;
diff --git a/cache.h b/cache.h
index c9fa3df..dd1b8f7 100644
--- a/cache.h
+++ b/cache.h@@ -548,6 +548,7 @@ extern size_t packed_git_window_size; extern size_t packed_git_limit; extern size_t delta_base_cache_limit; extern int read_replace_refs; +extern int overwrite_ignored; extern int fsync_object_files; extern int core_preload_index; extern int core_apply_sparse_checkout;
diff --git a/config.c b/config.c
index cdcf583..bd7956e 100644
--- a/config.c
+++ b/config.c@@ -563,6 +563,9 @@ static int git_default_core_config(const char *var, const char *value) if (!strcmp(var, "core.excludesfile")) return git_config_pathname(&excludes_file, var, value); + if (!strcmp(var, "core.overwriteignored")) + overwrite_ignored = git_config_bool(var, value); + if (!strcmp(var, "core.whitespace")) { if (!value) return config_error_nonbool(var);
diff --git a/environment.c b/environment.c
index 83d38d3..1b92f60 100644
--- a/environment.c
+++ b/environment.c@@ -30,6 +30,7 @@ const char *apply_default_ignorewhitespace; int zlib_compression_level = Z_BEST_SPEED; int core_compression_level; int core_compression_seen; +int overwrite_ignored = 1; int fsync_object_files; size_t packed_git_window_size = DEFAULT_PACKED_GIT_WINDOW_SIZE; size_t packed_git_limit = DEFAULT_PACKED_GIT_LIMIT;
--
1.7.2.1.1.g202c
Attachments
- signature.asc [application/pgp-signature] 490 bytes