Skip to content

Commit 887952b

Browse files
committed
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 2befe97 commit 887952b

File tree

4 files changed

+41
-5
lines changed

4 files changed

+41
-5
lines changed

Documentation/fetch-options.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,15 @@ documented in linkgit:git-config[1].
6464
--dry-run::
6565
Show what would be done, without making any changes.
6666

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+
6776
-f::
6877
--force::
6978
When 'git fetch' is used with `<src>:<dst>` refspec it may

builtin/fetch.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ static int prune_tags = -1; /* unspecified */
5656
#define PRUNE_TAGS_BY_DEFAULT 0 /* do we prune tags by default? */
5757

5858
static int all, append, dry_run, force, keep, multiple, update_head_ok;
59+
static int write_fetch_head = 1;
5960
static int verbosity, deepen_relative, set_upstream;
6061
static int progress = -1;
6162
static int enable_auto_gc = 1;
@@ -162,6 +163,8 @@ static struct option builtin_fetch_options[] = {
162163
PARSE_OPT_OPTARG, option_fetch_parse_recurse_submodules),
163164
OPT_BOOL(0, "dry-run", &dry_run,
164165
N_("dry run")),
166+
OPT_BOOL(0, "write-fetch-head", &write_fetch_head,
167+
N_("write fetched references to the FETCH_HEAD file")),
165168
OPT_BOOL('k', "keep", &keep, N_("keep downloaded pack")),
166169
OPT_BOOL('u', "update-head-ok", &update_head_ok,
167170
N_("allow updating of HEAD ref")),
@@ -893,7 +896,9 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
893896
const char *what, *kind;
894897
struct ref *rm;
895898
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));
897902
int want_status;
898903
int summary_width = transport_summary_width(ref_map);
899904

@@ -1327,7 +1332,7 @@ static int do_fetch(struct transport *transport,
13271332
}
13281333

13291334
/* if not appending, truncate FETCH_HEAD */
1330-
if (!append && !dry_run) {
1335+
if (!append && write_fetch_head) {
13311336
retcode = truncate_fetch_head();
13321337
if (retcode)
13331338
goto cleanup;
@@ -1594,7 +1599,7 @@ static int fetch_multiple(struct string_list *list, int max_children)
15941599
int i, result = 0;
15951600
struct strvec argv = STRVEC_INIT;
15961601

1597-
if (!append && !dry_run) {
1602+
if (!append && write_fetch_head) {
15981603
int errcode = truncate_fetch_head();
15991604
if (errcode)
16001605
return errcode;
@@ -1795,6 +1800,10 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
17951800
if (depth || deepen_since || deepen_not.nr)
17961801
deepen = 1;
17971802

1803+
/* FETCH_HEAD never gets updated in --dry-run mode */
1804+
if (dry_run)
1805+
write_fetch_head = 0;
1806+
17981807
if (all) {
17991808
if (argc == 1)
18001809
die(_("fetch --all does not take a repository argument"));

t/t5510-fetch.sh

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -543,13 +543,24 @@ test_expect_success 'fetch into the current branch with --update-head-ok' '
543543
544544
'
545545

546-
test_expect_success 'fetch --dry-run' '
547-
546+
test_expect_success 'fetch --dry-run does not touch FETCH_HEAD' '
548547
rm -f .git/FETCH_HEAD &&
549548
git fetch --dry-run . &&
550549
! test -f .git/FETCH_HEAD
551550
'
552551

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+
553564
test_expect_success "should be able to fetch with duplicate refspecs" '
554565
mkdir dups &&
555566
(

t/t5521-pull-options.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,13 @@ test_expect_success 'git pull --cleanup errors early on invalid argument' '
8585
test -s err)
8686
'
8787

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+
'
8895

8996
test_expect_success 'git pull --force' '
9097
mkdir clonedoldstyle &&

0 commit comments

Comments
 (0)