mirror of
https://github.com/git/git.git
synced 2024-11-24 10:26:17 +08:00
Merge branch 'nd/fetch-depth-is-broken'
"git fetch --depth" was broken in at least three ways. The resulting history was deeper than specified by one commit, it was unclear how to wipe the shallowness of the repository with the command, and documentation was misleading. * nd/fetch-depth-is-broken: fetch: elaborate --depth action upload-pack: fix off-by-one depth calculation in shallow clone fetch: add --unshallow for turning shallow repo into complete one
This commit is contained in:
commit
2532d891a4
@ -8,11 +8,15 @@
|
||||
option old data in `.git/FETCH_HEAD` will be overwritten.
|
||||
|
||||
--depth=<depth>::
|
||||
Deepen the history of a 'shallow' repository created by
|
||||
Deepen or shorten the history of a 'shallow' repository created by
|
||||
`git clone` with `--depth=<depth>` option (see linkgit:git-clone[1])
|
||||
to the specified number of commits from the tip of each remote
|
||||
branch history. Tags for the deepened commits are not fetched.
|
||||
|
||||
--unshallow::
|
||||
Convert a shallow repository to a complete one, removing all
|
||||
the limitations imposed by shallow repositories.
|
||||
|
||||
ifndef::git-pull[]
|
||||
--dry-run::
|
||||
Show what would be done, without making any changes.
|
||||
|
@ -84,6 +84,8 @@ be in a separate packet, and the list must end with a flush packet.
|
||||
|
||||
--depth=<n>::
|
||||
Limit fetching to ancestor-chains not longer than n.
|
||||
'git-upload-pack' treats the special depth 2147483647 as
|
||||
infinite even if there is an ancestor-chain that long.
|
||||
|
||||
--no-progress::
|
||||
Do not show the progress.
|
||||
|
@ -53,3 +53,6 @@ It also writes an appropriate $GIT_DIR/shallow.
|
||||
You can deepen a shallow repository with "git-fetch --depth 20
|
||||
repo branch", which will fetch branch from repo, but stop at depth
|
||||
20, updating $GIT_DIR/shallow.
|
||||
|
||||
The special depth 2147483647 (or 0x7fffffff, the largest positive
|
||||
number a signed 32-bit integer can contain) means infinite depth.
|
||||
|
@ -32,7 +32,7 @@ enum {
|
||||
|
||||
static int all, append, dry_run, force, keep, multiple, prune, update_head_ok, verbosity;
|
||||
static int progress = -1, recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
|
||||
static int tags = TAGS_DEFAULT;
|
||||
static int tags = TAGS_DEFAULT, unshallow;
|
||||
static const char *depth;
|
||||
static const char *upload_pack;
|
||||
static struct strbuf default_rla = STRBUF_INIT;
|
||||
@ -82,6 +82,9 @@ static struct option builtin_fetch_options[] = {
|
||||
OPT_BOOL(0, "progress", &progress, N_("force progress reporting")),
|
||||
OPT_STRING(0, "depth", &depth, N_("depth"),
|
||||
N_("deepen history of shallow clone")),
|
||||
{ OPTION_SET_INT, 0, "unshallow", &unshallow, NULL,
|
||||
N_("convert to a complete repository"),
|
||||
PARSE_OPT_NONEG | PARSE_OPT_NOARG, NULL, 1 },
|
||||
{ OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, N_("dir"),
|
||||
N_("prepend this to submodule path output"), PARSE_OPT_HIDDEN },
|
||||
{ OPTION_STRING, 0, "recurse-submodules-default",
|
||||
@ -970,6 +973,18 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
|
||||
argc = parse_options(argc, argv, prefix,
|
||||
builtin_fetch_options, builtin_fetch_usage, 0);
|
||||
|
||||
if (unshallow) {
|
||||
if (depth)
|
||||
die(_("--depth and --unshallow cannot be used together"));
|
||||
else if (!is_repository_shallow())
|
||||
die(_("--unshallow on a complete repository does not make sense"));
|
||||
else {
|
||||
static char inf_depth[12];
|
||||
sprintf(inf_depth, "%d", INFINITE_DEPTH);
|
||||
depth = inf_depth;
|
||||
}
|
||||
}
|
||||
|
||||
if (recurse_submodules != RECURSE_SUBMODULES_OFF) {
|
||||
if (recurse_submodules_default) {
|
||||
int arg = parse_fetch_recurse_submodules_arg("--recurse-submodules-default", recurse_submodules_default);
|
||||
|
3
commit.h
3
commit.h
@ -163,6 +163,9 @@ extern struct commit_list *get_merge_bases(struct commit *rev1, struct commit *r
|
||||
extern struct commit_list *get_merge_bases_many(struct commit *one, int n, struct commit **twos, int cleanup);
|
||||
extern struct commit_list *get_octopus_merge_bases(struct commit_list *in);
|
||||
|
||||
/* largest postive number a signed 32-bit integer can contain */
|
||||
#define INFINITE_DEPTH 0x7fffffff
|
||||
|
||||
extern int register_shallow(const unsigned char *sha1);
|
||||
extern int unregister_shallow(const unsigned char *sha1);
|
||||
extern int for_each_commit_graft(each_commit_graft_fn, void *);
|
||||
|
@ -72,8 +72,14 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
|
||||
}
|
||||
if (parse_commit(commit))
|
||||
die("invalid commit");
|
||||
commit->object.flags |= not_shallow_flag;
|
||||
cur_depth++;
|
||||
if (cur_depth >= depth) {
|
||||
commit_list_insert(commit, &result);
|
||||
commit->object.flags |= shallow_flag;
|
||||
commit = NULL;
|
||||
continue;
|
||||
}
|
||||
commit->object.flags |= not_shallow_flag;
|
||||
for (p = commit->parents, commit = NULL; p; p = p->next) {
|
||||
if (!p->item->util) {
|
||||
int *pointer = xmalloc(sizeof(int));
|
||||
|
@ -130,16 +130,25 @@ test_expect_success 'single given branch clone' '
|
||||
test_must_fail git --git-dir=branch-a/.git rev-parse origin/B
|
||||
'
|
||||
|
||||
test_expect_success 'clone shallow depth 1' '
|
||||
git clone --no-single-branch --depth 1 "file://$(pwd)/." shallow0 &&
|
||||
test "`git --git-dir=shallow0/.git rev-list --count HEAD`" = 1
|
||||
'
|
||||
|
||||
test_expect_success 'clone shallow' '
|
||||
git clone --no-single-branch --depth 2 "file://$(pwd)/." shallow
|
||||
'
|
||||
|
||||
test_expect_success 'clone shallow depth count' '
|
||||
test "`git --git-dir=shallow/.git rev-list --count HEAD`" = 2
|
||||
'
|
||||
|
||||
test_expect_success 'clone shallow object count' '
|
||||
(
|
||||
cd shallow &&
|
||||
git count-objects -v
|
||||
) > count.shallow &&
|
||||
grep "^in-pack: 18" count.shallow
|
||||
grep "^in-pack: 12" count.shallow
|
||||
'
|
||||
|
||||
test_expect_success 'clone shallow object count (part 2)' '
|
||||
@ -256,12 +265,36 @@ test_expect_success 'additional simple shallow deepenings' '
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'clone shallow depth count' '
|
||||
test "`git --git-dir=shallow/.git rev-list --count HEAD`" = 11
|
||||
'
|
||||
|
||||
test_expect_success 'clone shallow object count' '
|
||||
(
|
||||
cd shallow &&
|
||||
git count-objects -v
|
||||
) > count.shallow &&
|
||||
grep "^count: 52" count.shallow
|
||||
grep "^count: 55" count.shallow
|
||||
'
|
||||
|
||||
test_expect_success 'fetch --no-shallow on full repo' '
|
||||
test_must_fail git fetch --noshallow
|
||||
'
|
||||
|
||||
test_expect_success 'fetch --depth --no-shallow' '
|
||||
(
|
||||
cd shallow &&
|
||||
test_must_fail git fetch --depth=1 --noshallow
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'turn shallow to complete repository' '
|
||||
(
|
||||
cd shallow &&
|
||||
git fetch --unshallow &&
|
||||
! test -f .git/shallow &&
|
||||
git fsck --full
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'clone shallow without --no-single-branch' '
|
||||
@ -273,7 +306,7 @@ test_expect_success 'clone shallow object count' '
|
||||
cd shallow2 &&
|
||||
git count-objects -v
|
||||
) > count.shallow2 &&
|
||||
grep "^in-pack: 6" count.shallow2
|
||||
grep "^in-pack: 3" count.shallow2
|
||||
'
|
||||
|
||||
test_expect_success 'clone shallow with --branch' '
|
||||
@ -281,7 +314,7 @@ test_expect_success 'clone shallow with --branch' '
|
||||
'
|
||||
|
||||
test_expect_success 'clone shallow object count' '
|
||||
echo "in-pack: 6" > count3.expected &&
|
||||
echo "in-pack: 3" > count3.expected &&
|
||||
GIT_DIR=shallow3/.git git count-objects -v |
|
||||
grep "^in-pack" > count3.actual &&
|
||||
test_cmp count3.expected count3.actual
|
||||
@ -310,7 +343,7 @@ EOF
|
||||
GIT_DIR=shallow6/.git git tag -l >taglist.actual &&
|
||||
test_cmp taglist.expected taglist.actual &&
|
||||
|
||||
echo "in-pack: 7" > count6.expected &&
|
||||
echo "in-pack: 4" > count6.expected &&
|
||||
GIT_DIR=shallow6/.git git count-objects -v |
|
||||
grep "^in-pack" > count6.actual &&
|
||||
test_cmp count6.expected count6.actual
|
||||
@ -325,7 +358,7 @@ EOF
|
||||
GIT_DIR=shallow7/.git git tag -l >taglist.actual &&
|
||||
test_cmp taglist.expected taglist.actual &&
|
||||
|
||||
echo "in-pack: 7" > count7.expected &&
|
||||
echo "in-pack: 4" > count7.expected &&
|
||||
GIT_DIR=shallow7/.git git count-objects -v |
|
||||
grep "^in-pack" > count7.actual &&
|
||||
test_cmp count7.expected count7.actual
|
||||
|
@ -672,10 +672,17 @@ static void receive_needs(void)
|
||||
if (depth == 0 && shallows.nr == 0)
|
||||
return;
|
||||
if (depth > 0) {
|
||||
struct commit_list *result, *backup;
|
||||
struct commit_list *result = NULL, *backup = NULL;
|
||||
int i;
|
||||
backup = result = get_shallow_commits(&want_obj, depth,
|
||||
SHALLOW, NOT_SHALLOW);
|
||||
if (depth == INFINITE_DEPTH)
|
||||
for (i = 0; i < shallows.nr; i++) {
|
||||
struct object *object = shallows.objects[i].item;
|
||||
object->flags |= NOT_SHALLOW;
|
||||
}
|
||||
else
|
||||
backup = result =
|
||||
get_shallow_commits(&want_obj, depth,
|
||||
SHALLOW, NOT_SHALLOW);
|
||||
while (result) {
|
||||
struct object *object = &result->item->object;
|
||||
if (!(object->flags & (CLIENT_SHALLOW|NOT_SHALLOW))) {
|
||||
|
Loading…
Reference in New Issue
Block a user