From: Junio C Hamano Date: Sun, 12 Apr 2009 22:34:53 +0000 (-0700) Subject: Merge branch 'maint-1.6.1' into maint X-Git-Tag: v1.6.2.3~1 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/1966af81760aea2966f8f218d442aed5f296b992?ds=inline;hp=-c Merge branch 'maint-1.6.1' into maint * maint-1.6.1: State the effect of filter-branch on graft explicitly process_{tree,blob}: Remove useless xstrdup calls --- 1966af81760aea2966f8f218d442aed5f296b992 diff --combined Documentation/git-filter-branch.txt index 7ffe03f427,68f97cd5ae..c1193953a1 --- a/Documentation/git-filter-branch.txt +++ b/Documentation/git-filter-branch.txt @@@ -31,6 -31,9 +31,9 @@@ changes, which would normally have no e useful in the future for compensating for some git bugs or such, therefore such a usage is permitted. + *NOTE*: This command honors `.git/info/grafts`. If you have any grafts + defined, running this command will make them permanent. + *WARNING*! The rewritten history will have different object names for all the objects and will not converge with the original branch. You will not be able to easily push and distribute the rewritten branch on top of the @@@ -122,10 -125,6 +125,10 @@@ You can use the 'map' convenience funct convenience functions, too. For example, calling 'skip_commit "$@"' will leave out the current commit (but not its changes! If you want that, use 'git-rebase' instead). ++ +You can also use the 'git_commit_non_empty_tree "$@"' instead of +'git commit-tree "$@"' if you don't wish to keep commits with a single parent +and that makes no change to the tree. --tag-name-filter :: This is the filter for rewriting tag names. When passed, @@@ -155,16 -154,6 +158,16 @@@ to other tags will be rewritten to poin The result will contain that directory (and only that) as its project root. +--prune-empty:: + Some kind of filters will generate empty commits, that left the tree + untouched. This switch allow git-filter-branch to ignore such + commits. Though, this switch only applies for commits that have one + and only one parent, it will hence keep merges points. Also, this + option is not compatible with the use of '--commit-filter'. Though you + just need to use the function 'git_commit_non_empty_tree "$@"' instead + of the 'git commit-tree "$@"' idiom in your commit filter to make that + happen. + --original :: Use this option to set the namespace where the original commits will be stored. The default value is 'refs/original'. @@@ -212,11 -201,6 +215,11 @@@ git filter-branch --index-filter 'git r Now, you will get the rewritten history saved in HEAD. +As with using `rm filename`, `git rm --cached filename` will fail +if the file is absent from the tree of a commit. If it is not important +whether the file is already absent from the tree, you can use +`git rm --cached --ignore-unmatch filename` instead. + To rewrite the repository to look as if `foodir/` had been its project root, and discard all other history: @@@ -339,47 -323,6 +342,47 @@@ git filter-branch --index-filter --------------------------------------------------------------- + +Checklist for Shrinking a Repository +------------------------------------ + +git-filter-branch is often used to get rid of a subset of files, +usually with some combination of `\--index-filter` and +`\--subdirectory-filter`. People expect the resulting repository to +be smaller than the original, but you need a few more steps to +actually make it smaller, because git tries hard not to lose your +objects until you tell it to. First make sure that: + +* You really removed all variants of a filename, if a blob was moved + over its lifetime. `git log \--name-only \--follow \--all \-- + filename` can help you find renames. + +* You really filtered all refs: use `\--tag-name-filter cat \-- + \--all` when calling git-filter-branch. + +Then there are two ways to get a smaller repository. A safer way is +to clone, that keeps your original intact. + +* Clone it with `git clone +++file:///path/to/repo+++`. The clone + will not have the removed objects. See linkgit:git-clone[1]. (Note + that cloning with a plain path just hardlinks everything!) + +If you really don't want to clone it, for whatever reasons, check the +following points instead (in this order). This is a very destructive +approach, so *make a backup* or go back to cloning it. You have been +warned. + +* Remove the original refs backed up by git-filter-branch: say `git + for-each-ref \--format="%(refname)" refs/original/ | xargs -n 1 git + update-ref -d`. + +* Expire all reflogs with `git reflog expire \--expire=now \--all`. + +* Garbage collect all unreferenced objects with `git gc \--prune=now` + (or if your git-gc is not new enough to support arguments to + `\--prune`, use `git repack -ad; git prune` instead). + + Author ------ Written by Petr "Pasky" Baudis , diff --combined builtin-pack-objects.c index 9fc3b35547,a357cb04fc..6cf5b86e15 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@@ -78,7 -78,7 +78,7 @@@ static int progress = 1 static int window = 10; static uint32_t pack_size_limit, pack_size_limit_cfg; static int depth = 50; -static int delta_search_threads = 1; +static int delta_search_threads; static int pack_to_stdout; static int num_preferred_base; static struct progress *progress_state; @@@ -1611,18 -1611,11 +1611,18 @@@ static void ll_find_deltas(struct objec find_deltas(list, &list_size, window, depth, processed); return; } + if (progress > pack_to_stdout) + fprintf(stderr, "Delta compression using %d threads.\n", + delta_search_threads); /* Partition the work amongst work threads. */ for (i = 0; i < delta_search_threads; i++) { unsigned sub_size = list_size / (delta_search_threads - i); + /* don't use too small segments or no deltas will be found */ + if (sub_size < 2*window && i+1 < delta_search_threads) + sub_size = 0; + p[i].window = window; p[i].depth = depth; p[i].processed = processed; @@@ -1912,6 -1905,8 +1912,8 @@@ static void show_object(struct object_a add_preferred_base_object(p->name); add_object_entry(p->item->sha1, p->item->type, p->name, 0); p->item->flags |= OBJECT_ADDED; + free((char *)p->name); + p->name = NULL; } static void show_edge(struct commit *commit) @@@ -1966,7 -1961,11 +1968,7 @@@ static void add_objects_in_unpacked_pac const unsigned char *sha1; struct object *o; - for (i = 0; i < revs->num_ignore_packed; i++) { - if (matches_pack_name(p, revs->ignore_packed[i])) - break; - } - if (revs->num_ignore_packed <= i) + if (!p->pack_local || p->pack_keep) continue; if (open_pack_index(p)) die("cannot open pack index"); @@@ -1995,29 -1994,6 +1997,29 @@@ free(in_pack.array); } +static int has_sha1_pack_kept_or_nonlocal(const unsigned char *sha1) +{ + static struct packed_git *last_found = (void *)1; + struct packed_git *p; + + p = (last_found != (void *)1) ? last_found : packed_git; + + while (p) { + if ((!p->pack_local || p->pack_keep) && + find_pack_entry_one(sha1, p)) { + last_found = p; + return 1; + } + if (p == last_found) + p = packed_git; + else + p = p->next; + if (p == last_found) + p = p->next; + } + return 0; +} + static void loosen_unused_packed_objects(struct rev_info *revs) { struct packed_git *p; @@@ -2025,7 -2001,11 +2027,7 @@@ const unsigned char *sha1; for (p = packed_git; p; p = p->next) { - for (i = 0; i < revs->num_ignore_packed; i++) { - if (matches_pack_name(p, revs->ignore_packed[i])) - break; - } - if (revs->num_ignore_packed <= i) + if (!p->pack_local || p->pack_keep) continue; if (open_pack_index(p)) @@@ -2033,8 -2013,7 +2035,8 @@@ for (i = 0; i < p->num_objects; i++) { sha1 = nth_packed_object_sha1(p, i); - if (!locate_object_entry(sha1)) + if (!locate_object_entry(sha1) && + !has_sha1_pack_kept_or_nonlocal(sha1)) if (force_object_loose(sha1, p->mtime)) die("unable to force loose object"); } @@@ -2224,6 -2203,7 +2226,6 @@@ int cmd_pack_objects(int argc, const ch continue; } if (!strcmp("--unpacked", arg) || - !prefixcmp(arg, "--unpacked=") || !strcmp("--reflog", arg) || !strcmp("--all", arg)) { use_internal_rev_list = 1;