Re: [PATCH] git help: promote 'git help -av'
On Sat, Sep 22, 2018 at 9:29 PM Ævar Arnfjörð Bjarmason wrote: > > > On Sat, Sep 22 2018, Nguyễn Thái Ngọc Duy wrote: > > > When you type "git help" (or just "git") you are greeted with a list > > with commonly used commands and their short description and are > > suggested to use "git help -a" or "git help -g" for more details. > > > > "git help -av" would be more friendly and inline with what is shown > > with "git help" since it shows list of commands with description as > > well, and commands are properly grouped. > > > > Signed-off-by: Nguyễn Thái Ngọc Duy > > --- > > git.c | 2 +- > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > diff --git a/git.c b/git.c > > index a6f4b44af5..69c21f378b 100644 > > --- a/git.c > > +++ b/git.c > > @@ -31,7 +31,7 @@ const char git_usage_string[] = > > "[]"); > > > > const char git_more_info_string[] = > > - N_("'git help -a' and 'git help -g' list available subcommands and > > some\n" > > + N_("'git help -av' and 'git help -g' list available subcommands and > > some\n" > > "concept guides. See 'git help ' or 'git help > > '\n" > > "to read about a specific subcommand or concept."); > > A side-effect of this not noted in your commit message is that we'll now > invoke the pager, perhaps we should just do: > > diff --git a/builtin/help.c b/builtin/help.c > index 8d4f6dd301..1a3b174aaf 100644 > --- a/builtin/help.c > +++ b/builtin/help.c > @@ -436,9 +436,9 @@ int cmd_help(int argc, const char **argv, const char > *prefix) > parsed_help_format = help_format; > > if (show_all) { > + setup_pager(); > git_config(git_help_config, NULL); > if (verbose) { > - setup_pager(); > list_all_cmds_help(); > return 0; > } > @@ -460,8 +460,10 @@ int cmd_help(int argc, const char **argv, const char > *prefix) > return 0; > } > > - if (show_guides) > + if (show_guides) { > + setup_pager(); > list_common_guides_help(); > + } > > if (show_all || show_guides) { > printf("%s\n", _(git_more_info_string)); > > Or is there a good reason we shouldn't invoke the pager for e.g. -g when > the terminal is too small (per our default less config)? Different pagers may behave differently (and so far "help -a" still fits in my screen). So I don't think we should invoke pager more than necessary. -- Duy
Good day,
Good day, Death without a WILL is a damning circumstance that causes lot of problems to family. With confidentiality I am reaching out to you regarding a circumstance within my jurisdiction. One of our client passed on without a WILL over two years now. Efforts to trace any relation proved void hence I have to hire a private researcher who furnished me with your contact details because you share similar name with the deceased. Can I propose to nominate you as the next of kin? We can both share the outcome. Let me know your interest on this. Please reply me back urgently on rsisulu2...@tuta.io Regards, Raymond
Re: [PATCH v2 2/3] transport.c: introduce core.alternateRefsCommand
On Sat, Sep 22, 2018 at 06:02:31PM +, brian m. carlson wrote: > On Fri, Sep 21, 2018 at 02:47:43PM -0400, Taylor Blau wrote: > > +expect_haves () { > > + printf "%s .have\n" $(git rev-parse $@) >expect > > +} > > + > > +extract_haves () { > > + depacketize - | grep '\.have' | sed -e 's/\\0.*$//g' > > It looks like you're trying to match a NUL here in the sed expression, > but from my reading of it, POSIX doesn't permit BREs to match NUL. No, it's trying to literally match backslash followed by 0. The depacketize() script will have undone the NUL already. In perl, no less, making it more or less equivalent to your suggestion. ;) So I think this is fine (modulo that the grep and sed can be combined). Yet another option would be to simply strip away everything except the object id (which is all we care about), like: depacketize | perl -lne '/^(\S+) \.have/ and print $1' Or the equivalent in sed. I am happy with any solution that does the correct thing. -Peff
Re: [PATCH] git help: promote 'git help -av'
On Sat, Sep 22 2018, Nguyễn Thái Ngọc Duy wrote: > When you type "git help" (or just "git") you are greeted with a list > with commonly used commands and their short description and are > suggested to use "git help -a" or "git help -g" for more details. > > "git help -av" would be more friendly and inline with what is shown > with "git help" since it shows list of commands with description as > well, and commands are properly grouped. > > Signed-off-by: Nguyễn Thái Ngọc Duy > --- > git.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/git.c b/git.c > index a6f4b44af5..69c21f378b 100644 > --- a/git.c > +++ b/git.c > @@ -31,7 +31,7 @@ const char git_usage_string[] = > "[]"); > > const char git_more_info_string[] = > - N_("'git help -a' and 'git help -g' list available subcommands and > some\n" > + N_("'git help -av' and 'git help -g' list available subcommands and > some\n" > "concept guides. See 'git help ' or 'git help '\n" > "to read about a specific subcommand or concept."); A side-effect of this not noted in your commit message is that we'll now invoke the pager, perhaps we should just do: diff --git a/builtin/help.c b/builtin/help.c index 8d4f6dd301..1a3b174aaf 100644 --- a/builtin/help.c +++ b/builtin/help.c @@ -436,9 +436,9 @@ int cmd_help(int argc, const char **argv, const char *prefix) parsed_help_format = help_format; if (show_all) { + setup_pager(); git_config(git_help_config, NULL); if (verbose) { - setup_pager(); list_all_cmds_help(); return 0; } @@ -460,8 +460,10 @@ int cmd_help(int argc, const char **argv, const char *prefix) return 0; } - if (show_guides) + if (show_guides) { + setup_pager(); list_common_guides_help(); + } if (show_all || show_guides) { printf("%s\n", _(git_more_info_string)); Or is there a good reason we shouldn't invoke the pager for e.g. -g when the terminal is too small (per our default less config)? Another thing I noticed: We don't list -v in the git-help manpage, but since we use OPT_VERBOSE it's supported.
Re: Very simple popen() code request, ground-shaking functionality openned by it
On 22 września 2018 at 01:30:36, Ævar Arnfjörð Bjarmason (ava...@gmail.com) wrote: > Duy's > https://public-inbox.org/git/20180920161928.ga13...@duynguyen.home/ is > another recent thing that reminded me of this, i.e. that suggested > "\\|/-" spinner could be made much neater with non-ASCII. Here is a IMO very large collection of spinner-like unicode animations: https://asciinema.org/a/ex8z3z6d5m7uv4buww0o2qeq2 This comes from Zsh world, it's a plugin with spinners to use in Zsh scripts. I've never managed to see even 1/3 of them. > I'll just add that a 3rd thing that would also make sense would be to > add a feature to configure the value of these GIT_TRACE_*=* variables > via the .gitconfig, that's been suggested before (too lazy to dig up a > ML archive reference), and would make this as easy to configure as > Sebastian's suggestion. Yes git config setting of this is most convenient IMO, most expected to occur in ~/.gitconfig, in which it would be set once to a favourite gauge-box script, and rather long long before looking at this part of config again. Or maybe in the beginning, dawn of such gauge-scripts (if there actually would be any new group of such scripts; but as it's a quite broad problem (see last `PS.' paragraph), then who knows), when some unstable gauge-box would be breaking login/passwords prompt (but that's stdout not stderr, shouldn't go through gauge-box-script) or "fatal: ..." messages, etc., user might be disabling it temporarily or choosing an alternate gauge-box solution, editing the config option ;) So not rarely edited in the beginning. (I don't know how much important would a fancy gauge box be for a regular user; I can tell it would be quite important to me). I think this is more convenient and clean than `export GIT_*' in .bashrc/.zshrc, rarely edited, just sitting there. Guys you seem to like the idea, I hope someone will approach the coding! PS. There's much room for improvement in the git-process-output.zsh in the Asciinema video, gauge scripts won't be simple. In general, the number of 0..100% sequences (like: compressing, resolving, etc. – they all go 0 to 100% on their own) should be somehow predicted (does Git know this in advance?) and the gauge should be divided into that many segments, each filling up per one corresponding 0..100% sequence, together forming single global 0..100% gauge. -- Sebastian Gniazdowski News: https://twitter.com/ZdharmaI IRC: https://kiwiirc.com/client/chat.freenode.net:+6697/#zplugin Blog: http://zdharma.org
[PATCH 3/8] refs: new ref types to make per-worktree refs visible to all worktrees
One of the problems with multiple worktree is accessing per-worktree refs of one worktree from another worktree. This was sort of solved by multiple ref store, where the code can open the ref store of another worktree and has access to the ref space of that worktree. The problem with this is reporting. "HEAD" in another ref space is also called "HEAD" like in the current ref space. In order to differentiate them, all the code must somehow carry the ref store around and print something like "HEAD from this ref store". But that is not feasible (or possible with a _lot_ of work). With the current design, we pass a reference around as a string (so called "refname"). Extending this design to pass a string _and_ a ref store is a nightmare, especially when handling extended SHA-1 syntax. So we do it another way. Instead of entering a separate ref space, we make refs from other worktrees available in the current ref space. So "HEAD" is always HEAD of the current worktree, but then we can have "worktrees/blah/HEAD" to denote HEAD from a worktree named "blah". This syntax coincidentally matches the underlying directory structure which makes implementation a bit easier. The main worktree has to be treated specially because well.. it's special from the beginning. So HEAD from the main worktree is acccessible via the name "main/HEAD" (we can't use "worktrees/main/HEAD" because "main" under "worktrees" is not reserved). This patch also makes it possible to specify refs from one worktree in another one, e.g. git log worktrees/foo/HEAD Signed-off-by: Nguyễn Thái Ngọc Duy --- refs.c | 20 refs.h | 8 +--- refs/files-backend.c | 28 t/t1415-worktree-refs.sh | 30 ++ 4 files changed, 83 insertions(+), 3 deletions(-) diff --git a/refs.c b/refs.c index a851ef085b..90b73c7334 100644 --- a/refs.c +++ b/refs.c @@ -641,12 +641,32 @@ static int is_pseudoref_syntax(const char *refname) return 1; } +static int is_main_pseudoref_syntax(const char *refname) +{ + return skip_prefix(refname, "main/", &refname) && + is_pseudoref_syntax(refname); +} + +static int is_other_pseudoref_syntax(const char *refname) +{ + if (!skip_prefix(refname, "worktrees/", &refname)) + return 0; + refname = strchr(refname, '/'); + if (!refname) + return 0; + return is_pseudoref_syntax(refname + 1); +} + enum ref_type ref_type(const char *refname) { if (is_per_worktree_ref(refname)) return REF_TYPE_PER_WORKTREE; if (is_pseudoref_syntax(refname)) return REF_TYPE_PSEUDOREF; + if (is_main_pseudoref_syntax(refname)) + return REF_TYPE_MAIN_PSEUDOREF; + if (is_other_pseudoref_syntax(refname)) + return REF_TYPE_OTHER_PSEUDOREF; return REF_TYPE_NORMAL; } diff --git a/refs.h b/refs.h index bd52c1bbae..9b53dbeae8 100644 --- a/refs.h +++ b/refs.h @@ -704,9 +704,11 @@ int parse_hide_refs_config(const char *var, const char *value, const char *); int ref_is_hidden(const char *, const char *); enum ref_type { - REF_TYPE_PER_WORKTREE, - REF_TYPE_PSEUDOREF, - REF_TYPE_NORMAL, + REF_TYPE_PER_WORKTREE,/* refs inside refs/ but not shared */ + REF_TYPE_PSEUDOREF, /* refs outside refs/ in current worktree */ + REF_TYPE_MAIN_PSEUDOREF, /* pseudo refs from the main worktree */ + REF_TYPE_OTHER_PSEUDOREF, /* pseudo refs from other worktrees */ + REF_TYPE_NORMAL, /* normal/shared refs inside refs/*/ }; enum ref_type ref_type(const char *refname); diff --git a/refs/files-backend.c b/refs/files-backend.c index 416eafa453..bf9ed633b1 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -149,6 +149,23 @@ static struct files_ref_store *files_downcast(struct ref_store *ref_store, return refs; } +static void files_reflog_path_other_worktrees(struct files_ref_store *refs, + struct strbuf *sb, + const char *refname) +{ + const char *real_ref; + + if (!skip_prefix(refname, "worktrees/", &real_ref)) + BUG("refname %s is not a other-worktree ref", refname); + real_ref = strchr(real_ref, '/'); + if (!real_ref) + BUG("refname %s is not a other-worktree ref", refname); + real_ref++; + + strbuf_addf(sb, "%s/%.*slogs/%s", refs->gitcommondir, + (int)(real_ref - refname), refname, real_ref); +} + static void files_reflog_path(struct files_ref_store *refs, struct strbuf *sb, const char *refname) @@ -158,6 +175,12 @@ static void files_reflog_path(struct files_ref_store *refs, case REF_TYPE_PSEUDOREF: strbuf_addf(sb, "%s
[PATCH 8/8] reflog expire: cover reflog from all worktrees
Reported-by: Jeff King Signed-off-by: Nguyễn Thái Ngọc Duy --- Documentation/git-reflog.txt | 7 ++- builtin/reflog.c | 22 +++--- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/Documentation/git-reflog.txt b/Documentation/git-reflog.txt index 472a6808cd..ff487ff77d 100644 --- a/Documentation/git-reflog.txt +++ b/Documentation/git-reflog.txt @@ -20,7 +20,7 @@ depending on the subcommand: 'git reflog' ['show'] [log-options] [] 'git reflog expire' [--expire=] [--expire-unreachable=] [--rewrite] [--updateref] [--stale-fix] - [--dry-run | -n] [--verbose] [--all | ...] + [--dry-run | -n] [--verbose] [--all [--single-worktree] | ...] 'git reflog delete' [--rewrite] [--updateref] [--dry-run | -n] [--verbose] ref@\{specifier\}... 'git reflog exists' @@ -72,6 +72,11 @@ Options for `expire` --all:: Process the reflogs of all references. +--single-worktree:: + By default when `--all` is specified, reflogs from all working + trees are processed. This option limits the processing to reflogs + from the current working tree only. + --expire=:: Prune entries older than the specified time. If this option is not specified, the expiration time is taken from the diff --git a/builtin/reflog.c b/builtin/reflog.c index 3acef5a0ab..eed956851e 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -10,6 +10,7 @@ #include "diff.h" #include "revision.h" #include "reachable.h" +#include "worktree.h" /* NEEDSWORK: switch to using parse_options */ static const char reflog_expire_usage[] = @@ -52,6 +53,7 @@ struct collect_reflog_cb { struct collected_reflog **e; int alloc; int nr; + struct worktree *wt; }; /* Remember to update object flag allocation in object.h */ @@ -388,8 +390,12 @@ static int collect_reflog(const char *ref, const struct object_id *oid, int unus { struct collected_reflog *e; struct collect_reflog_cb *cb = cb_data; + struct strbuf newref = STRBUF_INIT; + + strbuf_worktree_ref(cb->wt, &newref, ref); + FLEX_ALLOC_STR(e, reflog, newref.buf); + strbuf_release(&newref); - FLEX_ALLOC_STR(e, reflog, ref); oidcpy(&e->oid, oid); ALLOC_GROW(cb->e, cb->nr + 1, cb->alloc); cb->e[cb->nr++] = e; @@ -512,7 +518,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) { struct expire_reflog_policy_cb cb; timestamp_t now = time(NULL); - int i, status, do_all; + int i, status, do_all, all_worktrees = 1; int explicit_expiry = 0; unsigned int flags = 0; @@ -549,6 +555,8 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) flags |= EXPIRE_REFLOGS_UPDATE_REF; else if (!strcmp(arg, "--all")) do_all = 1; + else if (!strcmp(arg, "--single-worktree")) + all_worktrees = 0; else if (!strcmp(arg, "--verbose")) flags |= EXPIRE_REFLOGS_VERBOSE; else if (!strcmp(arg, "--")) { @@ -577,10 +585,18 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) if (do_all) { struct collect_reflog_cb collected; + struct worktree **worktrees, **p; int i; memset(&collected, 0, sizeof(collected)); - for_each_reflog(collect_reflog, &collected); + worktrees = get_worktrees(0); + for (p = worktrees; *p; p++) { + if (!all_worktrees && !(*p)->is_current) + continue; + collected.wt = *p; + for_each_reflog(collect_reflog, &collected); + } + free_worktrees(worktrees); for (i = 0; i < collected.nr; i++) { struct collected_reflog *e = collected.e[i]; set_reflog_expiry_param(&cb.cmd, explicit_expiry, e->reflog); -- 2.19.0.647.gb9a6049235
[PATCH 5/8] revision.c: better error reporting on ref from different worktrees
Make use of the new ref aliases to pass refs from another worktree around and access them from the current ref store instead. This does not change any functionality, but when a problem shows up, we would report something like fatal: bad object worktrees/ztemp/HEAD warning: reflog of 'main/HEAD' references pruned commits instead of fatal: bad object HEAD warning: reflog of 'HEAD' references pruned commits which does not really tell where the refs are from. Signed-off-by: Nguyễn Thái Ngọc Duy --- revision.c | 21 + worktree.c | 32 +--- worktree.h | 14 ++ 3 files changed, 56 insertions(+), 11 deletions(-) diff --git a/revision.c b/revision.c index 63aae722c1..8ce660e3b1 100644 --- a/revision.c +++ b/revision.c @@ -1177,7 +1177,7 @@ struct all_refs_cb { int warned_bad_reflog; struct rev_info *all_revs; const char *name_for_errormsg; - struct ref_store *refs; + struct worktree *wt; }; int ref_excluded(struct string_list *ref_excludes, const char *path) @@ -1214,7 +1214,7 @@ static void init_all_refs_cb(struct all_refs_cb *cb, struct rev_info *revs, cb->all_revs = revs; cb->all_flags = flags; revs->rev_input_given = 1; - cb->refs = NULL; + cb->wt = NULL; } void clear_ref_exclusion(struct string_list **ref_excludes_p) @@ -1277,15 +1277,20 @@ static int handle_one_reflog_ent(struct object_id *ooid, struct object_id *noid, return 0; } -static int handle_one_reflog(const char *refname, +static int handle_one_reflog(const char *refname_in_wt, const struct object_id *oid, int flag, void *cb_data) { struct all_refs_cb *cb = cb_data; + struct strbuf refname = STRBUF_INIT; + cb->warned_bad_reflog = 0; - cb->name_for_errormsg = refname; - refs_for_each_reflog_ent(cb->refs, refname, + strbuf_worktree_ref(cb->wt, &refname, refname_in_wt); + cb->name_for_errormsg = refname.buf; + refs_for_each_reflog_ent(get_main_ref_store(the_repository), +refname.buf, handle_one_reflog_ent, cb_data); + strbuf_release(&refname); return 0; } @@ -1300,8 +1305,8 @@ static void add_other_reflogs_to_pending(struct all_refs_cb *cb) if (wt->is_current) continue; - cb->refs = get_worktree_ref_store(wt); - refs_for_each_reflog(cb->refs, + cb->wt = wt; + refs_for_each_reflog(get_worktree_ref_store(wt), handle_one_reflog, cb); } @@ -1314,7 +1319,7 @@ void add_reflogs_to_pending(struct rev_info *revs, unsigned flags) cb.all_revs = revs; cb.all_flags = flags; - cb.refs = get_main_ref_store(the_repository); + cb.wt = NULL; for_each_reflog(handle_one_reflog, &cb); if (!revs->single_worktree) diff --git a/worktree.c b/worktree.c index b0d0b5426d..ec1a5bc511 100644 --- a/worktree.c +++ b/worktree.c @@ -487,6 +487,28 @@ int submodule_uses_worktrees(const char *path) return ret; } +void strbuf_worktree_ref(const struct worktree *wt, +struct strbuf *sb, +const char *refname) +{ + if (wt && !wt->is_current) { + if (is_main_worktree(wt)) + strbuf_addstr(sb, "main/"); + else + strbuf_addf(sb, "worktrees/%s/", wt->id); + } + strbuf_addstr(sb, refname); +} + +const char *worktree_ref(const struct worktree *wt, const char *refname) +{ + static struct strbuf sb = STRBUF_INIT; + + strbuf_reset(&sb); + strbuf_worktree_ref(wt, &sb, refname); + return sb.buf; +} + int other_head_refs(each_ref_fn fn, void *cb_data) { struct worktree **worktrees, **p; @@ -495,13 +517,17 @@ int other_head_refs(each_ref_fn fn, void *cb_data) worktrees = get_worktrees(0); for (p = worktrees; *p; p++) { struct worktree *wt = *p; - struct ref_store *refs; + struct object_id oid; + int flag; if (wt->is_current) continue; - refs = get_worktree_ref_store(wt); - ret = refs_head_ref(refs, fn, cb_data); + if (!refs_read_ref_full(get_main_ref_store(the_repository), + worktree_ref(wt, "HEAD"), + RESOLVE_REF_READING, + &oid, &flag)) + ret = fn(worktree_ref(wt, "HEAD"), &oid, flag, cb_data); if (ret) break; } diff --git a/worktree.h b/worktree.h index df3fc30f73..0016eb9e88 100644 --- a/worktree.h
[PATCH 7/8] fsck: check HEAD and reflog from other worktrees
From: Elijah Newren fsck is a repo-wide operation and should check all references no matter which worktree they are associated to. Reported-by: Jeff King Helped-by: Elijah Newren Signed-off-by: Nguyễn Thái Ngọc Duy --- builtin/fsck.c | 55 ++--- t/t1450-fsck.sh | 39 +++ 2 files changed, 77 insertions(+), 17 deletions(-) diff --git a/builtin/fsck.c b/builtin/fsck.c index 24f8a09a3c..71492c158d 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -19,6 +19,7 @@ #include "packfile.h" #include "object-store.h" #include "run-command.h" +#include "worktree.h" #define REACHABLE 0x0001 #define SEEN 0x0002 @@ -444,7 +445,11 @@ static int fsck_handle_reflog_ent(struct object_id *ooid, struct object_id *noid static int fsck_handle_reflog(const char *logname, const struct object_id *oid, int flag, void *cb_data) { - for_each_reflog_ent(logname, fsck_handle_reflog_ent, (void *)logname); + struct strbuf refname = STRBUF_INIT; + + strbuf_worktree_ref(cb_data, &refname, logname); + for_each_reflog_ent(refname.buf, fsck_handle_reflog_ent, refname.buf); + strbuf_release(&refname); return 0; } @@ -482,20 +487,34 @@ static int fsck_handle_ref(const char *refname, const struct object_id *oid, return 0; } -static int fsck_head_link(const char **head_points_at, +static int fsck_head_link(const char *head_ref_name, + const char **head_points_at, struct object_id *head_oid); static void get_default_heads(void) { + struct worktree **worktrees, **p; const char *head_points_at; struct object_id head_oid; - fsck_head_link(&head_points_at, &head_oid); - if (head_points_at && !is_null_oid(&head_oid)) - fsck_handle_ref("HEAD", &head_oid, 0, NULL); for_each_rawref(fsck_handle_ref, NULL); - if (include_reflogs) - for_each_reflog(fsck_handle_reflog, NULL); + + worktrees = get_worktrees(0); + for (p = worktrees; *p; p++) { + struct worktree *wt = *p; + struct strbuf ref = STRBUF_INIT; + + strbuf_worktree_ref(wt, &ref, "HEAD"); + fsck_head_link(ref.buf, &head_points_at, &head_oid); + if (head_points_at && !is_null_oid(&head_oid)) + fsck_handle_ref(ref.buf, &head_oid, 0, NULL); + strbuf_release(&ref); + + if (include_reflogs) + refs_for_each_reflog(get_worktree_ref_store(wt), +fsck_handle_reflog, wt); + } + free_worktrees(worktrees); /* * Not having any default heads isn't really fatal, but @@ -584,34 +603,36 @@ static void fsck_object_dir(const char *path) stop_progress(&progress); } -static int fsck_head_link(const char **head_points_at, +static int fsck_head_link(const char *head_ref_name, + const char **head_points_at, struct object_id *head_oid) { int null_is_error = 0; if (verbose) - fprintf(stderr, "Checking HEAD link\n"); + fprintf(stderr, "Checking %s link\n", head_ref_name); - *head_points_at = resolve_ref_unsafe("HEAD", 0, head_oid, NULL); + *head_points_at = resolve_ref_unsafe(head_ref_name, 0, head_oid, NULL); if (!*head_points_at) { errors_found |= ERROR_REFS; - return error("Invalid HEAD"); + return error("Invalid %s", head_ref_name); } - if (!strcmp(*head_points_at, "HEAD")) + if (!strcmp(*head_points_at, head_ref_name)) /* detached HEAD */ null_is_error = 1; else if (!starts_with(*head_points_at, "refs/heads/")) { errors_found |= ERROR_REFS; - return error("HEAD points to something strange (%s)", -*head_points_at); + return error("%s points to something strange (%s)", +head_ref_name, *head_points_at); } if (is_null_oid(head_oid)) { if (null_is_error) { errors_found |= ERROR_REFS; - return error("HEAD: detached HEAD points at nothing"); + return error("%s: detached HEAD points at nothing", +head_ref_name); } - fprintf(stderr, "notice: HEAD points to an unborn branch (%s)\n", - *head_points_at + 11); + fprintf(stderr, "notice: %s points to an unborn branch (%s)\n", + head_ref_name, *head_points_at + 11); } return 0; } diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh index 0f2dd26f74..444e8c1ad9 100755 --- a/t/t1450-fsck.sh +++ b/t/t
[PATCH 1/8] refs.c: indent with tabs, not spaces
Signed-off-by: Nguyễn Thái Ngọc Duy --- refs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/refs.c b/refs.c index a7a75b4cc0..9f7268d5fe 100644 --- a/refs.c +++ b/refs.c @@ -646,7 +646,7 @@ enum ref_type ref_type(const char *refname) return REF_TYPE_PER_WORKTREE; if (is_pseudoref_syntax(refname)) return REF_TYPE_PSEUDOREF; - return REF_TYPE_NORMAL; + return REF_TYPE_NORMAL; } long get_files_ref_lock_timeout_ms(void) -- 2.19.0.647.gb9a6049235
[PATCH 0/8] fix per-worktree ref iteration in fsck/reflog expire
Sorry it took me so long to revisit these bugs, even though the first one was reported nearly a year ago. I guess I slept on it way longer than I should have. This series opens up the currrent worktree's ref space, allowing one worktree to see refs from other worktrees. With this, it's possible to have less confusing error reports (e.g. "heh.. what HEAD are you talking about?"). And it's possible to peek one worktree from another, e.g. now I could do git checkout main/HEAD make test -j8 in one terminal and go back to the original terminal and continue hacking while tests are being run in the background. With this issue out of the way, I could now continue to fix the "forget to look at all HEADs/reflogs" problem in fsck and "reflog expire". The fsck patches are mostly from Elijah with some code/test adaptation from me. I also take this opportunity to try to standardize a common/private space in $GIT_DIR or ref hierarchy so we don't have to add more rules in the future. One heads up. One remaining problem with "refs and worktrees" is the ability to completely separate ref space between worktrees (i.e. refs/heads/master on worktree A is completely different than one in worktree B). This is needed to make use worktrees in submodules. But the way I see it, per-worktree refs may have to be moved back to $GIT_COMMON_DIR/refs to be efficient. This may be backward incompatible change. Haven't thought it through yet (and didn't see it coming because I largely ignored refs/bisect, which should have made me think about this much earlier) Elijah Newren (2): fsck: Move fsck_head_link() to get_default_heads() to avoid some globals fsck: check HEAD and reflog from other worktrees Nguyễn Thái Ngọc Duy (6): refs.c: indent with tabs, not spaces Add a place for (not) sharing stuff between worktrees refs: new ref types to make per-worktree refs visible to all worktrees revision.c: correct a parameter name revision.c: better error reporting on ref from different worktrees reflog expire: cover reflog from all worktrees Documentation/git-reflog.txt | 7 ++- Documentation/gitrepository-layout.txt | 11 - builtin/fsck.c | 68 ++ builtin/reflog.c | 22 +++-- path.c | 1 + refs.c | 23 - refs.h | 8 +-- refs/files-backend.c | 42 ++-- revision.c | 22 ++--- t/t0060-path-utils.sh | 2 + t/t1415-worktree-refs.sh | 66 + t/t1450-fsck.sh| 39 +++ worktree.c | 32 ++-- worktree.h | 14 ++ 14 files changed, 312 insertions(+), 45 deletions(-) create mode 100755 t/t1415-worktree-refs.sh -- 2.19.0.647.gb9a6049235
[PATCH 4/8] revision.c: correct a parameter name
This function is a callback of for_each_reflog() which will pass a ref name as the first argument, not a path (to a reflog file). Signed-off-by: Nguyễn Thái Ngọc Duy --- revision.c | 7 --- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/revision.c b/revision.c index e18bd530e4..63aae722c1 100644 --- a/revision.c +++ b/revision.c @@ -1277,13 +1277,14 @@ static int handle_one_reflog_ent(struct object_id *ooid, struct object_id *noid, return 0; } -static int handle_one_reflog(const char *path, const struct object_id *oid, +static int handle_one_reflog(const char *refname, +const struct object_id *oid, int flag, void *cb_data) { struct all_refs_cb *cb = cb_data; cb->warned_bad_reflog = 0; - cb->name_for_errormsg = path; - refs_for_each_reflog_ent(cb->refs, path, + cb->name_for_errormsg = refname; + refs_for_each_reflog_ent(cb->refs, refname, handle_one_reflog_ent, cb_data); return 0; } -- 2.19.0.647.gb9a6049235
[PATCH 2/8] Add a place for (not) sharing stuff between worktrees
When multiple worktrees are used, we need rules to determine if something belongs to one worktree or all of them. Instead of keeping adding rules when new stuff comes, have a generic rule: - Inside $GIT_DIR, which is per-worktree by default, add $GIT_DIR/common which is always shared. New features that want to share stuff should put stuff under this directory. - Inside refs/, which is shared by default except refs/bisect, add refs/local/ which is per-worktree. We may eventually move refs/bisect to this new location and remove the exception in refs code. Signed-off-by: Nguyễn Thái Ngọc Duy --- Documentation/gitrepository-layout.txt | 11 ++-- path.c | 1 + refs.c | 1 + refs/files-backend.c | 14 +++--- t/t0060-path-utils.sh | 2 ++ t/t1415-worktree-refs.sh | 36 ++ 6 files changed, 60 insertions(+), 5 deletions(-) create mode 100755 t/t1415-worktree-refs.sh diff --git a/Documentation/gitrepository-layout.txt b/Documentation/gitrepository-layout.txt index e85148f05e..fad404ed7c 100644 --- a/Documentation/gitrepository-layout.txt +++ b/Documentation/gitrepository-layout.txt @@ -95,8 +95,10 @@ refs:: References are stored in subdirectories of this directory. The 'git prune' command knows to preserve objects reachable from refs found in this directory and - its subdirectories. This directory is ignored if $GIT_COMMON_DIR - is set and "$GIT_COMMON_DIR/refs" will be used instead. + its subdirectories. + This directory is ignored (except refs/bisect and refs/local) + if $GIT_COMMON_DIR is set and "$GIT_COMMON_DIR/refs" will be + used instead. refs/heads/`name`:: records tip-of-the-tree commit objects of branch `name` @@ -165,6 +167,11 @@ hooks:: each hook. This directory is ignored if $GIT_COMMON_DIR is set and "$GIT_COMMON_DIR/hooks" will be used instead. +common:: + When multiple working trees are used, most of files in + $GIT_DIR are per-worktree with a few known exceptions. All + files under 'common' however will be shared between all + working trees. index:: The current index file for the repository. It is diff --git a/path.c b/path.c index 34f0f98349..7eb61bf31b 100644 --- a/path.c +++ b/path.c @@ -108,6 +108,7 @@ struct common_dir { static struct common_dir common_list[] = { { 0, 1, 0, "branches" }, + { 0, 1, 0, "common" }, { 0, 1, 0, "hooks" }, { 0, 1, 0, "info" }, { 0, 0, 1, "info/sparse-checkout" }, diff --git a/refs.c b/refs.c index 9f7268d5fe..a851ef085b 100644 --- a/refs.c +++ b/refs.c @@ -624,6 +624,7 @@ int dwim_log(const char *str, int len, struct object_id *oid, char **log) static int is_per_worktree_ref(const char *refname) { return !strcmp(refname, "HEAD") || + starts_with(refname, "refs/local/") || starts_with(refname, "refs/bisect/") || starts_with(refname, "refs/rewritten/"); } diff --git a/refs/files-backend.c b/refs/files-backend.c index 16ef9325e0..416eafa453 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -269,9 +269,9 @@ static void loose_fill_ref_dir(struct ref_store *ref_store, closedir(d); /* -* Manually add refs/bisect, which, being per-worktree, might -* not appear in the directory listing for refs/ in the main -* repo. +* Manually add refs/bisect and refs/local, which, being +* per-worktree, might not appear in the directory listing for +* refs/ in the main repo. */ if (!strcmp(dirname, "refs/")) { int pos = search_ref_dir(dir, "refs/bisect/", 12); @@ -281,6 +281,14 @@ static void loose_fill_ref_dir(struct ref_store *ref_store, dir->cache, "refs/bisect/", 12, 1); add_entry_to_dir(dir, child_entry); } + + pos = search_ref_dir(dir, "refs/local/", 11); + + if (pos < 0) { + struct ref_entry *child_entry = create_dir_entry( + dir->cache, "refs/local/", 11, 1); + add_entry_to_dir(dir, child_entry); + } } } diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh index cd74c0a471..c7b53e494b 100755 --- a/t/t0060-path-utils.sh +++ b/t/t0060-path-utils.sh @@ -306,6 +306,8 @@ test_git_path GIT_COMMON_DIR=bar hooks/me bar/hooks/me test_git_path GIT_COMMON_DIR=bar config bar/config test_git_path GIT_COMMON_DIR=bar packed-refs bar/packed-refs test_git_path GIT_COMMON_DIR=bar shallow bar/shallow +test_git_path GIT_COMMON_DIR=bar common bar/common +test_git_path GIT_COMMON_DIR=bar common/file
[PATCH 6/8] fsck: Move fsck_head_link() to get_default_heads() to avoid some globals
From: Elijah Newren This will make it easier to check the HEAD of other worktrees from fsck. Signed-off-by: Elijah Newren Signed-off-by: Nguyễn Thái Ngọc Duy --- builtin/fsck.c | 27 --- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/builtin/fsck.c b/builtin/fsck.c index 63c8578cc1..24f8a09a3c 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -36,8 +36,6 @@ static int check_strict; static int keep_cache_objects; static struct fsck_options fsck_walk_options = FSCK_OPTIONS_DEFAULT; static struct fsck_options fsck_obj_options = FSCK_OPTIONS_DEFAULT; -static struct object_id head_oid; -static const char *head_points_at; static int errors_found; static int write_lost_and_found; static int verbose; @@ -484,8 +482,15 @@ static int fsck_handle_ref(const char *refname, const struct object_id *oid, return 0; } +static int fsck_head_link(const char **head_points_at, + struct object_id *head_oid); + static void get_default_heads(void) { + const char *head_points_at; + struct object_id head_oid; + + fsck_head_link(&head_points_at, &head_oid); if (head_points_at && !is_null_oid(&head_oid)) fsck_handle_ref("HEAD", &head_oid, 0, NULL); for_each_rawref(fsck_handle_ref, NULL); @@ -579,33 +584,34 @@ static void fsck_object_dir(const char *path) stop_progress(&progress); } -static int fsck_head_link(void) +static int fsck_head_link(const char **head_points_at, + struct object_id *head_oid) { int null_is_error = 0; if (verbose) fprintf(stderr, "Checking HEAD link\n"); - head_points_at = resolve_ref_unsafe("HEAD", 0, &head_oid, NULL); - if (!head_points_at) { + *head_points_at = resolve_ref_unsafe("HEAD", 0, head_oid, NULL); + if (!*head_points_at) { errors_found |= ERROR_REFS; return error("Invalid HEAD"); } - if (!strcmp(head_points_at, "HEAD")) + if (!strcmp(*head_points_at, "HEAD")) /* detached HEAD */ null_is_error = 1; - else if (!starts_with(head_points_at, "refs/heads/")) { + else if (!starts_with(*head_points_at, "refs/heads/")) { errors_found |= ERROR_REFS; return error("HEAD points to something strange (%s)", -head_points_at); +*head_points_at); } - if (is_null_oid(&head_oid)) { + if (is_null_oid(head_oid)) { if (null_is_error) { errors_found |= ERROR_REFS; return error("HEAD: detached HEAD points at nothing"); } fprintf(stderr, "notice: HEAD points to an unborn branch (%s)\n", - head_points_at + 11); + *head_points_at + 11); } return 0; } @@ -720,7 +726,6 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) git_config(fsck_config, NULL); - fsck_head_link(); if (connectivity_only) { for_each_loose_object(mark_loose_for_connectivity, NULL, 0); for_each_packed_object(mark_packed_for_connectivity, NULL, 0); -- 2.19.0.647.gb9a6049235
Re: [PATCH v2 2/3] transport.c: introduce core.alternateRefsCommand
On Fri, Sep 21, 2018 at 02:47:43PM -0400, Taylor Blau wrote: > +expect_haves () { > + printf "%s .have\n" $(git rev-parse $@) >expect > +} > + > +extract_haves () { > + depacketize - | grep '\.have' | sed -e 's/\\0.*$//g' It looks like you're trying to match a NUL here in the sed expression, but from my reading of it, POSIX doesn't permit BREs to match NUL. Perhaps someone can come up with a better solution, but I'd write this as the following: depacketize - | perl -ne 'next unless /\.have/; s/\0.*$//g; print' -- brian m. carlson: Houston, Texas, US OpenPGP: https://keybase.io/bk2204 signature.asc Description: PGP signature
hi
i'm diagnosed with laryngeal cancer, i want to leave money to you,am giving my body to science for research. i want this last act of mine to be an offering to GOD and humanity. respond so i know you got this.God bless you abundantly
[PATCH] git help: promote 'git help -av'
When you type "git help" (or just "git") you are greeted with a list with commonly used commands and their short description and are suggested to use "git help -a" or "git help -g" for more details. "git help -av" would be more friendly and inline with what is shown with "git help" since it shows list of commands with description as well, and commands are properly grouped. Signed-off-by: Nguyễn Thái Ngọc Duy --- git.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git.c b/git.c index a6f4b44af5..69c21f378b 100644 --- a/git.c +++ b/git.c @@ -31,7 +31,7 @@ const char git_usage_string[] = "[]"); const char git_more_info_string[] = - N_("'git help -a' and 'git help -g' list available subcommands and some\n" + N_("'git help -av' and 'git help -g' list available subcommands and some\n" "concept guides. See 'git help ' or 'git help '\n" "to read about a specific subcommand or concept."); -- 2.19.0.647.gb9a6049235
[PATCH] ref-filter: don't look for objects when outside of a repository
The command 'git ls-remote --sort=authordate ' segfaults when run outside of a repository, ever since the introduction of its '--sort' option in 1fb20dfd8e (ls-remote: create '--sort' option, 2018-04-09). While in general the 'git ls-remote' command can be run outside of a repository just fine, its '--sort=' option with certain keys does require access to the referenced objects. This sorting is implemented using the generic ref-filter sorting facility, which already handles missing objects gracefully with the appropriate 'missing object deadbeef for HEAD' message. However, being generic means that it checks replace refs while trying to retrieve an object, and while doing so it accesses the 'git_replace_ref_base' variable, which has not been initialized and is still a NULL pointer when outside of a repository, thus causing the segfault. Make ref-filter more careful and only attempt to retrieve an object when we are in a repository. Also add a test to ensure that 'git ls-remote --sort' fails gracefully when executed outside of a repository. Reported-by: H.Merijn Brand Signed-off-by: SZEDER Gábor --- I'm not quite sure that this is the best place to add this check... but hey, it's a Saturday afternoon after all ;) ref-filter.c | 3 ++- t/t5512-ls-remote.sh | 6 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ref-filter.c b/ref-filter.c index e1bcb4ca8a..3555bc29e7 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -1473,7 +1473,8 @@ static int get_object(struct ref_array_item *ref, int deref, struct object **obj oi->info.sizep = &oi->size; oi->info.typep = &oi->type; } - if (oid_object_info_extended(the_repository, &oi->oid, &oi->info, + if (!have_git_dir() || + oid_object_info_extended(the_repository, &oi->oid, &oi->info, OBJECT_INFO_LOOKUP_REPLACE)) return strbuf_addf_ret(err, -1, _("missing object %s for %s"), oid_to_hex(&oi->oid), ref->refname); diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh index bc5703ff9b..7dd081da01 100755 --- a/t/t5512-ls-remote.sh +++ b/t/t5512-ls-remote.sh @@ -302,4 +302,10 @@ test_expect_success 'ls-remote works outside repository' ' nongit git ls-remote dst.git ' +test_expect_success 'ls-remote --sort fails gracefully outside repository' ' + # Use a sort key that requires access to the referenced objects. + nongit test_must_fail git ls-remote --sort=authordate "$TRASH_DIRECTORY" 2>err && + test_i18ngrep "^fatal: missing object" err +' + test_done -- 2.19.0.355.geb876cd9d6
Re: Feature request: Provide porcelain to manage symbolic references as branch aliases
Updating the proof-of-concept script for this feature request. (See attachment.) I'm quoting the entire original message for reference, just because it's been a while since I proposed this. -Phil On 30/04/14 00:51, Phil Sainty wrote: > Most of the plumbing for having branch name aliases already exists > in the form of symbolic references, and people do use them for this > purpose; but I get the impression that it's not really supported > officially, and I'm not aware of any porcelain features to > facilitate this use-case. > > I'd like to propose that such porcelain be added. I feel that a new > argument to 'git branch' would make the most sense: > > git branch --alias [] > > For reference/testing, I'm attaching a wrapper script I wrote to > implement the same functionality (as a separate command). I did this > primarily to provide the error-checking I felt was needed to make it > practical to use branch aliases -- git symbolic-ref will happily > trash your branch references if you make a mistake, whereas it's > pretty difficult to mess anything up with my git-branch-alias script. > > Thus far it's worked nicely for me. Examples: > > $ git branch-alias # create alias > $ git branch-alias # create alias for current branch > $ git branch # view branches and branch aliases > $ git log > $ git checkout > $ git push origin # pushes the branch, not the alias/reference > $ git branch-alias -d # delete an alias safely > > n.b. For my proposed porcelain change, these examples would become: > $ git branch --alias # creates alias > $ git branch --alias # create alias for current branch > $ git branch --delete # works since 1.8.0.1, but see below. > > > Since using this script, the only thing I've spotted that I'd like > to be different is the commit message if I "git merge ". The > commit message indicates that I've merged rather than the > that it points at. I'd prefer that it was dereferenced > when the message was generated, so that the real branch name was > printed instead. > > > That niggle aside, significant things I noted along the way were: > > 1. Git 1.8.0.1 fixed the problem whereby git branch -d >used to dereference and therefore delete the branch >it pointed at, rather than the reference. > > 2. HOWEVER if you have checked out at the time you >delete it, you're in trouble -- git allows you to do it, and >you're then left with an invalid HEAD reference. > >(I think this ought to be considered a current bug in git.) > > 3. I resolved that situation (2) by using "git symbolic-ref HEAD" >to find the target ref, and setting HEAD to that target. Nothing >changes for the user, but we can now delete the reference safely. > >HOWEVER, there's a problem with detecting that situation (2) >in the first place: > > 4. Chains of references are de-referenced atomically -- the entire >reference chain is followed to its end; and I could find no >facility to obtain ONLY the "next link of the chain". > >This means we can't use "git symbolic-ref HEAD" to check whether >it points to another reference. In my script I had to resort to >inspecting HEAD manually, which obviously isn't desirable. > >I think a new argument is warranted here, perhaps something like: >"git symbolic-ref --max-deref-count=1" > >I'll justify that on the assumption that (2) needs fixing in git >regardless, either by: > >(i) Not allowing the user to delete the checked-out symref (which >would be consistent with the behaviour if the user attempts to >"git branch -d " (for an actual branch name) when that >is the currently checked-out branch. > >or, >(ii) Using the approach I've taken: silently setting HEAD to the > branch to which the symref points before deleting that symref. > (I couldn't see any reason not to use this approach.) > >But as in both cases we need to detect that HEAD is the symref >being deleted, which means that we need the ability to explicitly >dereference only a single step of a reference chain. > > > -Phil > #!/bin/sh # git branch-alias # Author: Phil S. # Version 1.11 version=1.11 # Creates branch aliases, so that you can refer to a long branch name # by a convenient short alias. This is particularly useful for branch # names beginning with bug-tracker ID numbers (or similar), where the # benefits of tab-completion are greatly reduced. # This is mostly a "do what I mean" wrapper around "git symbolic-ref", # with numerous safety measures included in order to eliminate the # (otherwise considerable) risk of trashing a branch if you get your # arguments wrong. # Installation: # Place this script somewhere in your PATH and name it "git-branch-alias" # and you will be able to invoke it with "git branch-alias" as per the # following examples. # Examples: # git branch-alias # create alias # git branch-alias # create alias for current branch # git branch # view branches and branc
Hello
Good day. Please did you receive my previous email to you?
Re: [PATCH 1/8] sha1-array: provide oid_array_filter
On Fri, Sep 21 2018, Stefan Beller wrote: > +/* > + * Apply want to each entry in array, retaining only the entries for > + * which the function returns true. Preserve the order of the entries > + * that are retained. > + */ > +void oid_array_filter(struct oid_array *array, > + for_each_oid_fn want, > + void *cbdata); > + > #endif /* SHA1_ARRAY_H */ The code LGTM, but this comment should instead be an update to the API docs, see my recent 5cc044e025 ("get_short_oid: sort ambiguous objects by type, then SHA-1", 2018-05-10) for an addition of a new function to this API where I added some new docs.
Re: Coredump on ls-remote + --sort
On Sat, Sep 22 2018, H.Merijn Brand wrote: > A small background why I wanted this: I need to build a new version of > some software hosted in git, add a lot of shared/static stuff and > automatically test it. I want to get the most recent *tag* and create a > folder with the tagname in it, go into that folder and clone the repo, > check out the tag, add the rest of the stuff, build and test > > As the default outpout of «git ls-remote --tags» or «git ls-remote» is > topologically sorted by tagname, the most recent tag is likely to be in > the middle. > > Linux 4.12.14-lp150.12.16-default [openSUSE Leap 15.0] > > $ git --version > git version 2.19.0 > > $ git ls-remote --tags github.com:Tux/App-ccdiff > 5e2513ab6dd4a24c8f3a3ace0a3faba6a291d818refs/tags/0.04 > 2f7ea0f1e751dc20c1ddb15f6d61c6fa62d5d6f1refs/tags/0.05 > a3802907be5b10383c7438f1d1c660fe13a05d3frefs/tags/0.06 > 3e4bfa7cde75fba221650b9d3aab706803dfrefs/tags/0.07 > 05829d1ac5b49bbdd2167bc363b94f8a12e752b3refs/tags/0.08 > 9c6e5861ea9c6e50c501663d43c5a9f6d31b54bcrefs/tags/0.09 > e815b059f6326da936c3a92272ba67e273b1dc3erefs/tags/0.10 > e6b40e331c945449bb8e71023de4920ca5574adcrefs/tags/0.20 > be55e6336b1db5ffad23a6a0a663763e2f5da779refs/tags/0.21 > e283d563f02bb8d2131e8b95852072ac204b28b4refs/tags/0.22 > 0d3d1830f542121bfef1d984f21343c6d9c774f8refs/tags/0.23 > d7bf195a92095a4f0b810584810450e4001b1a2crefs/tags/0.24 > 5c517cf3f79cb18173714e63bc5b80a3e3f888f1refs/tags/0.25 > > Whether or not supported, it should not dump core > > $ git ls-remote --tags --sort=authordate github.com:Tux/App-ccdiff > Segmentation fault (core dumped) > > (gdb) where > #0 0x774784a6 in __strlen_sse2 () from /lib64/libc.so.6 > #1 0x0057a956 in for_each_replace_ref () > #2 0x00596cec in do_lookup_replace_object () > #3 0x005c14eb in oid_object_info_extended () > #4 0x0058b984 in get_object () > #5 0x0058ddde in populate_value () > #6 0x0058e36b in compare_refs () > #7 0x0061447a in msort_with_tmp.part () > #8 0x00614505 in msort_with_tmp.part () > #9 0x00614518 in msort_with_tmp.part () > #10 0x00614518 in msort_with_tmp.part () > #11 0x0061459e in git_qsort_s () > #12 0x0058ed40 in ref_array_sort () > #13 0x0044ef66 in cmd_ls_remote () > #14 0x0040784f in handle_builtin () > #15 0x00407bb0 in cmd_main () > #16 0x00406b04 in main () > > Linux 3.10.0-862.6.3.el7.x86_64 [CentOS Linux 7.5.1804 (Core)] > > $ git --version > git version 2.18.0 > > $ git ls-remote --tags https://github.com/Tux/App-ccdiff > 5e2513ab6dd4a24c8f3a3ace0a3faba6a291d818refs/tags/0.04 > 2f7ea0f1e751dc20c1ddb15f6d61c6fa62d5d6f1refs/tags/0.05 > a3802907be5b10383c7438f1d1c660fe13a05d3frefs/tags/0.06 > 3e4bfa7cde75fba221650b9d3aab706803dfrefs/tags/0.07 > 05829d1ac5b49bbdd2167bc363b94f8a12e752b3refs/tags/0.08 > 9c6e5861ea9c6e50c501663d43c5a9f6d31b54bcrefs/tags/0.09 > e815b059f6326da936c3a92272ba67e273b1dc3erefs/tags/0.10 > e6b40e331c945449bb8e71023de4920ca5574adcrefs/tags/0.20 > be55e6336b1db5ffad23a6a0a663763e2f5da779refs/tags/0.21 > e283d563f02bb8d2131e8b95852072ac204b28b4refs/tags/0.22 > 0d3d1830f542121bfef1d984f21343c6d9c774f8refs/tags/0.23 > d7bf195a92095a4f0b810584810450e4001b1a2crefs/tags/0.24 > 5c517cf3f79cb18173714e63bc5b80a3e3f888f1refs/tags/0.25 > > $ git ls-remote --tags --sort=authordate https://github.com/Tux/App-ccdiff > Segmentation fault > > (gdb) where > #0 0x7751a67f in __strlen_sse42 () from /lib64/libc.so.6 > #1 0x00561c06 in for_each_replace_ref () > #2 0x0057c3fa in do_lookup_replace_object () > #3 0x005a6aa8 in read_object_file_extended () > #4 0x005731e5 in get_object () > #5 0x005749df in populate_value () > #6 0x00574e9d in compare_refs () > #7 0x005efe57 in msort_with_tmp.part.0 () > #8 0x005efe31 in msort_with_tmp.part.0 () > #9 0x005efe0e in msort_with_tmp.part.0 () > #10 0x005efe0e in msort_with_tmp.part.0 () > #11 0x005eff5c in git_qsort_s () > #12 0x005757e0 in ref_array_sort () > #13 0x0044c6b6 in cmd_ls_remote () > #14 0x0040730e in handle_builtin () > #15 0x0040760e in cmd_main () > #16 0x00406554 in main () I can't reproduce this, I just get for both ssh and https: $ ~/g/git/git --exec-path=$PWD ls-remote --tags --sort=authordate https://github.com/Tux/App-ccdiff fatal: missing object 2f7ea0f1e751dc20c1ddb15f6d61c6fa62d5d6f1 for refs/tags/0.05 $ ~/g/git/git --exec-path=$PWD version git version 2.18.0 Same thing on latest 'master' (v2.19.0-221-g150f307afc). But maybe that's just a symptom of the same bug, when I clone the repo I get a working 0.05 tag, and
Coredump on ls-remote + --sort
A small background why I wanted this: I need to build a new version of some software hosted in git, add a lot of shared/static stuff and automatically test it. I want to get the most recent *tag* and create a folder with the tagname in it, go into that folder and clone the repo, check out the tag, add the rest of the stuff, build and test As the default outpout of «git ls-remote --tags» or «git ls-remote» is topologically sorted by tagname, the most recent tag is likely to be in the middle. Linux 4.12.14-lp150.12.16-default [openSUSE Leap 15.0] $ git --version git version 2.19.0 $ git ls-remote --tags github.com:Tux/App-ccdiff 5e2513ab6dd4a24c8f3a3ace0a3faba6a291d818refs/tags/0.04 2f7ea0f1e751dc20c1ddb15f6d61c6fa62d5d6f1refs/tags/0.05 a3802907be5b10383c7438f1d1c660fe13a05d3frefs/tags/0.06 3e4bfa7cde75fba221650b9d3aab706803dfrefs/tags/0.07 05829d1ac5b49bbdd2167bc363b94f8a12e752b3refs/tags/0.08 9c6e5861ea9c6e50c501663d43c5a9f6d31b54bcrefs/tags/0.09 e815b059f6326da936c3a92272ba67e273b1dc3erefs/tags/0.10 e6b40e331c945449bb8e71023de4920ca5574adcrefs/tags/0.20 be55e6336b1db5ffad23a6a0a663763e2f5da779refs/tags/0.21 e283d563f02bb8d2131e8b95852072ac204b28b4refs/tags/0.22 0d3d1830f542121bfef1d984f21343c6d9c774f8refs/tags/0.23 d7bf195a92095a4f0b810584810450e4001b1a2crefs/tags/0.24 5c517cf3f79cb18173714e63bc5b80a3e3f888f1refs/tags/0.25 Whether or not supported, it should not dump core $ git ls-remote --tags --sort=authordate github.com:Tux/App-ccdiff Segmentation fault (core dumped) (gdb) where #0 0x774784a6 in __strlen_sse2 () from /lib64/libc.so.6 #1 0x0057a956 in for_each_replace_ref () #2 0x00596cec in do_lookup_replace_object () #3 0x005c14eb in oid_object_info_extended () #4 0x0058b984 in get_object () #5 0x0058ddde in populate_value () #6 0x0058e36b in compare_refs () #7 0x0061447a in msort_with_tmp.part () #8 0x00614505 in msort_with_tmp.part () #9 0x00614518 in msort_with_tmp.part () #10 0x00614518 in msort_with_tmp.part () #11 0x0061459e in git_qsort_s () #12 0x0058ed40 in ref_array_sort () #13 0x0044ef66 in cmd_ls_remote () #14 0x0040784f in handle_builtin () #15 0x00407bb0 in cmd_main () #16 0x00406b04 in main () Linux 3.10.0-862.6.3.el7.x86_64 [CentOS Linux 7.5.1804 (Core)] $ git --version git version 2.18.0 $ git ls-remote --tags https://github.com/Tux/App-ccdiff 5e2513ab6dd4a24c8f3a3ace0a3faba6a291d818refs/tags/0.04 2f7ea0f1e751dc20c1ddb15f6d61c6fa62d5d6f1refs/tags/0.05 a3802907be5b10383c7438f1d1c660fe13a05d3frefs/tags/0.06 3e4bfa7cde75fba221650b9d3aab706803dfrefs/tags/0.07 05829d1ac5b49bbdd2167bc363b94f8a12e752b3refs/tags/0.08 9c6e5861ea9c6e50c501663d43c5a9f6d31b54bcrefs/tags/0.09 e815b059f6326da936c3a92272ba67e273b1dc3erefs/tags/0.10 e6b40e331c945449bb8e71023de4920ca5574adcrefs/tags/0.20 be55e6336b1db5ffad23a6a0a663763e2f5da779refs/tags/0.21 e283d563f02bb8d2131e8b95852072ac204b28b4refs/tags/0.22 0d3d1830f542121bfef1d984f21343c6d9c774f8refs/tags/0.23 d7bf195a92095a4f0b810584810450e4001b1a2crefs/tags/0.24 5c517cf3f79cb18173714e63bc5b80a3e3f888f1refs/tags/0.25 $ git ls-remote --tags --sort=authordate https://github.com/Tux/App-ccdiff Segmentation fault (gdb) where #0 0x7751a67f in __strlen_sse42 () from /lib64/libc.so.6 #1 0x00561c06 in for_each_replace_ref () #2 0x0057c3fa in do_lookup_replace_object () #3 0x005a6aa8 in read_object_file_extended () #4 0x005731e5 in get_object () #5 0x005749df in populate_value () #6 0x00574e9d in compare_refs () #7 0x005efe57 in msort_with_tmp.part.0 () #8 0x005efe31 in msort_with_tmp.part.0 () #9 0x005efe0e in msort_with_tmp.part.0 () #10 0x005efe0e in msort_with_tmp.part.0 () #11 0x005eff5c in git_qsort_s () #12 0x005757e0 in ref_array_sort () #13 0x0044c6b6 in cmd_ls_remote () #14 0x0040730e in handle_builtin () #15 0x0040760e in cmd_main () #16 0x00406554 in main () -- H.Merijn Brand http://tux.nl Perl Monger http://amsterdam.pm.org/ using perl5.00307 .. 5.29 porting perl5 on HP-UX, AIX, and openSUSE http://mirrors.develooper.com/hpux/http://www.test-smoke.org/ http://qa.perl.org http://www.goldmark.org/jeff/stupid-disclaimers/ pgpjvSaVY9Mix.pgp Description: OpenPGP digital signature