@matheusbsbs / matheus-bagliano / commits / 887952b8c6
Fork 0

fetch: optionally allow disabling FETCH_HEAD update

If you run fetch but record the result in remote-tracking branches, and either if you do nothing with the fetched refs (e.g. you are merely mirroring) or if you always work from the remote-tracking refs (e.g. you fetch and then merge origin/branchname separately), you can get away with having no FETCH_HEAD at all. Teach "git fetch" a command line option "--[no-]write-fetch-head". The default is to write FETCH_HEAD, and the option is primarily meant to be used with the "--no-" prefix to override this default, because there is no matching fetch.writeFetchHEAD configuration variable to flip the default to off (in which case, the positive form may become necessary to defeat it). Note that under "--dry-run" mode, FETCH_HEAD is never written; otherwise you'd see list of objects in the file that you do not actually have. Passing `--write-fetch-head` does not force `git fetch` to write the file. Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Aug 18, 2020 at 14:25 UTC 887952b8c680626f4721cb5fa57704478801aca4
4 files changed +41 -5
Documentation/fetch-options.txt
+9
@@ -64,6 +64,15 @@ documented in linkgit:git-config[1].
64 --dry-run::
65 Show what would be done, without making any changes.
66
67 +ifndef::git-pull[]
68 +--[no-]write-fetch-head::
69 + Write the list of remote refs fetched in the `FETCH_HEAD`
70 + file directly under `$GIT_DIR`. This is the default.
71 + Passing `--no-write-fetch-head` from the command line tells
72 + Git not to write the file. Under `--dry-run` option, the
73 + file is never written.
74 +endif::git-pull[]
75 +
76 -f::
77 --force::
78 When 'git fetch' is used with `<src>:<dst>` refspec it may
builtin/fetch.c
+12 -3
@@ -56,6 +56,7 @@ static int prune_tags = -1; /* unspecified */
56 #define PRUNE_TAGS_BY_DEFAULT 0 /* do we prune tags by default? */
57
58 static int all, append, dry_run, force, keep, multiple, update_head_ok;
59 +static int write_fetch_head = 1;
60 static int verbosity, deepen_relative, set_upstream;
61 static int progress = -1;
62 static int enable_auto_gc = 1;
@@ -162,6 +163,8 @@ static struct option builtin_fetch_options[] = {
163 PARSE_OPT_OPTARG, option_fetch_parse_recurse_submodules),
164 OPT_BOOL(0, "dry-run", &dry_run,
165 N_("dry run")),
166 + OPT_BOOL(0, "write-fetch-head", &write_fetch_head,
167 + N_("write fetched references to the FETCH_HEAD file")),
168 OPT_BOOL('k', "keep", &keep, N_("keep downloaded pack")),
169 OPT_BOOL('u', "update-head-ok", &update_head_ok,
170 N_("allow updating of HEAD ref")),
@@ -893,7 +896,9 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
896 const char *what, *kind;
897 struct ref *rm;
898 char *url;
896 - const char *filename = dry_run ? "/dev/null" : git_path_fetch_head(the_repository);
899 + const char *filename = (!write_fetch_head
900 + ? "/dev/null"
901 + : git_path_fetch_head(the_repository));
902 int want_status;
903 int summary_width = transport_summary_width(ref_map);
904
@@ -1327,7 +1332,7 @@ static int do_fetch(struct transport *transport,
1332 }
1333
1334 /* if not appending, truncate FETCH_HEAD */
1330 - if (!append && !dry_run) {
1335 + if (!append && write_fetch_head) {
1336 retcode = truncate_fetch_head();
1337 if (retcode)
1338 goto cleanup;
@@ -1594,7 +1599,7 @@ static int fetch_multiple(struct string_list *list, int max_children)
1599 int i, result = 0;
1600 struct strvec argv = STRVEC_INIT;
1601
1597 - if (!append && !dry_run) {
1602 + if (!append && write_fetch_head) {
1603 int errcode = truncate_fetch_head();
1604 if (errcode)
1605 return errcode;
@@ -1795,6 +1800,10 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
1800 if (depth || deepen_since || deepen_not.nr)
1801 deepen = 1;
1802
1803 + /* FETCH_HEAD never gets updated in --dry-run mode */
1804 + if (dry_run)
1805 + write_fetch_head = 0;
1806 +
1807 if (all) {
1808 if (argc == 1)
1809 die(_("fetch --all does not take a repository argument"));
t/t5510-fetch.sh
+13 -2
@@ -543,13 +543,24 @@ test_expect_success 'fetch into the current branch with --update-head-ok' '
543
544 '
545
546 -test_expect_success 'fetch --dry-run' '
547 -
546 +test_expect_success 'fetch --dry-run does not touch FETCH_HEAD' '
547 rm -f .git/FETCH_HEAD &&
548 git fetch --dry-run . &&
549 ! test -f .git/FETCH_HEAD
550 '
551
552 +test_expect_success '--no-write-fetch-head does not touch FETCH_HEAD' '
553 + rm -f .git/FETCH_HEAD &&
554 + git fetch --no-write-fetch-head . &&
555 + ! test -f .git/FETCH_HEAD
556 +'
557 +
558 +test_expect_success '--write-fetch-head gets defeated by --dry-run' '
559 + rm -f .git/FETCH_HEAD &&
560 + git fetch --dry-run --write-fetch-head . &&
561 + ! test -f .git/FETCH_HEAD
562 +'
563 +
564 test_expect_success "should be able to fetch with duplicate refspecs" '
565 mkdir dups &&
566 (
t/t5521-pull-options.sh
+7
@@ -85,6 +85,13 @@ test_expect_success 'git pull --cleanup errors early on invalid argument' '
85 test -s err)
86 '
87
88 +test_expect_success 'git pull --no-write-fetch-head fails' '
89 + mkdir clonedwfh &&
90 + (cd clonedwfh && git init &&
91 + test_expect_code 129 git pull --no-write-fetch-head "../parent" >out 2>err &&
92 + test_must_be_empty out &&
93 + test_i18ngrep "no-write-fetch-head" err)
94 +'
95
96 test_expect_success 'git pull --force' '
97 mkdir clonedoldstyle &&