Re: [PATCH] clone: allow initial sparse checkouts
On Sun, Feb 23, 2014 at 09:52:16AM +0700, Duy Nguyen wrote: > On Sun, Feb 23, 2014 at 9:31 AM, Robin H. Johnson wrote: > > Presently if you want to perform a sparse checkout, you must either do a > > full clone and then recheckout, or do a git init, manually set up > > sparse, and then fetch and checkout. > I think you could do "clone -n" (no checkout), set up sparse, then checkout. Yes, I think there are a few more ways, but still would be nice to > > > This patch implements easily accessible sparse checkouts during clone, > > in the --sparse-checkout option. > > > > $ git clone REPO --sparse-checkout PATH > Or take a file as input if there are lots of paths/rules. How much demand for taking a file of rules, and opinions of syntax to do that vs specify on the commandline? --sparse-checkout-from FILE vs. --sparse-checkout 'http://vger.kernel.org/majordomo-info.html
Re: [PATCH] clone: allow initial sparse checkouts
On Sun, Feb 23, 2014 at 9:31 AM, Robin H. Johnson wrote: > Presently if you want to perform a sparse checkout, you must either do a > full clone and then recheckout, or do a git init, manually set up > sparse, and then fetch and checkout. I think you could do "clone -n" (no checkout), set up sparse, then checkout. > This patch implements easily accessible sparse checkouts during clone, > in the --sparse-checkout option. > > $ git clone REPO --sparse-checkout PATH Or take a file as input if there are lots of paths/rules. -- Duy -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 0/8] Hiding refs
(Digging up an old thread about initial refs listing in git protocol) On Thu, Feb 7, 2013 at 7:12 AM, Junio C Hamano wrote: > Ævar Arnfjörð Bjarmason writes: > >> I think there's a simpler way to do this, which is that: >> >> * New clients supporting v2 of the protocol send some piece of data >>that would break old servers. >> >> * If that fails the new client goes "oh jeeze, I guess it's an old >>server", and try again with the old protocol. >> >> * The client then saves a date (or the version the server gave us) >>indicating that it tried the new protocol on that remote, tries >>again sometime later. > > For that to work, the new server needs to wait for the client to > speak first. How would that server handle old clients who expect to > be spoken first? Wait with a read timeout (no timeout is the right > timeout for everybody)? I think the client always speaks first when it asks for a remote service. Earlier in this thread you described the new protocol upload-pack-2. Why can't it be a new service "upload-pack-2" in git-daemon? So new client will try requesting "upload-pack-2" service with client capability advertisement before ref listing. Old servers do not recognize this service and disconnect so the new client falls back to the good old "upload-pack" (one more round trip though, but you could configure new client to use old protocol for certain "old" hosts). Similar thing happens for ssh transport. "upload-pack" service is always there for old clients. -- Duy -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] clone: allow initial sparse checkouts
Presently if you want to perform a sparse checkout, you must either do a full clone and then recheckout, or do a git init, manually set up sparse, and then fetch and checkout. This patch implements easily accessible sparse checkouts during clone, in the --sparse-checkout option. $ git clone REPO --sparse-checkout PATH Signed-off-by: Robin H. Johnson --- Documentation/git-clone.txt | 5 + builtin/clone.c | 24 2 files changed, 29 insertions(+) diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt index 0363d00..1c21207 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -14,6 +14,7 @@ SYNOPSIS [-o ] [-b ] [-u ] [--reference ] [--separate-git-dir ] [--depth ] [--[no-]single-branch] + [--sparse-checkout ] [--recursive | --recurse-submodules] [--] [] @@ -209,6 +210,10 @@ objects from the source repository into a pack in the cloned repository. The result is Git repository can be separated from working tree. +--sparse-checkout :: + Perform the initial checkout as a sparse checkout, checking out only the + paths specified by this option. This option may occur multiple times, with + one path per instance. :: The (possibly remote) repository to clone from. See the diff --git a/builtin/clone.c b/builtin/clone.c index 43e772c..1137371 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -48,6 +48,7 @@ static int option_verbosity; static int option_progress = -1; static struct string_list option_config; static struct string_list option_reference; +static struct string_list option_sparse_checkout_path; static int opt_parse_reference(const struct option *opt, const char *arg, int unset) { @@ -97,6 +98,8 @@ static struct option builtin_clone_options[] = { N_("separate git dir from working tree")), OPT_STRING_LIST('c', "config", &option_config, N_("key=value"), N_("set config inside the new repository")), + OPT_STRING_LIST(0, "sparse-checkout", &option_sparse_checkout_path, N_("path"), + N_("set path for sparse checkout")), OPT_END() }; @@ -270,6 +273,24 @@ static void setup_reference(void) for_each_string_list(&option_reference, add_one_reference, NULL); } +static void setup_sparse_checkout(void) +{ + FILE *info_sparse_checkout_fp; + struct string_list_item *item; + char *path = git_pathdup("info/sparse-checkout"); + git_config_set("core.sparsecheckout", "true"); + safe_create_leading_directories(path); + info_sparse_checkout_fp = fopen(path, "w"); + if (!info_sparse_checkout_fp) + die(_("unable to create %s"), path); + for_each_string_list_item(item, &option_sparse_checkout_path) { + fprintf(info_sparse_checkout_fp, "%s\n", item->string); + } + fclose(info_sparse_checkout_fp); + adjust_shared_perm(path); + free(path); +} + static void copy_alternates(struct strbuf *src, struct strbuf *dst, const char *src_repo) { @@ -873,6 +894,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix) init_db(option_template, INIT_DB_QUIET); write_config(&option_config); + if(option_sparse_checkout_path.nr) + setup_sparse_checkout(); + git_config(git_default_config, NULL); if (option_bare) { -- 1.9.0.291.g027825b.dirty -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] i18n: mark all progress lines for translation
Nguy?n Thái Ng?c Duy: I can't think of any case that progress lines are for machine. It started because of the only local untranslated line in "git clone". But I think we should do all at once. Indeed, a good move. Anything that is to be displayed to the end user should be subject to localization; if it is part of a protocol, then it needs to be translated on the receiving end. -- \\// Peter - http://www.softwolves.pp.se/ -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Fwd: git-reviewed: linking commits to review discussion in git
Jeff King writes: > On Mon, Feb 17, 2014 at 03:12:48PM -0500, Murtuza Mukadam wrote: > >> We have linked peer review discussions on >> git@vger.kernel.org to their respective commits within the main >> git.git repository. You can view the linked reviews from 2012 >> until present in the GitHub repo at: >> https://github.com/mmukadam/git/tree/review > > Neat. We've experimented in the past with mapping commits back to > mailing list discussions. Thomas (cc'd) has a script that creates > git-notes trees mapping commits to the relevant message-id, which can > then be found in the list archive. > > To me, the interesting bits of such a project are: > > 1. How do we decide which messages led to which commits? There is > definitely some room for heuristics here, as patches are sometimes > tweaked in transit, or come in multiple stages (e.g., the original > patch, then somebody suggests a fixup on top). You might want to > compare your work with the script from Thomas here: > >http://repo.or.cz/w/trackgit.git Eh, or don't. My script nowadays uses Junio's suggestion of matching on (author, authordate) with a little bit of tweaking in case there is no match. The name/date match works for most cases even in slightly tweaked forms. (The very first version elaborately tried all sorts of things, including attempting to patch on master, next etc. to see where it applies, and turned out to be wy too slow.) I'm no longer convinced that there's anything a computer can do beyond (author, authordate), anyway. Perhaps someone with a clue in UIs -- that's definitely not me -- could make a website where users can complete or correct the autogenerated mappings to go further. -- Thomas Rast t...@thomasrast.ch -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] builtin/blame.c::find_copy_in_blob: no need to scan for line end
David Kastrup writes: Oh, good grief. Forgot to sign off, and on rereading, the commit message is clearly subfabulous. So forget this one. The content is fine, though. -- David Kastrup -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] builtin/blame.c::find_copy_in_blob: no need to scan for region end
The region end can be looked up just like its beginning. Signed-off-by: David Kastrup --- builtin/blame.c | 9 + 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/builtin/blame.c b/builtin/blame.c index e44a6bb..96716dd 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -939,7 +939,6 @@ static void find_copy_in_blob(struct scoreboard *sb, mmfile_t *file_p) { const char *cp; - int cnt; mmfile_t file_o; struct handle_split_cb_data d; @@ -950,13 +949,7 @@ static void find_copy_in_blob(struct scoreboard *sb, */ cp = nth_line(sb, ent->lno); file_o.ptr = (char *) cp; - cnt = ent->num_lines; - - while (cnt && cp < sb->final_buf + sb->final_buf_size) { - if (*cp++ == '\n') - cnt--; - } - file_o.size = cp - file_o.ptr; + file_o.size = nth_line(sb, ent->lno + ent->num_lines) - cp; /* * file_o is a part of final image we are annotating. -- 1.8.3.2 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] builtin/blame.c::find_copy_in_blob: no need to scan for line end
--- builtin/blame.c | 9 + 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/builtin/blame.c b/builtin/blame.c index e44a6bb..96716dd 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -939,7 +939,6 @@ static void find_copy_in_blob(struct scoreboard *sb, mmfile_t *file_p) { const char *cp; - int cnt; mmfile_t file_o; struct handle_split_cb_data d; @@ -950,13 +949,7 @@ static void find_copy_in_blob(struct scoreboard *sb, */ cp = nth_line(sb, ent->lno); file_o.ptr = (char *) cp; - cnt = ent->num_lines; - - while (cnt && cp < sb->final_buf + sb->final_buf_size) { - if (*cp++ == '\n') - cnt--; - } - file_o.size = cp - file_o.ptr; + file_o.size = nth_line(sb, ent->lno + ent->num_lines) - cp; /* * file_o is a part of final image we are annotating. -- 1.8.3.2 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] sha1_file: fix delta_stack memory leak in unpack_entry
Junio C Hamano writes: > Jeff King writes: > >> On Fri, Feb 21, 2014 at 06:47:47AM +0700, Nguyễn Thái Ngọc Duy wrote: >> >>> This delta_stack array can grow to any length depending on the actual >>> delta chain, but we forget to free it. Normally it does not matter >>> because we use small_delta_stack[] from stack and small_delta_stack >>> can hold 64-delta chains, more than standard --depth=50 in pack-objects. >>> >>> Signed-off-by: Nguyễn Thái Ngọc Duy >>> --- >>> Found when trying to see if making some objects loose at this phase >>> could help git-blame and how many objects will be loosened. Gotta go >>> soon, didn't really test it, but I bet it'll work. >> >> This looks correct to me. > > This comes from abe601bb, right? The change looks correct to me, too. Ow, sorry about that. Thanks for the fix! -- Thomas Rast t...@thomasrast.ch -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: git gc --aggressive led to about 40 times slower "git log --raw"
On Sat, Feb 22, 2014 at 4:14 PM, Duy Nguyen wrote: > On Sat, Feb 22, 2014 at 3:53 PM, David Kastrup wrote: >> David Kastrup writes: >> >>> Duy Nguyen writes: >>> OK with git://git.savannah.gnu.org/emacs.git we have - a 209MB pack with --aggressive - 1.3GB with --depth=50 - 1.3GB with --window=4000 --depth=32 - 1.3GB with --depth=20 - 821MB with --depth=250 for commits --before=2.years.ago, --depth=50 for the rest ... I'm not really happy with --depth=250 producing 209MB while --depth=250 --before=2.year.ago a 800MB pack. It looks wrong (or maybe I did something wrong) >> Another thing: did you really use --depth=250 here or did you use >> --aggressive? It may be that the latter also sets other options? > > I can't use --aggressive because I need to feed revisions directly to > pack-objects. --aggressive also sets --window=250. Thanks for > checking. My machine will have another workout session. And 800MB is reduced to 177MB, containing history older than 2 years. The final pack is 199MB, within the size range of current --aggressive and should be reasonably fast on most operations. Again blame could still hit long delta chains but I think we should just unpack some trees/blobs when we hit long delta chains. I think we should update --aggressive to do it this way. So - gc.aggressiveDepth defaults to 50 (or 20?), this is used for recent history - gc.aggressiveDeepDepth defaults to 250 (or smaller??), used for ancient history - gc.aggressiveDeepOption is rev-list a rev-list option to define "ancient history", default to --before=2.years.ago. This option could be specified multiple times. Both packing phases use the same gc.aggressiveWindow. We could add gc.aggressiveDeepWindow too. GSoC project? -- Duy -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Still waiting for your response
Hello, I am Mrs. Supini Thrunkul from Tai Yau Bank Hong Kong, I need your cooperation to transfer $ 47.3 million US Dollars to any trusted account within your control. Contact me for more details. Mrs. Supini Thrunkul Tel: +85 2580 848 65 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] diff: do not reuse_worktree_file for submodules
Junio C Hamano writes: > Thomas Rast writes: > >> @@ -2845,8 +2845,9 @@ static struct diff_tempfile *prepare_temp_file(const >> char *name, >> remove_tempfile_installed = 1; >> } >> >> -if (!one->sha1_valid || >> -reuse_worktree_file(name, one->sha1, 1)) { >> +if (!S_ISGITLINK(one->mode) && >> +(!one->sha1_valid || >> + reuse_worktree_file(name, one->sha1, 1))) { > > I agree with the goal/end result, but I have to wonder if the > reuse_worktree_file() be the helper function that ought to > encapsulate such a logic? > > Instead of feeding it an object name and a path, if we passed a > diff_filespec to the helper, it would have access to the mode as > well. It would result in a more intrusive change, so I'd prefer to > see your patch applied first and then build such a refactor on top, > perhaps like the attached. I see that you already queued 721e727, which has the change you described plus moving the S_ISGITLINK test into reuse_worktree_file. The change looks good to me. However, two nits about the comments: diff.c now says /* * Given a name and sha1 pair, if the index tells us the file in * the work tree has that object contents, return true, so that * prepare_temp_file() does not have to inflate and extract. */ static int reuse_worktree_file(const struct diff_filespec *spec, int want_file) { const struct cache_entry *ce; struct stat st; int pos, len; const char *name = spec->path; const unsigned char *sha1 = spec->sha1; /* reading the directory will not give us "Submodule commit XYZ" */ if (S_ISGITLINK(spec->mode)) return 0; But the function comment is no longer accurate, and the comment about the S_ISGITLINK exit is rather obscure if one doesn't know what the callers want. So how about this on top? diff.c | 17 + 1 file changed, 13 insertions(+), 4 deletions(-) diff --git i/diff.c w/diff.c index a342ea6..dabf913 100644 --- i/diff.c +++ w/diff.c @@ -2578,9 +2578,14 @@ void fill_filespec(struct diff_filespec *spec, const unsigned char *sha1, } /* - * Given a name and sha1 pair, if the index tells us the file in - * the work tree has that object contents, return true, so that - * prepare_temp_file() does not have to inflate and extract. + * Given a diff_filespec, determine if the corresponding worktree file + * can be used for diffing instead of reading the object from the + * repository. + * + * We normally try packfiles, worktree, loose objects in this order. + * + * If want_file=1 or git was compiled with NO_FAST_WORKING_DIRECTORY, + * the order is: worktree, packfiles, loose objects. */ static int reuse_worktree_file(const struct diff_filespec *spec, int want_file) { @@ -2590,7 +2595,11 @@ static int reuse_worktree_file(const struct diff_filespec *spec, int want_file) const char *name = spec->path; const unsigned char *sha1 = spec->sha1; - /* reading the directory will not give us "Submodule commit XYZ" */ + /* +* The diff representation of a submodule is "Submodule commit +* XYZ", but in the worktree we have a directory. So they +* never match. +*/ if (S_ISGITLINK(spec->mode)) return 0; -- Thomas Rast t...@thomasrast.ch -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: git gc --aggressive led to about 40 times slower "git log --raw"
David Kastrup writes: > That does look strange: Emacs has a history of more than 30 years. But > the Git mirror is quite younger. Maybe one needs to make sure to use > the author date rather than the commit date here? There is no difference between commit and author date in the Emacs git mirror since bzr doesn't keep that distinction (and cvs didn't either). Andreas. -- Andreas Schwab, sch...@linux-m68k.org GPG Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5 "And now for something completely different." -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 2/8] merge-recursive: internal flag to avoid touching the worktree
From: Thomas Rast o->call_depth has a double function: a nonzero call_depth means we want to construct virtual merge bases, but it also means we want to avoid touching the worktree. Introduce a new flag o->no_worktree to trigger only the latter. Signed-off-by: Thomas Rast Signed-off-by: Junio C Hamano --- merge-recursive.c | 37 + merge-recursive.h | 1 + 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/merge-recursive.c b/merge-recursive.c index c36dc79..35be144 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -408,10 +408,10 @@ static void record_df_conflict_files(struct merge_options *o, int i; /* -* If we're merging merge-bases, we don't want to bother with -* any working directory changes. +* If we're working in-core only (e.g., merging merge-bases), +* we don't want to bother with any working directory changes. */ - if (o->call_depth) + if (o->call_depth || o->no_worktree) return; /* Ensure D/F conflicts are adjacent in the entries list. */ @@ -724,7 +724,7 @@ static void update_file_flags(struct merge_options *o, int update_cache, int update_wd) { - if (o->call_depth) + if (o->call_depth || o->no_worktree) update_wd = 0; if (update_wd) { @@ -931,7 +931,8 @@ static struct merge_file_info merge_file_1(struct merge_options *o, result.clean = merge_submodule(result.sha, one->path, one->sha1, a->sha1, b->sha1, - !o->call_depth); + !(o->call_depth || +o->no_worktree)); } else if (S_ISLNK(a->mode)) { hashcpy(result.sha, a->sha1); @@ -1003,7 +1004,7 @@ static void handle_change_delete(struct merge_options *o, const char *change, const char *change_past) { char *renamed = NULL; - if (dir_in_way(path, !o->call_depth)) { + if (dir_in_way(path, !(o->call_depth || o->no_worktree))) { renamed = unique_path(o, path, a_sha ? o->branch1 : o->branch2); } @@ -1128,10 +1129,10 @@ static void handle_file(struct merge_options *o, char *add_name = unique_path(o, rename->path, other_branch); update_file(o, 0, add->sha1, add->mode, add_name); - remove_file(o, 0, rename->path, 0); + remove_file(o, 0, rename->path, o->call_depth || o->no_worktree); dst_name = unique_path(o, rename->path, cur_branch); } else { - if (dir_in_way(rename->path, !o->call_depth)) { + if (dir_in_way(rename->path, !(o->call_depth || o->no_worktree))) { dst_name = unique_path(o, rename->path, cur_branch); output(o, 1, _("%s is a directory in %s adding as %s instead"), rename->path, other_branch, dst_name); @@ -1238,7 +1239,7 @@ static void conflict_rename_rename_2to1(struct merge_options *o, * merge base just undo the renames; they can be detected * again later for the non-recursive merge. */ - remove_file(o, 0, path, 0); + remove_file(o, 0, path, o->call_depth || o->no_worktree); update_file(o, 0, mfi_c1.sha, mfi_c1.mode, a->path); update_file(o, 0, mfi_c2.sha, mfi_c2.mode, b->path); } else { @@ -1246,7 +1247,7 @@ static void conflict_rename_rename_2to1(struct merge_options *o, char *new_path2 = unique_path(o, path, ci->branch2); output(o, 1, _("Renaming %s to %s and %s to %s instead"), a->path, new_path1, b->path, new_path2); - remove_file(o, 0, path, 0); + remove_file(o, 0, path, o->call_depth || o->no_worktree); update_file(o, 0, mfi_c1.sha, mfi_c1.mode, new_path1); update_file(o, 0, mfi_c2.sha, mfi_c2.mode, new_path2); free(new_path2); @@ -1405,6 +1406,7 @@ static int process_renames(struct merge_options *o, * add-source case). */ remove_file(o, 1, ren1_src, + o->call_depth || o->no_worktree || renamed_stage == 2 || !was_tracked(ren1_src)); hashcpy(src_other.sha1, ren1->src_entry->stages[other_stage].sha); @@ -1601,7 +1603,7 @@ static int merge_content(struct merge_options *o, o->branch2 == rename_conflict_info->branch1) ?
[PATCH v2 3/8] merge-recursive: -Xindex-only to leave worktree unchanged
From: Thomas Rast Using the new no_worktree flag from the previous commit, we can teach merge-recursive to leave the worktree untouched. Expose this with a new strategy option so that scripts can use it. Signed-off-by: Junio C Hamano --- Documentation/merge-strategies.txt | 4 merge-recursive.c | 2 ++ t/t3030-merge-recursive.sh | 13 + 3 files changed, 19 insertions(+) diff --git a/Documentation/merge-strategies.txt b/Documentation/merge-strategies.txt index fb6e593..2934e99 100644 --- a/Documentation/merge-strategies.txt +++ b/Documentation/merge-strategies.txt @@ -92,6 +92,10 @@ subtree[=];; is prefixed (or stripped from the beginning) to make the shape of two trees to match. +index-only;; + Write the merge result only to the index; do not touch the + worktree. + octopus:: This resolves cases with more than two heads, but refuses to do a complex merge that needs manual resolution. It is diff --git a/merge-recursive.c b/merge-recursive.c index 35be144..f59c1d3 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -2096,6 +2096,8 @@ int parse_merge_opt(struct merge_options *o, const char *s) if ((o->rename_score = parse_rename_score(&score)) == -1 || *score != 0) return -1; } + else if (!strcmp(s, "index-only")) + o->no_worktree = 1; else return -1; return 0; diff --git a/t/t3030-merge-recursive.sh b/t/t3030-merge-recursive.sh index 2f96100..2f3a16c 100755 --- a/t/t3030-merge-recursive.sh +++ b/t/t3030-merge-recursive.sh @@ -296,6 +296,19 @@ test_expect_success 'merge-recursive result' ' ' +test_expect_success 'merge-recursive --index-only' ' + + rm -fr [abcd] && + git checkout -f "$c2" && + test_expect_code 1 git merge-recursive --index-only "$c0" -- "$c2" "$c1" && + git ls-files -s >actual && + # reuses "expected" from previous test! + test_cmp expected actual && + git diff HEAD >actual-diff && + : >expected-diff && + test_cmp expected-diff actual-diff +' + test_expect_success 'fail if the index has unresolved entries' ' rm -fr [abcd] && -- 1.9.0.313.g3d0a325 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 4/8] combine-diff: do not pass revs->dense_combined_merges redundantly
The existing code passed revs->dense_combined_merges along revs itself into the combine-diff functions, which is rather redundant. Remove the 'dense' argument until much further down the callchain to simplify callers. Note that while the caller in submodule.c needs to do extra work now, the next commit will simplify this to a single setting again. Signed-off-by: Thomas Rast --- builtin/diff.c | 3 +-- combine-diff.c | 13 ++--- diff-lib.c | 6 ++ diff.h | 6 +++--- log-tree.c | 2 +- submodule.c| 5 - 6 files changed, 17 insertions(+), 18 deletions(-) diff --git a/builtin/diff.c b/builtin/diff.c index 0f247d2..47f663b 100644 --- a/builtin/diff.c +++ b/builtin/diff.c @@ -196,8 +196,7 @@ static int builtin_diff_combined(struct rev_info *revs, revs->dense_combined_merges = revs->combine_merges = 1; for (i = 1; i < ents; i++) sha1_array_append(&parents, ent[i].item->sha1); - diff_tree_combined(ent[0].item->sha1, &parents, - revs->dense_combined_merges, revs); + diff_tree_combined(ent[0].item->sha1, &parents, revs); sha1_array_clear(&parents); return 0; } diff --git a/combine-diff.c b/combine-diff.c index 3b92c448..6e80a73 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -952,7 +952,7 @@ static void show_combined_header(struct combine_diff_path *elem, } static void show_patch_diff(struct combine_diff_path *elem, int num_parent, - int dense, int working_tree_file, + int working_tree_file, struct rev_info *rev) { struct diff_options *opt = &rev->diffopt; @@ -967,6 +967,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, struct userdiff_driver *textconv = NULL; int is_binary; const char *line_prefix = diff_line_prefix(opt); + int dense = rev->dense_combined_merges; context = opt->context; userdiff = userdiff_find_by_path(elem->path); @@ -1214,7 +1215,6 @@ static void show_raw_diff(struct combine_diff_path *p, int num_parent, struct re */ void show_combined_diff(struct combine_diff_path *p, int num_parent, - int dense, struct rev_info *rev) { struct diff_options *opt = &rev->diffopt; @@ -1226,7 +1226,7 @@ void show_combined_diff(struct combine_diff_path *p, DIFF_FORMAT_NAME_STATUS)) show_raw_diff(p, num_parent, rev); else if (opt->output_format & DIFF_FORMAT_PATCH) - show_patch_diff(p, num_parent, dense, 1, rev); + show_patch_diff(p, num_parent, 1, rev); } static void free_combined_pair(struct diff_filepair *pair) @@ -1297,7 +1297,6 @@ static void handle_combined_callback(struct diff_options *opt, void diff_tree_combined(const unsigned char *sha1, const struct sha1_array *parents, - int dense, struct rev_info *rev) { struct diff_options *opt = &rev->diffopt; @@ -1365,7 +1364,7 @@ void diff_tree_combined(const unsigned char *sha1, opt->line_termination); for (p = paths; p; p = p->next) { if (p->len) - show_patch_diff(p, num_parent, dense, + show_patch_diff(p, num_parent, 0, rev); } } @@ -1381,7 +1380,7 @@ void diff_tree_combined(const unsigned char *sha1, free_pathspec(&diffopts.pathspec); } -void diff_tree_combined_merge(const struct commit *commit, int dense, +void diff_tree_combined_merge(const struct commit *commit, struct rev_info *rev) { struct commit_list *parent = get_saved_parents(rev, commit); @@ -1391,6 +1390,6 @@ void diff_tree_combined_merge(const struct commit *commit, int dense, sha1_array_append(&parents, parent->item->object.sha1); parent = parent->next; } - diff_tree_combined(commit->object.sha1, &parents, dense, rev); + diff_tree_combined(commit->object.sha1, &parents, rev); sha1_array_clear(&parents); } diff --git a/diff-lib.c b/diff-lib.c index 346cac6..8d0f572 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -174,9 +174,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option) i--; if (revs->combine_merges && num_compare_stages == 2) { - show_combined_diff(dpath, 2, - revs->dense_combined_merges, - revs); + show_combined_diff(dpath, 2, revs);
[PATCH v2 1/8] merge-recursive: remove dead conditional in update_stages()
From: Thomas Rast 650467c (merge-recursive: Consolidate different update_stages functions, 2011-08-11) changed the former argument 'clear' to always be true. Remove the useless conditional. Signed-off-by: Thomas Rast Signed-off-by: Junio C Hamano --- merge-recursive.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/merge-recursive.c b/merge-recursive.c index 8400a8e..c36dc79 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -545,11 +545,9 @@ static int update_stages(const char *path, const struct diff_filespec *o, * would_lose_untracked). Instead, reverse the order of the calls * (executing update_file first and then update_stages). */ - int clear = 1; int options = ADD_CACHE_OK_TO_ADD | ADD_CACHE_SKIP_DFCHECK; - if (clear) - if (remove_file_from_cache(path)) - return -1; + if (remove_file_from_cache(path)) + return -1; if (o) if (add_cacheinfo(o->mode, o->sha1, path, 1, 0, options)) return -1; -- 1.9.0.313.g3d0a325 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 6/8] merge-recursive: allow storing conflict hunks in index
Add a --conflicts-in-index option to merge-recursive, which instructs it to always store the 3-way merged result in the index. (Normally it only does so in recursive invocations, but not for the final result.) This serves as a building block for the "remerge diff" feature coming up in a subsequent patch. The external option lets us easily use it from tests, where we'd otherwise need a new test-* helper to access the feature. Furthermore, it might occasionally be useful for scripts that want to look at the result of invoking git-merge without tampering with the worktree. They could already get the _conflicts_ with --index-only, but not (conveniently) the conflict-hunk formatted files that would normally be written to the worktree. Signed-off-by: Thomas Rast --- Documentation/merge-strategies.txt | 5 + merge-recursive.c | 4 merge-recursive.h | 1 + t/t3030-merge-recursive.sh | 20 4 files changed, 30 insertions(+) diff --git a/Documentation/merge-strategies.txt b/Documentation/merge-strategies.txt index 2934e99..3468d99 100644 --- a/Documentation/merge-strategies.txt +++ b/Documentation/merge-strategies.txt @@ -96,6 +96,11 @@ index-only;; Write the merge result only to the index; do not touch the worktree. +conflicts-in-index;; + For conflicted files, write 3-way merged contents with + conflict hunks to the index, instead of leaving their entries + unresolved. + octopus:: This resolves cases with more than two heads, but refuses to do a complex merge that needs manual resolution. It is diff --git a/merge-recursive.c b/merge-recursive.c index f59c1d3..b682812 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -724,6 +724,8 @@ static void update_file_flags(struct merge_options *o, int update_cache, int update_wd) { + if (o->conflicts_in_index) + update_cache = 1; if (o->call_depth || o->no_worktree) update_wd = 0; @@ -2098,6 +2100,8 @@ int parse_merge_opt(struct merge_options *o, const char *s) } else if (!strcmp(s, "index-only")) o->no_worktree = 1; + else if (!strcmp(s, "conflicts-in-index")) + o->conflicts_in_index = 1; else return -1; return 0; diff --git a/merge-recursive.h b/merge-recursive.h index d8dd7a1..9b8e20b 100644 --- a/merge-recursive.h +++ b/merge-recursive.h @@ -16,6 +16,7 @@ struct merge_options { unsigned buffer_output : 1; unsigned renormalize : 1; unsigned no_worktree : 1; /* do not touch worktree */ + unsigned conflicts_in_index : 1; /* index will contain conflict hunks */ long xdl_opts; int verbosity; int diff_rename_limit; diff --git a/t/t3030-merge-recursive.sh b/t/t3030-merge-recursive.sh index 2f3a16c..4192fd3 100755 --- a/t/t3030-merge-recursive.sh +++ b/t/t3030-merge-recursive.sh @@ -309,6 +309,26 @@ test_expect_success 'merge-recursive --index-only' ' test_cmp expected-diff actual-diff ' +test_expect_success 'merge-recursive --index-only --conflicts-in-index' ' + # first pass: do a merge as usual to obtain "expected" + rm -fr [abcd] && + git checkout -f "$c2" && + test_expect_code 1 git merge-recursive "$c0" -- "$c2" "$c1" && + git add [abcd] && + git ls-files -s >expected && + # second pass: actual test + rm -fr [abcd] && + git checkout -f "$c2" && + test_expect_code 1 \ + git merge-recursive --index-only --conflicts-in-index \ + "$c0" -- "$c2" "$c1" && + git ls-files -s >actual && + test_cmp expected actual && + git diff HEAD >actual-diff && + : >expected-diff && + test_cmp expected-diff actual-diff +' + test_expect_success 'fail if the index has unresolved entries' ' rm -fr [abcd] && -- 1.9.0.313.g3d0a325 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 5/8] Fold all merge diff variants into an enum
The four ways of displaying merge diffs, * none: no diff * -m: against each parent * -c: combined * --cc: combined-condensed were encoded in three flag bits in struct rev_info. Fold them all into a single enum field that captures the variants. This makes it easier to add new merge diff variants without yet more special casing. It should also be slightly easier to read because one does not have to ensure that the flag bits are set in an expected combination. Signed-off-by: Thomas Rast --- builtin/diff-files.c| 5 +++-- builtin/diff-tree.c | 2 +- builtin/diff.c | 9 + builtin/fmt-merge-msg.c | 2 +- builtin/log.c | 9 - builtin/merge.c | 1 - combine-diff.c | 2 +- diff-lib.c | 7 --- log-tree.c | 4 ++-- revision.c | 13 +++-- revision.h | 22 +++--- submodule.c | 4 +--- 12 files changed, 44 insertions(+), 36 deletions(-) diff --git a/builtin/diff-files.c b/builtin/diff-files.c index 9200069..172b50d 100644 --- a/builtin/diff-files.c +++ b/builtin/diff-files.c @@ -57,9 +57,10 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix) * was not asked to. "diff-files -c -p" should not densify * (the user should ask with "diff-files --cc" explicitly). */ - if (rev.max_count == -1 && !rev.combine_merges && + if (rev.max_count == -1 && + !merge_diff_mode_is_any_combined(&rev) && (rev.diffopt.output_format & DIFF_FORMAT_PATCH)) - rev.combine_merges = rev.dense_combined_merges = 1; + rev.merge_diff_mode = MERGE_DIFF_COMBINED_CONDENSED; if (read_cache_preload(&rev.diffopt.pathspec) < 0) { perror("read_cache_preload"); diff --git a/builtin/diff-tree.c b/builtin/diff-tree.c index be6417d..2950f80 100644 --- a/builtin/diff-tree.c +++ b/builtin/diff-tree.c @@ -96,7 +96,7 @@ static int diff_tree_stdin(char *line) static void diff_tree_tweak_rev(struct rev_info *rev, struct setup_revision_opt *opt) { if (!rev->diffopt.output_format) { - if (rev->dense_combined_merges) + if (rev->merge_diff_mode == MERGE_DIFF_COMBINED_CONDENSED) rev->diffopt.output_format = DIFF_FORMAT_PATCH; else rev->diffopt.output_format = DIFF_FORMAT_RAW; diff --git a/builtin/diff.c b/builtin/diff.c index 47f663b..fd4c75f 100644 --- a/builtin/diff.c +++ b/builtin/diff.c @@ -192,8 +192,8 @@ static int builtin_diff_combined(struct rev_info *revs, if (argc > 1) usage(builtin_diff_usage); - if (!revs->dense_combined_merges && !revs->combine_merges) - revs->dense_combined_merges = revs->combine_merges = 1; + if (!merge_diff_mode_is_any_combined(revs)) + revs->merge_diff_mode = MERGE_DIFF_COMBINED_CONDENSED; for (i = 1; i < ents; i++) sha1_array_append(&parents, ent[i].item->sha1); diff_tree_combined(ent[0].item->sha1, &parents, revs); @@ -242,9 +242,10 @@ static int builtin_diff_files(struct rev_info *revs, int argc, const char **argv * dense one, --cc can be explicitly asked for, or just rely * on the default). */ - if (revs->max_count == -1 && !revs->combine_merges && + if (revs->max_count == -1 && + !merge_diff_mode_is_any_combined(revs) && (revs->diffopt.output_format & DIFF_FORMAT_PATCH)) - revs->combine_merges = revs->dense_combined_merges = 1; + revs->merge_diff_mode = MERGE_DIFF_COMBINED_CONDENSED; setup_work_tree(); if (read_cache_preload(&revs->diffopt.pathspec) < 0) { diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c index 3906eda..2deeacd 100644 --- a/builtin/fmt-merge-msg.c +++ b/builtin/fmt-merge-msg.c @@ -637,7 +637,7 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out, head = lookup_commit_or_die(head_sha1, "HEAD"); init_revisions(&rev, NULL); rev.commit_format = CMIT_FMT_ONELINE; - rev.ignore_merges = 1; + rev.merge_diff_mode = MERGE_DIFF_IGNORE; rev.limited = 1; strbuf_complete_line(out); diff --git a/builtin/log.c b/builtin/log.c index b97373d..cebebea 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -499,13 +499,12 @@ static int show_tree_object(const unsigned char *sha1, static void show_rev_tweak_rev(struct rev_info *rev, struct setup_revision_opt *opt) { - if (rev->ignore_merges) { + if (!rev->merge_diff_mode) { /* There was no "-m" on the command line */ - rev->ignore_merges = 0; - if (!rev->first_parent_only && !rev->combine_merges) { + rev->merge_diff_mode = MERGE_DIFF_EACH; + if (!rev->first_parent_only) {
[PATCH v2 8/8] log --remerge-diff: show what the conflict resolution changed
Git has --cc as a very fast inspection tool that shows a brief summary of what a conflicted merge "looks like", and -c/-m as "give me the full information" data dumps. But --cc actually loses information: if the merge lost(!) some changes from one side, that hunk would fully agree with the other side, and therefore be elided. So --cc cannot be used to investigate mismerges. Indeed it is rather hard to find a merge that has lost changes, unless one knows where to look. The new option --remerge-diff is an attempt at filling this gap, admittedly at the cost of a lot of CPU cycles. For each merge commit, it diffs the merge result against a recursive merge of the merge's parents. For files that can be auto-merged cleanly, it will typically show nothing. However, it will make it obvious when the merge introduces extra changes. For files that result in merge conflicts, we diff against the representation with conflict hunks (what the user would usually see in the worktree). So the diff will show what was changed in the conflict hunks to resolve the conflict. It still takes a bit of staring to tell an evil from a regular merge. But at least the information is there, unlike with --cc; and the output is usually much shorter than with -c. Signed-off-by: Thomas Rast --- Documentation/rev-list-options.txt | 7 + log-tree.c | 298 + merge-recursive.c | 3 +- merge-recursive.h | 1 + revision.c | 2 + revision.h | 4 +- t/t4213-log-remerge-diff.sh| 222 +++ 7 files changed, 535 insertions(+), 2 deletions(-) create mode 100755 t/t4213-log-remerge-diff.sh diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt index 03533af..73264dc 100644 --- a/Documentation/rev-list-options.txt +++ b/Documentation/rev-list-options.txt @@ -790,6 +790,13 @@ options may be given. See linkgit:git-diff-files[1] for more options. in that case, the output represents the changes the merge brought _into_ the then-current branch. +--remerge-diff:: + Diff merge commits against a recursive merge of their parents, + with conflict hunks. Intuitively speaking, this shows what + the author of the merge changed to resolve the merge. It + assumes that all (or most) merges are recursive merges; other + strategies are not supported. + -r:: Show recursive diffs. diff --git a/log-tree.c b/log-tree.c index 30b3063..9b831e9 100644 --- a/log-tree.c +++ b/log-tree.c @@ -11,6 +11,8 @@ #include "gpg-interface.h" #include "sequencer.h" #include "line-log.h" +#include "cache-tree.h" +#include "merge-recursive.h" struct decoration name_decoration = { "object names" }; @@ -723,6 +725,300 @@ static int do_diff_combined(struct rev_info *opt, struct commit *commit) } /* + * Helpers for make_asymmetric_conflict_entries() below. + */ +static char *load_cache_entry_blob(struct cache_entry *entry, + unsigned long *size) +{ + enum object_type type; + void *data; + + if (!entry) + return NULL; + + data = read_sha1_file(entry->sha1, &type, size); + if (type != OBJ_BLOB) + die("BUG: load_cache_entry_blob for non-blob"); + + return data; +} + +static void strbuf_append_cache_entry_blob(struct strbuf *sb, + struct cache_entry *entry) +{ + unsigned long size; + char *data = load_cache_entry_blob(entry, &size);; + + if (!data) + return; + + strbuf_add(sb, data, size); + free(data); +} + +static void assemble_conflict_entry(struct strbuf *sb, + const char *branch1, + const char *branch2, + struct cache_entry *entry1, + struct cache_entry *entry2) +{ + strbuf_addf(sb, "<<< %s\n", branch1); + strbuf_append_cache_entry_blob(sb, entry1); + strbuf_addstr(sb, "===\n"); + strbuf_append_cache_entry_blob(sb, entry2); + strbuf_addf(sb, ">>> %s\n", branch2); +} + +/* + * For --remerge-diff, we need conflicted (<<< ... >>>) + * representations of as many conflicts as possible. Default conflict + * generation only applies to files that have all three stages. + * + * This function generates conflict hunk representations for files + * that have only one of stage 2 or 3. The corresponding side in the + * conflict hunk format will be empty. A stage 1, if any, will be + * dropped in the process. + */ +static void make_asymmetric_conflict_entries(const char *branch1, +const char *branch2) +{ + int o = 0, i = 0; + + /* +* NEEDSWORK: we trample all over the cache below, so we need +
[PATCH v2 7/8] name-hash: allow dir hashing even when !ignore_case
The directory hash (for fast checks if the index already has a directory) was only used in ignore_case mode and so depended on that flag. Make it generally available on request. Signed-off-by: Thomas Rast --- cache.h | 2 ++ name-hash.c | 19 --- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/cache.h b/cache.h index dc040fb..e162021 100644 --- a/cache.h +++ b/cache.h @@ -276,6 +276,7 @@ struct index_state { struct cache_tree *cache_tree; struct cache_time timestamp; unsigned name_hash_initialized : 1, +has_dir_hash : 1, initialized : 1; struct hash_table name_hash; struct hash_table dir_hash; @@ -284,6 +285,7 @@ struct index_state { extern struct index_state the_index; /* Name hashing */ +extern void init_name_hash(struct index_state *istate, int force_dir_hash); extern void add_name_hash(struct index_state *istate, struct cache_entry *ce); extern void remove_name_hash(struct index_state *istate, struct cache_entry *ce); extern void free_name_hash(struct index_state *istate); diff --git a/name-hash.c b/name-hash.c index e5b6e1a..c8953be 100644 --- a/name-hash.c +++ b/name-hash.c @@ -141,16 +141,19 @@ static void hash_index_entry(struct index_state *istate, struct cache_entry *ce) *pos = ce; } - if (ignore_case && !(ce->ce_flags & CE_UNHASHED)) + if (istate->has_dir_hash && !(ce->ce_flags & CE_UNHASHED)) add_dir_entry(istate, ce); } -static void lazy_init_name_hash(struct index_state *istate) +void init_name_hash(struct index_state *istate, int force_dir_hash) { int nr; if (istate->name_hash_initialized) return; + + istate->has_dir_hash = force_dir_hash || ignore_case; + if (istate->cache_nr) preallocate_hash(&istate->name_hash, istate->cache_nr); for (nr = 0; nr < istate->cache_nr; nr++) @@ -161,7 +164,7 @@ static void lazy_init_name_hash(struct index_state *istate) void add_name_hash(struct index_state *istate, struct cache_entry *ce) { /* if already hashed, add reference to directory entries */ - if (ignore_case && (ce->ce_flags & CE_STATE_MASK) == CE_STATE_MASK) + if (istate->has_dir_hash && (ce->ce_flags & CE_STATE_MASK) == CE_STATE_MASK) add_dir_entry(istate, ce); ce->ce_flags &= ~CE_UNHASHED; @@ -181,7 +184,7 @@ void add_name_hash(struct index_state *istate, struct cache_entry *ce) void remove_name_hash(struct index_state *istate, struct cache_entry *ce) { /* if already hashed, release reference to directory entries */ - if (ignore_case && (ce->ce_flags & CE_STATE_MASK) == CE_HASHED) + if (istate->has_dir_hash && (ce->ce_flags & CE_STATE_MASK) == CE_HASHED) remove_dir_entry(istate, ce); ce->ce_flags |= CE_UNHASHED; @@ -228,7 +231,7 @@ struct cache_entry *index_dir_exists(struct index_state *istate, const char *nam struct cache_entry *ce; struct dir_entry *dir; - lazy_init_name_hash(istate); + init_name_hash(istate, 0); dir = find_dir_entry(istate, name, namelen); if (dir && dir->nr) return dir->ce; @@ -250,7 +253,7 @@ struct cache_entry *index_file_exists(struct index_state *istate, const char *na unsigned int hash = hash_name(name, namelen); struct cache_entry *ce; - lazy_init_name_hash(istate); + init_name_hash(istate, 0); ce = lookup_hash(hash, &istate->name_hash); while (ce) { @@ -286,9 +289,11 @@ void free_name_hash(struct index_state *istate) if (!istate->name_hash_initialized) return; istate->name_hash_initialized = 0; - if (ignore_case) + if (istate->has_dir_hash) { /* free directory entries */ for_each_hash(&istate->dir_hash, free_dir_entry, NULL); + istate->has_dir_hash = 0; + } free_hash(&istate->name_hash); free_hash(&istate->dir_hash); -- 1.9.0.313.g3d0a325 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 0/8] log --remerge-diff
This is the second iteration of http://thread.gmane.org/gmane.comp.version-control.git/241565 Changes since the last version: * Dropped patches 4 and 5 (log --merge-bases) * Implemented the "full-file conflict" scheme explained in the previous cover letter: if the conflicted version is lacking one stage of a file, it synthesizes a conflict file of the form <<< === content of the stage that exists >>> (or the other way around if stage3 is missing). This occurs at least with delete/modify conflicts. * Implemented some basic handling of directory/file conflicts. I'm not completely happy yet -- see the NEEDSWORK comments -- but at least it gives consistent input to the diffing stage. This required access to the dir hash, so there's a new patch 7 that makes this possible. Patches 1-6 (used to be 1-3 and 6-8) are unchanged. Thomas Rast (8): merge-recursive: remove dead conditional in update_stages() merge-recursive: internal flag to avoid touching the worktree merge-recursive: -Xindex-only to leave worktree unchanged combine-diff: do not pass revs->dense_combined_merges redundantly Fold all merge diff variants into an enum merge-recursive: allow storing conflict hunks in index name-hash: allow dir hashing even when !ignore_case log --remerge-diff: show what the conflict resolution changed Documentation/merge-strategies.txt | 9 ++ Documentation/rev-list-options.txt | 7 + builtin/diff-files.c | 5 +- builtin/diff-tree.c| 2 +- builtin/diff.c | 12 +- builtin/fmt-merge-msg.c| 2 +- builtin/log.c | 9 +- builtin/merge.c| 1 - cache.h| 2 + combine-diff.c | 13 +- diff-lib.c | 13 +- diff.h | 6 +- log-tree.c | 304 - merge-recursive.c | 52 --- merge-recursive.h | 3 + name-hash.c| 19 ++- revision.c | 15 +- revision.h | 24 ++- submodule.c| 3 +- t/t3030-merge-recursive.sh | 33 t/t4213-log-remerge-diff.sh| 222 +++ 21 files changed, 678 insertions(+), 78 deletions(-) create mode 100755 t/t4213-log-remerge-diff.sh -- 1.9.0.313.g3d0a325 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: git gc --aggressive led to about 40 times slower "git log --raw"
On Sat, Feb 22, 2014 at 3:53 PM, David Kastrup wrote: > David Kastrup writes: > >> Duy Nguyen writes: >> >>> OK with git://git.savannah.gnu.org/emacs.git we have >>> >>> - a 209MB pack with --aggressive >>> - 1.3GB with --depth=50 >>> - 1.3GB with --window=4000 --depth=32 >>> - 1.3GB with --depth=20 >>> - 821MB with --depth=250 for commits --before=2.years.ago, --depth=50 >>> for the rest >>> >>> So I don't think we should go with your following patch because the >>> size explosion is just too much no matter how faster it could be. An >>> immediate action could be just make --depth=250 configurable and let >>> people deal with it. A better option is something like "3 repack >>> steps" you described where we pack deep depth first, mark .keep, pack >>> shallower depth and combine them all into one. >>> >>> I'm not really happy with --depth=250 producing 209MB while >>> --depth=250 --before=2.year.ago a 800MB pack. It looks wrong (or maybe >>> I did something wrong) >> >> That does look strange: Emacs has a history of more than 30 years. But >> the Git mirror is quite younger. Maybe one needs to make sure to use >> the author date rather than the commit date here? I think commit date is fine because it covers a large portion of objects (649946 per total 739990) and it does not (or should not) affect object ordering in pack-objects/rev-list. > Another thing: did you really use --depth=250 here or did you use > --aggressive? It may be that the latter also sets other options? I can't use --aggressive because I need to feed revisions directly to pack-objects. --aggressive also sets --window=250. Thanks for checking. My machine will have another workout session. -- Duy -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] tag: support --sort=version
On Sat, Feb 22, 2014 at 2:59 PM, Jeff King wrote: > On Fri, Feb 21, 2014 at 06:58:16PM +0700, Duy Nguyen wrote: > >> > --sort=[-][comparison:]field >> [...] >> Why not reversed order? So its syntax could be >> >> [ "-" ] FIELD [ ":" [ "version" | "v" ] ] >> >> It fits better to current f-e-r syntax where modifiers are after the >> colon. And it avoids the possibility that someone adds field "version" >> and we can't tell what "version" is what. > > I find my version a bit more obvious, for two reasons: > > 1. "version" here is not a modifier of the field name, it is a > modifier of the sort. You cannot use it in non-sort contexts (like > --format), and you cannot order it like other modifiers (you cannot > say "refname:version:short", only "refname:short:version"). Or you can read it like "type cast this field as a version", where sorting is affected but formatting, not so much. So you can specify it with --format (but it's no-op, unless we find a fancy way to color versions). I don't see a problem with accepting both refname:version:short and refname:short:version in future for-each-ref either. It will be the first time we accept multiple modifiers though. > 2. There are actually two sort-modifiers: "-" for ordering, and then a > comparator. In your proposal, they are split, whereas in mine, they > are next to each other. -- Duy -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: git gc --aggressive led to about 40 times slower "git log --raw"
David Kastrup writes: > Duy Nguyen writes: > >> OK with git://git.savannah.gnu.org/emacs.git we have >> >> - a 209MB pack with --aggressive >> - 1.3GB with --depth=50 >> - 1.3GB with --window=4000 --depth=32 >> - 1.3GB with --depth=20 >> - 821MB with --depth=250 for commits --before=2.years.ago, --depth=50 >> for the rest >> >> So I don't think we should go with your following patch because the >> size explosion is just too much no matter how faster it could be. An >> immediate action could be just make --depth=250 configurable and let >> people deal with it. A better option is something like "3 repack >> steps" you described where we pack deep depth first, mark .keep, pack >> shallower depth and combine them all into one. >> >> I'm not really happy with --depth=250 producing 209MB while >> --depth=250 --before=2.year.ago a 800MB pack. It looks wrong (or maybe >> I did something wrong) > > That does look strange: Emacs has a history of more than 30 years. But > the Git mirror is quite younger. Maybe one needs to make sure to use > the author date rather than the commit date here? Another thing: did you really use --depth=250 here or did you use --aggressive? It may be that the latter also sets other options? -- David Kastrup -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: git gc --aggressive led to about 40 times slower "git log --raw"
Duy Nguyen writes: > OK with git://git.savannah.gnu.org/emacs.git we have > > - a 209MB pack with --aggressive > - 1.3GB with --depth=50 > - 1.3GB with --window=4000 --depth=32 > - 1.3GB with --depth=20 > - 821MB with --depth=250 for commits --before=2.years.ago, --depth=50 > for the rest > > So I don't think we should go with your following patch because the > size explosion is just too much no matter how faster it could be. An > immediate action could be just make --depth=250 configurable and let > people deal with it. A better option is something like "3 repack > steps" you described where we pack deep depth first, mark .keep, pack > shallower depth and combine them all into one. > > I'm not really happy with --depth=250 producing 209MB while > --depth=250 --before=2.year.ago a 800MB pack. It looks wrong (or maybe > I did something wrong) That does look strange: Emacs has a history of more than 30 years. But the Git mirror is quite younger. Maybe one needs to make sure to use the author date rather than the commit date here? -- David Kastrup -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 4/4] config: teach "git config --file -" to read from the standard input
On Wed, Feb 19, 2014 at 12:58:55AM +0200, Kirill A. Shutemov wrote: > The patch extends git config --file interface to allow read config from > stdin. > > Editing stdin or setting value in stdin is an error. > > Include by absolute path is allowed in stdin config, but not by relative > path. > > Signed-off-by: Kirill A. Shutemov > --- This version of the series looks good to me. -Peff -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] demonstrate git-commit --dry-run exit code behaviour
On Fri, Feb 21, 2014 at 12:21:13PM -0800, Junio C Hamano wrote: > Tay Ray Chuan writes: > > > In particular, show that --short and --porcelain, while implying > > --dry-run, do not return the same exit code as --dry-run. This is due to > > the wt_status.commitable flag being set only when a long status is > > requested. > > I am not sure if --short/--porcelain should even be accepted by "git > commit" in the first place. It used to be that "git status" and > "git commit" were the same program in a different guise and "git > status " were merely a "git commit --dry-run ", > but the recent push is in the direction of making them totally > separate in the end-user's minds. So if we want a proper fix, I > would actually think that these options should *error out* at the > command line parser level, way before checking if there is anything > to commit. I do not think they are any less useful than "git commit --dry-run" in the first place. If you want to ask "what would happen if I ran commit with these arguments", you can get the answer in any of several formats (and --porcelain is the only machine-readable one). I have never found "commit --dry-run" to be useful, but I assumed that somebody does. -Peff -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 3/3] make commit --verbose work with --no-status
On Sat, Feb 22, 2014 at 03:09:22AM +0800, Tay Ray Chuan wrote: > @@ -1141,7 +1146,12 @@ static int parse_and_validate_options(int argc, const > char *argv[], > if (all && argc > 0) > die(_("Paths with -a does not make sense.")); > > - if (status_format != STATUS_FORMAT_DEFAULT) > + if (verbose && !include_status) { > + include_status = 1; > + status_format = STATUS_FORMAT_NONE; > + } > + > + if (status_format != STATUS_FORMAT_DEFAULT && !verbose) > dry_run = 1; What happens here when there is an alternate status format _and_ --verbose is used? If I say "git commit --porcelain" it should imply --dry-run. But "git commit --porcelain --verbose" no longer does so after your patch. -Peff -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/3] rename STATUS_FORMAT_NONE to STATUS_FORMAT_DEFAULT
On Sat, Feb 22, 2014 at 03:09:20AM +0800, Tay Ray Chuan wrote: > In f3f47a1 (status: add --long output format option), STATUS_FORMAT_NONE > was introduced, meaning "the user did not specify anything". Rename this > to *_DEFAULT to better indicate its meaning. Hmm. We later introduced STATUS_FORMAT_UNSPECIFIED in 84b4202d. It seems like that is the same thing as the _DEFAULT you are proposing here. Can we collapse them into a single value? -Peff -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] sha1_file: fix delta_stack memory leak in unpack_entry
On Fri, Feb 21, 2014 at 10:09:33AM -0800, Junio C Hamano wrote: > >> This delta_stack array can grow to any length depending on the actual > >> delta chain, but we forget to free it. Normally it does not matter > >> because we use small_delta_stack[] from stack and small_delta_stack > >> can hold 64-delta chains, more than standard --depth=50 in pack-objects. > [...] > > This comes from abe601bb, right? The change looks correct to me, too. Yes, it does. -Peff -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] tag: support --sort=
On Sat, Feb 22, 2014 at 10:29:22AM +0700, Nguyễn Thái Ngọc Duy wrote: > Signed-off-by: Nguyễn Thái Ngọc Duy > --- > The new prereq GNULINUX is an ugly workaround until people provide > strverscmp compat implementation. I hope that will happen soon as > strverscmp.c does not look very complex. Should GNULINUX be called HAVE_STRVERSCMP in the Makefile? Then this: > --- a/git-compat-util.h > +++ b/git-compat-util.h > @@ -721,4 +721,11 @@ void warn_on_inaccessible(const char *path); > /* Get the passwd entry for the UID of the current process. */ > struct passwd *xgetpwuid_self(void); > > +#ifndef __GNU_LIBRARY__ > +static inline int strverscmp(const char *s1, const char *s2) > +{ > + die("strverscmp() not supported"); > +} > +#endif becomes "#ifndef HAVE_STRVERSCMP", and this: > diff --git a/t/test-lib.sh b/t/test-lib.sh > index 1531c24..5e8c39a 100644 > --- a/t/test-lib.sh > +++ b/t/test-lib.sh > @@ -771,6 +771,8 @@ case $(uname -s) in > ;; > esac > > +[ "$(uname -o)" = "GNU/Linux" ] && test_set_prereq GNULINUX > + can pick up the value from GIT-BUILD-OPTIONS as a prerequisite (see the way we handle NO_PERL for an example). Though if we can just grab the glibc version as a fallback, we can do away with that completely. -Peff -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] tag: support --sort=version
On Fri, Feb 21, 2014 at 06:58:16PM +0700, Duy Nguyen wrote: > > --sort=[-][comparison:]field > [...] > Why not reversed order? So its syntax could be > > [ "-" ] FIELD [ ":" [ "version" | "v" ] ] > > It fits better to current f-e-r syntax where modifiers are after the > colon. And it avoids the possibility that someone adds field "version" > and we can't tell what "version" is what. I find my version a bit more obvious, for two reasons: 1. "version" here is not a modifier of the field name, it is a modifier of the sort. You cannot use it in non-sort contexts (like --format), and you cannot order it like other modifiers (you cannot say "refname:version:short", only "refname:short:version"). 2. There are actually two sort-modifiers: "-" for ordering, and then a comparator. In your proposal, they are split, whereas in mine, they are next to each other. -Peff -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html