Reply
Hello My Name is Capt. Lucas Alves from the US Army base here in Damascus, Syria. I have a Deal of Sixteen Million Two Hundred Thousand United States I would like to partner with you. Kindly get back to me if it would be of interest to you for more details. Regards, Lucas Alves alvescaptlu...@gmail.com -- 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
git --literal-pathspecs add -u says "fatal: pathspec ':/' did not match any files"
~/tmp/tmprepo$ git init Initialized empty Git repository in /home/npostavs/tmp/tmprepo/.git/ ~/tmp/tmprepo$ git --literal-pathspecs add -u fatal: pathspec ':/' did not match any files ~/tmp/tmprepo$ git --version git version 2.6.1 It was reported[1] that 2.0.2 and several following versions also fail with the same error; I found that version 1.9.5 succeeds. Adding a "." argument: git --literal-pathspecs add -u . succeeds in all versions. [1]: https://github.com/magit/magit/issues/2354#issuecomment-150665961 -- 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: ancestor and descendant ~ clarification needed
On Sat, Oct 24, 2015 at 12:56 AM, Junio C Hamano wrote: >> I see. Thank you. What do you think about the following minor patch >> for user-manual.txt? > > While the updated text is more correct than the original, I do not > know if that is sufficient, or we would also want to mention the > "Already up-to-date!" case here while at it. I thought about that, and IMHO it's not needed. The section name is "Fast-forward merges" and intends to introduce the "fast-forward" concept, which is irrelevant to "Already up-to-date!". Although the "Already up-to-date!" case isn't mentioned all over the manual, it's pretty clear to me (as someone who isn't quite familiar with Git). >> -However, if the current branch is a descendant of the other--so every >> -commit present in the one is already contained in the other--then Git >> -just performs a "fast-forward"; the head of the current branch is moved >> -forward to point at the head of the merged-in branch, without any new >> -commits being created. >> +However, if the current branch is an ancestor of the other--so every commit >> +present in the current branch is already contained in the other >> branch--then Git >> +just performs a "fast-forward"; the head of the current branch is moved >> forward >> +to point at the head of the merged-in branch, without any new commits being >> +created. -- 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: Make "git checkout" automatically update submodules?
Stefan Beller google.com> writes: > [1] https://github.com/jlehmann/git-submod-enhancements/wiki Oh wow, Christmas came early! I'll give this code a try. -- 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-cherry doesn't detect a "copied" commit
Francis Moreau writes: > I was mislead by the git-cherry manpage somehow which says: > > "git-cherry therefore > detects when commits have been "copied" by means of git-cherry-pick(1), > > which is not exactly true. Yeah, I agree; the sentence is merely giving a description from layperson's point of view, and it should have expressed it as such, e.g. "roughly speaking, you can think of it like so", not sounding as if it is giving a strictly correct and authoritative statement. > Would it make sense to add a "--fuzz" option which would reduce the > diff context area used to generate the hash ? There could be situations where such fuzzing might be useful, but I do not think this particular use case of yours is one of them. I'd imagine that you had two branches A (with "Unkown") and B (with "Unknown"), and wanted to apply changes in them to your integration branch (let's call that 'master'). You ask cherry "what commits in A are missing in my 'master'?" and apply them. Next you ask cherry "what commits in B are missing in my 'master' now?" and apply them. Because "Unkown" and "Unknown" are not considered the "same" patches (one is most likely an update to the other), you get conflict when applying the second copy, and that is how you can notice that one of them is a stale and buggy one. If you haven't made your interim integration result available to others after processing branch A, you even have a chance to replace the "Unkown" one you already applied with the corrected "Unknown" one before continuing. Even if you choose not to bother and skip the "Unknown" one from branch B, at least you know that in the end result you have a typo that would eventually need to be fixed from "Unkown" into "Unknown". If you did a fuzzy version and ignored s/Unkown/Unknown/ typofix between the "same" patches, you can avoid the conflict and all patches from branch B may apply cleanly and automatically on top of applying changes from branch A. But depending on the order you processed A and B, you have a 50% chance of keeping the buggy version without even realizing. So erring on the safe side and judging "Unkown" and "Unknown" are different changes, inducing one extra conflict you had to look at, is actively a good thing in this case. One thing that helps to know while learning Git is that we try to avoid being overly clever and outsmarting human users. Instead, we err on the safe side to avoid silently doing a wrong thing. This is because a tool that automates 100% of cases with 2% chance of producing wrong result cannot be trusted---you have to manually inspect all 100% cases it automatically handled to make sure it did the right thing. We instead automate 98% of simple cases where it is obvious what the right result is, and ask the human user for help on the remaining 2%. And this design principle is not limited to cherry. The design of our merge algorithms is the same way, for example. -- 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] Add git-grep threads-num param
Please pay attention to your title. It no longer matches what the patch does. It may also be beneficial to study recent titles and log messages from other developers (you can find them in "git log --no-merges" and "git shortlog --no-merges") and learn and imitate their format, style and tone. We want our log to tell a story in a consistent voice, no matter who the authors of individual commits are. Victor Leschuk writes: > It's a follow up to "[PATCH] Add git-grep threads-num param": Do you think anybody wants to see this line in the output from "git log" six months from now? I doubt it. The previous one will not be committed to my tree anyway, so the readers would not know (nor care) what other patch you are talking about. > @@ -832,7 +836,7 @@ int cmd_grep(int argc, const char **argv, const char > *prefix) > } > > #ifndef NO_PTHREADS > - if (list.nr || cached || online_cpus() == 1) > + if (list.nr || cached || online_cpus() == 1 || opt.num_threads <= 1) > use_threads = 0; This avoid --threads=0 to take the threading codepath and spawning no threads, which would have happend in the previous patch. But it makes me wonder if the logic should be more like this: - Because the code is not prepared to go multi-thread when searching in the object data (not working tree), we always disable threading if 'list' is not empty or 'cached' is given; otherwise - If the user explicitly said that she wants N threads, we use that many threads; otherwise - If there is only one CPU, we do not do multi-thread; otherwise - We use the default number of threads. IOW, I'd suggest making opt.num_threads an "int" (not "unsigned"), initialize it to -1 (unspecified), and then make this part more like this, perhaps? if (!opt.num_threads) use_threads = 0; /* the user tells us not to use threads */ else if (list.nr || cached) use_threads = 0; /* cannot multi-thread object lookup */ else if (opt.num_threads >= 1) use_threads = 1; /* the user explicitly wants this many */ else if (online_cpus() <= 1) use_threads = 0; else { use_threads = 1; opt.num_threads = GREP_NUM_THREADS_DEFAULT; } Something like this code structure makes it very clear what needs to be changed when we want to add some sort of auto-scaling (instead of assigning the DEFAULT constant, you'd see how many cores you have, how many files you will be grepping in, etc. and come up with a good number dynamically). > @@ -150,6 +159,8 @@ void grep_init(struct grep_opt *opt, const char *prefix) > opt->pathname = def->pathname; > opt->regflags = def->regflags; > opt->relative = def->relative; > + if(!opt->num_threads) You forgot a required SP between a keyword for a syntactic construct and its open parenthesis. Thanks. -- 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 0/3] expose parallelism for submodule {update, clone}
On Fri, Oct 23, 2015 at 12:25 PM, Junio C Hamano wrote: > Stefan Beller writes: > >> submodule update: Expose parallelism to the user >> clone: Allow an explicit argument for parallel submodule clones > > downcase Expose and Allow, perhaps? Will do, thanks! > > > > I was looking at the previous one and I am getting the feeling that > everything up to "run-command: fix missing output from late callbacks" > is ready for 'next'. Am I being too optimistic and missing something > that may make you want to do another reroll? I would even argue for "submodule config: keep update strategy around" to be ready for next. ;) But as that is quite unrelated to the previous patches and only needed for the last patch, we can omit that safely too. All the fixes up to "run-command: fix missing output from late callbacks" sound good to me for next. I have run into a problem cloning big repositories though, but I haven't found the problem. So the whole parallel processing machine may need another bug fix later on. > > 37bc721 submodule.c: write "Fetching submodule " to stderr > 0904370 xread: poll on non blocking fds > fd6ed7c xread_nonblock: add functionality to read from fds without blocking > e7ba957 strbuf: add strbuf_read_once to read without blocking > 8fc3f2e sigchain: add command to pop all common signals > f57c806 run-command: add an asynchronous parallel child processor > 4733d9e fetch_populated_submodules: use new parallel job processing > dca8113 submodules: allow parallel fetching, add tests and documentation > 79f3857 run-command: fix early shutdown > 1c53754 run-command: clear leftover state from child_process structure > 63ce47e run-command: initialize the shutdown flag > c3a5d11 test-run-command: test for gracefully aborting > 74cc04d test-run-command: increase test coverage > 376d400 run-command: fix missing output from late callbacks -- 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 0/3] expose parallelism for submodule {update, clone}
Stefan Beller writes: > submodule update: Expose parallelism to the user > clone: Allow an explicit argument for parallel submodule clones downcase Expose and Allow, perhaps? I was looking at the previous one and I am getting the feeling that everything up to "run-command: fix missing output from late callbacks" is ready for 'next'. Am I being too optimistic and missing something that may make you want to do another reroll? 37bc721 submodule.c: write "Fetching submodule " to stderr 0904370 xread: poll on non blocking fds fd6ed7c xread_nonblock: add functionality to read from fds without blocking e7ba957 strbuf: add strbuf_read_once to read without blocking 8fc3f2e sigchain: add command to pop all common signals f57c806 run-command: add an asynchronous parallel child processor 4733d9e fetch_populated_submodules: use new parallel job processing dca8113 submodules: allow parallel fetching, add tests and documentation 79f3857 run-command: fix early shutdown 1c53754 run-command: clear leftover state from child_process structure 63ce47e run-command: initialize the shutdown flag c3a5d11 test-run-command: test for gracefully aborting 74cc04d test-run-command: increase test coverage 376d400 run-command: fix missing output from late callbacks -- 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 0/3] expose parallelism for submodule {update, clone}
This goes on top of origin/sb/submodule-parallel-fetch^ The first patch replaces the last patch of origin/sb/submodule-parallel-fetch using clearer names for the callback functions. The patches 2 and 3 introduce CLI options for {submodule update, clone} to instruct Git to be parallel for cloning submodule operations. Additionally `git submodule update` respects the config option "submodule.jobs". I also want to make "git fetch --recurse-submodules" and "git clone --recursive" respect the same "submodule.jobs" config option, but that code change would collide with origin/sb/submodule-config-parse, so I will put the patches on top of that. Stefan Beller (3): git submodule update: have a dedicated helper for cloning submodule update: Expose parallelism to the user clone: Allow an explicit argument for parallel submodule clones Documentation/git-clone.txt | 5 +- Documentation/git-submodule.txt | 6 +- builtin/clone.c | 23 ++-- builtin/submodule--helper.c | 234 git-submodule.sh| 54 -- t/t7400-submodule-basic.sh | 4 +- 6 files changed, 282 insertions(+), 44 deletions(-) -- 2.6.2.280.g74301d6 -- 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: Make "git checkout" automatically update submodules?
Stefan Beller writes: > Checkout [1]. There are lots of good patches, but hard to find. > (Including, but not limited to a recursive git checkout enhancement!) > ... > [1] https://github.com/jlehmann/git-submod-enhancements/wiki Yes, Jens is not just one of the people who have been working on harder, and thinking longer about, submodules than anybody else, but also has demonstrated that he has good taste and balanced view on the design of the subsystem over time, whose technical judgment we can trust. Not all the changes listed on the page may necessarily be good as-is (e.g. some may help only a subset of users while hurting others, like the "recursively check-out everything unconditionally" that trigerred this thread), but the page has a good collection to remind anybody, who designs a coherent whole, of issues that need to be taken into account. Thanks for a pointer to an excellent starting page. -- 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 3/3] clone: Allow an explicit argument for parallel submodule clones
Just pass it along to "git submodule update", which may pick reasonable defaults if you don't specify an explicit number. TODO: Add a test for this. Signed-off-by: Stefan Beller --- Documentation/git-clone.txt | 5 - builtin/clone.c | 23 +-- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt index f1f2a3f..affa52e 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -14,7 +14,7 @@ SYNOPSIS [-o ] [-b ] [-u ] [--reference ] [--dissociate] [--separate-git-dir ] [--depth ] [--[no-]single-branch] - [--recursive | --recurse-submodules] [--] + [--recursive | --recurse-submodules] [--jobs ] [--] [] DESCRIPTION @@ -216,6 +216,9 @@ objects from the source repository into a pack in the cloned repository. The result is Git repository can be separated from working tree. +-j:: +--jobs:: + The number of submodules fetched at the same time. :: The (possibly remote) repository to clone from. See the diff --git a/builtin/clone.c b/builtin/clone.c index 5864ad1..59ec984 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -50,6 +50,7 @@ static int option_progress = -1; static struct string_list option_config; static struct string_list option_reference; static int option_dissociate; +static int max_children; static struct option builtin_clone_options[] = { OPT__VERBOSITY(&option_verbosity), @@ -72,6 +73,8 @@ static struct option builtin_clone_options[] = { N_("initialize submodules in the clone")), OPT_BOOL(0, "recurse-submodules", &option_recursive, N_("initialize submodules in the clone")), + OPT_INTEGER('j', "jobs", &max_children, + N_("number of submodules cloned in parallel")), OPT_STRING(0, "template", &option_template, N_("template-directory"), N_("directory from which templates will be used")), OPT_STRING_LIST(0, "reference", &option_reference, N_("repo"), @@ -95,10 +98,6 @@ static struct option builtin_clone_options[] = { OPT_END() }; -static const char *argv_submodule[] = { - "submodule", "update", "--init", "--recursive", NULL -}; - static const char *get_repo_path_1(struct strbuf *path, int *is_bundle) { static char *suffix[] = { "/.git", "", ".git/.git", ".git" }; @@ -674,8 +673,20 @@ static int checkout(void) err |= run_hook_le(NULL, "post-checkout", sha1_to_hex(null_sha1), sha1_to_hex(sha1), "1", NULL); - if (!err && option_recursive) - err = run_command_v_opt(argv_submodule, RUN_GIT_CMD); + if (!err && option_recursive) { + struct argv_array args = ARGV_ARRAY_INIT; + argv_array_pushl(&args, "submodule", "update", "--init", "--recursive", NULL); + + if (max_children) { + struct strbuf sb = STRBUF_INIT; + strbuf_addf(&sb, "--jobs=%d", max_children); + argv_array_push(&args, sb.buf); + strbuf_release(&sb); + } + + err = run_command_v_opt(args.argv, RUN_GIT_CMD); + argv_array_clear(&args); + } return err; } -- 2.6.2.280.g74301d6 -- 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 1/3] git submodule update: have a dedicated helper for cloning
This introduces a new helper function in git submodule--helper which takes care of cloning all submodules, which we want to parallelize eventually. Some tests (such as empty URL, update_mode=none) are required in the helper to make the decision for cloning. These checks have been moved into the C function as well (no need to repeat them in the shell script). As we can only access the stderr channel from within the parallel processing engine, we need to reroute the error message for specified but initialized submodules to stderr. As it is an error message, this should have gone to stderr in the first place, so it is a bug fix along the way. Signed-off-by: Stefan Beller --- builtin/submodule--helper.c | 225 git-submodule.sh| 45 +++-- t/t7400-submodule-basic.sh | 4 +- 3 files changed, 238 insertions(+), 36 deletions(-) diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index f4c3eff..e6bce76 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -255,6 +255,230 @@ static int module_clone(int argc, const char **argv, const char *prefix) return 0; } +static int git_submodule_config(const char *var, const char *value, void *cb) +{ + return parse_submodule_config_option(var, value); +} + +struct submodule_update_clone { + int count; + int quiet; + int print_unmatched; + char *reference; + char *depth; + char *update; + const char *recursive_prefix; + const char *prefix; + struct module_list list; + struct string_list projectlines; + struct pathspec pathspec; +}; +#define SUBMODULE_UPDATE_CLONE_INIT {0, 0, 0, NULL, NULL, NULL, NULL, NULL, MODULE_LIST_INIT, STRING_LIST_INIT_DUP} + +static void fill_clone_command(struct child_process *cp, int quiet, + const char *prefix, const char *path, + const char *name, const char *url, + const char *reference, const char *depth) +{ + cp->git_cmd = 1; + cp->no_stdin = 1; + cp->stdout_to_stderr = 1; + cp->err = -1; + argv_array_push(&cp->args, "submodule--helper"); + argv_array_push(&cp->args, "clone"); + if (quiet) + argv_array_push(&cp->args, "--quiet"); + + if (prefix) { + argv_array_push(&cp->args, "--prefix"); + argv_array_push(&cp->args, prefix); + } + argv_array_push(&cp->args, "--path"); + argv_array_push(&cp->args, path); + + argv_array_push(&cp->args, "--name"); + argv_array_push(&cp->args, name); + + argv_array_push(&cp->args, "--url"); + argv_array_push(&cp->args, url); + if (reference) + argv_array_push(&cp->args, reference); + if (depth) + argv_array_push(&cp->args, depth); +} + +static int update_clone_get_next_task(void **pp_task_cb, + struct child_process *cp, + struct strbuf *err, + void *pp_cb) +{ + struct submodule_update_clone *pp = pp_cb; + + for (; pp->count < pp->list.nr; pp->count++) { + const struct submodule *sub = NULL; + const char *displaypath = NULL; + const struct cache_entry *ce = pp->list.entries[pp->count]; + struct strbuf sb = STRBUF_INIT; + const char *update_module = NULL; + const char *url = NULL; + int just_cloned = 0; + + if (ce_stage(ce)) { + if (pp->recursive_prefix) + strbuf_addf(err, "Skipping unmerged submodule %s/%s\n", + pp->recursive_prefix, ce->name); + else + strbuf_addf(err, "Skipping unmerged submodule %s\n", + ce->name); + continue; + } + + sub = submodule_from_path(null_sha1, ce->name); + if (pp->recursive_prefix) + displaypath = relative_path(pp->recursive_prefix, ce->name, &sb); + else + displaypath = ce->name; + + if (pp->update) + update_module = pp->update; + if (!update_module) + update_module = sub->update; + if (!update_module) + update_module = "checkout"; + if (!strcmp(update_module, "none")) { + strbuf_addf(err, "Skipping submodule '%s'\n", displaypath); + continue; + } + + /* +* Looking up the url in .git/config. +* We cannot fall back to .gitmodules as we only want to process +* configured submo
[PATCH 2/3] submodule update: Expose parallelism to the user
Expose possible parallelism either via the "--jobs" CLI parameter or the "submodule.jobs" setting. By having the variable initialized to -1, we make sure 0 can be passed into the parallel processing machine, which will then pick as many parallel workers as there are CPUs. Signed-off-by: Stefan Beller --- Documentation/git-submodule.txt | 6 +- builtin/submodule--helper.c | 17 + git-submodule.sh| 9 + 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt index f17687e..f5429fa 100644 --- a/Documentation/git-submodule.txt +++ b/Documentation/git-submodule.txt @@ -16,7 +16,7 @@ SYNOPSIS 'git submodule' [--quiet] deinit [-f|--force] [--] ... 'git submodule' [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--rebase|--merge] [--reference ] - [--depth ] [--recursive] [--] [...] + [--depth ] [--recursive] [--jobs ] [--] [...] 'git submodule' [--quiet] summary [--cached|--files] [(-n|--summary-limit) ] [commit] [--] [...] 'git submodule' [--quiet] foreach [--recursive] @@ -374,6 +374,10 @@ for linkgit:git-clone[1]'s `--reference` and `--shared` options carefully. clone with a history truncated to the specified number of revisions. See linkgit:git-clone[1] +-j:: +--jobs:: + This option is only valid for the update command. + Clone new submodules in parallel with as many jobs. ...:: Paths to submodule(s). When specified this will restrict the command diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index e6bce76..4888e84 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -422,6 +422,7 @@ static int update_clone_task_finished(int result, static int update_clone(int argc, const char **argv, const char *prefix) { + int max_jobs = -1; struct string_list_item *item; struct submodule_update_clone pp = SUBMODULE_UPDATE_CLONE_INIT; @@ -442,6 +443,8 @@ static int update_clone(int argc, const char **argv, const char *prefix) OPT_STRING(0, "depth", &pp.depth, "", N_("Create a shallow clone truncated to the " "specified number of revisions")), + OPT_INTEGER('j', "jobs", &max_jobs, + N_("parallel jobs")), OPT__QUIET(&pp.quiet, N_("do't print cloning progress")), OPT_END() }; @@ -463,10 +466,16 @@ static int update_clone(int argc, const char **argv, const char *prefix) gitmodules_config(); /* Overlay the parsed .gitmodules file with .git/config */ git_config(git_submodule_config, NULL); - run_processes_parallel(1, update_clone_get_next_task, - update_clone_start_failure, - update_clone_task_finished, - &pp); + + if (max_jobs == -1) + if (git_config_get_int("submodule.jobs", &max_jobs)) + max_jobs = 1; + + run_processes_parallel(max_jobs, + update_clone_get_next_task, + update_clone_start_failure, + update_clone_task_finished, + &pp); if (pp.print_unmatched) { printf("#unmatched\n"); diff --git a/git-submodule.sh b/git-submodule.sh index ea883b9..c2dfb16 100755 --- a/git-submodule.sh +++ b/git-submodule.sh @@ -636,6 +636,14 @@ cmd_update() --depth=*) depth=$1 ;; + -j|--jobs) + case "$2" in '') usage ;; esac + jobs="--jobs=$2" + shift + ;; + --jobs=*) + jobs=$1 + ;; --) shift break @@ -661,6 +669,7 @@ cmd_update() ${update:+--update "$update"} \ ${reference:+--reference "$reference"} \ ${depth:+--depth "$depth"} \ + ${jobs:+$jobs} \ "$@" | { err= while read mode sha1 stage just_cloned sm_path -- 2.6.2.280.g74301d6 -- 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: Make "git checkout" automatically update submodules?
On Thu, Oct 15, 2015 at 3:50 PM, Kannan Goundan wrote: > Git submodules seem to be a great fit for one of our repos. The biggest > pain point is that it's too easy to forget to update submodules. > > 1. I often forget since most repos don't need it. > 2. Infrequent users of our repo almost never know to update submodules and > end up coming to us with strange build errors. > 3. Existing scripts that work with Git repos are usually not built to handle > submodules. > > In the common case of the submodule content having no local edits, it would > be nice if "git checkout" automatically updated submodules [1]. If there > are local edits, it could error out (maybe override with > "--ignore-modified-submodules" or something). > > I'm not a Git expert, though. Is there a reason something like this isn't > already implemented? Maybe there's an existing write-up or mailing list > thread I can read to get some background information? > > Thanks! > > [1] Our post-checkout procedure is: > > git submodule sync > git submodule update --init > git submodule foreach --recursive \ > 'git submodule sync ; git submodule update --init' > > (Not sure if this is correct. Different articles/blogs suggest a slightly > different set of commands.) > Checkout [1]. There are lots of good patches, but hard to find. (Including, but not limited to a recursive git checkout enhancement!) That said I've recently started working on submodules, too. I am trying to push my work upstream as fast as possible as that works best for us. [1] https://github.com/jlehmann/git-submod-enhancements/wiki -- 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/2 jk/war-on-sprintf] read_branches_file: plug a FILE* leak
Johannes Sixt writes: > The earlier rewrite f28e3ab2 (read_branches_file: simplify string handling) > of read_branches_file() lost an fclose() call. Put it back. > > As on Windows files that are open cannot be removed, the leak manifests in > a failure of 'git remote rename origin origin' when the remote's URL is > specified in .git/branches/origin, because by the time that the command > attempts to remove this file, it is still open. > > Signed-off-by: Johannes Sixt > --- Thanks (and also for 2/2). > remote.c | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/remote.c b/remote.c > index 1101f82..fb16153 100644 > --- a/remote.c > +++ b/remote.c > @@ -282,6 +282,7 @@ static void read_branches_file(struct remote *remote) > return; > > strbuf_getline(&buf, f, '\n'); > + fclose(f); > strbuf_trim(&buf); > if (!buf.len) { > strbuf_release(&buf); -- 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: Make "git checkout" automatically update submodules?
Kannan Goundan writes: > I think the way I described it ("sponsoring a feature") doesn't really > reflect how I was imagining it. In my head, it looked like this: > ... > I could try doing that myself, but someone familiar with the Git > codebase/community/history would be better at it (and probably be easier for > you guys to work with :-) > > I guess I'm just wondering if there are people who meet those qualifications > and are interested in going through those steps for pay. Or maybe there's a > company that does this, like the old Cygnus Solutions? > > In particular, I don't expect anything to change about the project's > development process. In other words, the sponsoring entity is paying for effort and not for result--money does not buy inclusion. That may be workable from the project's point of view; I however wonder if that is workable from the sponsor's point of view. Things that may be problematic inside the sponsoring entity (i.e. between those with money and those who interact with the hired person) include: - Does the hired person really meet the right qualifications? - Did the hired person make a good faith effort? - Was it the right time to start the topic, or was the codebase too much in flux at the moment to accept work in that area? But these are problems between the sponsor and the hired person and do not concern us ;-) -- 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/5] gc: remove unused #include "sigchain.h"
Tobias Klauser writes: > On 2015-10-22 at 22:14:29 +0200, Junio C Hamano wrote: >> Tobias Klauser writes: >> >> > After switching to use the tempfile module in commit ebebeaea (gc: use >> > tempfile module to handle gc.pid file), no declarations from sigchain.h >> > are used in builtin/gc.c anymore. Thus, remove the #include. >> > >> > Signed-off-by: Tobias Klauser >> > --- >> >> I'll drop this one as we seem to have gained another user of the API >> in this file in the nd/gc-auto-background-fix topic. > > Opps, sorry I didn't check against 'pu' carefully enough. Thanks for > catching it. Heh, that topic has been in master since Oct 15, I think. -- 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: ancestor and descendant ~ clarification needed
Xue Fuqiao writes: > Hi Junio, > > On Fri, Oct 23, 2015 at 4:22 AM, Junio C Hamano wrote: > >> Yeah, that is the other way around. >> >> (1) If the current branch is a descendant of the other--so every >> commit present in the other branch is already contained in the >> current branch--then merging the other branch into the current >> branch is a no-op "Already up-to-date!". >> >> (2) If the current branch is an ancestor of the other--so every >> commit present in the current branch is already contained in >> the other branch--then merging the other branch into the >> current branch can be fast-forwarded, by moving the tip of the >> current branch to point at the commit at the tip of the other >> branch, and by default Git does so, instead of creating an >> unnecessary merge. > > I see. Thank you. What do you think about the following minor patch > for user-manual.txt? While the updated text is more correct than the original, I do not know if that is sufficient, or we would also want to mention the "Already up-to-date!" case here while at it. > -However, if the current branch is a descendant of the other--so every > -commit present in the one is already contained in the other--then Git > -just performs a "fast-forward"; the head of the current branch is moved > -forward to point at the head of the merged-in branch, without any new > -commits being created. > +However, if the current branch is an ancestor of the other--so every commit > +present in the current branch is already contained in the other > branch--then Git > +just performs a "fast-forward"; the head of the current branch is moved > forward > +to point at the head of the merged-in branch, without any new commits being > +created. -- 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: Question about about a trivial merge conflict that git should resolve alone
Hi Francis, On Fri, 23 Oct 2015, Francis Moreau wrote: > I have a simple merge conflict use case: > > $ mkdir foo > $ cd foo/ > $ git init > $ echo line1 > a > $ git add . > $ git commit -q -m init > $ echo line2 >>a > $ git commit -a -q -m "add line2" > $ git checkout -b foo HEAD~1 > $ git cherry-pick -x master > $ echo line3 >>a > $ git stage a > $ git commit -q -m "add line3" > $ git checkout master > $ git merge foo > $ git diff > diff --cc a > index c0d0fb4,83db48f..000 > --- a/a > +++ b/a > @@@ -1,2 -1,3 +1,6 @@@ > line1 > line2 > ++<<< HEAD > ++=== > + line3 > ++>>> foo > > Why does git think there's a conflict here since the "line2" string > was added in both branch by the same commit ? This is intentional, because what actually happens is that Git figures out that line2 & line3 were added in one branch, but only line2 in the other, and it helpfully reduces the conflict to the difference between the two. The rationale is that you do not know which version is correct: was line2 sufficient, or do you really also need line3? Ciao, Johannes -- 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: Bug: gitk crashes for single file with German environment
On Fri, 23 Oct 2015 15:32:10 +0200 Jörg Bühmann wrote: > gitk crashes for single file with German environment [...] http://thread.gmane.org/gmane.comp.version-control.git/279910 -- 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
Bug: gitk crashes for single file with German environment
gitk crashes for single file with German environment Git 2.6.2 Installed with homebrew Platform Apple OS X 10.10.5 shell: zsh 5.0.5 (x86_64-apple-darwin14.0) environment: LANG=de_DE.UTF-8 gitk is very useful to show the commit history of one file. However it crashes on me. gitk myfile produces the following error: Error in startup script: bad menu entry index "Ansicht bearbeiten ..." while executing ".bar.view entryconf [mca "Edit view..."] -state normal" invoked from within "if {$cmdline_files ne {} || $revtreeargs ne {} || $revtreeargscmd ne {}} { # create a view for the files/dirs specified on the command line se..." (file "/usr/local/bin/gitk" line 12442) It seems the problem has to do with the start script trying to get the localized menu item of "Edit view..." in German "Ansicht bearbeiten ..." and that fails. When I change the language in my environment export LANG=en_US.UTF-8 everything works as expected. If I start gitk without any arguments and German environment (LANG=de_DE.UTF-8), it starts up fine. However the German localization is missing from the menubar, it's completely in English. Buttons and labels inside the window are localized into German properly. See screenshot http://i.imgur.com/VZZljPb.png It's apparent then, that the script does not get a menu entry that corresponds to the localized string. Thank you Jörg Bühmann -- 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
Question about about a trivial merge conflict that git should resolve alone
Hi, I have a simple merge conflict use case: $ mkdir foo $ cd foo/ $ git init $ echo line1 > a $ git add . $ git commit -q -m init $ echo line2 >>a $ git commit -a -q -m "add line2" $ git checkout -b foo HEAD~1 $ git cherry-pick -x master $ echo line3 >>a $ git stage a $ git commit -q -m "add line3" $ git checkout master $ git merge foo $ git diff diff --cc a index c0d0fb4,83db48f..000 --- a/a +++ b/a @@@ -1,2 -1,3 +1,6 @@@ line1 line2 ++<<< HEAD ++=== + line3 ++>>> foo Why does git think there's a conflict here since the "line2" string was added in both branch by the same commit ? Thanks. -- Francis -- 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-cherry doesn't detect a "copied" commit
On Fri, Oct 23, 2015 at 12:57 PM, Kevin Daudt wrote: > On Tue, Oct 20, 2015 at 06:32:12PM +0200, Francis Moreau wrote: >> Hi, >> >> I'm seeing something odd with git-cherry: it doesn't seem to detect >> that a commit has been cherry-picked from master branch. >> >> This happens with the systemd git repository (from github) so it >> should be fairly simple to reproduce. >> >> What I did: >> >> $ git --version >> git version 2.6.0 >> $ git checkout -b foo v210 >> $ git cherry-pick -x 9ea28c55a2488e6cd4a44ac5786f12b71ad5bc9f >> $ git branch --contains 9ea28c55a2488e6cd4a44ac5786f12b71ad5bc9f >> master >> $ git cherry master HEAD >> + fef60bf34d1b372bea1db2515a8d936386dfc523 >> >> so git-cherry tells me that the cherry-picked commit has not >> equivalent in master, which is no the case. >> >> What am I missing ? >> > > Let's see: > > $ git show | git patch-id > 50c9f9548e1fd25401ff9540c82c1d5f9723c3d5 > b4c86d2965aaf0736e4ab30be1d1a08931009a08 > > $ git show 9ea28c55a2488e6cd4a44ac5786f12b71ad5bc9f | git patch-id > a5cfbb542882bd9cbe192b43026354d1f2741673 > 9ea28c55a2488e6cd4a44ac5786f12b71ad5bc9f > > Git patch-id calculates the hash over the diff, and, when gives in this > case two hashes, first the patch-id and the second the commit hash. > > The patch-ids are different, explaining why git cherry does not see them > as equivalent. If I take a diff of the diff, I notice something: > >diff --git a/src/udev/udevadm-settle.c b/src/udev/udevadm-settle.c > -index 927ea2a..65fc35f 100644 > +index b026155..ea9b078 100644 >--- a/src/udev/udevadm-settle.c >+++ b/src/udev/udevadm-settle.c >@@ -41,42 +41,28 @@ > @@ -1094,7 +1094,7 @@ > exit(EXIT_SUCCESS); >@@ -102,44 +85,13 @@ static int adm_settle(struct udev *udev, int argc, > char *argv[]) > default: > - assert_not_reached("Unknown argument"); > + assert_not_reached("Unkown argument"); > } >+} > > If you look at the lines with assert_not_reached, it seems there is a > difference in the context of both diffs, causing the diffs to be > different. > > Hope this helps, Kevin Thanks Kevin I was mislead by the git-cherry manpage somehow which says: "git-cherry therefore detects when commits have been "copied" by means of git-cherry-pick(1), which is not exactly true. Isn't there a way to get git-cherry less "strict" ? I mean in this case most of 90% of the diff is the same, only one line of context is not identical... Would it make sense to add a "--fuzz" option which would reduce the diff context area used to generate the hash ? Thanks. -- Francis -- 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 2/2 jk/war-on-sprintf] compat/mingw.c: remove printf format warning
On Fri, Oct 23, 2015 at 08:02:52AM +0200, Johannes Sixt wrote: > 5096d490 (convert trivial sprintf / strcpy calls to xsnprintf) converted > two sprintf calls. Now GCC warns that "format '%u' expects argument of > type 'unsigned int', but argument 4 has type 'long unsigned int'". > Instead of changing the format string, use a variable of type unsigned > in place of the typedef-ed type DWORD, which hides that it is actually an > unsigned long. > > There is no correctness issue with the old code because unsigned long and > unsigned are always of the same size on Windows, even in 64-bit builds. > > Signed-off-by: Johannes Sixt > --- > I do not know why there are no warnings with the old code. Apparently, the > system provided sprintf declaration does not have format-printf > annotation. Makes sense, and the patch looks obviously correct. -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/2 jk/war-on-sprintf] read_branches_file: plug a FILE* leak
On Fri, Oct 23, 2015 at 08:02:51AM +0200, Johannes Sixt wrote: > The earlier rewrite f28e3ab2 (read_branches_file: simplify string handling) > of read_branches_file() lost an fclose() call. Put it back. > > As on Windows files that are open cannot be removed, the leak manifests in > a failure of 'git remote rename origin origin' when the remote's URL is > specified in .git/branches/origin, because by the time that the command > attempts to remove this file, it is still open. Thanks for catching. This was due to my last-minute rewrite of strbuf_read_file into fopen/strbuf_getline. Your patch 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: git-cherry doesn't detect a "copied" commit
On Tue, Oct 20, 2015 at 06:32:12PM +0200, Francis Moreau wrote: > Hi, > > I'm seeing something odd with git-cherry: it doesn't seem to detect > that a commit has been cherry-picked from master branch. > > This happens with the systemd git repository (from github) so it > should be fairly simple to reproduce. > > What I did: > > $ git --version > git version 2.6.0 > $ git checkout -b foo v210 > $ git cherry-pick -x 9ea28c55a2488e6cd4a44ac5786f12b71ad5bc9f > $ git branch --contains 9ea28c55a2488e6cd4a44ac5786f12b71ad5bc9f > master > $ git cherry master HEAD > + fef60bf34d1b372bea1db2515a8d936386dfc523 > > so git-cherry tells me that the cherry-picked commit has not > equivalent in master, which is no the case. > > What am I missing ? > Let's see: $ git show | git patch-id 50c9f9548e1fd25401ff9540c82c1d5f9723c3d5 b4c86d2965aaf0736e4ab30be1d1a08931009a08 $ git show 9ea28c55a2488e6cd4a44ac5786f12b71ad5bc9f | git patch-id a5cfbb542882bd9cbe192b43026354d1f2741673 9ea28c55a2488e6cd4a44ac5786f12b71ad5bc9f Git patch-id calculates the hash over the diff, and, when gives in this case two hashes, first the patch-id and the second the commit hash. The patch-ids are different, explaining why git cherry does not see them as equivalent. If I take a diff of the diff, I notice something: diff --git a/src/udev/udevadm-settle.c b/src/udev/udevadm-settle.c -index 927ea2a..65fc35f 100644 +index b026155..ea9b078 100644 --- a/src/udev/udevadm-settle.c +++ b/src/udev/udevadm-settle.c @@ -41,42 +41,28 @@ @@ -1094,7 +1094,7 @@ exit(EXIT_SUCCESS); @@ -102,44 +85,13 @@ static int adm_settle(struct udev *udev, int argc, char *argv[]) default: - assert_not_reached("Unknown argument"); + assert_not_reached("Unkown argument"); } +} If you look at the lines with assert_not_reached, it seems there is a difference in the context of both diffs, causing the diffs to be different. Hope this helps, Kevin -- 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] Add git-grep threads-num param
It's a follow up to "[PATCH] Add git-grep threads-num param": Make number of git-grep worker threads a configuration parameter. I have run several tests on systems with different number of CPU cores. It appeared that the hard-coded number 8 lowers performance on both of my systems: on my 4-core and 8-core systems the thread number of 4 worked about 20% faster than default 8. So I think it is better to allow users tune this parameter. Signed-off-by: Victor Leschuk --- Documentation/config.txt | 4 Documentation/git-grep.txt | 4 builtin/grep.c | 20 contrib/completion/git-completion.bash | 1 + grep.c | 11 +++ grep.h | 2 ++ 6 files changed, 34 insertions(+), 8 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 391a0c3..1c95587 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -1447,6 +1447,10 @@ grep.extendedRegexp:: option is ignored when the 'grep.patternType' option is set to a value other than 'default'. +grep.threads:: + Number of grep worker threads, use it to tune up performance on + multicore machines. Default value is 8. + gpg.program:: Use this custom program instead of "gpg" found on $PATH when making or verifying a PGP signature. The program must support the diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt index 4a44d6d..fbd4f83 100644 --- a/Documentation/git-grep.txt +++ b/Documentation/git-grep.txt @@ -22,6 +22,7 @@ SYNOPSIS [--color[=] | --no-color] [--break] [--heading] [-p | --show-function] [-A ] [-B ] [-C ] + [--threads ] [-W | --function-context] [-f ] [-e] [--and|--or|--not|(|)|-e ...] @@ -220,6 +221,9 @@ OPTIONS Show leading lines, and place a line containing `--` between contiguous groups of matches. +--threads :: + Set number of worker threads to . Default is 8. + -W:: --function-context:: Show the surrounding text from the previous line containing a diff --git a/builtin/grep.c b/builtin/grep.c index d04f440..3950725 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -27,8 +27,7 @@ static char const * const grep_usage[] = { static int use_threads = 1; #ifndef NO_PTHREADS -#define THREADS 8 -static pthread_t threads[THREADS]; +static pthread_t *threads; /* We use one producer thread and THREADS consumer * threads. The producer adds struct work_items to 'todo' and the @@ -206,7 +205,8 @@ static void start_threads(struct grep_opt *opt) strbuf_init(&todo[i].out, 0); } - for (i = 0; i < ARRAY_SIZE(threads); i++) { + threads = xcalloc(opt->num_threads, sizeof(pthread_t)); + for (i = 0; i < opt->num_threads; i++) { int err; struct grep_opt *o = grep_opt_dup(opt); o->output = strbuf_out; @@ -220,7 +220,7 @@ static void start_threads(struct grep_opt *opt) } } -static int wait_all(void) +static int wait_all(struct grep_opt *opt) { int hit = 0; int i; @@ -238,12 +238,14 @@ static int wait_all(void) pthread_cond_broadcast(&cond_add); grep_unlock(); - for (i = 0; i < ARRAY_SIZE(threads); i++) { + for (i = 0; i < opt->num_threads; i++) { void *h; pthread_join(threads[i], &h); hit |= (int) (intptr_t) h; } + free(threads); + pthread_mutex_destroy(&grep_mutex); pthread_mutex_destroy(&grep_read_mutex); pthread_mutex_destroy(&grep_attr_mutex); @@ -256,7 +258,7 @@ static int wait_all(void) } #else /* !NO_PTHREADS */ -static int wait_all(void) +static int wait_all(struct grep_opt *opt) { return 0; } @@ -702,6 +704,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix) N_("show context lines before matches")), OPT_INTEGER('A', "after-context", &opt.post_context, N_("show context lines after matches")), + OPT_INTEGER(0, "threads", &opt.num_threads, + N_("use worker threads")), OPT_NUMBER_CALLBACK(&opt, N_("shortcut for -C NUM"), context_callback), OPT_BOOL('p', "show-function", &opt.funcname, @@ -832,7 +836,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix) } #ifndef NO_PTHREADS - if (list.nr || cached || online_cpus() == 1) + if (list.nr || cached || online_cpus() == 1 || opt.num_threads <= 1) use_threads = 0; #else use_threads = 0; @@ -910,7 +914,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix) } if (use_threads) - hit |= wait_all(); + hit |= wait_all(&opt);
Re: ancestor and descendant ~ clarification needed
Hi Junio, On Fri, Oct 23, 2015 at 4:22 AM, Junio C Hamano wrote: > Yeah, that is the other way around. > > (1) If the current branch is a descendant of the other--so every > commit present in the other branch is already contained in the > current branch--then merging the other branch into the current > branch is a no-op "Already up-to-date!". > > (2) If the current branch is an ancestor of the other--so every > commit present in the current branch is already contained in > the other branch--then merging the other branch into the > current branch can be fast-forwarded, by moving the tip of the > current branch to point at the commit at the tip of the other > branch, and by default Git does so, instead of creating an > unnecessary merge. I see. Thank you. What do you think about the following minor patch for user-manual.txt? I can send a more formal one using format-patch and send-email if needed. diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index 1b7987e..d68df13 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -1431,11 +1431,11 @@ differently. Normally, a merge results in a merge commit, with two parents, one pointing at each of the two lines of development that were merged. -However, if the current branch is a descendant of the other--so every -commit present in the one is already contained in the other--then Git -just performs a "fast-forward"; the head of the current branch is moved -forward to point at the head of the merged-in branch, without any new -commits being created. +However, if the current branch is an ancestor of the other--so every commit +present in the current branch is already contained in the other branch--then Git +just performs a "fast-forward"; the head of the current branch is moved forward +to point at the head of the merged-in branch, without any new commits being +created. [[fixing-mistakes]] Fixing mistakes -- 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/5] gc: remove unused #include "sigchain.h"
On 2015-10-22 at 22:14:29 +0200, Junio C Hamano wrote: > Tobias Klauser writes: > > > After switching to use the tempfile module in commit ebebeaea (gc: use > > tempfile module to handle gc.pid file), no declarations from sigchain.h > > are used in builtin/gc.c anymore. Thus, remove the #include. > > > > Signed-off-by: Tobias Klauser > > --- > > I'll drop this one as we seem to have gained another user of the API > in this file in the nd/gc-auto-background-fix topic. Opps, sorry I didn't check against 'pu' carefully enough. Thanks for catching it. -- 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