diff options
60 files changed, 2092 insertions, 790 deletions
diff --git a/.gitignore b/.gitignore index b670877510..4c8c8e4115 100644 --- a/.gitignore +++ b/.gitignore @@ -75,6 +75,7 @@ git-name-rev git-mv git-pack-redundant git-pack-objects +git-pack-refs git-parse-remote git-patch-id git-peek-remote @@ -106,6 +107,7 @@ git-shortlog git-show git-show-branch git-show-index +git-show-ref git-ssh-fetch git-ssh-pull git-ssh-push diff --git a/Documentation/config.txt b/Documentation/config.txt index 026d4cf9ad..d9e73da2a7 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -71,12 +71,16 @@ core.preferSymlinkRefs:: expect HEAD to be a symbolic link. core.logAllRefUpdates:: - If true, `git-update-ref` will append a line to - "$GIT_DIR/logs/<ref>" listing the new SHA1 and the date/time - of the update. If the file does not exist it will be - created automatically. This information can be used to - determine what commit was the tip of a branch "2 days ago". - This value is false by default (no logging). + Updates to a ref <ref> is logged to the file + "$GIT_DIR/logs/<ref>", by appending the new and old + SHA1, the date/time and the reason of the update, but + only when the file exists. If this configuration + variable is set to true, missing "$GIT_DIR/logs/<ref>" + file is automatically created for branch heads. + + This information can be used to determine what commit + was the tip of a branch "2 days ago". This value is + false by default (no automated creation of log files). core.repositoryFormatVersion:: Internal variable identifying the repository format and layout diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt index f973c64313..86060472ad 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -75,6 +75,7 @@ OPTIONS this option is used, neither the `origin` branch nor the default `remotes/origin` file is created. +--origin <name>:: -o <name>:: Instead of using the branch name 'origin' to keep track of the upstream repository, use <name> instead. Note diff --git a/Documentation/git-diff-index.txt b/Documentation/git-diff-index.txt index 9cd43f105b..2df581c2c9 100644 --- a/Documentation/git-diff-index.txt +++ b/Documentation/git-diff-index.txt @@ -54,7 +54,7 @@ If '--cached' is specified, it allows you to ask: For example, let's say that you have worked on your working directory, updated some files in the index and are ready to commit. You want to see exactly -*what* you are going to commit is without having to write a new tree +*what* you are going to commit, without having to write a new tree object and compare it that way, and to do that, you just do git-diff-index --cached HEAD @@ -68,7 +68,7 @@ matches my working directory. But doing a "git-diff-index" does: -100644 blob 4161aecc6700a2eb579e842af0b7f22b98443f74 commit.c +100644 blob 4161aecc6700a2eb579e842af0b7f22b98443f74 git-commit.c -You can trivially see that the above is a rename. +You can see easily that the above is a rename. In fact, "git-diff-index --cached" *should* always be entirely equivalent to actually doing a "git-write-tree" and comparing that. Except this one is much diff --git a/Documentation/git-pack-objects.txt b/Documentation/git-pack-objects.txt index a1e55054bd..9bd1e39feb 100644 --- a/Documentation/git-pack-objects.txt +++ b/Documentation/git-pack-objects.txt @@ -47,9 +47,8 @@ base-name:: <base-name> to determine the name of the created file. When this option is used, the two files are written in <base-name>-<SHA1>.{pack,idx} files. <SHA1> is a hash - of object names (currently in random order so it does - not have any useful meaning) to make the resulting - filename reasonably unique, and written to the standard + of the sorted object names to make the resulting filename + based on the pack content, and written to the standard output of the command. --stdout:: diff --git a/Documentation/git-repo-config.txt b/Documentation/git-repo-config.txt index 8a1ab61e94..8199615dde 100644 --- a/Documentation/git-repo-config.txt +++ b/Documentation/git-repo-config.txt @@ -3,19 +3,19 @@ git-repo-config(1) NAME ---- -git-repo-config - Get and set options in .git/config +git-repo-config - Get and set repository or global options. SYNOPSIS -------- [verse] -'git-repo-config' [type] name [value [value_regex]] -'git-repo-config' [type] --replace-all name [value [value_regex]] -'git-repo-config' [type] --get name [value_regex] -'git-repo-config' [type] --get-all name [value_regex] -'git-repo-config' [type] --unset name [value_regex] -'git-repo-config' [type] --unset-all name [value_regex] -'git-repo-config' -l | --list +'git-repo-config' [--global] [type] name [value [value_regex]] +'git-repo-config' [--global] [type] --replace-all name [value [value_regex]] +'git-repo-config' [--global] [type] --get name [value_regex] +'git-repo-config' [--global] [type] --get-all name [value_regex] +'git-repo-config' [--global] [type] --unset name [value_regex] +'git-repo-config' [--global] [type] --unset-all name [value_regex] +'git-repo-config' [--global] -l | --list DESCRIPTION ----------- @@ -41,8 +41,9 @@ This command will fail if: . Can not write to .git/config, . no section was provided, . the section or key is invalid, -. you try to unset an option which does not exist, or -. you try to unset/set an option for which multiple lines match. +. you try to unset an option which does not exist, +. you try to unset/set an option for which multiple lines match, or +. you use --global option without $HOME being properly set. OPTIONS @@ -64,14 +65,17 @@ OPTIONS --get-regexp:: Like --get-all, but interprets the name as a regular expression. +--global:: + Use global ~/.gitconfig file rather than the repository .git/config. + --unset:: - Remove the line matching the key from .git/config. + Remove the line matching the key from config file. --unset-all:: - Remove all matching lines from .git/config. + Remove all matching lines from config file. -l, --list:: - List all variables set in .git/config. + List all variables set in config file. ENVIRONMENT @@ -79,6 +83,7 @@ ENVIRONMENT GIT_CONFIG:: Take the configuration from the given file instead of .git/config. + Using the "--global" option forces this to ~/.gitconfig. GIT_CONFIG_LOCAL:: Currently the same as $GIT_CONFIG; when Git will support global diff --git a/Documentation/git-show-ref.txt b/Documentation/git-show-ref.txt new file mode 100644 index 0000000000..5973a82517 --- /dev/null +++ b/Documentation/git-show-ref.txt @@ -0,0 +1,156 @@ +git-show-ref(1) +=============== + +NAME +---- +git-show-ref - List references in a local repository + +SYNOPSIS +-------- +[verse] +'git-show-ref' [-q|--quiet] [--verify] [-h|--head] [-d|--dereference] + [-s|--hash] [--abbrev] [--tags] [--heads] [--] <pattern>... + +DESCRIPTION +----------- + +Displays references available in a local repository along with the associated +commit IDs. Results can be filtered using a pattern and tags can be +dereferenced into object IDs. Additionally, it can be used to test whether a +particular ref exists. + +Use of this utility is encouraged in favor of directly accessing files under +in the `.git` directory. + +OPTIONS +------- + +-h, --head:: + + Show the HEAD reference. + +--tags, --heads:: + + Limit to only "refs/heads" and "refs/tags", respectively. These + options are not mutually exclusive; when given both, references stored + in "refs/heads" and "refs/tags" are displayed. + +-d, --dereference:: + + Dereference tags into object IDs as well. They will be shown with "^{}" + appended. + +-s, --hash:: + + Only show the SHA1 hash, not the reference name. When also using + --dereference the dereferenced tag will still be shown after the SHA1. + +--verify:: + + Enable stricter reference checking by requiring an exact ref path. + Aside from returning an error code of 1, it will also print an error + message if '--quiet' was not specified. + +--abbrev, --abbrev=len:: + + Abbreviate the object name. When using `--hash`, you do + not have to say `--hash --abbrev`; `--hash=len` would do. + +-q, --quiet:: + + Do not print any results to stdout. When combined with '--verify' this + can be used to silently check if a reference exists. + +<pattern>:: + + Show references matching one or more patterns. + +OUTPUT +------ + +The output is in the format: '<SHA-1 ID>' '<space>' '<reference name>'. + +----------------------------------------------------------------------------- +$ git show-ref --head --dereference +832e76a9899f560a90ffd62ae2ce83bbeff58f54 HEAD +832e76a9899f560a90ffd62ae2ce83bbeff58f54 refs/heads/master +832e76a9899f560a90ffd62ae2ce83bbeff58f54 refs/heads/origin +3521017556c5de4159da4615a39fa4d5d2c279b5 refs/tags/v0.99.9c +6ddc0964034342519a87fe013781abf31c6db6ad refs/tags/v0.99.9c^{} +055e4ae3ae6eb344cbabf2a5256a49ea66040131 refs/tags/v1.0rc4 +423325a2d24638ddcc82ce47be5e40be550f4507 refs/tags/v1.0rc4^{} +... +----------------------------------------------------------------------------- + +When using --hash (and not --dereference) the output format is: '<SHA-1 ID>' + +----------------------------------------------------------------------------- +$ git show-ref --heads --hash +2e3ba0114a1f52b47df29743d6915d056be13278 +185008ae97960c8d551adcd9e23565194651b5d1 +03adf42c988195b50e1a1935ba5fcbc39b2b029b +... +----------------------------------------------------------------------------- + +EXAMPLE +------- + +To show all references called "master", whether tags or heads or anything +else, and regardless of how deep in the reference naming hierarchy they are, +use: + +----------------------------------------------------------------------------- + git show-ref master +----------------------------------------------------------------------------- + +This will show "refs/heads/master" but also "refs/remote/other-repo/master", +if such references exists. + +When using the '--verify' flag, the command requires an exact path: + +----------------------------------------------------------------------------- + git show-ref --verify refs/heads/master +----------------------------------------------------------------------------- + +will only match the exact branch called "master". + +If nothing matches, gitlink:git-show-ref[1] will return an error code of 1, +and in the case of verification, it will show an error message. + +For scripting, you can ask it to be quiet with the "--quiet" flag, which +allows you to do things like + +----------------------------------------------------------------------------- + git-show-ref --quiet --verify -- "refs/heads/$headname" || + echo "$headname is not a valid branch" +----------------------------------------------------------------------------- + +to check whether a particular branch exists or not (notice how we don't +actually want to show any results, and we want to use the full refname for it +in order to not trigger the problem with ambiguous partial matches). + +To show only tags, or only proper branch heads, use "--tags" and/or "--heads" +respectively (using both means that it shows tags and heads, but not other +random references under the refs/ subdirectory). + +To do automatic tag object dereferencing, use the "-d" or "--dereference" +flag, so you can do + +----------------------------------------------------------------------------- + git show-ref --tags --dereference +----------------------------------------------------------------------------- + +to get a listing of all tags together with what they dereference. + +SEE ALSO +-------- +gitlink:git-ls-remote[1], gitlink:git-peek-remote[1] + +AUTHORS +------- +Written by Linus Torvalds <torvalds@osdl.org>. +Man page by Jonas Fonseca <fonseca@diku.dk>. + +GIT +--- +Part of the gitlink:git[7] suite diff --git a/Documentation/git-update-ref.txt b/Documentation/git-update-ref.txt index e062030e91..71bcb7954f 100644 --- a/Documentation/git-update-ref.txt +++ b/Documentation/git-update-ref.txt @@ -7,7 +7,7 @@ git-update-ref - update the object name stored in a ref safely SYNOPSIS -------- -'git-update-ref' [-m <reason>] <ref> <newvalue> [<oldvalue>] +'git-update-ref' [-m <reason>] (-d <ref> <oldvalue> | <ref> <newvalue> [<oldvalue>]) DESCRIPTION ----------- @@ -20,7 +20,9 @@ possibly dereferencing the symbolic refs, after verifying that the current value of the <ref> matches <oldvalue>. E.g. `git-update-ref refs/heads/master <newvalue> <oldvalue>` updates the master branch head to <newvalue> only if its current -value is <oldvalue>. +value is <oldvalue>. You can specify 40 "0" or an empty string +as <oldvalue> to make sure that the ref you are creating does +not exist. It also allows a "ref" file to be a symbolic pointer to another ref file by starting with the four-byte header sequence of @@ -49,6 +51,10 @@ for reading but not for writing (so we'll never write through a ref symlink to some other tree, if you have copied a whole archive by creating a symlink tree). +With `-d` flag, it deletes the named <ref> after verifying it +still contains <oldvalue>. + + Logging Updates --------------- If config parameter "core.logAllRefUpdates" is true or the file @@ -158,8 +158,8 @@ BASIC_CFLAGS = BASIC_LDFLAGS = SCRIPT_SH = \ - git-bisect.sh git-branch.sh git-checkout.sh \ - git-cherry.sh git-clean.sh git-clone.sh git-commit.sh \ + git-bisect.sh git-checkout.sh \ + git-clean.sh git-clone.sh git-commit.sh \ git-fetch.sh \ git-ls-remote.sh \ git-merge-one-file.sh git-parse-remote.sh \ @@ -212,7 +212,7 @@ PROGRAMS = \ EXTRA_PROGRAMS = BUILT_INS = \ - git-format-patch$X git-show$X git-whatchanged$X \ + git-format-patch$X git-show$X git-whatchanged$X git-cherry$X \ git-get-tar-commit-id$X \ $(patsubst builtin-%.o,git-%$X,$(BUILTIN_OBJS)) @@ -270,6 +270,7 @@ BUILTIN_OBJS = \ builtin-annotate.o \ builtin-apply.o \ builtin-archive.o \ + builtin-branch.o \ builtin-cat-file.o \ builtin-checkout-index.o \ builtin-check-ref-format.o \ @@ -310,7 +311,9 @@ BUILTIN_OBJS = \ builtin-update-ref.o \ builtin-upload-archive.o \ builtin-verify-pack.o \ - builtin-write-tree.o + builtin-write-tree.o \ + builtin-show-ref.o \ + builtin-pack-refs.o GITLIBS = $(LIB_FILE) $(XDIFF_LIB) EXTLIBS = -lz diff --git a/builtin-apply.c b/builtin-apply.c index 11397f5504..db7cdce1d3 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -1043,10 +1043,14 @@ static int parse_single_patch(char *line, unsigned long size, struct patch *patc * then not having oldlines means the patch is creation, * and not having newlines means the patch is deletion. */ - if (patch->is_new < 0 && !oldlines) + if (patch->is_new < 0 && !oldlines) { patch->is_new = 1; - if (patch->is_delete < 0 && !newlines) + patch->old_name = NULL; + } + if (patch->is_delete < 0 && !newlines) { patch->is_delete = 1; + patch->new_name = NULL; + } } if (0 < patch->is_new && oldlines) diff --git a/builtin-branch.c b/builtin-branch.c new file mode 100644 index 0000000000..368b68ec91 --- /dev/null +++ b/builtin-branch.c @@ -0,0 +1,221 @@ +/* + * Builtin "git branch" + * + * Copyright (c) 2006 Kristian Høgsberg <krh@redhat.com> + * Based on git-branch.sh by Junio C Hamano. + */ + +#include "cache.h" +#include "refs.h" +#include "commit.h" +#include "builtin.h" + +static const char builtin_branch_usage[] = +"git-branch (-d | -D) <branchname> | [-l] [-f] <branchname> [<start-point>] | [-r]"; + + +static const char *head; +static unsigned char head_sha1[20]; + +static int in_merge_bases(const unsigned char *sha1, + struct commit *rev1, + struct commit *rev2) +{ + struct commit_list *bases, *b; + int ret = 0; + + bases = get_merge_bases(rev1, rev2, 1); + for (b = bases; b; b = b->next) { + if (!hashcmp(sha1, b->item->object.sha1)) { + ret = 1; + break; + } + } + + free_commit_list(bases); + return ret; +} + +static void delete_branches(int argc, const char **argv, int force) +{ + struct commit *rev, *head_rev; + unsigned char sha1[20]; + char *name; + int i; + + head_rev = lookup_commit_reference(head_sha1); + for (i = 0; i < argc; i++) { + if (!strcmp(head, argv[i])) + die("Cannot delete the branch you are currently on."); + + name = xstrdup(mkpath("refs/heads/%s", argv[i])); + if (!resolve_ref(name, sha1, 1, NULL)) + die("Branch '%s' not found.", argv[i]); + + rev = lookup_commit_reference(sha1); + if (!rev || !head_rev) + die("Couldn't look up commit objects."); + + /* This checks whether the merge bases of branch and + * HEAD contains branch -- which means that the HEAD + * contains everything in both. + */ + + if (!force && + !in_merge_bases(sha1, rev, head_rev)) { + fprintf(stderr, + "The branch '%s' is not a strict subset of your current HEAD.\n" + "If you are sure you want to delete it, run 'git branch -D %s'.\n", + argv[i], argv[i]); + exit(1); + } + + if (delete_ref(name, sha1)) + printf("Error deleting branch '%s'\n", argv[i]); + else + printf("Deleted branch %s.\n", argv[i]); + + free(name); + } +} + +static int ref_index, ref_alloc; +static char **ref_list; + +static int append_ref(const char *refname, const unsigned char *sha1, int flags, + void *cb_data) +{ + if (ref_index >= ref_alloc) { + ref_alloc = alloc_nr(ref_alloc); + ref_list = xrealloc(ref_list, ref_alloc * sizeof(char *)); + } + + ref_list[ref_index++] = xstrdup(refname); + + return 0; +} + +static int ref_cmp(const void *r1, const void *r2) +{ + return strcmp(*(char **)r1, *(char **)r2); +} + +static void print_ref_list(int remote_only) +{ + int i; + char c; + + if (remote_only) + for_each_remote_ref(append_ref, NULL); + else + for_each_branch_ref(append_ref, NULL); + + qsort(ref_list, ref_index, sizeof(char *), ref_cmp); + + for (i = 0; i < ref_index; i++) { + c = ' '; + if (!strcmp(ref_list[i], head)) + c = '*'; + + printf("%c %s\n", c, ref_list[i]); + } +} + +static void create_branch(const char *name, const char *start, + int force, int reflog) +{ + struct ref_lock *lock; + struct commit *commit; + unsigned char sha1[20]; + char ref[PATH_MAX], msg[PATH_MAX + 20]; + + snprintf(ref, sizeof ref, "refs/heads/%s", name); + if (check_ref_format(ref)) + die("'%s' is not a valid branch name.", name); + + if (resolve_ref(ref, sha1, 1, NULL)) { + if (!force) + die("A branch named '%s' already exists.", name); + else if (!strcmp(head, name)) + die("Cannot force update the current branch."); + } + + if (get_sha1(start, sha1) || + (commit = lookup_commit_reference(sha1)) == NULL) + die("Not a valid branch point: '%s'.", start); + hashcpy(sha1, commit->object.sha1); + + lock = lock_any_ref_for_update(ref, NULL); + if (!lock) + die("Failed to lock ref for update: % |