From 211fb4fe787ba5dc8103d5920fb890febffbf6df Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 10 May 2007 21:59:13 -0700 Subject: [PATCH 01/86] Minor copyediting on Release Notes for 1.5.2 Signed-off-by: Junio C Hamano --- Documentation/RelNotes-1.5.2.txt | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Documentation/RelNotes-1.5.2.txt b/Documentation/RelNotes-1.5.2.txt index 42e7fa5bec..d1c2cac4fc 100644 --- a/Documentation/RelNotes-1.5.2.txt +++ b/Documentation/RelNotes-1.5.2.txt @@ -40,7 +40,7 @@ Updates since v1.5.1 This release supports the "version 2" format of the .idx file. This is automatically enabled when a huge packfile needs more than 32-bit to express offsets of objects in the - pack + pack. * Comes with an updated git-gui 0.7.0 @@ -114,7 +114,7 @@ Updates since v1.5.1 - Local "git fetch" from a repository whose object store is one of the alternates (e.g. fetching from the origin in a repository created with "git clone -l -s") avoids - downloading objects unnecessary. + downloading objects unnecessarily. - "git blame" uses .mailmap to canonicalize the author name just like "git shortlog" does. @@ -124,7 +124,7 @@ Updates since v1.5.1 - "git cherry-pick" and "git revert" does not use .msg file in the working tree to prepare commit message; instead it uses - $GIT_DIR/MERGE_MSG as other commands. + $GIT_DIR/MERGE_MSG as other commands do. * Builds @@ -134,7 +134,7 @@ Updates since v1.5.1 - gitk and git-gui can be configured out. - Generated documentation pages automatically get version - information from GIT_VERSION + information from GIT_VERSION. - Parallel build with "make -j" descending into subdirectory was fixed. @@ -151,11 +151,13 @@ Updates since v1.5.1 - The recursive merge strategy updated a worktree file that was changed identically in two branches, when one of them renamed it. We do not do that when there is no rename, so - match that behaviour. + match that behaviour. This avoids excessive rebuilds. - The default pack depth has been increased to 50, as the recent addition of delta_base_cache makes deeper delta chains - much less expensive to access. + much less expensive to access. Depending on the project, it was + reported that this reduces the resulting pack file by 10% + or so. Fixes since v1.5.1 @@ -194,6 +196,6 @@ this release, unless otherwise noted. -- exec >/var/tmp/1 -O=v1.5.2-rc2-91-g616e40b +O=v1.5.2-rc3 echo O=`git describe refs/heads/master` git shortlog --no-merges $O..refs/heads/master ^refs/heads/maint From f859c846e90b385c7ef873df22403529208ade50 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 11 May 2007 22:11:07 -0700 Subject: [PATCH 02/86] Add has_symlink_leading_path() function. When we are applying a patch that creates a blob at a path, or when we are switching from a branch that does not have a blob at the path to another branch that has one, we need to make sure that there is nothing at the path in the working tree, as such a file is a local modification made by the user that would be lost by the operation. Normally, lstat() on the path and making sure ENOENT is returned is good enough for that purpose. However there is a twist. We may be creating a regular file arch/x86_64/boot/Makefile, while removing an existing symbolic link at arch/x86_64/boot that points at existing ../i386/boot directory that has Makefile in it. We always first check without touching filesystem and then perform the actual operation, so when we verify the new file, arch/x86_64/boot/Makefile, does not exist, we haven't removed the symbolic link arc/x86_64/boot symbolic link yet. lstat() on the file sees through the symbolic link and reports the file is there, which is not what we want. The function has_symlink_leading_path() function takes a path, and sees if any of the leading directory component is a symbolic link. When files in a new directory are created, we tend to process them together because both index and tree are sorted. The function takes advantage of this and allows the caller to cache and reuse which symbolic link on the filesystem caused the function to return true. The calling sequence would be: char last_symlink[PATH_MAX]; *last_symlink = '\0'; for each index entry { if (!lose) continue; if (lstat(it)) if (errno == ENOENT) ; /* happy */ else error; else if (has_symlink_leading_path(it, last_symlink)) ; /* happy */ else error; /* would lose local changes */ unlink_entry(it, last_symlink); } Signed-off-by: Junio C Hamano --- cache.h | 1 + symlinks.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 symlinks.c diff --git a/cache.h b/cache.h index 8e76152645..aaeb04a1b9 100644 --- a/cache.h +++ b/cache.h @@ -410,6 +410,7 @@ struct checkout { }; extern int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *topath); +extern int has_symlink_leading_path(const char *name, char *last_symlink); extern struct alternate_object_database { struct alternate_object_database *next; diff --git a/symlinks.c b/symlinks.c new file mode 100644 index 0000000000..be9ace6c04 --- /dev/null +++ b/symlinks.c @@ -0,0 +1,48 @@ +#include "cache.h" + +int has_symlink_leading_path(const char *name, char *last_symlink) +{ + char path[PATH_MAX]; + const char *sp, *ep; + char *dp; + + sp = name; + dp = path; + + if (last_symlink && *last_symlink) { + size_t last_len = strlen(last_symlink); + size_t len = strlen(name); + if (last_len < len && + !strncmp(name, last_symlink, last_len) && + name[last_len] == '/') + return 1; + *last_symlink = '\0'; + } + + while (1) { + size_t len; + struct stat st; + + ep = strchr(sp, '/'); + if (!ep) + break; + len = ep - sp; + if (PATH_MAX <= dp + len - path + 2) + return 0; /* new name is longer than that??? */ + memcpy(dp, sp, len); + dp[len] = 0; + + if (lstat(path, &st)) + return 0; + if (S_ISLNK(st.st_mode)) { + if (last_symlink) + strcpy(last_symlink, path); + return 1; + } + + dp[len++] = '/'; + dp = dp + len; + sp = ep + 1; + } + return 0; +} From 64cab59159d1308365d56e218a10bfc0d3cd0fd0 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 11 May 2007 22:26:08 -0700 Subject: [PATCH 03/86] apply: do not get confused by symlinks in the middle HPA noticed that git-rebase fails when changes involve symlinks in the middle of the hierarchy. Consider: * The tree state before the patch is applied has arch/x86_64/boot as a symlink pointing at ../i386/boot/ * The patch tries to remove arch/x86_64/boot symlink, and create bunch of files there: .gitignore, Makefile, etc. git-apply tries to be careful while applying patches; it never touches the working tree until it is convinced that the patch would apply cleanly. One of the check it does is that when it knows a path is going to be created by the patch, it runs lstat() on the path to make sure it does not exist. This leads to a false alarm. Because we do not touch the working tree before all the check passes, when we try to make sure that arch/x86_64/boot/.gitignore does not exist yet, we haven't removed the arch/x86_64/boot symlink. The lstat() check ends up seeing arch/i386/boot/.gitignore through the yet-to-be-removed symlink, and says "Hey, you already have a file there, but what you fed me is a patch to create a new file. I am not going to clobber what you have in the working tree." We have similar checks to see a file we are going to modify does exist and match the preimage of the diff, which is done by directly opening and reading the file. For a file we are going to delete, we make sure that it does exist and matches what is going to be removed (a removal patch records the full preimage, so we check what you have in your working tree matches it in full -- otherwise we would risk losing your local changes), which again is done by directly opening and reading the file. These checks need to be adjusted so that they are not fooled by symlinks in the middle. - To make sure something does not exist, first lstat(). If it does not exist, it does not, so be happy. If it _does_, we might be getting fooled by a symlink in the middle, so break leading paths and see if there are symlinks involved. When we are checking for a path a/b/c/d, if any of a, a/b, a/b/c is a symlink, then a/b/c/d does _NOT_ exist, for the purpose of our test. This would fix this particular case you saw, and would not add extra overhead in the usual case. - To make sure something already exists, first lstat(). If it does not exist, barf (up to this, we already do). Even if it does seem to exist, we might be getting fooled by a symlink in the middle, so make sure leading paths are not symlinks. This would make the normal codepath much more expensive for deep trees, which is a bit worrisome. This patch implements the first side of the check "making sure it does not exist". The latter "making sure it exists" check is not done yet, so applying the patch in reverse would still fail, but we have to start from somewhere. Signed-off-by: Junio C Hamano --- Makefile | 2 +- builtin-apply.c | 35 ++++++++++++++------ t/t4122-apply-symlink-inside.sh | 57 +++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 10 deletions(-) create mode 100755 t/t4122-apply-symlink-inside.sh diff --git a/Makefile b/Makefile index 7cf146ba7b..29243c6e8b 100644 --- a/Makefile +++ b/Makefile @@ -318,7 +318,7 @@ LIB_OBJS = \ write_or_die.o trace.o list-objects.o grep.o match-trees.o \ alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \ color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \ - convert.o attr.o decorate.o progress.o mailmap.o + convert.o attr.o decorate.o progress.o mailmap.o symlinks.o BUILTIN_OBJS = \ builtin-add.o \ diff --git a/builtin-apply.c b/builtin-apply.c index f94d0dbf48..8b8705a6c0 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -2009,6 +2009,29 @@ static int apply_data(struct patch *patch, struct stat *st, struct cache_entry * return 0; } +static int check_to_create_blob(const char *new_name, int ok_if_exists) +{ + struct stat nst; + if (!lstat(new_name, &nst)) { + if (S_ISDIR(nst.st_mode) || ok_if_exists) + return 0; + /* + * A leading component of new_name might be a symlink + * that is going to be removed with this patch, but + * still pointing at somewhere that has the path. + * In such a case, path "new_name" does not exist as + * far as git is concerned. + */ + if (has_symlink_leading_path(new_name, NULL)) + return 0; + + return error("%s: already exists in working directory", new_name); + } + else if ((errno != ENOENT) && (errno != ENOTDIR)) + return error("%s: %s", new_name, strerror(errno)); + return 0; +} + static int check_patch(struct patch *patch, struct patch *prev_patch) { struct stat st; @@ -2095,15 +2118,9 @@ static int check_patch(struct patch *patch, struct patch *prev_patch) !ok_if_exists) return error("%s: already exists in index", new_name); if (!cached) { - struct stat nst; - if (!lstat(new_name, &nst)) { - if (S_ISDIR(nst.st_mode) || ok_if_exists) - ; /* ok */ - else - return error("%s: already exists in working directory", new_name); - } - else if ((errno != ENOENT) && (errno != ENOTDIR)) - return error("%s: %s", new_name, strerror(errno)); + int err = check_to_create_blob(new_name, ok_if_exists); + if (err) + return err; } if (!patch->new_mode) { if (0 < patch->is_new) diff --git a/t/t4122-apply-symlink-inside.sh b/t/t4122-apply-symlink-inside.sh new file mode 100755 index 0000000000..37c9a9f254 --- /dev/null +++ b/t/t4122-apply-symlink-inside.sh @@ -0,0 +1,57 @@ +#!/bin/sh + +test_description='apply to deeper directory without getting fooled with symlink' +. ./test-lib.sh + +lecho () { + for l_ + do + echo "$l_" + done +} + +test_expect_success setup ' + + mkdir -p arch/i386/boot arch/x86_64 && + lecho 1 2 3 4 5 >arch/i386/boot/Makefile && + ln -s ../i386/boot arch/x86_64/boot && + git add . && + test_tick && + git commit -m initial && + git branch test && + + rm arch/x86_64/boot && + mkdir arch/x86_64/boot && + lecho 2 3 4 5 6 >arch/x86_64/boot/Makefile && + git add . && + test_tick && + git commit -a -m second && + + git format-patch --binary -1 --stdout >test.patch + +' + +test_expect_success apply ' + + git checkout test && + git reset --hard && #### checkout seems to be buggy + git diff --exit-code test && + git diff --exit-code --cached test && + git apply --index test.patch + +' + +test_expect_success 'check result' ' + + git diff --exit-code master && + git diff --exit-code --cached master && + test_tick && + git commit -m replay && + T1=$(git rev-parse "master^{tree}") && + T2=$(git rev-parse "HEAD^{tree}") && + test "z$T1" = "z$T2" + +' + +test_done + From 16a4c6176ad096881d0021f1a922fbcc2835f799 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 10 May 2007 23:44:53 -0700 Subject: [PATCH 04/86] read-tree -m -u: avoid getting confused by intermediate symlinks. When switching from a branch with both x86_64/boot/Makefile and i386/boot/Makefile to another branch that has x86_64/boot as a symlink pointing at ../i386/boot, the code incorrectly removed i386/boot/Makefile. This was because we first removed everything under x86_64/boot to make room to create a symbolic link x86_64/boot, then removed x86_64/boot/Makefile which no longer exists but now is pointing at i386/boot/Makefile, thanks to the symlink we just created. This fixes it by using the has_symlink_leading_path() function introduced previously for git-apply in the checkout codepath. Earlier, "git checkout" was broken in t4122 test due to this bug, and the test had an extra "git reset --hard" as a workaround, which is removed because it is not needed anymore. Signed-off-by: Junio C Hamano --- t/t4122-apply-symlink-inside.sh | 1 - unpack-trees.c | 14 ++++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/t/t4122-apply-symlink-inside.sh b/t/t4122-apply-symlink-inside.sh index 37c9a9f254..3ddfe64b02 100755 --- a/t/t4122-apply-symlink-inside.sh +++ b/t/t4122-apply-symlink-inside.sh @@ -34,7 +34,6 @@ test_expect_success setup ' test_expect_success apply ' git checkout test && - git reset --hard && #### checkout seems to be buggy git diff --exit-code test && git diff --exit-code --cached test && git apply --index test.patch diff --git a/unpack-trees.c b/unpack-trees.c index 675a9998dc..906ce69ea6 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -264,10 +264,12 @@ static int unpack_trees_rec(struct tree_entry_list **posns, int len, * directories, in case this unlink is the removal of the * last entry in the directory -- empty directories are removed. */ -static void unlink_entry(char *name) +static void unlink_entry(char *name, char *last_symlink) { char *cp, *prev; + if (has_symlink_leading_path(name, last_symlink)) + return; if (unlink(name)) return; prev = NULL; @@ -291,11 +293,12 @@ static void unlink_entry(char *name) static struct checkout state; static void check_updates(struct cache_entry **src, int nr, - struct unpack_trees_options *o) + struct unpack_trees_options *o) { unsigned short mask = htons(CE_UPDATE); unsigned cnt = 0, total = 0; struct progress progress; + char last_symlink[PATH_MAX]; if (o->update && o->verbose_update) { for (total = cnt = 0; cnt < nr; cnt++) { @@ -309,6 +312,7 @@ static void check_updates(struct cache_entry **src, int nr, cnt = 0; } + *last_symlink = '\0'; while (nr--) { struct cache_entry *ce = *src++; @@ -317,13 +321,15 @@ static void check_updates(struct cache_entry **src, int nr, display_progress(&progress, ++cnt); if (!ce->ce_mode) { if (o->update) - unlink_entry(ce->name); + unlink_entry(ce->name, last_symlink); continue; } if (ce->ce_flags & mask) { ce->ce_flags &= ~mask; - if (o->update) + if (o->update) { checkout_entry(ce, &state, NULL); + *last_symlink = '\0'; + } } } if (total) From 93c44d493b8c98b9bb74e4f78aa90ee20a01f078 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Sat, 12 May 2007 02:42:00 -0400 Subject: [PATCH 05/86] git-add: allow path limiting with -u Rather than updating all working tree paths, we limit ourselves to paths listed on the command line. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- builtin-add.c | 13 ++++++------- t/t2200-add-update.sh | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 7 deletions(-) create mode 100755 t/t2200-add-update.sh diff --git a/builtin-add.c b/builtin-add.c index 5e6748f356..159117106a 100644 --- a/builtin-add.c +++ b/builtin-add.c @@ -16,7 +16,7 @@ static const char builtin_add_usage[] = "git-add [-n] [-v] [-f] [--interactive | -i] [-u] [--] ..."; -static int take_all_worktree_changes; +static int take_worktree_changes; static const char *excludes_file; static void prune_directory(struct dir_struct *dir, const char **pathspec, int prefix) @@ -122,11 +122,12 @@ static void update_callback(struct diff_queue_struct *q, } } -static void update_all(int verbose) +static void update(int verbose, const char **files) { struct rev_info rev; init_revisions(&rev, ""); setup_revisions(0, NULL, &rev, NULL); + rev.prune_data = get_pathspec(rev.prefix, files); rev.diffopt.output_format = DIFF_FORMAT_CALLBACK; rev.diffopt.format_callback = update_callback; rev.diffopt.format_callback_data = &verbose; @@ -200,16 +201,14 @@ int cmd_add(int argc, const char **argv, const char *prefix) continue; } if (!strcmp(arg, "-u")) { - take_all_worktree_changes = 1; + take_worktree_changes = 1; continue; } usage(builtin_add_usage); } - if (take_all_worktree_changes) { - if (i < argc) - die("-u and explicit paths are incompatible"); - update_all(verbose); + if (take_worktree_changes) { + update(verbose, argv + i); goto finish; } diff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh new file mode 100755 index 0000000000..83005e70d0 --- /dev/null +++ b/t/t2200-add-update.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +test_description='git-add -u with path limiting + +This test creates a working tree state with three files: + + top (previously committed, modified) + dir/sub (previously committed, modified) + dir/other (untracked) + +and issues a git-add -u with path limiting on "dir" to add +only the updates to dir/sub.' + +. ./test-lib.sh + +test_expect_success 'setup' ' +echo initial >top && +mkdir dir && +echo initial >dir/sub && +git-add dir/sub top && +git-commit -m initial && +echo changed >top && +echo changed >dir/sub && +echo other >dir/other +' + +test_expect_success 'update' 'git-add -u dir' + +test_expect_success 'update touched correct path' \ + 'test "`git-diff-files --name-status dir/sub`" = ""' + +test_expect_success 'update did not touch other tracked files' \ + 'test "`git-diff-files --name-status top`" = "M top"' + +test_expect_success 'update did not touch untracked files' \ + 'test "`git-diff-files --name-status dir/other`" = ""' + +test_done From 7e9116b1d8adef635ae900af7eff4b320390eeb3 Mon Sep 17 00:00:00 2001 From: Marco Costalba Date: Sat, 12 May 2007 12:35:29 +0200 Subject: [PATCH 06/86] Fix an unmatched comment end in arm/sha1_arm.S Signed-off-by: Marco Costalba Acked-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- arm/sha1_arm.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arm/sha1_arm.S b/arm/sha1_arm.S index da92d20e84..a328b73375 100644 --- a/arm/sha1_arm.S +++ b/arm/sha1_arm.S @@ -23,7 +23,7 @@ sha_transform: stmfd sp!, {r4 - r8, lr} @ for (i = 0; i < 16; i++) - @ W[i] = ntohl(((uint32_t *)data)[i]); */ + @ W[i] = ntohl(((uint32_t *)data)[i]); #ifdef __ARMEB__ mov r4, r0 From 2206537c07973fc2933092313d95340e076440e4 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sat, 12 May 2007 12:42:32 +0200 Subject: [PATCH 07/86] gitweb: Test if $from_id and $to_id are defined before comparison Get rid of "Use of uninitialized value in string eq at gitweb/gitweb.perl line 2320" warning caused by the fact that "empty" patches, consisting only of extended git diff header and with patch body empty, such as patch for pure rename, does not have "index" line in extended diff header. For such patches $from_id and $to_id, filled from parsing extended diff header, are undefined. But such patches cannot be continuation patches. Test if $from_id and $to_id are defined before comparing them with $diffinfo. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 21864c62a9..fff01834de 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2660,9 +2660,10 @@ sub git_patchset_body { # check if current patch belong to current raw line # and parse raw git-diff line if needed if (defined $diffinfo && + defined $from_id && defined $to_id && from_ids_eq($diffinfo->{'from_id'}, $from_id) && $diffinfo->{'to_id'} eq $to_id) { - # this is split patch + # this is continuation of a split patch print "
\n"; } else { # advance raw git-diff output if needed From a6e3768f641c2703266422aa05c05f1d01e886b2 Mon Sep 17 00:00:00 2001 From: Steffen Prohaska Date: Sat, 12 May 2007 13:32:34 +0200 Subject: [PATCH 08/86] tiny fix in documentation of git-clone path in example was missing '../' Signed-off-by: Steffen Prohaska Signed-off-by: Junio C Hamano --- Documentation/git-clone.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt index 6d32c491a5..644bf126fb 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -132,7 +132,7 @@ Make a local clone that borrows from the current directory, without checking thi + ------------ $ git clone -l -s -n . ../copy -$ cd copy +$ cd ../copy $ git show-branch ------------ From 02851e0b9ed840c2e6881dd56072eefc17c8b98b Mon Sep 17 00:00:00 2001 From: Lars Hjemli Date: Fri, 11 May 2007 18:55:21 +0200 Subject: [PATCH 09/86] git-archive: don't die when repository uses subprojects Both archive-tar and archive-zip needed to be taught about subprojects. The tar function died when trying to read the subproject commit object, while the zip function reported "unsupported file mode". This fixes both by representing the subproject as an empty directory. Signed-off-by: Lars Hjemli Signed-off-by: Junio C Hamano --- archive-tar.c | 4 ++-- archive-zip.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/archive-tar.c b/archive-tar.c index d9c30d33dc..56ff356966 100644 --- a/archive-tar.c +++ b/archive-tar.c @@ -166,7 +166,7 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path, } else { if (verbose) fprintf(stderr, "%.*s\n", path->len, path->buf); - if (S_ISDIR(mode)) { + if (S_ISDIR(mode) || S_ISDIRLNK(mode)) { *header.typeflag = TYPEFLAG_DIR; mode = (mode | 0777) & ~tar_umask; } else if (S_ISLNK(mode)) { @@ -278,7 +278,7 @@ static int write_tar_entry(const unsigned char *sha1, memcpy(path.buf, base, baselen); memcpy(path.buf + baselen, filename, filenamelen); path.len = baselen + filenamelen; - if (S_ISDIR(mode)) { + if (S_ISDIR(mode) || S_ISDIRLNK(mode)) { strbuf_append_string(&path, "/"); buffer = NULL; size = 0; diff --git a/archive-zip.c b/archive-zip.c index 7c4984886f..1eaf262b74 100644 --- a/archive-zip.c +++ b/archive-zip.c @@ -182,10 +182,10 @@ static int write_zip_entry(const unsigned char *sha1, goto out; } - if (S_ISDIR(mode)) { + if (S_ISDIR(mode) || S_ISDIRLNK(mode)) { method = 0; attr2 = 16; - result = READ_TREE_RECURSIVE; + result = (S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0); out = NULL; uncompressed_size = 0; compressed_size = 0; From 96f12b54f7b2067d668a1ea578a1fc3773e31148 Mon Sep 17 00:00:00 2001 From: Alex Riesen Date: Fri, 11 May 2007 22:35:22 +0200 Subject: [PATCH 10/86] Allow fetching references from any namespace not only from the three defined: heads, tags and remotes. Noticed when I tried to fetch the references created by git-p4-import.bat: they are placed into separate namespace (refs/p4import/, to avoid showing them in git-branch output). As canon_refs_list_for_fetch always prepended refs/heads/ it was impossible, and annoying: it worked before. Normally, the p4import references are useless anywhere but in the directory managed by perforce, but in this special case the cloned directory was supposed to be a backup, including the p4import branch: it keeps information about where the imported perforce state came from. Signed-off-by: Alex Riesen Signed-off-by: Junio C Hamano --- git-parse-remote.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/git-parse-remote.sh b/git-parse-remote.sh index 437b0c3b1b..0506b12cb2 100755 --- a/git-parse-remote.sh +++ b/git-parse-remote.sh @@ -143,13 +143,13 @@ canon_refs_list_for_fetch () { fi case "$remote" in '' | HEAD ) remote=HEAD ;; - refs/heads/* | refs/tags/* | refs/remotes/*) ;; + refs/*) ;; heads/* | tags/* | remotes/* ) remote="refs/$remote" ;; *) remote="refs/heads/$remote" ;; esac case "$local" in '') local= ;; - refs/heads/* | refs/tags/* | refs/remotes/*) ;; + refs/*) ;; heads/* | tags/* | remotes/* ) local="refs/$local" ;; *) local="refs/heads/$local" ;; esac From a25907dac4a3b79523290f19232157b9705dfe55 Mon Sep 17 00:00:00 2001 From: Junio Hamano Date: Fri, 11 May 2007 16:35:18 -0700 Subject: [PATCH 11/86] t9400: Use the repository config and nothing else. git-cvsserver has a bug in its configuration file output parser that makes it choke if the configuration has these: [diff] color = auto [diff.color] whitespace = blue reverse This needs to be fixed, but thanks to that bug, a separate bug in t9400 test script was discovered. The test discarded GIT_CONFIG instead of pointing at the proper one to be used in the exoprted repository. This allowed user's .gitconfig and (if exists) systemwide /etc/gitconfig to affect the outcome of the test, which is a big no-no. The patch fixes the problem in the test. Fixing the git-cvsserver's configuration parser is left as an exercise to motivated volunteers ;-) Signed-off-by: Junio C Hamano --- t/t9400-git-cvsserver-server.sh | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/t/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh index f137b308f3..d406a8824a 100755 --- a/t/t9400-git-cvsserver-server.sh +++ b/t/t9400-git-cvsserver-server.sh @@ -26,8 +26,9 @@ perl -e 'use DBI; use DBD::SQLite' >/dev/null 2>&1 || { unset GIT_DIR GIT_CONFIG WORKDIR=$(pwd) SERVERDIR=$(pwd)/gitcvs.git +git_config="$SERVERDIR/config" CVSROOT=":fork:$SERVERDIR" -CVSWORK=$(pwd)/cvswork +CVSWORK="$(pwd)/cvswork" CVS_SERVER=git-cvsserver export CVSROOT CVS_SERVER @@ -43,7 +44,7 @@ echo >empty && # note that cvs doesn't accept absolute pathnames # as argument to co -d test_expect_success 'basic checkout' \ - 'cvs -Q co -d cvswork master && + 'GIT_CONFIG="$git_config" cvs -Q co -d cvswork master && test "$(echo $(grep -v ^D cvswork/CVS/Entries|cut -d/ -f2,3,5))" = "empty/1.1/"' test_expect_success 'cvs update (create new file)' \ @@ -52,7 +53,7 @@ test_expect_success 'cvs update (create new file)' \ git commit -q -m "Add testfile1" && git push gitcvs.git >/dev/null && cd cvswork && - cvs -Q update && + GIT_CONFIG="$git_config" cvs -Q update && test "$(echo $(grep testfile1 CVS/Entries|cut -d/ -f2,3,5))" = "testfile1/1.1/" && diff -q testfile1 ../testfile1' @@ -63,7 +64,7 @@ test_expect_success 'cvs update (update existing file)' \ git commit -q -m "Append to testfile1" && git push gitcvs.git >/dev/null && cd cvswork && - cvs -Q update && + GIT_CONFIG="$git_config" cvs -Q update && test "$(echo $(grep testfile1 CVS/Entries|cut -d/ -f2,3,5))" = "testfile1/1.2/" && diff -q testfile1 ../testfile1' @@ -76,7 +77,7 @@ test_expect_failure "cvs update w/o -d doesn't create subdir (TODO)" \ git commit -q -m "Single Subdirectory" && git push gitcvs.git >/dev/null && cd cvswork && - cvs -Q update && + GIT_CONFIG="$git_config" cvs -Q update && test ! -d test' cd "$WORKDIR" @@ -89,7 +90,7 @@ test_expect_success 'cvs update (subdirectories)' \ git commit -q -m "deep sub directory structure" && git push gitcvs.git >/dev/null && cd cvswork && - cvs -Q update -d && + GIT_CONFIG="$git_config" cvs -Q update -d && (for dir in A A/B A/B/C A/D E; do filename="file_in_$(echo $dir|sed -e "s#/# #g")" && if test "$(echo $(grep -v ^D $dir/CVS/Entries|cut -d/ -f2,3,5))" = "$filename/1.1/" && @@ -107,7 +108,7 @@ test_expect_success 'cvs update (delete file)' \ git commit -q -m "Remove testfile1" && git push gitcvs.git >/dev/null && cd cvswork && - cvs -Q update && + GIT_CONFIG="$git_config" cvs -Q update && test -z "$(grep testfile1 CVS/Entries)" && test ! -f testfile1' @@ -118,7 +119,7 @@ test_expect_success 'cvs update (re-add deleted file)' \ git commit -q -m "Re-Add testfile1" && git push gitcvs.git >/dev/null && cd cvswork && - cvs -Q update && + GIT_CONFIG="$git_config" cvs -Q update && test "$(echo $(grep testfile1 CVS/Entries|cut -d/ -f2,3,5))" = "testfile1/1.4/" && diff -q testfile1 ../testfile1' From cbb84e5d174cf33fd4dcf3136de50a886ff9a2e2 Mon Sep 17 00:00:00 2001 From: Jan Hudec Date: Sat, 12 May 2007 19:11:13 +0200 Subject: [PATCH 12/86] Updated documentation of hooks in git-receive-pack. Added documentation of pre-receive and post-receive hooks and updated documentation of update and post-update hooks. [jc: with minor copy-editing] Signed-off-by: Jan Hudec Signed-off-by: Junio C Hamano --- Documentation/hooks.txt | 77 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 70 insertions(+), 7 deletions(-) diff --git a/Documentation/hooks.txt b/Documentation/hooks.txt index b083290d12..80ba6709ad 100644 --- a/Documentation/hooks.txt +++ b/Documentation/hooks.txt @@ -90,6 +90,35 @@ parameter, and is invoked after a commit is made. This hook is meant primarily for notification, and cannot affect the outcome of `git-commit`. +[[pre-receive]] +pre-receive +----------- + +This hook is invoked by `git-receive-pack` on the remote repository, +which happens when a `git push` is done on a local repository. +Just before starting to update refs on the remote repository, the +pre-receive hook is invoked. Its exit status determines the success +or failure of the update. + +This hook executes once for the receive operation. It takes no +arguments, but for each ref to be updated it receives on standard +input a line of the format: + + SP SP LF + +where `` is the old object name stored in the ref, +`` is the new object name to be stored in the ref and +`` is the full name of the ref. +When creating a new ref, `` is 40 `0`. + +If the hook exits with non-zero status, none of the refs will be +updated. If the hook exits with zero, updating of individual refs can +still be prevented by the <> hook. + +If you want to report something to the `git-send-pack` on the other end, +you can simply `echo` your messages. + +[[update]] update ------ @@ -108,7 +137,7 @@ three parameters: A zero exit from the update hook allows the ref to be updated. Exiting with a non-zero status prevents `git-receive-pack` -from updating the ref. +from updating that ref. This hook can be used to prevent 'forced' update on certain refs by making sure that the object name is a commit object that is a @@ -117,7 +146,8 @@ That is, to enforce a "fast forward only" policy. It could also be used to log the old..new status. However, it does not know the entire set of branches, so it would end up -firing one e-mail per ref when used naively, though. +firing one e-mail per ref when used naively, though. The +<> hook is more suited to that. Another use suggested on the mailing list is to use this hook to implement access control which is finer grained than the one @@ -127,9 +157,38 @@ The standard output of this hook is sent to `stderr`, so if you want to report something to the `git-send-pack` on the other end, you can simply `echo` your messages. -The default 'update' hook, when enabled, demonstrates how to -send out a notification e-mail. +The default 'update' hook, when enabled--and with +`hooks.allowunannotated` config option turned on--prevents +unannotated tags to be pushed. +[[post-receive]] +post-receive +------------ + +This hook is invoked by `git-receive-pack` on the remote repository, +which happens when a `git push` is done on a local repository. +It executes on the remote repository once after all the refs have +been updated. + +This hook executes once for the receive operation. It takes no +arguments, but gets the same information as the `pre-receive` +hook does on its standard input. + +This hook does not affect the outcome of `git-receive-pack`, as it +is called after the real work is done. + +This supersedes the [[post-update]] hook in that it actually get's +both old and new values of all the refs. + +If you want to report something to the `git-send-pack` on the +other end, you can simply `echo` your messages. + +The default 'post-receive' hook is empty, but there is +a sample script `post-receive-email` provided in the `contrib/hooks` +directory in git distribution, which implements sending commit +emails. + +[[post-update]] post-update ----------- @@ -148,12 +207,16 @@ The 'post-update' hook can tell what are the heads that were pushed, but it does not know what their original and updated values are, so it is a poor place to do log old..new. +In general, `post-receive` hook is preferred when the hook needs +to decide its acion on the status of the entire set of refs +being updated, as this hook is called once per ref, with +information only on a single ref at a time. + When enabled, the default 'post-update' hook runs `git-update-server-info` to keep the information used by dumb transports (e.g., HTTP) up-to-date. If you are publishing a git repository that is accessible via HTTP, you should probably enable this hook. -The standard output of this hook is sent to `/dev/null`; if you -want to report something to the `git-send-pack` on the other end, -you can redirect your output to your `stderr`. +Both standard output and standard error output are forwarded to +`git-send-pack` on the other end. From fdc99cbbdcdcf4ee2c336f02b7b2dbcb11696392 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 29 Mar 2007 01:02:50 -0700 Subject: [PATCH 13/86] checkout: allow detaching to HEAD even when switching to the tip of a branch You cannot currently checkout the tip of an existing branch without moving to the branch. This allows you to detach your HEAD and place it at such a commit, with: $ git checkout master^0 Signed-off-by: Junio C Hamano --- git-checkout.sh | 4 ++-- t/t7201-co.sh | 63 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/git-checkout.sh b/git-checkout.sh index a7390e808c..deb0a9a3c7 100755 --- a/git-checkout.sh +++ b/git-checkout.sh @@ -170,7 +170,7 @@ describe_detached_head () { } } -if test -z "$branch$newbranch" && test "$new" != "$old" +if test -z "$branch$newbranch" && test "$new_name" != "$old_name" then detached="$new" if test -n "$oldbranch" && test -z "$quiet" @@ -180,7 +180,7 @@ If you want to create a new branch from this checkout, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b " fi -elif test -z "$oldbranch" +elif test -z "$oldbranch" && test "$new" != "$old" then describe_detached_head 'Previous HEAD position was' "$old" fi diff --git a/t/t7201-co.sh b/t/t7201-co.sh index 867bbd26cb..5fa6a45577 100755 --- a/t/t7201-co.sh +++ b/t/t7201-co.sh @@ -3,7 +3,20 @@ # Copyright (c) 2006 Junio C Hamano # -test_description='git-checkout tests.' +test_description='git-checkout tests. + +Creates master, forks renamer and side branches from it. +Test switching across them. + + ! [master] Initial A one, A two + * [renamer] Renamer R one->uno, M two + ! [side] Side M one, D two, A three + --- + + [side] Side M one, D two, A three + * [renamer] Renamer R one->uno, M two + +*+ [master] Initial A one, A two + +' . ./test-lib.sh @@ -129,4 +142,52 @@ test_expect_success 'checkout -m with merge conflict' ' ! test -s current ' +test_expect_success 'checkout to detach HEAD' ' + + git checkout -f renamer && git clean && + git checkout renamer^ && + H=$(git rev-parse --verify HEAD) && + M=$(git show-ref -s --verify refs/heads/master) && + test "z$H" = "z$M" && + if git symbolic-ref HEAD >/dev/null 2>&1 + then + echo "OOPS, HEAD is still symbolic???" + false + else + : happy + fi +' + +test_expect_success 'checkout to detach HEAD with branchname^' ' + + git checkout -f master && git clean && + git checkout renamer^ && + H=$(git rev-parse --verify HEAD) && + M=$(git show-ref -s --verify refs/heads/master) && + test "z$H" = "z$M" && + if git symbolic-ref HEAD >/dev/null 2>&1 + then + echo "OOPS, HEAD is still symbolic???" + false + else + : happy + fi +' + +test_expect_success 'checkout to detach HEAD with HEAD^0' ' + + git checkout -f master && git clean && + git checkout HEAD^0 && + H=$(git rev-parse --verify HEAD) && + M=$(git show-ref -s --verify refs/heads/master) && + test "z$H" = "z$M" && + if git symbolic-ref HEAD >/dev/null 2>&1 + then + echo "OOPS, HEAD is still symbolic???" + false + else + : happy + fi +' + test_done From 24a0d61e51c0a5e3b9d799af4fcfdd5dc4405502 Mon Sep 17 00:00:00 2001 From: Jan Hudec Date: Sat, 12 May 2007 23:43:11 +0200 Subject: [PATCH 14/86] Minor fixup to documentation of hooks in git-receive-pack. Small additional changes to the cbb84e5d174cf33fd4dcf3136de50a886ff9a2e2 commit, which introduced documentation to pre-receive and post-receive: - Mention that stdout and stderr are equivalent. - Add one cross-section link and fix one other. - Fix information on advantages of post-receive over post-update. Signed-off-by: Jan Hudec Signed-off-by: Junio C Hamano --- Documentation/hooks.txt | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/Documentation/hooks.txt b/Documentation/hooks.txt index 80ba6709ad..aabb9750fd 100644 --- a/Documentation/hooks.txt +++ b/Documentation/hooks.txt @@ -115,8 +115,9 @@ If the hook exits with non-zero status, none of the refs will be updated. If the hook exits with zero, updating of individual refs can still be prevented by the <> hook. -If you want to report something to the `git-send-pack` on the other end, -you can simply `echo` your messages. +Both standard output and standard error output are forwarded to +`git-send-pack` on the other end, so you can simply `echo` messages +for the user. [[update]] update @@ -153,9 +154,9 @@ Another use suggested on the mailing list is to use this hook to implement access control which is finer grained than the one based on filesystem group. -The standard output of this hook is sent to `stderr`, so if you -want to report something to the `git-send-pack` on the other end, -you can simply `echo` your messages. +Both standard output and standard error output are forwarded to +`git-send-pack` on the other end, so you can simply `echo` messages +for the user. The default 'update' hook, when enabled--and with `hooks.allowunannotated` config option turned on--prevents @@ -171,17 +172,20 @@ It executes on the remote repository once after all the refs have been updated. This hook executes once for the receive operation. It takes no -arguments, but gets the same information as the `pre-receive` +arguments, but gets the same information as the +<> hook does on its standard input. This hook does not affect the outcome of `git-receive-pack`, as it is called after the real work is done. -This supersedes the [[post-update]] hook in that it actually get's -both old and new values of all the refs. +This supersedes the <> hook in that it get's +both old and new values of all the refs in addition to their +names. -If you want to report something to the `git-send-pack` on the -other end, you can simply `echo` your messages. +Both standard output and standard error output are forwarded to +`git-send-pack` on the other end, so you can simply `echo` messages +for the user. The default 'post-receive' hook is empty, but there is a sample script `post-receive-email` provided in the `contrib/hooks` @@ -205,12 +209,10 @@ the outcome of `git-receive-pack`. The 'post-update' hook can tell what are the heads that were pushed, but it does not know what their original and updated values are, -so it is a poor place to do log old..new. - -In general, `post-receive` hook is preferred when the hook needs -to decide its acion on the status of the entire set of refs -being updated, as this hook is called once per ref, with -information only on a single ref at a time. +so it is a poor place to do log old..new. The +<> hook does get both original and +updated values of the refs. You might consider it instead if you need +them. When enabled, the default 'post-update' hook runs `git-update-server-info` to keep the information used by dumb @@ -219,4 +221,5 @@ a git repository that is accessible via HTTP, you should probably enable this hook. Both standard output and standard error output are forwarded to -`git-send-pack` on the other end. +`git-send-pack` on the other end, so you can simply `echo` messages +for the user. From ae9ee41de86cc98adad1a0c70651c55acc3fb699 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 12 May 2007 21:49:33 -0700 Subject: [PATCH 15/86] git-config: do not forget seeing "a.b.var" means we are out of "a.var" section. Earlier code tried to be half-careful and knew the logic that seeing "a.var" after seeing "a.b.var" is a sign of the previous "a.b." section has ended, but forgot it has to handle the other way. Seeing "a.b.var" after seeing "a.var" is a sign that "a." section has ended, so a new "a.var2" variable should be added before the location "a.b.var" appears. Signed-off-by: Junio C Hamano --- config.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/config.c b/config.c index 70d1055679..7b655fdb78 100644 --- a/config.c +++ b/config.c @@ -451,6 +451,9 @@ static int matches(const char* key, const char* value) static int store_aux(const char* key, const char* value) { + const char *ep; + size_t section_len; + switch (store.state) { case KEY_SEEN: if (matches(key, value)) { @@ -468,12 +471,29 @@ static int store_aux(const char* key, const char* value) } break; case SECTION_SEEN: - if (strncmp(key, store.key, store.baselen+1)) { + /* + * What we are looking for is in store.key (both + * section and var), and its section part is baselen + * long. We found key (again, both section and var). + * We would want to know if this key is in the same + * section as what we are looking for. We already + * know we are in the same section as what should + * hold store.key. + */ + ep = strrchr(key, '.'); + section_len = ep - key; + + if ((section_len != store.baselen) || + memcmp(key, store.key, section_len+1)) { store.state = SECTION_END_SEEN; break; - } else - /* do not increment matches: this is no match */ - store.offset[store.seen] = ftell(config_file); + } + + /* + * Do not increment matches: this is no match, but we + * just made sure we are in the desired section. + */ + store.offset[store.seen] = ftell(config_file); /* fallthru */ case SECTION_END_SEEN: case START: From b18a2be37a0de27902ad6491960ed910083b0310 Mon Sep 17 00:00:00 2001 From: Steffen Prohaska Date: Sun, 13 May 2007 09:12:52 +0200 Subject: [PATCH 16/86] git-config: test for 'do not forget "a.b.var" ends "a.var" section'. Added test for mentioned bugfix. Signed-off-by: Steffen Prohaska Signed-off-by: Junio C Hamano --- t/t1300-repo-config.sh | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh index 78c2e0864f..a1d777ca81 100755 --- a/t/t1300-repo-config.sh +++ b/t/t1300-repo-config.sh @@ -407,6 +407,25 @@ EOF test_expect_success "section was removed properly" \ "git diff -u expect .git/config" +rm .git/config + +cat > expect << EOF +[gitcvs] + enabled = true + dbname = %Ggitcvs2.%a.%m.sqlite +[gitcvs "ext"] + dbname = %Ggitcvs1.%a.%m.sqlite +EOF + +test_expect_success 'section ending' ' + + git-config gitcvs.enabled true && + git-config gitcvs.ext.dbname %Ggitcvs1.%a.%m.sqlite && + git-config gitcvs.dbname %Ggitcvs2.%a.%m.sqlite && + cmp .git/config expect + +' + test_expect_success numbers ' git-config kilo.gram 1k && From 0ab311d60108f8d93dbcac53623e8e593901b5ea Mon Sep 17 00:00:00 2001 From: Matthieu Castet Date: Sun, 13 May 2007 11:57:00 -0700 Subject: [PATCH 17/86] Remove stale non-static-inline prototype for tree_entry_extract() When 4651ece8 made the function a "static inline", it should have removd the stale prototype but everybody missed that. Thomas Glanzmann noticed this broke compilation with Forte12 compiler on his Sun boxes. Signed-off-by: Junio C Hamano --- tree-walk.h | 1 - 1 file changed, 1 deletion(-) diff --git a/tree-walk.h b/tree-walk.h index 43458cf8ce..ee747aba0b 100644 --- a/tree-walk.h +++ b/tree-walk.h @@ -27,7 +27,6 @@ static inline int tree_entry_len(const char *name, const unsigned char *sha1) void update_tree_entry(struct tree_desc *); void init_tree_desc(struct tree_desc *desc, const void *buf, unsigned long size); -const unsigned char *tree_entry_extract(struct tree_desc *, const char **, unsigned int *); /* Helper function that does both of the above and returns true for success */ int tree_entry(struct tree_desc *, struct name_entry *); From b24dd51bf6102f5341d4753fad8ff73413ca66d3 Mon Sep 17 00:00:00 2001 From: Quy Tonthat Date: Sun, 13 May 2007 21:41:45 +1000 Subject: [PATCH 18/86] RPM spec: include files in technical/ to package. Not only that they are interesting to users, some of the files are linked to by the included "Git User's Manual" Signed-off-by: Quy Tonthat Signed-off-by: Junio C Hamano --- git.spec.in | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/git.spec.in b/git.spec.in index b0ea62884f..2170424599 100644 --- a/git.spec.in +++ b/git.spec.in @@ -167,8 +167,13 @@ rm -rf $RPM_BUILD_ROOT %{_datadir}/git-core/ %doc README COPYING Documentation/*.txt %{!?_without_docs: %doc Documentation/*.html Documentation/howto} +%{!?_without_docs: %doc Documentation/technical} %changelog +* Tue May 13 2007 Quy Tonthat +- Added lib files for git-gui +- Added Documentation/technical (As needed by Git Users Manual) + * Tue May 8 2007 Quy Tonthat - Added howto files From 645833b564f585a25acd75c878ffda752909c273 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 12 May 2007 14:36:20 -0700 Subject: [PATCH 19/86] git-svn: don't drop the username from URLs when dcommit is run We no longer store usernames in URLs stored in git-svn-id lines for dcommit, so we shouldn't rely on those URLs when connecting to the remote repository to commit. --- git-svn.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-svn.perl b/git-svn.perl index 3c4f490b74..d74e6d3112 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -393,7 +393,7 @@ sub cmd_dcommit { } else { my %ed_opts = ( r => $last_rev, log => get_commit_entry($d)->{log}, - ra => Git::SVN::Ra->new($url), + ra => Git::SVN::Ra->new($gs->full_url), tree_a => "$d~1", tree_b => $d, editor_cb => sub { From 0dc03d6a30213e9aa0eb88886cee24b993a24a29 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 13 May 2007 01:04:43 -0700 Subject: [PATCH 20/86] git-svn: clean up caching of SVN::Ra functions This patch was originally intended to make the Perl GC more sensitive to the SVN::Pool objects and not accidentally clean them up when they shouldn't be (causing segfaults). That didn't work, but this patch makes the code a bit cleaner regardless Put our caches for get_dir and check_path calls directly into the SVN::Ra object so they auto-expire when it is destroyed. dirents returned by get_dir() no longer needs the pool object stored persistently along with the cache data, as they'll be converted to native Perl hash references. Since calling rev_proplist repeatedly per-revision is no longer needed in git-svn, we do not cache calls to it. Signed-off-by: Eric Wong --- git-svn.perl | 68 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/git-svn.perl b/git-svn.perl index d74e6d3112..721a46817b 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -1390,7 +1390,7 @@ sub traverse_ignore { } } foreach (sort keys %$dirent) { - next if $dirent->{$_}->kind != $SVN::Node::dir; + next if $dirent->{$_}->{kind} != $SVN::Node::dir; $self->traverse_ignore($fh, "$path/$_", $r); } } @@ -2888,7 +2888,7 @@ my ($can_do_switch, %ignored_err, $RA); BEGIN { # enforce temporary pool usage for some simple functions my $e; - foreach (qw/get_latest_revnum get_uuid get_repos_root/) { + foreach (qw/rev_proplist get_latest_revnum get_uuid get_repos_root/) { $e .= "sub $_ { my \$self = shift; my \$pool = SVN::Pool->new; @@ -2897,29 +2897,7 @@ BEGIN { wantarray ? \@ret : \$ret[0]; }\n"; } - # get_dir needs $pool held in cache for dirents to work, - # check_path is cacheable and rev_proplist is close enough - # for our purposes. - foreach (qw/check_path get_dir rev_proplist/) { - $e .= "my \%${_}_cache; my \$${_}_rev = 0; sub $_ { - my \$self = shift; - my \$r = pop; - my \$k = join(\"\\0\", \@_); - if (my \$x = \$${_}_cache{\$r}->{\$k}) { - return wantarray ? \@\$x : \$x->[0]; - } - my \$pool = SVN::Pool->new; - my \@ret = \$self->SUPER::$_(\@_, \$r, \$pool); - if (\$r != \$${_}_rev) { - \%${_}_cache = ( pool => [] ); - \$${_}_rev = \$r; - } - \$${_}_cache{\$r}->{\$k} = \\\@ret; - push \@{\$${_}_cache{pool}}, \$pool; - wantarray ? \@ret : \$ret[0]; }\n"; - } - $e .= "\n1;"; - eval $e or die $@; + eval "$e; 1;" or die $@; } sub new { @@ -2952,9 +2930,47 @@ sub new { $self->{svn_path} = $url; $self->{repos_root} = $self->get_repos_root; $self->{svn_path} =~ s#^\Q$self->{repos_root}\E(/|$)##; + $self->{cache} = { check_path => { r => 0, data => {} }, + get_dir => { r => 0, data => {} } }; $RA = bless $self, $class; } +sub check_path { + my ($self, $path, $r) = @_; + my $cache = $self->{cache}->{check_path}; + if ($r == $cache->{r} && exists $cache->{data}->{$path}) { + return $cache->{data}->{$path}; + } + my $pool = SVN::Pool->new; + my $t = $self->SUPER::check_path($path, $r, $pool); + $pool->clear; + if ($r != $cache->{r}) { + %{$cache->{data}} = (); + $cache->{r} = $r; + } + $cache->{data}->{$path} = $t; +} + +sub get_dir { + my ($self, $dir, $r) = @_; + my $cache = $self->{cache}->{get_dir}; + if ($r == $cache->{r}) { + if (my $x = $cache->{data}->{$dir}) { + return wantarray ? @$x : $x->[0]; + } + } + my $pool = SVN::Pool->new; + my ($d, undef, $props) = $self->SUPER::get_dir($dir, $r, $pool); + my %dirents = map { $_ => { kind => $d->{$_}->kind } } keys %$d; + $pool->clear; + if ($r != $cache->{r}) { + %{$cache->{data}} = (); + $cache->{r} = $r; + } + $cache->{data}->{$dir} = [ \%dirents, $r, $props ]; + wantarray ? (\%dirents, $r, $props) : \%dirents; +} + sub DESTROY { # do not call the real DESTROY since we store ourselves in $RA } @@ -3169,7 +3185,7 @@ sub match_globs { return unless scalar @x == 3; my $dirents = $x[0]; foreach my $de (keys %$dirents) { - next if $dirents->{$de}->kind != $SVN::Node::dir; + next if $dirents->{$de}->{kind} != $SVN::Node::dir; my $p = $g->{path}->full_path($de); next if $exists->{$p}; next if (length $g->{path}->{right} && From 4c03c3eb4e31c2d1f88ca0c7106c647a246e81ff Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 13 May 2007 01:04:44 -0700 Subject: [PATCH 21/86] git-svn: fix segfaults due to initial SVN pool being cleared Some parts of SVN always seem to use it, even if the SVN::Ra object we're using is no longer used and we've created a new one in its place. It's also true that only one SVN::Ra connection can exist at once... Using SVN::Pool->new_default when the SVN::Ra object is created doesn't seem to help very much, either... Hopefully this fixes all segfault problems users have been experiencing over the past few months. Signed-off-by: Eric Wong --- git-svn.perl | 1 - 1 file changed, 1 deletion(-) diff --git a/git-svn.perl b/git-svn.perl index 721a46817b..ae14bab3a9 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -2904,7 +2904,6 @@ sub new { my ($class, $url) = @_; $url =~ s!/+$!!; return $RA if ($RA && $RA->{url} eq $url); - $RA->{pool}->clear if $RA; SVN::_Core::svn_config_ensure($config_dir, undef); my ($baton, $callbacks) = SVN::Core::auth_open_helper([ From 4a1bb4c3f87f355dd52fcd0babcbd005d59d7ed6 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 13 May 2007 09:58:14 -0700 Subject: [PATCH 22/86] git-svn: don't attempt to minimize URLs by default For tracking branches and tags, git-svn prefers to connect to the root of the repository or at least the level that houses branches and tags as well as trunk. However, users that are accustomed to tracking a single directory have no use for this feature. As pointed out by Junio, users may not have permissions to connect to connect to a higher-level path in the repository. While the current minimize_url() function detects lack of permissions to certain paths _after_ successful logins, it cannot effectively determine if it is trying to access a login-only portion of a repo when the user expects to connect to a part where anonymous access is allowed. For people used to the git-svnimport switches of --trunk, --tags, --branches, they'll already pass the repository root (or root+subdirectory), so minimize URL isn't of too much use to them, either. For people *not* used to git-svnimport, git-svn also supports: git svn init --minimize-url \ --trunk http://repository-root/foo/trunk \ --branches http://repository-root/foo/branches \ --tags http://repository-root/foo/tags And this is where the new --minimize-url command-line switch comes in to allow for this behavior to continue working. --- git-svn.perl | 5 +++-- t/t9100-git-svn-basic.sh | 2 +- t/t9104-git-svn-follow-parent.sh | 13 +++++++------ t/t9105-git-svn-commit-diff.sh | 2 +- t/t9110-git-svn-use-svm-props.sh | 7 ++++--- t/t9111-git-svn-use-svnsync-props.sh | 6 +++--- 6 files changed, 19 insertions(+), 16 deletions(-) diff --git a/git-svn.perl b/git-svn.perl index ae14bab3a9..f4c9ff1b85 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -80,6 +80,7 @@ my %icv; my %init_opts = ( 'template=s' => \$_template, 'shared:s' => \$_shared, 'trunk|T=s' => \$_trunk, 'tags|t=s' => \$_tags, 'branches|b=s' => \$_branches, 'prefix=s' => \$_prefix, + 'minimize-url|m' => \$Git::SVN::_minimize_url, 'no-metadata' => sub { $icv{noMetadata} = 1 }, 'use-svm-props' => sub { $icv{useSvmProps} = 1 }, 'use-svnsync-props' => sub { $icv{useSvnsyncProps} = 1 }, @@ -820,7 +821,7 @@ use strict; use warnings; use vars qw/$default_repo_id $default_ref_id $_no_metadata $_follow_parent $_repack $_repack_flags $_use_svm_props $_head - $_use_svnsync_props $no_reuse_existing/; + $_use_svnsync_props $no_reuse_existing $_minimize_url/; use Carp qw/croak/; use File::Path qw/mkpath/; use File::Copy qw/copy/; @@ -1037,7 +1038,7 @@ sub init_remote_config { "[svn-remote \"$existing\"]\n"; } $self->{repo_id} = $existing; - } else { + } elsif ($_minimize_url) { my $min_url = Git::SVN::Ra->new($url)->minimize_url; $existing = find_existing_remote($min_url, $r); if ($existing) { diff --git a/t/t9100-git-svn-basic.sh b/t/t9100-git-svn-basic.sh index eb628fe075..70c3669ee8 100755 --- a/t/t9100-git-svn-basic.sh +++ b/t/t9100-git-svn-basic.sh @@ -229,7 +229,7 @@ test_expect_failure 'exit if init-ing a would clobber a URL' " test_expect_success \ 'init allows us to connect to another directory in the same repo' " - git-svn init -i bar $svnrepo/bar && + git-svn init --minimize-url -i bar $svnrepo/bar && git config --get svn-remote.svn.fetch \ '^bar:refs/remotes/bar$' && git config --get svn-remote.svn.fetch \ diff --git a/t/t9104-git-svn-follow-parent.sh b/t/t9104-git-svn-follow-parent.sh index bd4f366e86..35aa45cb9a 100755 --- a/t/t9104-git-svn-follow-parent.sh +++ b/t/t9104-git-svn-follow-parent.sh @@ -28,7 +28,7 @@ test_expect_success 'initialize repo' " " test_expect_success 'init and fetch a moved directory' " - git-svn init -i thunk $svnrepo/thunk && + git-svn init --minimize-url -i thunk $svnrepo/thunk && git-svn fetch -i thunk && test \"\`git-rev-parse --verify refs/remotes/thunk@2\`\" \ = \"\`git-rev-parse --verify refs/remotes/thunk~1\`\" && @@ -68,7 +68,8 @@ test_expect_success 'follow larger parent' " echo hi > import/trunk/thunk/bump/thud/file && svn import -m 'import a larger parent' import $svnrepo/larger-parent && svn cp -m 'hi' $svnrepo/larger-parent $svnrepo/another-larger && - git-svn init -i larger $svnrepo/another-larger/trunk/thunk/bump/thud && + git-svn init --minimize-url -i larger \ + $svnrepo/another-larger/trunk/thunk/bump/thud && git-svn fetch -i larger && git-rev-parse --verify refs/remotes/larger && git-rev-parse --verify \ @@ -90,14 +91,14 @@ test_expect_success 'follow higher-level parent' " cd .. svn mkdir -m 'new glob at top level' $svnrepo/glob && svn mv -m 'move blob down a level' $svnrepo/blob $svnrepo/glob/blob && - git-svn init -i blob $svnrepo/glob/blob && + git-svn init --minimize-url -i blob $svnrepo/glob/blob && git-svn fetch -i blob " test_expect_success 'follow deleted directory' " svn mv -m 'bye!' $svnrepo/glob/blob/hi $svnrepo/glob/blob/bye && svn rm -m 'remove glob' $svnrepo/glob && - git-svn init -i glob $svnrepo/glob && + git-svn init --minimize-url -i glob $svnrepo/glob && git-svn fetch -i glob && test \"\`git cat-file blob refs/remotes/glob:blob/bye\`\" = hi && test \"\`git ls-tree refs/remotes/glob | wc -l \`\" -eq 1 @@ -127,7 +128,7 @@ test_expect_success 'follow-parent avoids deleting relevant info' " poke native/t/c.t && svn commit -m 'reorg test' && cd .. && - git-svn init -i r9270-t \ + git-svn init --minimize-url -i r9270-t \ $svnrepo/r9270/trunk/subversion/bindings/swig/perl/native/t && git-svn fetch -i r9270-t && test \`git rev-list r9270-t | wc -l\` -eq 2 && @@ -137,7 +138,7 @@ test_expect_success 'follow-parent avoids deleting relevant info' " test_expect_success "track initial change if it was only made to parent" " svn cp -m 'wheee!' $svnrepo/r9270/trunk $svnrepo/r9270/drunk && - git-svn init -i r9270-d \ + git-svn init --minimize-url -i r9270-d \ $svnrepo/r9270/drunk/subversion/bindings/swig/perl/native/t && git-svn fetch -i r9270-d && test \`git rev-list r9270-d | wc -l\` -eq 3 && diff --git a/t/t9105-git-svn-commit-diff.sh b/t/t9105-git-svn-commit-diff.sh index c668dd1270..318e172ef5 100755 --- a/t/t9105-git-svn-commit-diff.sh +++ b/t/t9105-git-svn-commit-diff.sh @@ -33,7 +33,7 @@ test_expect_success 'test the commit-diff command' " test_expect_success 'commit-diff to a sub-directory (with git-svn config)' " svn import -m 'sub-directory' import $svnrepo/subdir && - git-svn init $svnrepo/subdir && + git-svn init --minimize-url $svnrepo/subdir && git-svn fetch && git-svn commit-diff -r3 '$prev' '$head' && svn cat $svnrepo/subdir/readme > readme.2 && diff --git a/t/t9110-git-svn-use-svm-props.sh b/t/t9110-git-svn-use-svm-props.sh index 9db0d8fd8d..59e17f2663 100755 --- a/t/t9110-git-svn-use-svm-props.sh +++ b/t/t9110-git-svn-use-svm-props.sh @@ -9,9 +9,10 @@ test_description='git-svn useSvmProps test' test_expect_success 'load svm repo' " svnadmin load -q $rawsvnrepo < ../t9110/svm.dump && - git-svn init -R arr -i bar $svnrepo/mirror/arr && - git-svn init -R argh -i dir $svnrepo/mirror/argh && - git-svn init -R argh -i e $svnrepo/mirror/argh/a/b/c/d/e && + git-svn init --minimize-url -R arr -i bar $svnrepo/mirror/arr && + git-svn init --minimize-url -R argh -i dir $svnrepo/mirror/argh && + git-svn init --minimize-url -R argh -i e \ + $svnrepo/mirror/argh/a/b/c/d/e && git-config svn.useSvmProps true && git-svn fetch --all " diff --git a/t/t9111-git-svn-use-svnsync-props.sh b/t/t9111-git-svn-use-svnsync-props.sh index 483d7f8159..e52321471a 100755 --- a/t/t9111-git-svn-use-svnsync-props.sh +++ b/t/t9111-git-svn-use-svnsync-props.sh @@ -9,9 +9,9 @@ test_description='git-svn useSvnsyncProps test' test_expect_success 'load svnsync repo' " svnadmin load -q $rawsvnrepo < ../t9111/svnsync.dump && - git-svn init -R arr -i bar $svnrepo/bar && - git-svn init -R argh -i dir $svnrepo/dir && - git-svn init -R argh -i e $svnrepo/dir/a/b/c/d/e && + git-svn init --minimize-url -R arr -i bar $svnrepo/bar && + git-svn init --minimize-url -R argh -i dir $svnrepo/dir && + git-svn init --minimize-url -R argh -i e $svnrepo/dir/a/b/c/d/e && git-config svn.useSvnsyncProps true && git-svn fetch --all " From a2983cb7406210c69415b35528f83afa8e9c7b68 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 12 May 2007 11:47:38 -0700 Subject: [PATCH 23/86] Link to HTML version of external doc if available Currently $ git grep '\([^t]\|^\)'link: user-manual.txt gives four hits that refer to .txt version of the documentation set, but at least "hooks" and "cvs-migration" have HTML variants installed, so refer to them instead. Signed-off-by: Junio C Hamano --- Documentation/user-manual.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index 13db9699c1..a7abeaa1d7 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -1875,7 +1875,7 @@ $ chmod a+x hooks/post-update (For an explanation of the last two lines, see gitlink:git-update-server-info[1], and the documentation -link:hooks.txt[Hooks used by git].) +link:hooks.html[Hooks used by git].) Advertise the url of proj.git. Anybody else should then be able to clone or pull from that url, for example with a commandline like: @@ -1959,7 +1959,7 @@ Setting up a shared repository Another way to collaborate is by using a model similar to that commonly used in CVS, where several developers with special rights all push to and pull from a single shared repository. See -link:cvs-migration.txt[git for CVS users] for instructions on how to +link:cvs-migration.html[git for CVS users] for instructions on how to set this up. [[setting-up-gitweb]] From 198a2a8a69921327513c32512bdac77f52ab95d3 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sat, 12 May 2007 21:16:34 +0200 Subject: [PATCH 24/86] gitweb: Check if requested object exists Try to avoid "Use of uninitialized value ..." errors caused by bad revision, incorrect filename, wrong object id, bad file etc. (wrong value of 'h', 'hb', 'f', etc. parameters). This avoids polluting web server errors log. Correct git_get_hash_by_path and parse_commit_text (and, in turn, parse_commit) to return undef if object does not exist. Check in git_tag if requested tag exists. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index fff01834de..d467bf372a 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1060,6 +1060,11 @@ sub git_get_hash_by_path { my $line = <$fd>; close $fd or return undef; + if (!defined $line) { + # there is no tree or hash given by $path at $base + return undef; + } + #'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa panic.c' $line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t/; if (defined $type && $type ne $2) { @@ -1376,8 +1381,12 @@ sub parse_commit_text { pop @commit_lines; # Remove '\0' + if (! @commit_lines) { + return; + } + my $header = shift @commit_lines; - if (!($header =~ m/^[0-9a-fA-F]{40}/)) { + if ($header !~ m/^[0-9a-fA-F]{40}/) { return; } ($co{'id'}, my @parents) = split ' ', $header; @@ -3409,6 +3418,11 @@ sub git_tag { git_header_html(); git_print_page_nav('','', $head,undef,$head); my %tag = parse_tag($hash); + + if (! %tag) { + die_error(undef, "Unknown tag object"); + } + git_print_header_div('commit', esc_html($tag{'name'}), $hash); print "
\n" . "\n" . From f987afa8fe13c2a1512094362b06172419977bc4 Mon Sep 17 00:00:00 2001 From: Frank Lichtenheld Date: Sun, 13 May 2007 02:16:24 +0200 Subject: [PATCH 25/86] cvsserver: Limit config parser to needed options Change the configuration parser so that it ignores everything except for ^gitcvs.((ext|pserver).)? This greatly reduces the risk of failing while parsing some unknown and irrelevant config option. The bug that triggered this change was that the parsing doesn't handle sections that have a subsection and a variable with the same name. While this bug still remains, all remaining causes can be attributed to user error, since there are no defined variables gitcvs.ext and gitcvs.pserver. Signed-off-by: Frank Lichtenheld Signed-off-by: Junio C Hamano --- git-cvsserver.perl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/git-cvsserver.perl b/git-cvsserver.perl index 3e7bf5b54a..a07c72526f 100755 --- a/git-cvsserver.perl +++ b/git-cvsserver.perl @@ -183,9 +183,9 @@ sub req_Root } foreach my $line ( @gitvars ) { - next unless ( $line =~ /^(.*?)\.(.*?)(?:\.(.*?))?=(.*)$/ ); - unless ($3) { - $cfg->{$1}{$2} = $4; + next unless ( $line =~ /^(gitcvs)\.(?:(ext|pserver)\.)?([\w-]+)=(.*)$/ ); + unless ($2) { + $cfg->{$1}{$3} = $4; } else { $cfg->{$1}{$2}{$3} = $4; } From 785cdea9befecc63b2b576c8042c5482fbf7bceb Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sun, 13 May 2007 12:39:22 +0200 Subject: [PATCH 26/86] gitweb: Fix "Use of unitialized value" warnings in empty repository Fix it so gitweb doesn't write "Use of unitialized value..." warnings (which gets written in web server logs) for empty (no commits) repository. In empty repository "last change" (last activity) doesn't make sense; also there is no sense in parsing commits which aren't there. In projects list for empty repositories gitweb now writes "No commits" using "noage" class, instead of leaving cell empty, in the last change column. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index d467bf372a..c2eeca9fa0 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -728,7 +728,9 @@ sub chop_str { sub age_class { my $age = shift; - if ($age < 60*60*2) { + if (!defined $age) { + return "noage"; + } elsif ($age < 60*60*2) { return "age0"; } elsif ($age < 60*60*24*2) { return "age1"; @@ -1258,7 +1260,8 @@ sub git_get_last_activity { 'refs/heads') or return; my $most_recent = <$fd>; close $fd or return; - if ($most_recent =~ / (\d+) [-+][01]\d\d\d$/) { + if (defined $most_recent && + $most_recent =~ / (\d+) [-+][01]\d\d\d$/) { my $timestamp = $1; my $age = time - $timestamp; return ($age, age_string($age)); @@ -2983,7 +2986,7 @@ sub git_project_list_body { esc_html($pr->{'descr'})) . "\n" . "\n"; print "\n" . + (defined $pr->{'age_string'} ? $pr->{'age_string'} : "No commits") . "\n" . "
" . chop_str($pr->{'owner'}, 15) . "{'age'}) . "\">" . - $pr->{'age_string'} . "" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary")}, "summary") . " | " . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"shortlog")}, "shortlog") . " | " . @@ -3335,7 +3338,7 @@ sub git_project_index { sub git_summary { my $descr = git_get_project_description($project) || "none"; my %co = parse_commit("HEAD"); - my %cd = parse_date($co{'committer_epoch'}, $co{'committer_tz'}); + my %cd = %co ? parse_date($co{'committer_epoch'}, $co{'committer_tz'}) : (); my $head = $co{'id'}; my $owner = git_get_project_owner($project); @@ -3358,8 +3361,11 @@ sub git_summary { print "
 
\n"; print "\n" . "\n" . - "\n" . - "\n"; + "\n"; + if (defined $cd{'rfc2822'}) { + print "\n"; + } + # use per project git URL list in $projectroot/$project/cloneurl # or make project git URL from git base URL and project name my $url_tag = "URL"; @@ -3382,11 +3388,13 @@ sub git_summary { # we need to request one more than 16 (0..15) to check if # those 16 are all - my @commitlist = parse_commits($head, 17); - git_print_header_div('shortlog'); - git_shortlog_body(\@commitlist, 0, 15, $refs, - $#commitlist <= 15 ? undef : - $cgi->a({-href => href(action=>"shortlog")}, "...")); + my @commitlist = $head ? parse_commits($head, 17) : (); + if (@commitlist) { + git_print_header_div('shortlog'); + git_shortlog_body(\@commitlist, 0, 15, $refs, + $#commitlist <= 15 ? undef : + $cgi->a({-href => href(action=>"shortlog")}, "...")); + } if (@taglist) { git_print_header_div('tags'); From 331b51d24050c221221049421a924c1a150887db Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Mon, 14 May 2007 01:25:45 +0200 Subject: [PATCH 27/86] Documentation: Split description of pretty formats of commit log Split description of pretty formats into list of pretty options (--pretty and --encoding) in new file Documentation/pretty-options.txt and description of formats itself as a separate "PRETTY FORMATS" section in pretty-formats.txt While at it correct formatting a bit, to be better laid out in the resulting manpages: git-rev-list(1), git-show(1), git-log(1) and git-diff-tree(1). Those manpages now include pretty options in the same place as it was before, and description of formats just after all options. Inspired by the split into two filesdocumentation for merge strategies: Documentation/merge-options.txt and Documentation/merge-strategies.txt Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- Documentation/git-diff-tree.txt | 5 ++- Documentation/git-log.txt | 5 ++- Documentation/git-rev-list.txt | 6 +++- Documentation/git-show.txt | 3 ++ Documentation/pretty-formats.txt | 62 +++++++++++++++----------------- Documentation/pretty-options.txt | 14 ++++++++ 6 files changed, 58 insertions(+), 37 deletions(-) create mode 100644 Documentation/pretty-options.txt diff --git a/Documentation/git-diff-tree.txt b/Documentation/git-diff-tree.txt index 5d6e9dc751..6e660e2d08 100644 --- a/Documentation/git-diff-tree.txt +++ b/Documentation/git-diff-tree.txt @@ -73,7 +73,7 @@ separated with a single space are given. This flag causes "git-diff-tree --stdin" to also show the commit message before the differences. -include::pretty-formats.txt[] +include::pretty-options.txt[] --no-commit-id:: git-diff-tree outputs a line with the commit ID when @@ -104,6 +104,9 @@ include::pretty-formats.txt[] if the diff itself is empty. +include::pretty-formats.txt[] + + Limiting Output --------------- If you're only interested in differences in a subset of files, for diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt index dd06527a1e..0f353f6558 100644 --- a/Documentation/git-log.txt +++ b/Documentation/git-log.txt @@ -25,7 +25,7 @@ This manual page describes only the most frequently used options. OPTIONS ------- -include::pretty-formats.txt[] +include::pretty-options.txt[] -:: Limits the number of commits to show. @@ -58,6 +58,9 @@ include::pretty-formats.txt[] Show only commits that affect the specified paths. +include::pretty-formats.txt[] + + Examples -------- git log --no-merges:: diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt index 1b12b4f2a4..ab90a22f11 100644 --- a/Documentation/git-rev-list.txt +++ b/Documentation/git-rev-list.txt @@ -87,7 +87,7 @@ Using these options, gitlink:git-rev-list[1] will act similar to the more specialized family of commit log tools: gitlink:git-log[1], gitlink:git-show[1], and gitlink:git-whatchanged[1] -include::pretty-formats.txt[] +include::pretty-options.txt[] --relative-date:: @@ -367,6 +367,10 @@ These options are mostly targeted for packing of git repositories. Only useful with '--objects'; print the object IDs that are not in packs. + +include::pretty-formats.txt[] + + Author ------ Written by Linus Torvalds diff --git a/Documentation/git-show.txt b/Documentation/git-show.txt index 5a219ab577..34c5caf2d0 100644 --- a/Documentation/git-show.txt +++ b/Documentation/git-show.txt @@ -38,6 +38,9 @@ OPTIONS For a more complete list of ways to spell object names, see "SPECIFYING REVISIONS" section in gitlink:git-rev-parse[1]. +include::pretty-options.txt[] + + include::pretty-formats.txt[] diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt index d7ffc21ddf..d922e8e86c 100644 --- a/Documentation/pretty-formats.txt +++ b/Documentation/pretty-formats.txt @@ -1,31 +1,32 @@ ---pretty[='']:: +PRETTY FORMATS +-------------- - Pretty-prints the details of a commit. `--pretty` - without an explicit `=` defaults to 'medium'. - If the commit is a merge, and if the pretty-format - is not 'oneline', 'email' or 'raw', an additional line is - inserted before the 'Author:' line. This line begins with - "Merge: " and the sha1s of ancestral commits are printed, - separated by spaces. Note that the listed commits may not - necessarily be the list of the *direct* parent commits if you - have limited your view of history: for example, if you are - only interested in changes related to a certain directory or - file. Here are some additional details for each format: +If the commit is a merge, and if the pretty-format +is not 'oneline', 'email' or 'raw', an additional line is +inserted before the 'Author:' line. This line begins with +"Merge: " and the sha1s of ancestral commits are printed, +separated by spaces. Note that the listed commits may not +necessarily be the list of the *direct* parent commits if you +have limited your view of history: for example, if you are +only interested in changes related to a certain directory or +file. - * 'oneline' +Here are some additional details for each format: + +* 'oneline' + This is designed to be as compact as possible. - * 'short' +* 'short' commit <sha1> Author: <author> <title line> - * 'medium' +* 'medium' commit <sha1> Author: <author> @@ -35,7 +36,7 @@ This is designed to be as compact as possible. <full commit message> - * 'full' +* 'full' commit <sha1> Author: <author> @@ -45,7 +46,7 @@ This is designed to be as compact as possible. <full commit message> - * 'fuller' +* 'fuller' commit <sha1> Author: <author> @@ -57,18 +58,16 @@ This is designed to be as compact as possible. <full commit message> - - * 'email' +* 'email' From <sha1> <date> From: <author> Date: <date & time> Subject: [PATCH] <title line> - full commit message> + <full commit message> - - * 'raw' +* 'raw' + The 'raw' format shows the entire commit exactly as stored in the commit object. Notably, the SHA1s are @@ -77,19 +76,22 @@ displayed in full, regardless of whether --abbrev or true parent commits, without taking grafts nor history simplification into account. - * 'format:' +* 'format:' + The 'format:' format allows you to specify which information you want to show. It works a little bit like printf format, with the notable exception that you get a newline with '%n' instead of '\n'. - -E.g, 'format:"The author of %h was %an, %ar%nThe title was >>%s<<"' ++ +E.g, 'format:"The author of %h was %an, %ar%nThe title was >>%s<<%n"' would show something like this: - ++ +------- The author of fe6e0ee was Junio C Hamano, 23 hours ago The title was >>t4119: test autocomputing -p<n> for traditional diff input.<< +-------- ++ The placeholders are: - '%H': commit hash @@ -120,11 +122,3 @@ The placeholders are: - '%m': left, right or boundary mark - '%n': newline - ---encoding[=<encoding>]:: - The commit objects record the encoding used for the log message - in their encoding header; this option can be used to tell the - command to re-code the commit log message in the encoding - preferred by the user. For non plumbing commands this - defaults to UTF-8. - diff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt new file mode 100644 index 0000000000..7d515be0fd --- /dev/null +++ b/Documentation/pretty-options.txt @@ -0,0 +1,14 @@ +--pretty[='<format>']:: + + Pretty print the contents of the commit logs in a given format, + where '<format>' can be one of 'oneline', 'short', 'medium', + 'full', 'fuller', 'email', 'raw' and 'format:<string>'. + When left out the format default to 'medium'. + +--encoding[=<encoding>]:: + The commit objects record the encoding used for the log message + in their encoding header; this option can be used to tell the + command to re-code the commit log message in the encoding + preferred by the user. For non plumbing commands this + defaults to UTF-8. + From dfaa61bd524799d61b50bbbcee8b7972910ea41c Mon Sep 17 00:00:00 2001 From: Jeff King <peff@peff.net> Date: Sun, 13 May 2007 20:39:11 -0400 Subject: [PATCH 28/86] Documentation/git-add: clarify -u with path limiting Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <junkio@cox.net> --- Documentation/git-add.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt index ea2701846f..27b9c0f8cc 100644 --- a/Documentation/git-add.txt +++ b/Documentation/git-add.txt @@ -57,8 +57,11 @@ OPTIONS the index. -u:: - Update all files that git already knows about. This is what - "git commit -a" does in preparation for making a commit. + Update only files that git already knows about. This is similar + to what "git commit -a" does in preparation for making a commit, + except that the update is limited to paths specified on the + command line. If no paths are specified, all tracked files are + updated. \--:: This option can be used to separate command-line options from From 460c6996e27208898d3e24897e2ea35295c1cbf1 Mon Sep 17 00:00:00 2001 From: Frank Lichtenheld <frank@lichtenheld.de> Date: Sun, 13 May 2007 19:49:05 +0200 Subject: [PATCH 29/86] cvsserver: Don't send mixed messages to clients After we send I HATE YOU we should probably exit and not happily continue with I LOVE YOU and further communication. Most clients will probably just exit and ignore everything we send after the I HATE YOU and it is not a security problem either because we don't really care about the user name anyway. But it is still the right thing to do. [jc: with a minor fixup to its exit code...] Signed-off-by: Frank Lichtenheld <frank@lichtenheld.de> Acked-by: "Martin Langhoff" <martin.langhoff@gmail.com> Signed-off-by: Junio C Hamano <junkio@cox.net> --- git-cvsserver.perl | 1 + 1 file changed, 1 insertion(+) diff --git a/git-cvsserver.perl b/git-cvsserver.perl index a07c72526f..ac88625fc2 100755 --- a/git-cvsserver.perl +++ b/git-cvsserver.perl @@ -105,6 +105,7 @@ if (@ARGV && $ARGV[0] eq 'pserver') { unless ($line eq 'anonymous') { print "E Only anonymous user allowed via pserver\n"; print "I HATE YOU\n"; + exit; } $line = <STDIN>; chomp $line; # validate the password? $line = <STDIN>; chomp $line; From 223fa32784c79bdae7e68266511f9b5e0d65d03e Mon Sep 17 00:00:00 2001 From: Junio C Hamano <junkio@cox.net> Date: Mon, 14 May 2007 14:24:02 -0700 Subject: [PATCH 30/86] Fix git-clone buglet for remote case. c2f599e09fd0496413d1744b5b89b9b5c223555d introduced a buglet while cloning from a remote URL; we forgot to squelch the unnecessary error message when we try to cd to the given "remote" name, in order to see if it is a local directory. Signed-off-by: Junio C Hamano <junkio@cox.net> --- git-clone.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/git-clone.sh b/git-clone.sh index 70374aaaf0..fdd354f2da 100755 --- a/git-clone.sh +++ b/git-clone.sh @@ -22,10 +22,10 @@ get_repo_base() { cd "`/bin/pwd`" && cd "$1" && { - cd .git 2>/dev/null + cd .git pwd } - ) + ) 2>/dev/null } if [ -n "$GIT_SSL_NO_VERIFY" ]; then From 2dc189a3536a367444a4176684c89b994e93e736 Mon Sep 17 00:00:00 2001 From: Frank Lichtenheld <frank@lichtenheld.de> Date: Mon, 14 May 2007 16:44:51 +0200 Subject: [PATCH 31/86] builtin-log.c: Fix typo in comment s/fmt-patch/format-patch/ Signed-off-by: Frank Lichtenheld <frank@lichtenheld.de> Signed-off-by: Junio C Hamano <junkio@cox.net> --- builtin-log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin-log.c b/builtin-log.c index 71df957eaa..51294900dd 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -439,7 +439,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) /* * Parse the arguments before setup_revisions(), or something - * like "git fmt-patch -o a123 HEAD^.." may fail; a123 is + * like "git format-patch -o a123 HEAD^.." may fail; a123 is * possibly a valid SHA1. */ for (i = 1, j = 1; i < argc; i++) { From 7b1885d1e74029fe978be739d2d8d911a34ed8bf Mon Sep 17 00:00:00 2001 From: Frank Lichtenheld <frank@lichtenheld.de> Date: Mon, 14 May 2007 16:44:52 +0200 Subject: [PATCH 32/86] Documentation: format-patch has no --mbox option git-applymbox and git-mailinfo refer to a --mbox option of git-format-patch when talking about their -k options. But there is no such option. What -k does to the former two commands is to keep the Subject: lines unmunged, meant to be used on output generated with format-patch -k. Signed-off-by: Frank Lichtenheld <frank@lichtenheld.de> Signed-off-by: Junio C Hamano <junkio@cox.net> --- Documentation/git-applymbox.txt | 2 +- Documentation/git-mailinfo.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/git-applymbox.txt b/Documentation/git-applymbox.txt index 3bc92d8cf1..ea919ba5d7 100644 --- a/Documentation/git-applymbox.txt +++ b/Documentation/git-applymbox.txt @@ -31,7 +31,7 @@ OPTIONS whitespaces, (3) '[' up to ']', typically '[PATCH]', and then prepends "[PATCH] ". This flag forbids this munging, and is most useful when used to read back 'git - format-patch --mbox' output. + format-patch -k' output. -m:: Patches are applied with `git-apply` command, and unless diff --git a/Documentation/git-mailinfo.txt b/Documentation/git-mailinfo.txt index ba18133ead..8eadcebfcf 100644 --- a/Documentation/git-mailinfo.txt +++ b/Documentation/git-mailinfo.txt @@ -30,7 +30,7 @@ OPTIONS whitespaces, (3) '[' up to ']', typically '[PATCH]', and then prepends "[PATCH] ". This flag forbids this munging, and is most useful when used to read back 'git - format-patch --mbox' output. + format-patch -k' output. -u:: The commit log message, author name and author email are From 870e0d61d30a943dc050a67574f3f32faff226db Mon Sep 17 00:00:00 2001 From: Frank Lichtenheld <frank@lichtenheld.de> Date: Mon, 14 May 2007 16:44:53 +0200 Subject: [PATCH 33/86] git-am: Clean up the asciidoc documentation Add --keep to synopsis. The synopsys used a mix of tabs and spaces, unify to use only spaces. Shuffle options around in synopsys and description for grouping them logically. Add more gitlink references to other commands. Various grammatical fixes and improvements. Signed-off-by: Frank Lichtenheld <frank@lichtenheld.de> Signed-off-by: Junio C Hamano <junkio@cox.net> --- Documentation/git-am.txt | 45 +++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt index f0405a35e9..ba79773f79 100644 --- a/Documentation/git-am.txt +++ b/Documentation/git-am.txt @@ -9,9 +9,10 @@ git-am - Apply a series of patches from a mailbox SYNOPSIS -------- [verse] -'git-am' [--signoff] [--dotest=<dir>] [--utf8 | --no-utf8] [--binary] [--3way] - [--interactive] [--whitespace=<option>] [-C<n>] [-p<n>] - <mbox>... +'git-am' [--signoff] [--dotest=<dir>] [--keep] [--utf8 | --no-utf8] + [--3way] [--interactive] [--binary] + [--whitespace=<option>] [-C<n>] [-p<n>] + <mbox>... 'git-am' [--skip | --resolved] DESCRIPTION @@ -40,7 +41,7 @@ OPTIONS -u, --utf8:: Pass `-u` flag to `git-mailinfo` (see gitlink:git-mailinfo[1]). The proposed commit log message taken from the e-mail - are re-coded into UTF-8 encoding (configuration variable + is re-coded into UTF-8 encoding (configuration variable `i18n.commitencoding` can be used to specify project's preferred encoding if it is not UTF-8). + @@ -51,31 +52,33 @@ default. You could use `--no-utf8` to override this. Pass `-n` flag to `git-mailinfo` (see gitlink:git-mailinfo[1]). --b, --binary:: - Pass `--allow-binary-replacement` flag to `git-apply` - (see gitlink:git-apply[1]). - -3, --3way:: When the patch does not apply cleanly, fall back on 3-way merge, if the patch records the identity of blobs it is supposed to apply to, and we have those blobs - locally. + available locally. + +-b, --binary:: + Pass `--allow-binary-replacement` flag to `git-apply` + (see gitlink:git-apply[1]). + +--whitespace=<option>:: + This flag is passed to the `git-apply` (see gitlink:git-apply[1]) + program that applies + the patch. + +-C<n>, -p<n>:: + These flags are passed to the `git-apply` (see gitlink:git-apply[1]) + program that applies + the patch. + +-i, --interactive:: + Run interactively. --skip:: Skip the current patch. This is only meaningful when restarting an aborted patch. ---whitespace=<option>:: - This flag is passed to the `git-apply` program that applies - the patch. - --C<n>, -p<n>:: - These flags are passed to the `git-apply` program that applies - the patch. - --i, --interactive:: - Run interactively, just like git-applymbox. - -r, --resolved:: After a patch failure (e.g. attempting to apply conflicting patch), the user has applied it by hand and @@ -126,7 +129,7 @@ to crunch. Upon seeing the first patch that does not apply, it aborts in the middle, just like 'git-applymbox' does. You can recover from this in one of two ways: -. skip the current one by re-running the command with '--skip' +. skip the current patch by re-running the command with '--skip' option. . hand resolve the conflict in the working directory, and update From b4b20b2164e433fead84beb526b713a889fc31df Mon Sep 17 00:00:00 2001 From: Jakub Narebski <jnareb@gmail.com> Date: Tue, 15 May 2007 01:55:44 +0200 Subject: [PATCH 34/86] gitweb: Add a few comments about %feature hash Signed-off-by: Jakub Narebski <jnareb@gmail.com> Signed-off-by: Junio C Hamano <junkio@cox.net> --- gitweb/gitweb.perl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 12c2e6685e..7b520f5fc1 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -98,10 +98,13 @@ our %feature = ( # 'override' => allow-override (boolean), # 'default' => [ default options...] (array reference)} # - # if feature is overridable (it means that allow-override has true value, + # if feature is overridable (it means that allow-override has true value), # then feature-sub will be called with default options as parameters; # return value of feature-sub indicates if to enable specified feature # + # if there is no 'sub' key (no feature-sub), then feature cannot be + # overriden + # # use gitweb_check_feature(<feature>) to check if <feature> is enabled # Enable the 'blame' blob view, showing the last commit that modified @@ -134,6 +137,7 @@ our %feature = ( # Enable text search, which will list the commits which match author, # committer or commit text to a given string. Enabled by default. + # Project specific override is not supported. 'search' => { 'override' => 0, 'default' => [1]}, From 52e7b744d365ad4fcbb49fbb2a7b59ddfea90440 Mon Sep 17 00:00:00 2001 From: Junio C Hamano <junkio@cox.net> Date: Mon, 14 May 2007 17:49:55 -0700 Subject: [PATCH 35/86] Prepare for 1.5.1.5 Release Notes Hopefully we will have 1.5.2 soonish, to contain all of these, but we should summarize what we have done regardless. Signed-off-by: Junio C Hamano <junkio@cox.net> --- Documentation/RelNotes-1.5.1.5.txt | 37 ++++++++++++++++++++++++++++++ RelNotes | 2 +- 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 Documentation/RelNotes-1.5.1.5.txt diff --git a/Documentation/RelNotes-1.5.1.5.txt b/Documentation/RelNotes-1.5.1.5.txt new file mode 100644 index 0000000000..5cfe0b5b06 --- /dev/null +++ b/Documentation/RelNotes-1.5.1.5.txt @@ -0,0 +1,37 @@ +GIT v1.5.1.5 Release Notes (draft) +========================== + +Fixes since v1.5.1.4 +-------------------- + +* Bugfixes + + - git-svn was reported to segfault for many people on list and + #git; hopefully this has been fixed. + + - "git-svn clone" does not try to minimize the URL + (i.e. connect to higher level hierarchy) by default, as this + can prevent clone to fail if only part of the repository + (e.g. 'trunk') is open to public. + + - "git checkout branch^0" did not detach the head when you are + already on 'branch'; backported the fix from the 'master'. + + - "git-config section.var" did not correctly work when + existing configuration file had both [section] and [section "name"] + next to each other. + + - "git clone ../other-directory" was fooled if the current + directory $PWD points at is a symbolic link. + + - (build) tree_entry_extract() function was both static inline + and extern, which caused trouble compiling with Forte12 + compilers on Sun. + + - Many documentation fixes. + +-- +exec >/var/tmp/1 +O=v1.5.1.4-26-gb4b20b2 +echo O=`git describe refs/heads/maint` +git shortlog --no-merges $O..refs/heads/maint diff --git a/RelNotes b/RelNotes index 4cad80a03c..8abe4c292b 120000 --- a/RelNotes +++ b/RelNotes @@ -1 +1 @@ -Documentation/RelNotes-1.5.1.4.txt \ No newline at end of file +Documentation/RelNotes-1.5.1.5.txt \ No newline at end of file From af9b54bb2cb0e15780bf3e820b5f1ce399deb2c4 Mon Sep 17 00:00:00 2001 From: Andy Parkins <andyparkins@gmail.com> Date: Mon, 14 May 2007 14:37:25 +0100 Subject: [PATCH 36/86] Use $Id$ as the ident attribute keyword rather than $ident$ to be consistent with other VCSs $Id$ is present already in SVN and CVS; it would mean that people converting their existing repositories won't have to make any changes to the source files should they want to make use of the ident attribute. Given that it's a feature that's meant to calm those very people, it seems obtuse to make them edit every file just to make use of it. I think that bzr uses $Id$; Mercurial has examples hooks for $Id$; monotone has $Id$ on its wishlist. I can't think of a good reason not to stick with the de-facto standard and call ours $Id$ instead of $ident$. Signed-off-by: Andy Parkins <andyparkins@gmail.com> Signed-off-by: Junio C Hamano <junkio@cox.net> --- Documentation/RelNotes-1.5.2.txt | 2 +- Documentation/gitattributes.txt | 6 ++--- convert.c | 44 ++++++++++++++++---------------- t/t0021-conversion.sh | 4 +-- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/Documentation/RelNotes-1.5.2.txt b/Documentation/RelNotes-1.5.2.txt index d1c2cac4fc..7dbdb26988 100644 --- a/Documentation/RelNotes-1.5.2.txt +++ b/Documentation/RelNotes-1.5.2.txt @@ -26,7 +26,7 @@ Updates since v1.5.1 considered a binary or text (the former would be treated by 'git diff' not to produce textual output; the latter can go through the line endings conversion process in repositories - with core.autocrlf set), expand and unexpand '$ident$' keyword + with core.autocrlf set), expand and unexpand '$Id$' keyword with blob object name, specify a custom 3-way merge driver, and specify a custom diff driver. You can also apply arbitrary filter to contents on check-in/check-out codepath diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt index 87723105d1..d3ac9c7181 100644 --- a/Documentation/gitattributes.txt +++ b/Documentation/gitattributes.txt @@ -138,11 +138,11 @@ upon checkout. ^^^^^^^ When the attribute `ident` is set to a path, git replaces -`$ident$` in the blob object with `$ident:`, followed by +`$Id$` in the blob object with `$Id:`, followed by 40-character hexadecimal blob object name, followed by a dollar sign `$` upon checkout. Any byte sequence that begins with -`$ident:` and ends with `$` in the worktree file is replaced -with `$ident$` upon check-in. +`$Id:` and ends with `$` in the worktree file is replaced +with `$Id$` upon check-in. Interaction between checkin/checkout attributes diff --git a/convert.c b/convert.c index 9ee31b0ee0..12abdaf2a5 100644 --- a/convert.c +++ b/convert.c @@ -412,7 +412,7 @@ static void setup_convert_check(struct git_attr_check *check) static int count_ident(const char *cp, unsigned long size) { /* - * "$ident: 0000000000000000000000000000000000000000 $" <=> "$ident$" + * "$Id: 0000000000000000000000000000000000000000 $" <=> "$Id$" */ int cnt = 0; char ch; @@ -422,20 +422,20 @@ static int count_ident(const char *cp, unsigned long size) size--; if (ch != '$') continue; - if (size < 6) + if (size < 3) break; - if (memcmp("ident", cp, 5)) + if (memcmp("Id", cp, 2)) continue; - ch = cp[5]; - cp += 6; - size -= 6; + ch = cp[2]; + cp += 3; + size -= 3; if (ch == '$') - cnt++; /* $ident$ */ + cnt++; /* $Id$ */ if (ch != ':') continue; /* - * "$ident: ... "; scan up to the closing dollar sign and discard. + * "$Id: ... "; scan up to the closing dollar sign and discard. */ while (size) { ch = *cp++; @@ -466,10 +466,10 @@ static char *ident_to_git(const char *path, const char *src, unsigned long *size for (dst = buf; size; size--) { char ch = *src++; *dst++ = ch; - if ((ch == '$') && (6 <= size) && - !memcmp("ident:", src, 6)) { - unsigned long rem = size - 6; - const char *cp = src + 6; + if ((ch == '$') && (3 <= size) && + !memcmp("Id:", src, 3)) { + unsigned long rem = size - 3; + const char *cp = src + 3; do { ch = *cp++; if (ch == '$') @@ -478,8 +478,8 @@ static char *ident_to_git(const char *path, const char *src, unsigned long *size } while (rem); if (!rem) continue; - memcpy(dst, "ident$", 6); - dst += 6; + memcpy(dst, "Id$", 3); + dst += 3; size -= (cp - src); src = cp; } @@ -511,13 +511,13 @@ static char *ident_to_worktree(const char *path, const char *src, unsigned long const char *cp; char ch = *src++; *dst++ = ch; - if ((ch != '$') || (size < 6) || memcmp("ident", src, 5)) + if ((ch != '$') || (size < 3) || memcmp("Id", src, 2)) continue; - if (src[5] == ':') { + if (src[2] == ':') { /* discard up to but not including the closing $ */ - unsigned long rem = size - 6; - cp = src + 6; + unsigned long rem = size - 3; + cp = src + 3; do { ch = *cp++; if (ch == '$') @@ -527,13 +527,13 @@ static char *ident_to_worktree(const char *path, const char *src, unsigned long if (!rem) continue; size -= (cp - src); - } else if (src[5] == '$') - cp = src + 5; + } else if (src[2] == '$') + cp = src + 2; else continue; - memcpy(dst, "ident: ", 7); - dst += 7; + memcpy(dst, "Id: ", 4); + dst += 4; memcpy(dst, sha1_to_hex(sha1), 40); dst += 40; *dst++ = ' '; diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh index bab9ecc34e..6c26fd829d 100755 --- a/t/t0021-conversion.sh +++ b/t/t0021-conversion.sh @@ -21,7 +21,7 @@ test_expect_success setup ' { echo a b c d e f g h i j k l m echo n o p q r s t u v w x y z - echo '\''$ident$'\'' + echo '\''$Id$'\'' } >test && cat test >test.t && cat test >test.o && @@ -31,7 +31,7 @@ test_expect_success setup ' git checkout -- test test.t test.i ' -script='s/^\$ident: \([0-9a-f]*\) \$/\1/p' +script='s/^\$Id: \([0-9a-f]*\) \$/\1/p' test_expect_success check ' From c56f0d9c661dc918a088e60d0ab69dd48019a9be Mon Sep 17 00:00:00 2001 From: Steffen Prohaska <prohaska@zib.de> Date: Thu, 10 May 2007 01:06:36 +0200 Subject: [PATCH 37/86] Optimized cvsexportcommit: calling 'cvs status' once instead of once per touched file. Runtime is now independent of the number of modified files. The old implementation executed 'cvs status' for each file touched by the patch to be applied. The new code calls 'cvs status' only once with all touched files and parses cvs's output to collect all available status information. Signed-off-by: Steffen Prohaska <prohaska@zib.de> Signed-off-by: Junio C Hamano <junkio@cox.net> --- git-cvsexportcommit.perl | 49 ++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/git-cvsexportcommit.perl b/git-cvsexportcommit.perl index 6ed471918d..d6ae99b8c0 100755 --- a/git-cvsexportcommit.perl +++ b/git-cvsexportcommit.perl @@ -160,36 +160,51 @@ foreach my $p (@afiles) { } } +# ... check dirs, foreach my $d (@dirs) { if (-e $d) { $dirty = 1; warn "$d exists and is not a directory!\n"; } } -foreach my $f (@afiles) { - # This should return only one value - if ($f =~ m,(.*)/[^/]*$,) { - my $p = $1; - next if (grep { $_ eq $p } @dirs); - } - my @status = grep(m/^File/, safe_pipe_capture(@cvs, '-q', 'status' ,$f)); - if (@status > 1) { warn 'Strange! cvs status returned more than one line?'}; - if (-d dirname $f and $status[0] !~ m/Status: Unknown$/ - and $status[0] !~ m/^File: no file /) { - $dirty = 1; - warn "File $f is already known in your CVS checkout -- perhaps it has been added by another user. Or this may indicate that it exists on a different branch. If this is the case, use -f to force the merge.\n"; - warn "Status was: $status[0]\n"; + +# ... query status of all files that we have a directory for and parse output of 'cvs status' to %cvsstat. +my @canstatusfiles; +foreach my $f (@files) { + my $path = dirname $f; + next if (grep { $_ eq $path } @dirs); + push @canstatusfiles, $f; +} + +my %cvsstat; +if (@canstatusfiles) { + my @cvsoutput; + @cvsoutput= safe_pipe_capture(@cvs, 'status', @canstatusfiles); + my $matchcount = 0; + foreach my $l (@cvsoutput) { + chomp $l; + if ( $l =~ /^File:/ and $l =~ /Status: (.*)$/ ) { + $cvsstat{$canstatusfiles[$matchcount]} = $1; + $matchcount++; + } } } +# ... validate new files, +foreach my $f (@afiles) { + if (defined ($cvsstat{$f}) and $cvsstat{$f} ne "Unknown") { + $dirty = 1; + warn "File $f is already known in your CVS checkout -- perhaps it has been added by another user. Or this may indicate that it exists on a different branch. If this is the case, use -f to force the merge.\n"; + warn "Status was: $cvsstat{$f}\n"; + } +} +# ... validate known files. foreach my $f (@files) { next if grep { $_ eq $f } @afiles; # TODO:we need to handle removed in cvs - my @status = grep(m/^File/, safe_pipe_capture(@cvs, '-q', 'status' ,$f)); - if (@status > 1) { warn 'Strange! cvs status returned more than one line?'}; - unless ($status[0] =~ m/Status: Up-to-date$/) { + unless (defined ($cvsstat{$f}) and $cvsstat{$f} eq "Up-to-date") { $dirty = 1; - warn "File $f not up to date in your CVS checkout!\n"; + warn "File $f not up to date but has status '$cvsstat{$f}' in your CVS checkout!\n"; } } if ($dirty) { From 045fe3ccdaeb81f12f657b44b5a117b65d9d38e2 Mon Sep 17 00:00:00 2001 From: Quy Tonthat <qtonthat@gmail.com> Date: Tue, 15 May 2007 12:51:02 +1000 Subject: [PATCH 38/86] Documentation/branch: fix small typo in -D example Signed-off-by: Quy Tonthat <qtonthat@gmail.com> Signed-off-by: Junio C Hamano <junkio@cox.net> --- Documentation/git-branch.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt index 603f87f3b5..8dc5171f5e 100644 --- a/Documentation/git-branch.txt +++ b/Documentation/git-branch.txt @@ -136,7 +136,7 @@ $ git branch -D test <2> + <1> delete remote-tracking branches "todo", "html", "man" <2> delete "test" branch even if the "master" branch does not have all -commits from todo branch. +commits from test branch. Notes From cf606e3ddd8666b990a6560be77eb9f28af0e47d Mon Sep 17 00:00:00 2001 From: Andy Whitcroft <apw@shadowen.org> Date: Tue, 15 May 2007 17:33:25 +0100 Subject: [PATCH 39/86] git name-rev writes beyond the end of malloc() with large generations When using git name-rev on my kernel tree I triggered a malloc() corruption warning from glibc. apw@pinky$ git log --pretty=one $N/base.. | git name-rev --stdin *** glibc detected *** malloc(): memory corruption: 0x0bff8950 *** Aborted This comes from name_rev() which is building the name of the revision in a malloc'd string, which it sprintf's into: char *new_name = xmalloc(len + 8); [...] sprintf(new_name, "%.*s~%d^%d", len, tip_name, generation, parent_number); This allocation is only sufficient if the generation number is less than 5 digits, in my case generation was 13432. In reality parent_number can be up to 16 so that also can require two digits, reducing us to 3 digits before we are at risk of blowing this allocation. This patch introduces a decimal_length() which approximates the number of digits a type may hold, it produces the following: Type Longest Value Len Est ---- ------------- --- --- unsigned char 256 3 4 unsigned short 65536 5 6 unsigned long 4294967296 10 11 unsigned long long 18446744073709551616 20 21 char -128 4 4 short -32768 6 6 long -2147483648 11 11 long long -9223372036854775808 20 21 This is then used to size the new_name. Signed-off-by: Andy Whitcroft <apw@shadowen.org> Signed-off-by: Junio C Hamano <junkio@cox.net> --- builtin-name-rev.c | 5 ++++- git-compat-util.h | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/builtin-name-rev.c b/builtin-name-rev.c index c022224361..ef16385907 100644 --- a/builtin-name-rev.c +++ b/builtin-name-rev.c @@ -58,7 +58,10 @@ copy_data: parents = parents->next, parent_number++) { if (parent_number > 1) { int len = strlen(tip_name); - char *new_name = xmalloc(len + 8); + char *new_name = xmalloc(len + + 1 + decimal_length(generation) + /* ~<n> */ + 1 + 2 + /* ^NN */ + 1); if (len > 2 && !strcmp(tip_name + len - 2, "^0")) len -= 2; diff --git a/git-compat-util.h b/git-compat-util.h index bd93b62578..7ed8b88b1f 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -13,6 +13,9 @@ #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) +/* Approximation of the length of the decimal representation of this type. */ +#define decimal_length(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1) + #if !defined(__APPLE__) && !defined(__FreeBSD__) #define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500, OpenBSD needs 600 for S_ISLNK() */ #define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */ From 2924415f4fb081d9dde687092248c86ec0c40195 Mon Sep 17 00:00:00 2001 From: Johan Herland <johan@herland.net> Date: Tue, 15 May 2007 14:39:25 +0200 Subject: [PATCH 40/86] Fix signedness on return value from xread() The return value from xread() is ssize_t. Paolo Teti <paolo.teti@gmail.com> pointed out that in this case, the signed return value was assigned to an unsigned type (size_t). This patch fixes that. Signed-off-by: Johan Herland <johan@herland.net> Signed-off-by: Junio C Hamano <junkio@cox.net> --- pack-write.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pack-write.c b/pack-write.c index de72f44dc8..ae2e481e55 100644 --- a/pack-write.c +++ b/pack-write.c @@ -25,7 +25,7 @@ void fixup_pack_header_footer(int pack_fd, buf = xmalloc(buf_sz); for (;;) { - size_t n = xread(pack_fd, buf, buf_sz); + ssize_t n = xread(pack_fd, buf, buf_sz); if (!n) break; if (n < 0) From 8a912bcb250d8bf57b225e1cf02c0d69d54c8920 Mon Sep 17 00:00:00 2001 From: Johan Herland <johan@herland.net> Date: Tue, 15 May 2007 14:49:22 +0200 Subject: [PATCH 41/86] Ensure return value from xread() is always stored into an ssize_t This patch fixes all calls to xread() where the return value is not stored into an ssize_t. The patch should not have any effect whatsoever, other than putting better/more appropriate type names on variables. Signed-off-by: Johan Herland <johan@herland.net> Signed-off-by: Junio C Hamano <junkio@cox.net> --- builtin-apply.c | 4 ++-- builtin-bundle.c | 2 +- builtin-fetch--tool.c | 4 ++-- builtin-unpack-objects.c | 2 +- combine-diff.c | 2 +- copy.c | 3 +-- diff.c | 2 +- imap-send.c | 2 +- index-pack.c | 2 +- pkt-line.c | 4 ++-- sha1_file.c | 2 +- ssh-upload.c | 2 +- 12 files changed, 15 insertions(+), 16 deletions(-) diff --git a/builtin-apply.c b/builtin-apply.c index 8b8705a6c0..0399743c4e 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -185,7 +185,7 @@ static void *read_patch_file(int fd, unsigned long *sizep) void *buffer = xmalloc(alloc); for (;;) { - int nr = alloc - size; + ssize_t nr = alloc - size; if (nr < 1024) { alloc += CHUNKSIZE; buffer = xrealloc(buffer, alloc); @@ -1468,7 +1468,7 @@ static int read_old_data(struct stat *st, const char *path, char **buf_p, unsign return error("unable to open %s", path); got = 0; for (;;) { - int ret = xread(fd, buf + got, size - got); + ssize_t ret = xread(fd, buf + got, size - got); if (ret <= 0) break; got += ret; diff --git a/builtin-bundle.c b/builtin-bundle.c index d1635a0a6b..306ad29597 100644 --- a/builtin-bundle.c +++ b/builtin-bundle.c @@ -48,7 +48,7 @@ static int read_string(int fd, char *buffer, int size) { int i; for (i = 0; i < size - 1; i++) { - int count = xread(fd, buffer + i, 1); + ssize_t count = xread(fd, buffer + i, 1); if (count < 0) return error("Read error: %s", strerror(errno)); if (count == 0) { diff --git a/builtin-fetch--tool.c b/builtin-fetch--tool.c index 2065466f27..12adb3833c 100644 --- a/builtin-fetch--tool.c +++ b/builtin-fetch--tool.c @@ -6,11 +6,11 @@ static char *get_stdin(void) { - int offset = 0; + size_t offset = 0; char *data = xmalloc(CHUNK_SIZE); while (1) { - int cnt = xread(0, data + offset, CHUNK_SIZE); + ssize_t cnt = xread(0, data + offset, CHUNK_SIZE); if (cnt < 0) die("error reading standard input: %s", strerror(errno)); diff --git a/builtin-unpack-objects.c b/builtin-unpack-objects.c index 2bbda67fab..a6ff62fd8c 100644 --- a/builtin-unpack-objects.c +++ b/builtin-unpack-objects.c @@ -34,7 +34,7 @@ static void *fill(int min) offset = 0; } do { - int ret = xread(0, buffer + len, sizeof(buffer) - len); + ssize_t ret = xread(0, buffer + len, sizeof(buffer) - len); if (ret <= 0) { if (!ret) die("early EOF"); diff --git a/combine-diff.c b/combine-diff.c index cff9c5dc42..ea3ca5f950 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -714,7 +714,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, result_size = len; result = xmalloc(len + 1); while (sz < len) { - int done = xread(fd, result+sz, len-sz); + ssize_t done = xread(fd, result+sz, len-sz); if (done == 0) break; if (done < 0) diff --git a/copy.c b/copy.c index 08a3d388a4..d340bb253e 100644 --- a/copy.c +++ b/copy.c @@ -3,10 +3,9 @@ int copy_fd(int ifd, int ofd) { while (1) { - int len; char buffer[8192]; char *buf = buffer; - len = xread(ifd, buffer, sizeof(buffer)); + ssize_t len = xread(ifd, buffer, sizeof(buffer)); if (!len) break; if (len < 0) { diff --git a/diff.c b/diff.c index 8354e71e07..33297aa8a7 100644 --- a/diff.c +++ b/diff.c @@ -1411,7 +1411,7 @@ static int populate_from_stdin(struct diff_filespec *s) #define INCREMENT 1024 char *buf; unsigned long size; - int got; + ssize_t got; size = 0; buf = NULL; diff --git a/imap-send.c b/imap-send.c index 84df2fabb7..4283a4acda 100644 --- a/imap-send.c +++ b/imap-send.c @@ -224,7 +224,7 @@ socket_perror( const char *func, Socket_t *sock, int ret ) static int socket_read( Socket_t *sock, char *buf, int len ) { - int n = xread( sock->fd, buf, len ); + ssize_t n = xread( sock->fd, buf, len ); if (n <= 0) { socket_perror( "read", sock, n ); close( sock->fd ); diff --git a/index-pack.c b/index-pack.c index b9da19f55b..58c4a9c41d 100644 --- a/index-pack.c +++ b/index-pack.c @@ -82,7 +82,7 @@ static void *fill(int min) die("cannot fill %d bytes", min); flush(); do { - int ret = xread(input_fd, input_buffer + input_len, + ssize_t ret = xread(input_fd, input_buffer + input_len, sizeof(input_buffer) - input_len); if (ret <= 0) { if (!ret) diff --git a/pkt-line.c b/pkt-line.c index b4cb7e2756..b60526869a 100644 --- a/pkt-line.c +++ b/pkt-line.c @@ -65,10 +65,10 @@ void packet_write(int fd, const char *fmt, ...) static void safe_read(int fd, void *buffer, unsigned size) { - int n = 0; + size_t n = 0; while (n < size) { - int ret = xread(fd, (char *) buffer + n, size - n); + ssize_t ret = xread(fd, (char *) buffer + n, size - n); if (ret < 0) die("read error (%s)", strerror(errno)); if (!ret) diff --git a/sha1_file.c b/sha1_file.c index 32244d704e..be991ed22a 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -2276,7 +2276,7 @@ int read_pipe(int fd, char** return_buf, unsigned long* return_size) { char* buf = *return_buf; unsigned long size = *return_size; - int iret; + ssize_t iret; unsigned long off = 0; do { diff --git a/ssh-upload.c b/ssh-upload.c index 2f04572787..498d41e19b 100644 --- a/ssh-upload.c +++ b/ssh-upload.c @@ -86,7 +86,7 @@ static int serve_ref(int fd_in, int fd_out) static void service(int fd_in, int fd_out) { char type; - int retval; + ssize_t retval; do { retval = xread(fd_in, &type, 1); if (retval < 1) { From df8cfac815a1fae75afd20a86beb194d9d947971 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin <Johannes.Schindelin@gmx.de> Date: Wed, 16 May 2007 17:22:26 +0100 Subject: [PATCH 42/86] import-tars: Use the "Link indicator" to identify directories Earlier, we used the mode to determine if a name was associated with a directory. This fails, since some tar programs do not set the mode correctly. However, the link indicator _has_ to be set correctly. Noticed by Chris Riddoch. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Acked-by: Junio C Hamano <junkio@cox.net> Signed-off-by: Shawn O. Pearce <spearce@spearce.org> --- contrib/fast-import/import-tars.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/fast-import/import-tars.perl b/contrib/fast-import/import-tars.perl index f0b9a43abd..5bfd205225 100755 --- a/contrib/fast-import/import-tars.perl +++ b/contrib/fast-import/import-tars.perl @@ -75,7 +75,7 @@ foreach my $tar_file (@ARGV) $mode = oct $mode; $size = oct $size; $mtime = oct $mtime; - next if $mode & 0040000; + next if $typeflag == 5; # directory print FI "blob\n", "mark :$next_mark\n", "data $size\n"; while ($size > 0 && read(I, $_, 512) == 512) { From 61d7256431da590dfca689e0681ed9437fd5d448 Mon Sep 17 00:00:00 2001 From: Steffen Prohaska <prohaska@zib.de> Date: Wed, 16 May 2007 07:48:47 +0200 Subject: [PATCH 43/86] Fixed link in user-manual link to git-mergetool was broken. Signed-off-by: Steffen Prohaska <prohaska@zib.de> Signed-off-by: Junio C Hamano <junkio@cox.net> --- Documentation/user-manual.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index 13db9699c1..dd1578dc8d 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -1357,7 +1357,7 @@ $ gitk --merge These will display all commits which exist only on HEAD or on MERGE_HEAD, and which touch an unmerged file. -You may also use gitlink:git-mergetool, which lets you merge the +You may also use gitlink:git-mergetool[1], which lets you merge the unmerged files using external tools such as emacs or kdiff3. Each time you resolve the conflicts in a file and update the index: From 0ab564be6e59c66c7aa4fc44997f3fc62ebcd0d9 Mon Sep 17 00:00:00 2001 From: Jeff King <peff@peff.net> Date: Tue, 15 May 2007 11:35:13 -0400 Subject: [PATCH 44/86] format-patch: add MIME-Version header when we add content-type. When we add Content-Type: header, we should also add MIME-Version: header as well. Signed-off-by: Junio C Hamano <junkio@cox.net> --- commit.c | 1 + 1 file changed, 1 insertion(+) diff --git a/commit.c b/commit.c index 7d78e786e9..43b767ce53 100644 --- a/commit.c +++ b/commit.c @@ -1057,6 +1057,7 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt, int sz; char header[512]; const char *header_fmt = + "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=%s\n" "Content-Transfer-Encoding: 8bit\n"; sz = snprintf(header, sizeof(header), header_fmt, From b211c320eb5d753a7a44a03eccb9a15cfbcc563b Mon Sep 17 00:00:00 2001 From: Jakub Narebski <jnareb@gmail.com> Date: Wed, 16 May 2007 01:59:55 +0200 Subject: [PATCH 45/86] gitweb: Do not use absolute font sizes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit David Kågedal proposed that gitweb should explicitely request being somewhat smaller than normal, because it has good use for long lines. However gitweb presents a table with several columns, so having wider line is OK for it. Therefore explicit 'font-size: small' would make sense. Apparently many people on the list seem to agree with him. Signed-off-by: Junio C Hamano <junkio@cox.net> --- gitweb/gitweb.css | 1 + 1 file changed, 1 insertion(+) diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css index b57c8beccb..02623cbb6d 100644 --- a/gitweb/gitweb.css +++ b/gitweb/gitweb.css @@ -1,5 +1,6 @@ body { font-family: sans-serif; + font-size: small; border: solid #d9d8d1; border-width: 1px; margin: 10px; From 7e431ef9ab933d7ff899a999e40627ab49774f3a Mon Sep 17 00:00:00 2001 From: Jakub Narebski <jnareb@gmail.com> Date: Wed, 16 May 2007 01:56:10 +0200 Subject: [PATCH 46/86] gitweb: Separate search regexp from search text Separate search text, which is saved in $searchtext global variable, and is used in links, as default value for the textfield in search form, and for pickaxe search, from search regexp, which is saved in $search_regexp global variable, and is used as parameter to --grep, --committer or --author options to git-rev-list, and for searching commit body in gitweb. For now $search_regexp is unconditionallt equal to quotemeta($searchtext), meaning that we always search for fixed string. This fixes bug where 'next page' links for 'search' view didn't work for searchtext containing quotable characters, like `@'. Signed-off-by: Jakub Narebski <jnareb@gmail.com> Signed-off-by: Junio C Hamano <junkio@cox.net> --- gitweb/gitweb.perl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index a13043deea..549e0270b6 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -365,6 +365,7 @@ if (defined $page) { } our $searchtext = $cgi->param('s'); +our $search_regexp; if (defined $searchtext) { if ($searchtext =~ m/[^a-zA-Z0-9_\.\/\-\+\:\@ ]/) { die_error(undef, "Invalid search parameter"); @@ -372,7 +373,7 @@ if (defined $searchtext) { if (length($searchtext) < 2) { die_error(undef, "At least two characters are required for search parameter"); } - $searchtext = quotemeta $searchtext; + $search_regexp = quotemeta $searchtext; } our $searchtype = $cgi->param('st'); @@ -3244,7 +3245,7 @@ sub git_search_grep_body { esc_html(chop_str($co{'title'}, 50)) . "<br/>"); my $comment = $co{'comment'}; foreach my $line (@$comment) { - if ($line =~ m/^(.*)($searchtext)(.*)$/i) { + if ($line =~ m/^(.*)($search_regexp)(.*)$/i) { my $lead = esc_html($1) || ""; $lead = chop_str($lead, 30, 10); my $match = esc_html($2) || ""; @@ -4626,7 +4627,7 @@ sub git_search { } elsif ($searchtype eq 'committer') { $greptype = "--committer="; } - $greptype .= $searchtext; + $greptype .= $search_regexp; my @commitlist = parse_commits($hash, 101, (100 * $page), $greptype); my $paging_nav = ''; From d26c4264e584a1a8cbadbc161fa52cf947f5230a Mon Sep 17 00:00:00 2001 From: Jakub Narebski <jnareb@gmail.com> Date: Thu, 17 May 2007 00:05:55 +0200 Subject: [PATCH 47/86] gitweb: Empty patch for merge means trivial merge, not no differences Earlier commit 4280cde95fa4e3fb012eb6d0c239a7777baaf60c made gitweb show "No differences found" message for empty diff, for the HTML output. But for merge commits, either -c format we use or --cc format, empty diff doesn't mean no differences, but trivial merge. Show "Trivial merge" message instead of "No differences found" for merges. While at it reword conditional in the code for easier reading. Signed-off-by: Jakub Narebski <jnareb@gmail.com> Signed-off-by: Junio C Hamano <junkio@cox.net> --- gitweb/gitweb.perl | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 549e0270b6..8c688be66d 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2877,7 +2877,14 @@ sub git_patchset_body { } continue { print "</div>\n"; # class="patch" } - print "<div class=\"diff nodifferences\">No differences found</div>\n" if (!$patch_number); + + if ($patch_number == 0) { + if (@hash_parents > 1) { + print "<div class=\"diff nodifferences\">Trivial merge</div>\n"; + } else { + print "<div class=\"diff nodifferences\">No differences found</div>\n"; + } + } print "</div>\n"; # class="patchset" } From 126640afbc3732f3d7c65d89d9f0505941c7ca24 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin <Johannes.Schindelin@gmx.de> Date: Thu, 10 May 2007 12:36:15 +0200 Subject: [PATCH 48/86] Add a birdview-on-the-source-code section to the user manual MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In http://thread.gmane.org/gmane.comp.version-control.git/42479, a birdview on the source code was requested. J. Bruce Fields suggested that my reply should be included in the user manual, and there was nothing of an outcry, so here it is, not 2 months later. It includes modifications as suggested by J. Bruce Fields, Karl Hasselström and Daniel Barkalow. Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de> --- Documentation/user-manual.txt | 219 ++++++++++++++++++++++++++++++++++ 1 file changed, 219 insertions(+) diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index dd1578dc8d..9e61798344 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -3160,6 +3160,225 @@ confusing and scary messages, but it won't actually do anything bad. In contrast, running "git prune" while somebody is actively changing the repository is a *BAD* idea). +[[birdview-on-the-source-code]] +A birdview on Git's source code +----------------------------- + +While Git's source code is quite elegant, it is not always easy for +new developers to find their way through it. A good idea is to look +at the contents of the initial commit: +_e83c5163316f89bfbde7d9ab23ca2e25604af290_ (also known as _v0.99~954_). + +Tip: you can see what files are in there with + +---------------------------------------------------- +$ git show e83c5163316f89bfbde7d9ab23ca2e25604af290: +---------------------------------------------------- + +and look at those files with something like + +----------------------------------------------------------- +$ git show e83c5163316f89bfbde7d9ab23ca2e25604af290:cache.h +----------------------------------------------------------- + +Be sure to read the README in that revision _after_ you are familiar with +the terminology (<<glossary>>), since the terminology has changed a little +since then. For example, we call the things "commits" now, which are +described in that README as "changesets". + +Actually a lot of the structure as it is now can be explained by that +initial commit. + +For example, we do not call it "cache" any more, but "index", however, the +file is still called `cache.h`. Remark: Not much reason to change it now, +especially since there is no good single name for it anyway, because it is +basically _the_ header file which is included by _all_ of Git's C sources. + +If you grasp the ideas in that initial commit (it is really small and you +can get into it really fast, and it will help you recognize things in the +much larger code base we have now), you should go on skimming `cache.h`, +`object.h` and `commit.h` in the current version. + +In the early days, Git (in the tradition of UNIX) was a bunch of programs +which were extremely simple, and which you used in scripts, piping the +output of one into another. This turned out to be good for initial +development, since it was easier to test new things. However, recently +many of these parts have become builtins, and some of the core has been +"libified", i.e. put into libgit.a for performance, portability reasons, +and to avoid code duplication. + +By now, you know what the index is (and find the corresponding data +structures in `cache.h`), and that there are just a couple of object types +(blobs, trees, commits and tags) which inherit their common structure from +`struct object`, which is their first member (and thus, you can cast e.g. +`(struct object *)commit` to achieve the _same_ as `&commit->object`, i.e. +get at the object name and flags). + +Now is a good point to take a break to let this information sink in. + +Next step: get familiar with the object naming. Read <<naming-commits>>. +There are quite a few ways to name an object (and not only revisions!). +All of these are handled in `sha1_name.c`. Just have a quick look at +the function `get_sha1()`. A lot of the special handling is done by +functions like `get_sha1_basic()` or the likes. + +This is just to get you into the groove for the most libified part of Git: +the revision walker. + +Basically, the initial version of `git log` was a shell script: + +---------------------------------------------------------------- +$ git-rev-list --pretty $(git-rev-parse --default HEAD "$@") | \ + LESS=-S ${PAGER:-less} +---------------------------------------------------------------- + +What does this mean? + +`git-rev-list` is the original version of the revision walker, which +_always_ printed a list of revisions to stdout. It is still functional, +and needs to, since most new Git programs start out as scripts using +`git-rev-list`. + +`git-rev-parse` is not as important any more; it was only used to filter out +options that were relevant for the different plumbing commands that were +called by the script. + +Most of what `git-rev-list` did is contained in `revision.c` and +`revision.h`. It wraps the options in a struct named `rev_info`, which +controls how and what revisions are walked, and more. + +The original job of `git-rev-parse` is now taken by the function +`setup_revisions()`, which parses the revisions and the common command line +options for the revision walker. This information is stored in the struct +`rev_info` for later consumption. You can do your own command line option +parsing after calling `setup_revisions()`. After that, you have to call +`prepare_revision_walk()` for initialization, and then you can get the +commits one by one with the function `get_revision()`. + +If you are interested in more details of the revision walking process, +just have a look at the first implementation of `cmd_log()`; call +`git-show v1.3.0~155^2~4` and scroll down to that function (note that you +no longer need to call `setup_pager()` directly). + +Nowadays, `git log` is a builtin, which means that it is _contained_ in the +command `git`. The source side of a builtin is + +- a function called `cmd_<bla>`, typically defined in `builtin-<bla>.c`, + and declared in `builtin.h`, + +- an entry in the `commands[]` array in `git.c`, and + +- an entry in `BUILTIN_OBJECTS` in the `Makefile`. + +Sometimes, more than one builtin is contained in one source file. For +example, `cmd_whatchanged()` and `cmd_log()` both reside in `builtin-log.c`, +since they share quite a bit of code. In that case, the commands which are +_not_ named like the `.c` file in which they live have to be listed in +`BUILT_INS` in the `Makefile`. + +`git log` looks more complicated in C than it does in the original script, +but that allows for a much greater flexibility and performance. + +Here again it is a good point to take a pause. + +Lesson three is: study the code. Really, it is the best way to learn about +the organization of Git (after you know the basic concepts). + +So, think about something which you are interested in, say, "how can I +access a blob just knowing the object name of it?". The first step is to +find a Git command with which you can do it. In this example, it is either +`git show` or `git cat-file`. + +For the sake of clarity, let's stay with `git cat-file`, because it + +- is plumbing, and + +- was around even in the initial commit (it literally went only through + some 20 revisions as `cat-file.c`, was renamed to `builtin-cat-file.c` + when made a builtin, and then saw less than 10 versions). + +So, look into `builtin-cat-file.c`, search for `cmd_cat_file()` and look what +it does. + +------------------------------------------------------------------ + git_config(git_default_config); + if (argc != 3) + usage("git-cat-file [-t|-s|-e|-p|<type>] <sha1>"); + if (get_sha1(argv[2], sha1)) + die("Not a valid object name %s", argv[2]); +------------------------------------------------------------------ + +Let's skip over the obvious details; the only really interesting part +here is the call to `get_sha1()`. It tries to interpret `argv[2]` as an +object name, and if it refers to an object which is present in the current +repository, it writes the resulting SHA-1 into the variable `sha1`. + +Two things are interesting here: + +- `get_sha1()` returns 0 on _success_. This might surprise some new + Git hackers, but there is a long tradition in UNIX to return different + negative numbers in case of different errors -- and 0 on success. + +- the variable `sha1` in the function signature of `get_sha1()` is `unsigned + char *`, but is actually expected to be a pointer to `unsigned + char[20]`. This variable will contain the 160-bit SHA-1 of the given + commit. Note that whenever a SHA-1 is passed as "unsigned char *", it + is the binary representation, as opposed to the ASCII representation in + hex characters, which is passed as "char *". + +You will see both of these things throughout the code. + +Now, for the meat: + +----------------------------------------------------------------------------- + case 0: + buf = read_object_with_reference(sha1, argv[1], &size, NULL); +----------------------------------------------------------------------------- + +This is how you read a blob (actually, not only a blob, but any type of +object). To know how the function `read_object_with_reference()` actually +works, find the source code for it (something like `git grep +read_object_with | grep ":[a-z]"` in the git repository), and read +the source. + +To find out how the result can be used, just read on in `cmd_cat_file()`: + +----------------------------------- + write_or_die(1, buf, size); +----------------------------------- + +Sometimes, you do not know where to look for a feature. In many such cases, +it helps to search through the output of `git log`, and then `git show` the +corresponding commit. + +Example: If you know that there was some test case for `git bundle`, but +do not remember where it was (yes, you _could_ `git grep bundle t/`, but that +does not illustrate the point!): + +------------------------ +$ git log --no-merges t/ +------------------------ + +In the pager (`less`), just search for "bundle", go a few lines back, +and see that it is in commit 18449ab0... Now just copy this object name, +and paste it into the command line + +------------------- +$ git show 18449ab0 +------------------- + +Voila. + +Another example: Find out what to do in order to make some script a +builtin: + +------------------------------------------------- +$ git log --no-merges --diff-filter=A builtin-*.c +------------------------------------------------- + +You see, Git is actually the best tool to find out about the source of Git +itself! + [[glossary]] include::glossary.txt[] From 2eb54efc6c12cb20403db9a4739bd736c3bfaad1 Mon Sep 17 00:00:00 2001 From: Junio C Hamano <junkio@cox.net> Date: Wed, 16 May 2007 21:04:16 -0700 Subject: [PATCH 49/86] gitweb: fix another use of undefined value Pasky and Jakub competed fixing these and in the confusion this ended up not being covered. Signed-off-by: Junio C Hamano <junkio@cox.net> --- gitweb/gitweb.perl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 8c688be66d..6f5df9174e 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1114,7 +1114,9 @@ sub git_get_project_description { open my $fd, "$projectroot/$path/description" or return undef; my $descr = <$fd>; close $fd; - chomp $descr; + if (defined $descr) { + chomp $descr; + } return $descr; } From 504ceab6d24bc19ed5a04b5978c8899fa58dffe1 Mon Sep 17 00:00:00 2001 From: Michael Hendricks <michael@ndrix.org> Date: Wed, 16 May 2007 23:15:16 -0600 Subject: [PATCH 50/86] git-send-email: allow leading white space on mutt aliases mutt version 1.5.14 (perhaps earlier versions too) permits alias files to have white space before the 'alias' keyword. Signed-off-by: Michael Hendricks <michael@ndrix.org> Signed-off-by: Junio C Hamano <junkio@cox.net> --- git-send-email.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-send-email.perl b/git-send-email.perl index 12ced28885..e60d8777f0 100755 --- a/git-send-email.perl +++ b/git-send-email.perl @@ -212,7 +212,7 @@ my $aliasfiletype = $repo->config('sendemail.aliasfiletype'); my %parse_alias = ( # multiline formats can be supported in the future mutt => sub { my $fh = shift; while (<$fh>) { - if (/^alias\s+(\S+)\s+(.*)$/) { + if (/^\s*alias\s+(\S+)\s+(.*)$/) { my ($alias, $addr) = ($1, $2); $addr =~ s/#.*$//; # mutt allows # comments # commas delimit multiple addresses From b9e7efb8b5f7d424466dd1ce61fd20658f60543f Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" <spearce@spearce.org> Date: Thu, 17 May 2007 18:01:50 -0400 Subject: [PATCH 51/86] git-gui: Gracefully handle bad TCL_PATH at compile time Petr Baudis pointed out the main git.git repository's Makefile dies now if git-gui 0.7.0-rc1 or later is being used and TCL_PATH was not set to a working tclsh program path. This breaks people who may have a working build configuration today and suddenly upgrade to the latest git release. The tclIndex is required for git-gui to load its associated lib files, but using the Tcl auto_load procedure to source only the files we need is a performance optimization. We can emulate the auto_load by just source'ing every file in that directory, assuming we source class.tcl first to initialize our crude class system. Signed-off-by: Shawn O. Pearce <spearce@spearce.org> --- Makefile | 19 ++++++++++++++++--- git-gui.sh | 29 ++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index e73b6453d9..ee564219c0 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,7 @@ SCRIPT_SH = git-gui.sh GITGUI_BUILT_INS = git-citool ALL_PROGRAMS = $(GITGUI_BUILT_INS) $(patsubst %.sh,%,$(SCRIPT_SH)) ALL_LIBFILES = $(wildcard lib/*.tcl) +PRELOAD_FILES = lib/class.tcl ifndef SHELL_PATH SHELL_PATH = /bin/sh @@ -32,6 +33,7 @@ ifndef V QUIET_GEN = @echo ' ' GEN $@; QUIET_BUILT_IN = @echo ' ' BUILTIN $@; QUIET_INDEX = @echo ' ' INDEX $(dir $@); + QUIET_2DEVNULL = 2>/dev/null endif TCL_PATH ?= tclsh @@ -45,6 +47,7 @@ endif DESTDIR_SQ = $(subst ','\'',$(DESTDIR)) gitexecdir_SQ = $(subst ','\'',$(gitexecdir)) SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) +TCL_PATH_SQ = $(subst ','\'',$(TCL_PATH)) TCLTK_PATH_SQ = $(subst ','\'',$(TCLTK_PATH)) libdir ?= $(sharedir)/git-gui/lib @@ -64,16 +67,26 @@ $(GITGUI_BUILT_INS): git-gui $(QUIET_BUILT_IN)rm -f $@ && ln git-gui $@ lib/tclIndex: $(ALL_LIBFILES) - $(QUIET_INDEX)echo \ - source lib/class.tcl \; \ + $(QUIET_INDEX)if echo \ + $(foreach p,$(PRELOAD_FILES),source $p\;) \ auto_mkindex lib '*.tcl' \ - | $(TCL_PATH) + | $(TCL_PATH) $(QUIET_2DEVNULL); then : ok; \ + else \ + echo 1>&2 " * $(TCL_PATH) failed; using unoptimized loading"; \ + rm -f $@ ; \ + echo '# Autogenerated by git-gui Makefile' >$@ && \ + echo >>$@ && \ + $(foreach p,$(PRELOAD_FILES) $(ALL_LIBFILES),echo '$(subst lib/,,$p)' >>$@ &&) \ + echo >>$@ ; \ + fi # These can record GITGUI_VERSION $(patsubst %.sh,%,$(SCRIPT_SH)): GIT-VERSION-FILE GIT-GUI-VARS +lib/tclIndex: GIT-GUI-VARS TRACK_VARS = \ $(subst ','\'',SHELL_PATH='$(SHELL_PATH_SQ)') \ + $(subst ','\'',TCL_PATH='$(TCL_PATH_SQ)') \ $(subst ','\'',TCLTK_PATH='$(TCLTK_PATH_SQ)') \ $(subst ','\'',libdir='$(libdir_SQ)') \ #end TRACK_VARS diff --git a/git-gui.sh b/git-gui.sh index 2fda4c2290..0a471a5c7d 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -28,7 +28,34 @@ set oguilib {@@GITGUI_LIBDIR@@} if {[string match @@* $oguilib]} { set oguilib [file join [file dirname [file normalize $argv0]] lib] } -set auto_path [concat [list $oguilib] $auto_path] +set idx [file join $oguilib tclIndex] +catch { + set fd [open $idx r] + if {[gets $fd] eq {# Autogenerated by git-gui Makefile}} { + set idx [list] + while {[gets $fd n] >= 0} { + if {$n ne {} && ![string match #* $n]} { + lappend idx $n + } + } + } else { + set idx {} + } + close $fd +} +if {$idx ne {}} { + set loaded [list] + foreach p $idx { + if {[lsearch -exact $loaded $p] >= 0} continue + puts $p + source [file join $oguilib $p] + lappend loaded $p + } + unset loaded p +} else { + set auto_path [concat [list $oguilib] $auto_path] +} +unset -nocomplain fd idx if {![catch {set _verbose $env(GITGUI_VERBOSE)}]} { unset _verbose From 5f85505265601823cc228fdc94d67d3b0ba582e4 Mon Sep 17 00:00:00 2001 From: Jakub Narebski <jnareb@gmail.com> Date: Thu, 17 May 2007 22:54:28 +0200 Subject: [PATCH 52/86] gitweb: Fix error in git_patchset_body for deletion in merge commit Checking if $diffinfo->{'status'} is equal 'D' is no longer the way to check if the file was deleted in result. For merge commits $diffinfo->{'status'} is reference to array of statuses for each parent. Use the fact that $diffinfo->{'to_id'} is all zeros as sign that file was deleted in result. Signed-off-by: Jakub Narebski <jnareb@gmail.com> Signed-off-by: Junio C Hamano <junkio@cox.net> --- gitweb/gitweb.perl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 6f5df9174e..66f306705f 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2722,8 +2722,9 @@ sub git_patchset_body { delete $from{'href'}; } } + $to{'file'} = $diffinfo->{'to_file'} || $diffinfo->{'file'}; - if ($diffinfo->{'status'} ne "D") { # not deleted file + if ($diffinfo->{'to_id'} ne ('0' x 40)) { # file exists in result $to{'href'} = href(action=>"blob", hash_base=>$hash, hash=>$diffinfo->{'to_id'}, file_name=>$to{'file'}); From 164b19893ab5bc66b531a26480149a0dff082969 Mon Sep 17 00:00:00 2001 From: Michael Hendricks <michael@ndrix.org> Date: Wed, 16 May 2007 23:08:50 -0600 Subject: [PATCH 53/86] Document core.excludesfile for git-add During the discussion of core.excludesfile in the user-manual, I realized that the configuration wasn't mentioned in the man pages. Signed-off-by: Michael Hendricks <michael@ndrix.org> Signed-off-by: Junio C Hamano <junkio@cox.net> --- Documentation/git-add.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt index 755d7186f5..38c72b8732 100644 --- a/Documentation/git-add.txt +++ b/Documentation/git-add.txt @@ -62,6 +62,15 @@ OPTIONS for command-line options). +Configuration +------------- + +The optional configuration variable 'core.excludesfile' indicates a path to a +file containing patterns of file names to exclude from git-add, similar to +$GIT_DIR/info/exclude. Patterns in the exclude file are used in addition to +those in info/exclude. See link:repository-layout.html[repository layout]. + + EXAMPLES -------- git-add Documentation/\\*.txt:: From d77b5673e90f47309d6bf87a7653896169945da0 Mon Sep 17 00:00:00 2001 From: Petr Baudis <pasky@suse.cz> Date: Thu, 17 May 2007 04:24:19 +0200 Subject: [PATCH 54/86] gitweb: Normalize searchbar font size Currently, searchbar font was as big as the page heading font, because font-size was made relative - but to the parent element, which was for some reason indeed page_header. Since that seems to be illogical to me, I just moved the div.search outside of div.page_header. I'm no CSS/DOM expert but no adverse effects were observed by me. Signed-off-by: Petr Baudis <pasky@suse.cz> Signed-off-by: Junio C Hamano <junkio@cox.net> --- gitweb/gitweb.perl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 66f306705f..260d79bd78 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1903,6 +1903,8 @@ EOF } print "\n"; } + print "</div>\n"; + my ($have_search) = gitweb_check_feature('search'); if ((defined $project) && ($have_search)) { if (!defined $searchtext) { @@ -1932,7 +1934,6 @@ EOF "</div>" . $cgi->end_form() . "\n"; } - print "</div>\n"; } sub git_footer_html { From e7738553723dcff0237b1aed2771886c8d87d224 Mon Sep 17 00:00:00 2001 From: Petr Baudis <pasky@suse.cz> Date: Thu, 17 May 2007 04:31:12 +0200 Subject: [PATCH 55/86] gitweb: Add support for grep searches The 'grep' type of search greps the currently selected tree for given regexp and shows the results in a fancy table with links into blob view. The number of shown matches is limited to 1000 and the whole feature can be turned off (grepping linux-2.6.git already makes repo.or.cz a bit unhappy). This second revision makes it in documentation explicit that grep accepts regexps, and makes grep accept extended regexps instead of basic regexps. Signed-off-by: Petr Baudis <pasky@suse.cz> Signed-off-by: Junio C Hamano <junkio@cox.net> --- gitweb/gitweb.css | 4 ++ gitweb/gitweb.perl | 123 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 125 insertions(+), 2 deletions(-) diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css index 02623cbb6d..9f0822fab3 100644 --- a/gitweb/gitweb.css +++ b/gitweb/gitweb.css @@ -484,3 +484,7 @@ span.atnight { span.match { color: #e00000; } + +div.binary { + font-style: italic; +} diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 260d79bd78..cc16e3137e 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -146,6 +146,19 @@ our %feature = ( 'override' => 0, 'default' => [1]}, + # Enable grep search, which will list the files in currently selected + # tree containing the given string. Enabled by default. This can be + # potentially CPU-intensive, of course. + + # To enable system wide have in $GITWEB_CONFIG + # $feature{'grep'}{'default'} = [1]; + # To have project specific config enable override in $GITWEB_CONFIG + # $feature{'grep'}{'override'} = 1; + # and in project config gitweb.grep = 0|1; + 'grep' => { + 'override' => 0, + 'default' => [1]}, + # Enable the pickaxe search, which will list the commits that modified # a given string in a file. This can be practical and quite faster # alternative to 'blame', but still potentially CPU-intensive. @@ -245,6 +258,18 @@ sub gitweb_have_snapshot { return $have_snapshot; } +sub feature_grep { + my ($val) = git_get_project_config('grep', '--bool'); + + if ($val eq 'true') { + return (1); + } elsif ($val eq 'false') { + return (0); + } + + return ($_[0]); +} + sub feature_pickaxe { my ($val) = git_get_project_config('pickaxe', '--bool'); @@ -364,10 +389,17 @@ if (defined $page) { } } +our $searchtype = $cgi->param('st'); +if (defined $searchtype) { + if ($searchtype =~ m/[^a-z]/) { + die_error(undef, "Invalid searchtype parameter"); + } +} + our $searchtext = $cgi->param('s'); our $search_regexp; if (defined $searchtext) { - if ($searchtext =~ m/[^a-zA-Z0-9_\.\/\-\+\:\@ ]/) { + if ($searchtype ne 'grep' and $searchtext =~ m/[^a-zA-Z0-9_\.\/\-\+\:\@ ]/) { die_error(undef, "Invalid search parameter"); } if (length($searchtext) < 2) { @@ -1927,7 +1959,7 @@ EOF $cgi->hidden(-name => "a") . "\n" . $cgi->hidden(-name => "h") . "\n" . $cgi->popup_menu(-name => 'st', -default => 'commit', - -values => ['commit', 'author', 'committer', 'pickaxe']) . + -values => ['commit', 'grep', 'author', 'committer', 'pickaxe']) . $cgi->sup($cgi->a({-href => href(action=>"search_help")}, "?")) . " search:\n", $cgi->textfield(-name => "s", -value => $searchtext) . "\n" . @@ -4626,6 +4658,12 @@ sub git_search { die_error('403 Permission denied', "Permission denied"); } } + if ($searchtype eq 'grep') { + my ($have_grep) = gitweb_check_feature('grep'); + if (!$have_grep) { + die_error('403 Permission denied', "Permission denied"); + } + } git_header_html(); @@ -4742,6 +4780,73 @@ sub git_search { print "</table>\n"; } + + if ($searchtype eq 'grep') { + git_print_page_nav('','', $hash,$co{'tree'},$hash); + git_print_header_div('commit', esc_html($co{'title'}), $hash); + + print "<table cellspacing=\"0\">\n"; + my $alternate = 1; + my $matches = 0; + $/ = "\n"; + open my $fd, "-|", git_cmd(), 'grep', '-n', '-i', '-E', $searchtext, $co{'tree'}; + my $lastfile = ''; + while (my $line = <$fd>) { + chomp $line; + my ($file, $lno, $ltext, $binary); + last if ($matches++ > 1000); + if ($line =~ /^Binary file (.+) matches$/) { + $file = $1; + $binary = 1; + } else { + (undef, $file, $lno, $ltext) = split(/:/, $line, 4); + } + if ($file ne $lastfile) { + $lastfile and print "</td></tr>\n"; + if ($alternate++) { + print "<tr class=\"dark\">\n"; + } else { + print "<tr class=\"light\">\n"; + } + print "<td class=\"list\">". + $cgi->a({-href => href(action=>"blob", hash=>$co{'hash'}, + file_name=>"$file"), + -class => "list"}, esc_path($file)); + print "</td><td>\n"; + $lastfile = $file; + } + if ($binary) { + print "<div class=\"binary\">Binary file</div>\n"; + } else { + $ltext = untabify($ltext); + if ($ltext =~ m/^(.*)($searchtext)(.*)$/i) { + $ltext = esc_html($1, -nbsp=>1); + $ltext .= '<span class="match">'; + $ltext .= esc_html($2, -nbsp=>1); + $ltext .= '</span>'; + $ltext .= esc_html($3, -nbsp=>1); + } else { + $ltext = esc_html($ltext, -nbsp=>1); + } + print "<div class=\"pre\">" . + $cgi->a({-href => href(action=>"blob", hash=>$co{'hash'}, + file_name=>"$file").'#l'.$lno, + -class => "linenr"}, sprintf('%4i', $lno)) + . ' ' . $ltext . "</div>\n"; + } + } + if ($lastfile) { + print "</td></tr>\n"; + if ($matches > 1000) { + print "<div class=\"diff nodifferences\">Too many matches, listing trimmed</div>\n"; + } + } else { + print "<div class=\"diff nodifferences\">No matches found</div>\n"; + } + close $fd; + + print "</table>\n"; + } git_footer_html(); } @@ -4752,6 +4857,20 @@ sub git_search_help { <dl> <dt><b>commit</b></dt> <dd>The commit messages and authorship information will be scanned for the given string.</dd> +EOT + my ($have_grep) = gitweb_check_feature('grep'); + if ($have_grep) { + print <<EOT; +<dt><b>grep</b></dt> +<dd>All files in the currently selected tree (HEAD unless you are explicitly browsing + a different one) are searched for the given +<a href="http://en.wikipedia.org/wiki/Regular_expression">regular expression</a> +(POSIX extended) and the matches are listed. On large +trees, this search can take a while and put some strain on the server, so please use it with +some consideration.</dd> +EOT + } + print <<EOT; <dt><b>author</b></dt> <dd>Name and e-mail of the change author and date of birth of the patch will be scanned for the given string.</dd> <dt><b>committer</b></dt> From 4229aa5141b5d7716d283fa8625209b59398d7ba Mon Sep 17 00:00:00 2001 From: Petr Baudis <pasky@suse.cz> Date: Thu, 17 May 2007 04:30:42 +0200 Subject: [PATCH 56/86] gitweb: Allow arbitrary strings to be dug with pickaxe Currently, there are rather draconian restrictions on the strings accepted by the pickaxe search, which degrades its usefulness for digging in code significantly. This patch remedies mentioned limitation. Signed-off-by: Petr Baudis <pasky@suse.cz> Signed-off-by: Junio C Hamano <junkio@cox.net> --- gitweb/gitweb.perl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index cc16e3137e..7c136ec0d3 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -399,7 +399,7 @@ if (defined $searchtype) { our $searchtext = $cgi->param('s'); our $search_regexp; if (defined $searchtext) { - if ($searchtype ne 'grep' and $searchtext =~ m/[^a-zA-Z0-9_\.\/\-\+\:\@ ]/) { + if ($searchtype ne 'grep' and $searchtype ne 'pickaxe' and $searchtext =~ m/[^a-zA-Z0-9_\.\/\-\+\:\@ ]/) { die_error(undef, "Invalid search parameter"); } if (length($searchtext) < 2) { @@ -4725,8 +4725,10 @@ sub git_search { my $alternate = 1; $/ = "\n"; my $git_command = git_cmd_str(); + my $searchqtext = $searchtext; + $searchqtext =~ s/'/'\\''/; open my $fd, "-|", "$git_command rev-list $hash | " . - "$git_command diff-tree -r --stdin -S\'$searchtext\'"; + "$git_command diff-tree -r --stdin -S\'$searchqtext\'"; undef %co; my @files; while (my $line = <$fd>) { From a5fc33b4937fb6f38918710be6f23ef925630a8a Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" <bfields@citi.umich.edu> Date: Sat, 12 May 2007 19:48:31 -0400 Subject: [PATCH 57/86] user-manual: revise birdseye-view chapter Some revisions suggested by Junio along with some minor style fixes and one compile fix (asterisks need escaping). Cc: Johannes Schindelin <Johannes.Schindelin@gmx.de> Signed-off-by: "J. Bruce Fields" <bfields@citi.umich.edu> --- Documentation/user-manual.txt | 46 ++++++++++++++--------------------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index 9e61798344..5f4e0a6e49 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -3161,43 +3161,33 @@ contrast, running "git prune" while somebody is actively changing the repository is a *BAD* idea). [[birdview-on-the-source-code]] -A birdview on Git's source code ------------------------------ +A birds-eye view of Git's source code +------------------------------------- -While Git's source code is quite elegant, it is not always easy for -new developers to find their way through it. A good idea is to look -at the contents of the initial commit: -_e83c5163316f89bfbde7d9ab23ca2e25604af290_ (also known as _v0.99~954_). +It is not always easy for new developers to find their way through Git's +source code. This section gives you a little guidance to show where to +start. -Tip: you can see what files are in there with +A good place to start is with the contents of the initial commit, with: ---------------------------------------------------- -$ git show e83c5163316f89bfbde7d9ab23ca2e25604af290: +$ git checkout e83c5163 ---------------------------------------------------- -and look at those files with something like +The initial revision lays the foundation for almost everything git has +today, but is small enough to read in one sitting. ------------------------------------------------------------ -$ git show e83c5163316f89bfbde7d9ab23ca2e25604af290:cache.h ------------------------------------------------------------ +Note that terminology has changed since that revision. For example, the +README in that revision uses the word "changeset" to describe what we +now call a <<def_commit_object,commit>>. -Be sure to read the README in that revision _after_ you are familiar with -the terminology (<<glossary>>), since the terminology has changed a little -since then. For example, we call the things "commits" now, which are -described in that README as "changesets". - -Actually a lot of the structure as it is now can be explained by that -initial commit. - -For example, we do not call it "cache" any more, but "index", however, the +Also, we do not call it "cache" any more, but "index", however, the file is still called `cache.h`. Remark: Not much reason to change it now, especially since there is no good single name for it anyway, because it is basically _the_ header file which is included by _all_ of Git's C sources. -If you grasp the ideas in that initial commit (it is really small and you -can get into it really fast, and it will help you recognize things in the -much larger code base we have now), you should go on skimming `cache.h`, -`object.h` and `commit.h` in the current version. +If you grasp the ideas in that initial commit, you should check out a +more recent version and skim `cache.h`, `object.h` and `commit.h`. In the early days, Git (in the tradition of UNIX) was a bunch of programs which were extremely simple, and which you used in scripts, piping the @@ -3320,11 +3310,11 @@ Two things are interesting here: negative numbers in case of different errors -- and 0 on success. - the variable `sha1` in the function signature of `get_sha1()` is `unsigned - char *`, but is actually expected to be a pointer to `unsigned + char \*`, but is actually expected to be a pointer to `unsigned char[20]`. This variable will contain the 160-bit SHA-1 of the given - commit. Note that whenever a SHA-1 is passed as "unsigned char *", it + commit. Note that whenever a SHA-1 is passed as `unsigned char \*`, it is the binary representation, as opposed to the ASCII representation in - hex characters, which is passed as "char *". + hex characters, which is passed as `char *`. You will see both of these things throughout the code. From 343cad921780be8eb55e10933c73bb5e04d2e0f2 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" <bfields@citi.umich.edu> Date: Sat, 12 May 2007 22:17:03 -0400 Subject: [PATCH 58/86] glossary: expand and clarify some definitions, prune cross-references Revise and expand some of the definitions in the glossary, based in part on a recent thread started by a user looking for help with some of the jargon. I've borrowed some of the language from Linus's email on that thread. (I'm assuming standing permission to plagiarize Linus's email....) Also start making a few changes to mitigate the appearance of "circularity" mentioned in that thread: - feel free to use somewhat longer definitions and to explain some things more than once instead of relying purely on cross-references - don't use cross-references when they're redundant: eliminate self-references and repeated references to the same entry. Cc: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: "J. Bruce Fields" <bfields@citi.umich.edu> --- Documentation/glossary.txt | 228 ++++++++++++++++++++++--------------- 1 file changed, 134 insertions(+), 94 deletions(-) diff --git a/Documentation/glossary.txt b/Documentation/glossary.txt index 2465514e46..489c3e9d5b 100644 --- a/Documentation/glossary.txt +++ b/Documentation/glossary.txt @@ -2,12 +2,12 @@ GIT Glossary ============ [[def_alternate_object_database]]alternate object database:: - Via the alternates mechanism, a <<def_repository,repository>> can - inherit part of its <<def_object_database,object database>> from another - <<def_object_database,object database>>, which is called "alternate". + Via the alternates mechanism, a <<def_repository,repository>> + can inherit part of its <<def_object_database,object database>> + from another object database, which is called "alternate". [[def_bare_repository]]bare repository:: - A <<def_bare_repository,bare repository>> is normally an appropriately + A bare repository is normally an appropriately named <<def_directory,directory>> with a `.git` suffix that does not have a locally checked-out copy of any of the files under <<def_revision,revision>> control. That is, all of the `git` @@ -21,10 +21,15 @@ GIT Glossary Untyped <<def_object,object>>, e.g. the contents of a file. [[def_branch]]branch:: - A non-cyclical graph of revisions, i.e. the complete history of a - particular <<def_revision,revision>>, which is called the - branch <<def_head,head>>. The heads - are stored in `$GIT_DIR/refs/heads/`. + A "branch" is an active line of development. The most recent + <<def_commit,commit>> on a branch is referred to as the tip of + that branch. The tip of the branch is referenced by a branch + <<def_head,head>>, which moves forward as additional development + is done on the branch. A single git + <<def_repository,repository>> can track an arbitrary number of + branches, but your <<def_working_tree,working tree>> is + associated with just one of them (the "current" or "checked out" + branch), and <<def_HEAD,HEAD>> points to that branch. [[def_cache]]cache:: Obsolete for: <<def_index,index>>. @@ -50,18 +55,25 @@ GIT Glossary as a new series of changes on top of different codebase. In GIT, this is performed by "git cherry-pick" command to extract the change introduced by an existing <<def_commit,commit>> and to record it based on the tip - of the current <<def_branch,branch>> as a new <<def_commit,commit>>. + of the current <<def_branch,branch>> as a new commit. [[def_clean]]clean:: - A <<def_working_tree,working tree>> is <<def_clean,clean>>, if it + A <<def_working_tree,working tree>> is clean, if it corresponds to the <<def_revision,revision>> referenced by the current <<def_head,head>>. Also see "<<def_dirty,dirty>>". [[def_commit]]commit:: - As a verb: The action of storing the current state of the - <<def_index,index>> in the <<def_object_database,object database>>. The - result is a <<def_revision,revision>>. As a noun: Short hand for - <<def_commit_object,commit object>>. + As a noun: A single point in the + git history; the entire history of a project is represented as a + set of interrelated commits. The word "commit" is often + used by git in the same places other revision control systems + use the words "revision" or "version". Also used as a short + hand for <<def_commit_object,commit object>>. ++ +As a verb: The action of storing a new snapshot of the project's +state in the git history, by creating a new commit representing the current +state of the <<def_index,index>> and advancing <<def_HEAD,HEAD>> +to point at the new commit. [[def_commit_object]]commit object:: An <<def_object,object>> which contains the information about a @@ -77,16 +89,22 @@ GIT Glossary [[def_DAG]]DAG:: Directed acyclic graph. The <<def_commit,commit>> objects form a directed acyclic graph, because they have parents (directed), and the - graph of <<def_commit,commit>> objects is acyclic (there is no + graph of commit objects is acyclic (there is no <<def_chain,chain>> which begins and ends with the same <<def_object,object>>). [[def_dangling_object]]dangling object:: An <<def_unreachable_object,unreachable object>> which is not <<def_reachable,reachable>> even from other unreachable objects; a - <<def_dangling_object,dangling object>> has no references to it from any + dangling object has no references to it from any reference or <<def_object,object>> in the <<def_repository,repository>>. +[[def_detached_HEAD]]detached HEAD:: + Normally the <<def_HEAD,HEAD>> stores the name of a + <<def_branch,branch>>. However, git also allows you to check + out an arbitrary commit that isn't necessarily the tip of any + particular branch. In this case HEAD is said to be "detached". + [[def_dircache]]dircache:: You are *waaaaay* behind. @@ -94,7 +112,7 @@ GIT Glossary The list you get with "ls" :-) [[def_dirty]]dirty:: - A <<def_working_tree,working tree>> is said to be <<def_dirty,dirty>> if + A <<def_working_tree,working tree>> is said to be "dirty" if it contains modifications which have not been committed to the current <<def_branch,branch>>. @@ -109,16 +127,16 @@ GIT Glossary <<def_branch,branch>>'s changes that happen to be a descendant of what you have. In such these cases, you do not make a new <<def_merge,merge>> <<def_commit,commit>> but instead just update to his - <<def_revision,revision>>. This will happen frequently on a + revision. This will happen frequently on a <<def_tracking_branch,tracking branch>> of a remote <<def_repository,repository>>. [[def_fetch]]fetch:: Fetching a <<def_branch,branch>> means to get the - <<def_branch,branch>>'s <<def_head_ref,head ref>> from a remote - <<def_repository,repository>>, to find out which objects are missing - from the local <<def_object_database,object database>>, and to get them, - too. + branch's <<def_head_ref,head ref>> from a remote + <<def_repository,repository>>, to find out which objects are + missing from the local <<def_object_database,object database>>, + and to get them, too. See also gitlink:git-fetch[1]. [[def_file_system]]file system:: Linus Torvalds originally designed git to be a user space file system, @@ -132,61 +150,83 @@ GIT Glossary Grafts enables two otherwise different lines of development to be joined together by recording fake ancestry information for commits. This way you can make git pretend the set of parents a <<def_commit,commit>> has - is different from what was recorded when the <<def_commit,commit>> was + is different from what was recorded when the commit was created. Configured via the `.git/info/grafts` file. [[def_hash]]hash:: In git's context, synonym to <<def_object_name,object name>>. [[def_head]]head:: - The top of a <<def_branch,branch>>. It contains a <<def_ref,ref>> to the - corresponding <<def_commit_object,commit object>>. + A named reference to the <<def_commit,commit>> at the tip of a + <<def_branch,branch>>. Heads are stored in + `$GIT_DIR/refs/heads/`, except when using packed refs. (See + gitlink:git-pack-refs[1].) + +[[def_HEAD]]HEAD:: + The current branch. In more detail: Your <<def_working_tree, + working tree>> is normally derived from the state of the tree + referred to by HEAD. HEAD is a reference to one of the + <<def_head,heads>> in your repository, except when using a + <<def_detached_HEAD,detached HEAD>>, in which case it may + reference an arbitrary commit. [[def_head_ref]]head ref:: - A <<def_ref,ref>> pointing to a <<def_head,head>>. Often, this is - abbreviated to "<<def_head,head>>". Head refs are stored in - `$GIT_DIR/refs/heads/`. + A synonym for <<def_head,head>>. [[def_hook]]hook:: During the normal execution of several git commands, call-outs are made to optional scripts that allow a developer to add functionality or checking. Typically, the hooks allow for a command to be pre-verified and potentially aborted, and allow for a post-notification after the - operation is done. The <<def_hook,hook>> scripts are found in the + operation is done. The hook scripts are found in the `$GIT_DIR/hooks/` <<def_directory,directory>>, and are enabled by simply making them executable. [[def_index]]index:: A collection of files with stat information, whose contents are stored - as objects. The <<def_index,index>> is a stored version of your working + as objects. The index is a stored version of your working <<def_tree,tree>>. Truth be told, it can also contain a second, and even a third version of a <<def_working_tree,working tree>>, which are used when merging. [[def_index_entry]]index entry:: The information regarding a particular file, stored in the - <<def_index,index>>. An <<def_index_entry,index entry>> can be unmerged, - if a <<def_merge,merge>> was started, but not yet finished (i.e. if the - <<def_index,index>> contains multiple versions of that file). + <<def_index,index>>. An index entry can be unmerged, if a + <<def_merge,merge>> was started, but not yet finished (i.e. if + the index contains multiple versions of that file). [[def_master]]master:: - The default development <<def_branch,branch>>. Whenever you create a git - <<def_repository,repository>>, a <<def_branch,branch>> named - "<<def_master,master>>" is created, and becomes the active - <<def_branch,branch>>. In most cases, this contains the local - development, though that is purely conventional and not required. + The default development <<def_branch,branch>>. Whenever you + create a git <<def_repository,repository>>, a branch named + "master" is created, and becomes the active branch. In most + cases, this contains the local development, though that is + purely by convention and is not required. [[def_merge]]merge:: - To <<def_merge,merge>> branches means to try to accumulate the changes - since a common ancestor and apply them to the first - <<def_branch,branch>>. An automatic <<def_merge,merge>> uses heuristics - to accomplish that. Evidently, an automatic <<def_merge,merge>> can - fail. + As a verb: To bring the contents of another + <<def_branch,branch>> (possibly from an external + <<def_repository,repository>>) into the current branch. In the + case where the merged-in branch is from a different repository, + this is done by first <<def_fetch,fetching>> the remote branch + and then merging the result into the current branch. This + combination of fetch and merge operations is called a + <<def_pull,pull>>. Merging is performed by an automatic process + that identifies changes made since the branches diverged, and + then applies all those changes together. In cases where changes + conflict, manual intervention may be required to complete the + merge. ++ +As a noun: unless it is a <<def_fast_forward,fast forward>>, a +successful merge results in the creation of a new <<def_commit,commit>> +representing the result of the merge, and having as +<<def_parent,parents>> the tips of the merged <<def_branch,branches>>. +This commit is referred to as a "merge commit", or sometimes just a +"merge". [[def_object]]object:: The unit of storage in git. It is uniquely identified by the <<def_SHA1,SHA1>> of its contents. Consequently, an - <<def_object,object>> can not be changed. + object can not be changed. [[def_object_database]]object database:: Stores a set of "objects", and an individual <<def_object,object>> is @@ -198,9 +238,9 @@ GIT Glossary [[def_object_name]]object name:: The unique identifier of an <<def_object,object>>. The <<def_hash,hash>> - of the <<def_object,object>>'s contents using the Secure Hash Algorithm + of the object's contents using the Secure Hash Algorithm 1 and usually represented by the 40 character hexadecimal encoding of - the <<def_hash,hash>> of the <<def_object,object>> (possibly followed by + the <<def_hash,hash>> of the object (possibly followed by a white space). [[def_object_type]]object type:: @@ -215,7 +255,7 @@ GIT Glossary [[def_origin]]origin:: The default upstream <<def_repository,repository>>. Most projects have at least one upstream project which they track. By default - '<<def_origin,origin>>' is used for that purpose. New upstream updates + 'origin' is used for that purpose. New upstream updates will be fetched into remote tracking branches named origin/name-of-upstream-branch, which you can see using "git <<def_branch,branch>> -r". @@ -227,7 +267,7 @@ GIT Glossary [[def_pack_index]]pack index:: The list of identifiers, and other information, of the objects in a <<def_pack,pack>>, to assist in efficiently accessing the contents of a - <<def_pack,pack>>. + pack. [[def_parent]]parent:: A <<def_commit_object,commit object>> contains a (possibly empty) list @@ -247,29 +287,29 @@ GIT Glossary [[def_porcelain]]porcelain:: Cute name for programs and program suites depending on <<def_core_git,core git>>, presenting a high level access to - <<def_core_git,core git>>. Porcelains expose more of a <<def_SCM,SCM>> + core git. Porcelains expose more of a <<def_SCM,SCM>> interface than the <<def_plumbing,plumbing>>. [[def_pull]]pull:: Pulling a <<def_branch,branch>> means to <<def_fetch,fetch>> it and - <<def_merge,merge>> it. + <<def_merge,merge>> it. See also gitlink:git-pull[1]. [[def_push]]push:: - Pushing a <<def_branch,branch>> means to get the <<def_branch,branch>>'s + Pushing a <<def_branch,branch>> means to get the branch's <<def_head_ref,head ref>> from a remote <<def_repository,repository>>, - find out if it is an ancestor to the <<def_branch,branch>>'s local - <<def_head_ref,head ref>> is a direct, and in that case, putting all + find out if it is an ancestor to the branch's local + head ref is a direct, and in that case, putting all objects, which are <<def_reachable,reachable>> from the local - <<def_head_ref,head ref>>, and which are missing from the remote - <<def_repository,repository>>, into the remote + head ref, and which are missing from the remote + repository, into the remote <<def_object_database,object database>>, and updating the remote - <<def_head_ref,head ref>>. If the remote <<def_head,head>> is not an - ancestor to the local <<def_head,head>>, the <<def_push,push>> fails. + head ref. If the remote <<def_head,head>> is not an + ancestor to the local head, the push fails. [[def_reachable]]reachable:: All of the ancestors of a given <<def_commit,commit>> are said to be - <<def_reachable,reachable>> from that <<def_commit,commit>>. More - generally, one <<def_object,object>> is <<def_reachable,reachable>> from + "reachable" from that commit. More + generally, one <<def_object,object>> is reachable from another if we can reach the one from the other by a <<def_chain,chain>> that follows <<def_tag,tags>> to whatever they tag, <<def_commit_object,commits>> to their parents or trees, and @@ -288,24 +328,23 @@ GIT Glossary [[def_refspec]]refspec:: A <<def_refspec,refspec>> is used by <<def_fetch,fetch>> and - <<def_push,push>> to describe the mapping between remote <<def_ref,ref>> - and local <<def_ref,ref>>. They are combined with a colon in the format - <src>:<dst>, preceded by an optional plus sign, +. For example: `git - fetch $URL refs/heads/master:refs/heads/origin` means - "grab the master <<def_branch,branch>> <<def_head,head>> - from the $URL and store it as my origin - <<def_branch,branch>> <<def_head,head>>". And `git <<def_push,push>> - $URL refs/heads/master:refs/heads/to-upstream` means - "publish my master <<def_branch,branch>> - <<def_head,head>> as to-upstream <<def_branch,branch>> at $URL". See - also gitlink:git-push[1] + <<def_push,push>> to describe the mapping between remote + <<def_ref,ref>> and local ref. They are combined with a colon in + the format <src>:<dst>, preceded by an optional plus sign, +. + For example: `git fetch $URL + refs/heads/master:refs/heads/origin` means "grab the master + <<def_branch,branch>> <<def_head,head>> from the $URL and store + it as my origin branch head". And `git push + $URL refs/heads/master:refs/heads/to-upstream` means "publish my + master branch head as to-upstream branch at $URL". See also + gitlink:git-push[1] [[def_repository]]repository:: - A collection of refs together with an <<def_object_database,object - database>> containing all objects which are <<def_reachable,reachable>> - from the refs, possibly accompanied by meta data from one or more - porcelains. A <<def_repository,repository>> can share an - <<def_object_database,object database>> with other repositories. + A collection of refs together with an + <<def_object_database,object database>> containing all objects + which are <<def_reachable,reachable>> from the refs, possibly + accompanied by meta data from one or more porcelains. A + repository can share an object database with other repositories. [[def_resolve]]resolve:: The action of fixing up manually what a failed automatic @@ -327,36 +366,37 @@ GIT Glossary Synonym for <<def_object_name,object name>>. [[def_shallow_repository]]shallow repository:: - A <<def_shallow_repository,shallow repository>> has an incomplete + A shallow repository has an incomplete history some of whose commits have parents cauterized away (in other words, git is told to pretend that these commits do not have the parents, even though they are recorded in the <<def_commit_object,commit object>>). This is sometimes useful when you are interested only in the recent history of a project even though the real history recorded in the - upstream is much larger. A <<def_shallow_repository,shallow repository>> + upstream is much larger. A shallow repository is created by giving the `--depth` option to gitlink:git-clone[1], and its history can be later deepened with gitlink:git-fetch[1]. [[def_symref]]symref:: - Symbolic reference: instead of containing the <<def_SHA1,SHA1>> id - itself, it is of the format 'ref: refs/some/thing' and when - referenced, it recursively dereferences to this reference. 'HEAD' is a - prime example of a <<def_symref,symref>>. Symbolic references are - manipulated with the gitlink:git-symbolic-ref[1] command. + Symbolic reference: instead of containing the <<def_SHA1,SHA1>> + id itself, it is of the format 'ref: refs/some/thing' and when + referenced, it recursively dereferences to this reference. + '<<def_HEAD,HEAD>>' is a prime example of a symref. Symbolic + references are manipulated with the gitlink:git-symbolic-ref[1] + command. [[def_tag]]tag:: - A <<def_ref,ref>> pointing to a <<def_tag,tag>> or + A <<def_ref,ref>> pointing to a tag or <<def_commit_object,commit object>>. In contrast to a <<def_head,head>>, a tag is not changed by a <<def_commit,commit>>. Tags (not <<def_tag_object,tag objects>>) are stored in `$GIT_DIR/refs/tags/`. A git tag has nothing to do with a Lisp tag (which would be called an <<def_object_type,object type>> in git's context). A tag is most typically used to mark a particular point in the - <<def_commit,commit>> ancestry <<def_chain,chain>>. + commit ancestry <<def_chain,chain>>. [[def_tag_object]]tag object:: An <<def_object,object>> containing a <<def_ref,ref>> pointing to - another <<def_object,object>>, which can contain a message just like a + another object, which can contain a message just like a <<def_commit_object,commit object>>. It can also contain a (PGP) signature, in which case it is called a "signed <<def_tag_object,tag object>>". @@ -370,16 +410,16 @@ GIT Glossary [[def_tracking_branch]]tracking branch:: A regular git <<def_branch,branch>> that is used to follow changes from - another <<def_repository,repository>>. A <<def_tracking_branch,tracking - branch>> should not contain direct modifications or have local commits - made to it. A <<def_tracking_branch,tracking branch>> can usually be + another <<def_repository,repository>>. A tracking + branch should not contain direct modifications or have local commits + made to it. A tracking branch can usually be identified as the right-hand-side <<def_ref,ref>> in a Pull: <<def_refspec,refspec>>. [[def_tree]]tree:: Either a <<def_working_tree,working tree>>, or a <<def_tree_object,tree - object>> together with the dependent blob and <<def_tree,tree>> objects - (i.e. a stored representation of a <<def_working_tree,working tree>>). + object>> together with the dependent blob and tree objects + (i.e. a stored representation of a working tree). [[def_tree_object]]tree object:: An <<def_object,object>> containing a list of file names and modes along @@ -389,8 +429,7 @@ GIT Glossary [[def_tree-ish]]tree-ish:: A <<def_ref,ref>> pointing to either a <<def_commit_object,commit object>>, a <<def_tree_object,tree object>>, or a <<def_tag_object,tag - object>> pointing to a <<def_tag,tag>> or <<def_commit,commit>> or - <<def_tree_object,tree object>>. + object>> pointing to a tag or commit or tree object. [[def_unmerged_index]]unmerged index:: An <<def_index,index>> which contains unmerged @@ -401,5 +440,6 @@ GIT Glossary <<def_branch,branch>>, <<def_tag,tag>>, or any other reference. [[def_working_tree]]working tree:: - The set of files and directories currently being worked on, i.e. you can - work in your <<def_working_tree,working tree>> without using git at all. + The tree of actual checked out files. The working tree is + normally equal to the <<def_HEAD,HEAD>> plus any local changes + that you have made but not yet committed. From 2624d9a5aa4a98fbfb91b330b297488365af4701 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" <bfields@citi.umich.edu> Date: Sat, 12 May 2007 22:55:40 -0400 Subject: [PATCH 59/86] user-manual: move quick-start to an appendix The quick start interrupts the flow of the manual a bit. Move it to "appendix A" but add a reference to it in the preface. Also rename the todo chapter to "appendix B", and revise the preface a little. Signed-off-by: "J. Bruce Fields" <bfields@citi.umich.edu> --- Documentation/user-manual.txt | 484 +++++++++++++++++----------------- 1 file changed, 245 insertions(+), 239 deletions(-) diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index 5f4e0a6e49..b89b9dbc0f 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -4,15 +4,13 @@ ______________________________________________ This manual is designed to be readable by someone with basic unix command-line skills, but no previous knowledge of git. -Chapter 1 gives a brief overview of git commands, without any -explanation; you may prefer to skip to chapter 2 on a first reading. +<<repositories-and-branches>> and <<exploring-git-history>> explain how +to fetch and study a project using git--read these chapters to learn how +to build and test a particular version of a software project, search for +regressions, and so on. -Chapters 2 and 3 explain how to fetch and study a project using -git--the tools you'd need to build and test a particular version of a -software project, to search for regressions, and so on. - -Chapter 4 explains how to do development with git, and chapter 5 how -to share that development with others. +People needing to do actual development will also want to read +<<Developing-with-git>> and <<sharing-development>>. Further chapters cover more specialized topics. @@ -23,237 +21,12 @@ pages. For a command such as "git clone", just use $ man git-clone ------------------------------------------------ -[[git-quick-start]] -Git Quick Start -=============== +See also <<git-quick-start>> for a brief overview of git commands, +without any explanation. -This is a quick summary of the major commands; the following chapters -will explain how these work in more detail. +Also, see <<todo>> for ways that you can help make this manual more +complete. -[[quick-creating-a-new-repository]] -Creating a new repository -------------------------- - -From a tarball: - ------------------------------------------------ -$ tar xzf project.tar.gz -$ cd project -$ git init -Initialized empty Git repository in .git/ -$ git add . -$ git commit ------------------------------------------------ - -From a remote repository: - ------------------------------------------------ -$ git clone git://example.com/pub/project.git -$ cd project ------------------------------------------------ - -[[managing-branches]] -Managing branches ------------------ - ------------------------------------------------ -$ git branch # list all local branches in this repo -$ git checkout test # switch working directory to branch "test" -$ git branch new # create branch "new" starting at current HEAD -$ git branch -d new # delete branch "new" ------------------------------------------------ - -Instead of basing new branch on current HEAD (the default), use: - ------------------------------------------------ -$ git branch new test # branch named "test" -$ git branch new v2.6.15 # tag named v2.6.15 -$ git branch new HEAD^ # commit before the most recent -$ git branch new HEAD^^ # commit before that -$ git branch new test~10 # ten commits before tip of branch "test" ------------------------------------------------ - -Create and switch to a new branch at the same time: - ------------------------------------------------ -$ git checkout -b new v2.6.15 ------------------------------------------------ - -Update and examine branches from the repository you cloned from: - ------------------------------------------------ -$ git fetch # update -$ git branch -r # list - origin/master - origin/next - ... -$ git checkout -b masterwork origin/master ------------------------------------------------ - -Fetch a branch from a different repository, and give it a new -name in your repository: - ------------------------------------------------ -$ git fetch git://example.com/project.git theirbranch:mybranch -$ git fetch git://example.com/project.git v2.6.15:mybranch ------------------------------------------------ - -Keep a list of repositories you work with regularly: - ------------------------------------------------ -$ git remote add example git://example.com/project.git -$ git remote # list remote repositories -example -origin -$ git remote show example # get details -* remote example - URL: git://example.com/project.git - Tracked remote branches - master next ... -$ git fetch example # update branches from example -$ git branch -r # list all remote branches ------------------------------------------------ - - -[[exploring-history]] -Exploring history ------------------ - ------------------------------------------------ -$ gitk # visualize and browse history -$ git log # list all commits -$ git log src/ # ...modifying src/ -$ git log v2.6.15..v2.6.16 # ...in v2.6.16, not in v2.6.15 -$ git log master..test # ...in branch test, not in branch master -$ git log test..master # ...in branch master, but not in test -$ git log test...master # ...in one branch, not in both -$ git log -S'foo()' # ...where difference contain "foo()" -$ git log --since="2 weeks ago" -$ git log -p # show patches as well -$ git show # most recent commit -$ git diff v2.6.15..v2.6.16 # diff between two tagged versions -$ git diff v2.6.15..HEAD # diff with current head -$ git grep "foo()" # search working directory for "foo()" -$ git grep v2.6.15 "foo()" # search old tree for "foo()" -$ git show v2.6.15:a.txt # look at old version of a.txt ------------------------------------------------ - -Search for regressions: - ------------------------------------------------ -$ git bisect start -$ git bisect bad # current version is bad -$ git bisect good v2.6.13-rc2 # last known good revision -Bisecting: 675 revisions left to test after this - # test here, then: -$ git bisect good # if this revision is good, or -$ git bisect bad # if this revision is bad. - # repeat until done. ------------------------------------------------ - -[[making-changes]] -Making changes --------------- - -Make sure git knows who to blame: - ------------------------------------------------- -$ cat >>~/.gitconfig <<\EOF -[user] - name = Your Name Comes Here - email = you@yourdomain.example.com -EOF ------------------------------------------------- - -Select file contents to include in the next commit, then make the -commit: - ------------------------------------------------ -$ git add a.txt # updated file -$ git add b.txt # new file -$ git rm c.txt # old file -$ git commit ------------------------------------------------ - -Or, prepare and create the commit in one step: - ------------------------------------------------ -$ git commit d.txt # use latest content only of d.txt -$ git commit -a # use latest content of all tracked files ------------------------------------------------ - -[[merging]] -Merging -------- - ------------------------------------------------ -$ git merge test # merge branch "test" into the current branch -$ git pull git://example.com/project.git master - # fetch and merge in remote branch -$ git pull . test # equivalent to git merge test ------------------------------------------------ - -[[sharing-your-changes]] -Sharing your changes --------------------- - -Importing or exporting patches: - ------------------------------------------------ -$ git format-patch origin..HEAD # format a patch for each commit - # in HEAD but not in origin -$ git am mbox # import patches from the mailbox "mbox" ------------------------------------------------ - -Fetch a branch in a different git repository, then merge into the -current branch: - ------------------------------------------------ -$ git pull git://example.com/project.git theirbranch ------------------------------------------------ - -Store the fetched branch into a local branch before merging into the -current branch: - ------------------------------------------------ -$ git pull git://example.com/project.git theirbranch:mybranch ------------------------------------------------ - -After creating commits on a local branch, update the remote -branch with your commits: - ------------------------------------------------ -$ git push ssh://example.com/project.git mybranch:theirbranch ------------------------------------------------ - -When remote and local branch are both named "test": - ------------------------------------------------ -$ git push ssh://example.com/project.git test ------------------------------------------------ - -Shortcut version for a frequently used remote repository: - ------------------------------------------------ -$ git remote add example ssh://example.com/project.git -$ git push example test ------------------------------------------------ - -[[repository-maintenance]] -Repository maintenance ----------------------- - -Check for corruption: - ------------------------------------------------ -$ git fsck ------------------------------------------------ - -Recompress, remove unused cruft: - ------------------------------------------------ -$ git gc ------------------------------------------------ [[repositories-and-branches]] Repositories and Branches @@ -3372,9 +3145,242 @@ itself! [[glossary]] include::glossary.txt[] +[[git-quick-start]] +Appendix A: Git Quick Start +=========================== + +This is a quick summary of the major commands; the following chapters +will explain how these work in more detail. + +[[quick-creating-a-new-repository]] +Creating a new repository +------------------------- + +From a tarball: + +----------------------------------------------- +$ tar xzf project.tar.gz +$ cd project +$ git init +Initialized empty Git repository in .git/ +$ git add . +$ git commit +----------------------------------------------- + +From a remote repository: + +----------------------------------------------- +$ git clone git://example.com/pub/project.git +$ cd project +----------------------------------------------- + +[[managing-branches]] +Managing branches +----------------- + +----------------------------------------------- +$ git branch # list all local branches in this repo +$ git checkout test # switch working directory to branch "test" +$ git branch new # create branch "new" starting at current HEAD +$ git branch -d new # delete branch "new" +----------------------------------------------- + +Instead of basing new branch on current HEAD (the default), use: + +----------------------------------------------- +$ git branch new test # branch named "test" +$ git branch new v2.6.15 # tag named v2.6.15 +$ git branch new HEAD^ # commit before the most recent +$ git branch new HEAD^^ # commit before that +$ git branch new test~10 # ten commits before tip of branch "test" +----------------------------------------------- + +Create and switch to a new branch at the same time: + +----------------------------------------------- +$ git checkout -b new v2.6.15 +----------------------------------------------- + +Update and examine branches from the repository you cloned from: + +----------------------------------------------- +$ git fetch # update +$ git branch -r # list + origin/master + origin/next + ... +$ git checkout -b masterwork origin/master +----------------------------------------------- + +Fetch a branch from a different repository, and give it a new +name in your repository: + +----------------------------------------------- +$ git fetch git://example.com/project.git theirbranch:mybranch +$ git fetch git://example.com/project.git v2.6.15:mybranch +----------------------------------------------- + +Keep a list of repositories you work with regularly: + +----------------------------------------------- +$ git remote add example git://example.com/project.git +$ git remote # list remote repositories +example +origin +$ git remote show example # get details +* remote example + URL: git://example.com/project.git + Tracked remote branches + master next ... +$ git fetch example # update branches from example +$ git branch -r # list all remote branches +----------------------------------------------- + + +[[exploring-history]] +Exploring history +----------------- + +----------------------------------------------- +$ gitk # visualize and browse history +$ git log # list all commits +$ git log src/ # ...modifying src/ +$ git log v2.6.15..v2.6.16 # ...in v2.6.16, not in v2.6.15 +$ git log master..test # ...in branch test, not in branch master +$ git log test..master # ...in branch master, but not in test +$ git log test...master # ...in one branch, not in both +$ git log -S'foo()' # ...where difference contain "foo()" +$ git log --since="2 weeks ago" +$ git log -p # show patches as well +$ git show # most recent commit +$ git diff v2.6.15..v2.6.16 # diff between two tagged versions +$ git diff v2.6.15..HEAD # diff with current head +$ git grep "foo()" # search working directory for "foo()" +$ git grep v2.6.15 "foo()" # search old tree for "foo()" +$ git show v2.6.15:a.txt # look at old version of a.txt +----------------------------------------------- + +Search for regressions: + +----------------------------------------------- +$ git bisect start +$ git bisect bad # current version is bad +$ git bisect good v2.6.13-rc2 # last known good revision +Bisecting: 675 revisions left to test after this + # test here, then: +$ git bisect good # if this revision is good, or +$ git bisect bad # if this revision is bad. + # repeat until done. +----------------------------------------------- + +[[making-changes]] +Making changes +-------------- + +Make sure git knows who to blame: + +------------------------------------------------ +$ cat >>~/.gitconfig <<\EOF +[user] + name = Your Name Comes Here + email = you@yourdomain.example.com +EOF +------------------------------------------------ + +Select file contents to include in the next commit, then make the +commit: + +----------------------------------------------- +$ git add a.txt # updated file +$ git add b.txt # new file +$ git rm c.txt # old file +$ git commit +----------------------------------------------- + +Or, prepare and create the commit in one step: + +----------------------------------------------- +$ git commit d.txt # use latest content only of d.txt +$ git commit -a # use latest content of all tracked files +----------------------------------------------- + +[[merging]] +Merging +------- + +----------------------------------------------- +$ git merge test # merge branch "test" into the current branch +$ git pull git://example.com/project.git master + # fetch and merge in remote branch +$ git pull . test # equivalent to git merge test +----------------------------------------------- + +[[sharing-your-changes]] +Sharing your changes +-------------------- + +Importing or exporting patches: + +----------------------------------------------- +$ git format-patch origin..HEAD # format a patch for each commit + # in HEAD but not in origin +$ git am mbox # import patches from the mailbox "mbox" +----------------------------------------------- + +Fetch a branch in a different git repository, then merge into the +current branch: + +----------------------------------------------- +$ git pull git://example.com/project.git theirbranch +----------------------------------------------- + +Store the fetched branch into a local branch before merging into the +current branch: + +----------------------------------------------- +$ git pull git://example.com/project.git theirbranch:mybranch +----------------------------------------------- + +After creating commits on a local branch, update the remote +branch with your commits: + +----------------------------------------------- +$ git push ssh://example.com/project.git mybranch:theirbranch +----------------------------------------------- + +When remote and local branch are both named "test": + +----------------------------------------------- +$ git push ssh://example.com/project.git test +----------------------------------------------- + +Shortcut version for a frequently used remote repository: + +----------------------------------------------- +$ git remote add example ssh://example.com/project.git +$ git push example test +----------------------------------------------- + +[[repository-maintenance]] +Repository maintenance +---------------------- + +Check for corruption: + +----------------------------------------------- +$ git fsck +----------------------------------------------- + +Recompress, remove unused cruft: + +----------------------------------------------- +$ git gc +----------------------------------------------- + + [[todo]] -Notes and todo list for this manual -=================================== +Appendix B: Notes and todo list for this manual +=============================================== This is a work in progress. From 4db75b70d1a4c56bb6d91e03e6f9a84bccb6c760 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" <bfields@citi.umich.edu> Date: Sat, 12 May 2007 23:52:24 -0400 Subject: [PATCH 60/86] Documentation: remove howto's now incorporated into manual These two howto's have both been copied into the manual. I'd rather not maintain both versions if possible, and I think the user-manual will be more visible than the howto directory. (Though I wouldn't mind some duplication if people really like having them here.) Signed-off-by: "J. Bruce Fields" <bfields@citi.umich.edu> --- Documentation/howto/dangling-objects.txt | 109 ------------------ .../howto/isolate-bugs-with-bisect.txt | 65 ----------- 2 files changed, 174 deletions(-) delete mode 100644 Documentation/howto/dangling-objects.txt delete mode 100644 Documentation/howto/isolate-bugs-with-bisect.txt diff --git a/Documentation/howto/dangling-objects.txt b/Documentation/howto/dangling-objects.txt deleted file mode 100644 index e82ddae3cf..0000000000 --- a/Documentation/howto/dangling-objects.txt +++ /dev/null @@ -1,109 +0,0 @@ -From: Linus Torvalds <torvalds@linux-foundation.org> -Subject: Re: Question about fsck-objects output -Date: Thu, 25 Jan 2007 12:01:06 -0800 (PST) -Message-ID: <Pine.LNX.4.64.0701251144290.25027@woody.linux-foundation.org> -Archived-At: <http://permalink.gmane.org/gmane.comp.version-control.git/37754> -Abstract: Linus describes what dangling objects are, when they - are left behind, and how to view their relationship with branch - heads in gitk - -On Thu, 25 Jan 2007, Larry Streepy wrote: - -> Sorry to ask such a basic question, but I can't quite decipher the output of -> fsck-objects. When I run it, I get this: -> -> git fsck-objects -> dangling commit 2213f6d4dd39ca8baebd0427723723e63208521b -> dangling commit f0d4e00196bd5ee54463e9ea7a0f0e8303da767f -> dangling blob 6a6d0b01b3e96d49a8f2c7addd4ef8c3bd1f5761 -> -> -> Even after a "repack -a -d" they still exist. The man page has a short -> explanation, but, at least for me, it wasn't fully enlightening. :-) -> -> The man page says that dangling commits could be "root" commits, but since my -> repo started as a clone of another repo, I don't see how I could have any root -> commits. Also, the page doesn't really describe what a dangling blob is. -> -> So, can someone explain what these artifacts are and if they are a problem -> that I should be worried about? - -The most common situation is that you've rebased a branch (or you have -pulled from somebody else who rebased a branch, like the "pu" branch in -the git.git archive itself). - -What happens is that the old head of the original branch still exists, as -does obviously everything it pointed to. The branch pointer itself just -doesn't, since you replaced it with another one. - -However, there are certainly other situations too that cause dangling -objects. For example, the "dangling blob" situation you have tends to be -because you did a "git add" of a file, but then, before you actually -committed it and made it part of the bigger picture, you changed something -else in that file and committed that *updated* thing - the old state that -you added originally ends up not being pointed to by any commit/tree, so -it's now a dangling blob object. - -Similarly, when the "recursive" merge strategy runs, and finds that there -are criss-cross merges and thus more than one merge base (which is fairly -unusual, but it does happen), it will generate one temporary midway tree -(or possibly even more, if you had lots of criss-crossing merges and -more than two merge bases) as a temporary internal merge base, and again, -those are real objects, but the end result will not end up pointing to -them, so they end up "dangling" in your repository. - -Generally, dangling objects aren't anything to worry about. They can even -be very useful: if you screw something up, the dangling objects can be how -you recover your old tree (say, you did a rebase, and realized that you -really didn't want to - you can look at what dangling objects you have, -and decide to reset your head to some old dangling state). - -For commits, the most useful thing to do with dangling objects tends to be -to do a simple - - gitk <dangling-commit-sha-goes-here> --not --all - -which means exactly what it sounds like: it says that you want to see the -commit history that is described by the dangling commit(s), but you do NOT -want to see the history that is described by all your branches and tags -(which are the things you normally reach). That basically shows you in a -nice way what the danglign commit was (and notice that it might not be -just one commit: we only report the "tip of the line" as being dangling, -but there might be a whole deep and complex commit history that has gotten -dropped - rebasing will do that). - -For blobs and trees, you can't do the same, but you can examine them. You -can just do - - git show <dangling-blob/tree-sha-goes-here> - -to show what the contents of the blob were (or, for a tree, basically what -the "ls" for that directory was), and that may give you some idea of what -the operation was that left that dangling object. - -Usually, dangling blobs and trees aren't very interesting. They're almost -always the result of either being a half-way mergebase (the blob will -often even have the conflict markers from a merge in it, if you have had -conflicting merges that you fixed up by hand), or simply because you -interrupted a "git fetch" with ^C or something like that, leaving _some_ -of the new objects in the object database, but just dangling and useless. - -Anyway, once you are sure that you're not interested in any dangling -state, you can just prune all unreachable objects: - - git prune - -and they'll be gone. But you should only run "git prune" on a quiescent -repository - it's kind of like doing a filesystem fsck recovery: you don't -want to do that while the filesystem is mounted. - -(The same is true of "git-fsck-objects" itself, btw - but since -git-fsck-objects never actually *changes* the repository, it just reports -on what it found, git-fsck-objects itself is never "dangerous" to run. -Running it while somebody is actually changing the repository can cause -confusing and scary messages, but it won't actually do anything bad. In -contrast, running "git prune" while somebody is actively changing the -repository is a *BAD* idea). - - Linus - diff --git a/Documentation/howto/isolate-bugs-with-bisect.txt b/Documentation/howto/isolate-bugs-with-bisect.txt deleted file mode 100644 index 926bbdc3cb..0000000000 --- a/Documentation/howto/isolate-bugs-with-bisect.txt +++ /dev/null @@ -1,65 +0,0 @@ -From: Linus Torvalds <torvalds () osdl ! org> -To: git@vger.kernel.org -Date: 2005-11-08 1:31:34 -Subject: Real-life kernel debugging scenario -Abstract: Short-n-sweet, Linus tells us how to leverage `git-bisect` to perform - bug isolation on a repository where "good" and "bad" revisions are known - in order to identify a suspect commit. - - -How To Use git-bisect To Isolate a Bogus Commit -=============================================== - -The way to use "git bisect" couldn't be easier. - -Figure out what the oldest bad state you know about is (that's usually the -head of "master", since that's what you just tried to boot and failed at). -Also, figure out the most recent known-good commit (usually the _previous_ -kernel you ran: and if you've only done a single "pull" in between, it -will be ORIG_HEAD). - -Then do - - git bisect start - git bisect bad master <- mark "master" as the bad state - git bisect good ORIG_HEAD <- mark ORIG_HEAD as good (or - whatever other known-good - thing you booted last) - -and at this point "git bisect" will churn for a while, and tell you what -the mid-point between those two commits are, and check that state out as -the head of the new "bisect" branch. - -Compile and reboot. - -If it's good, just do - - git bisect good <- mark current head as good - -otherwise, reboot into a good kernel instead, and do (surprise surprise, -git really is very intuitive): - - git bisect bad <- mark current head as bad - -and whatever you do, git will select a new half-way point. Do this for a -while, until git tells you exactly which commit was the first bad commit. -That's your culprit. - -It really works wonderfully well, except for the case where there was -_another_ commit that broke something in between, like introduced some -stupid compile error. In that case you should not mark that commit good or -bad: you should try to find another commit close-by, and do a "git reset ---hard <newcommit>" to try out _that_ commit instead, and then test that -instead (and mark it good or bad). - -You can do "git bisect visualize" while you do all this to see what's -going on by starting up gitk on the bisection range. - -Finally, once you've figured out exactly which commit was bad, you can -then go back to the master branch, and try reverting just that commit: - - git checkout master - git revert <bad-commit-id> - -to verify that the top-of-kernel works with that single commit reverted. - From 82c8bf28f8e4b5d2c647289abccb69b5fe69d3b1 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" <bfields@citi.umich.edu> Date: Sun, 13 May 2007 00:14:40 -0400 Subject: [PATCH 61/86] user-manual: move howto/make-dist.txt into user manual There seems to be a perception that the howto's are bit-rotting a little. The manual might be a more visible location for some of them, and make-dist.txt seems like a good candidate to include as an example in the manual. For now, incorporate much of it verbatim. Later we may want to update the example a bit. Signed-off-by: "J. Bruce Fields" <bfields@citi.umich.edu> --- Documentation/howto/make-dist.txt | 52 ------------------------------- Documentation/user-manual.txt | 42 +++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 52 deletions(-) delete mode 100644 Documentation/howto/make-dist.txt diff --git a/Documentation/howto/make-dist.txt b/Documentation/howto/make-dist.txt deleted file mode 100644 index 00e330b293..0000000000 --- a/Documentation/howto/make-dist.txt +++ /dev/null @@ -1,52 +0,0 @@ -Date: Fri, 12 Aug 2005 22:39:48 -0700 (PDT) -From: Linus Torvalds <torvalds@osdl.org> -To: Dave Jones <davej@redhat.com> -cc: git@vger.kernel.org -Subject: Re: Fwd: Re: git checkout -f branch doesn't remove extra files -Abstract: In this article, Linus talks about building a tarball, - incremental patch, and ChangeLog, given a base release and two - rc releases, following the convention of giving the patch from - the base release and the latest rc, with ChangeLog between the - last rc and the latest rc. - -On Sat, 13 Aug 2005, Dave Jones wrote: -> -> > Git actually has a _lot_ of nifty tools. I didn't realize that people -> > didn't know about such basic stuff as "git-tar-tree" and "git-ls-files". -> -> Maybe its because things are moving so fast :) Or maybe I just wasn't -> paying attention on that day. (I even read the git changes via RSS, -> so I should have no excuse). - -Well, git-tar-tree has been there since late April - it's actually one of -those really early commands. I'm pretty sure the RSS feed came later ;) - -I use it all the time in doing releases, it's a lot faster than creating a -tar tree by reading the filesystem (even if you don't have to check things -out). A hidden pearl. - -This is my crappy "release-script": - - [torvalds@g5 ~]$ cat bin/release-script - #!/bin/sh - stable="$1" - last="$2" - new="$3" - echo "# git-tag v$new" - echo "git-tar-tree v$new linux-$new | gzip -9 > ../linux-$new.tar.gz" - echo "git-diff-tree -p v$stable v$new | gzip -9 > ../patch-$new.gz" - echo "git-rev-list --pretty v$new ^v$last > ../ChangeLog-$new" - echo "git-rev-list --pretty=short v$new ^v$last | git-shortlog > ../ShortLog" - echo "git-diff-tree -p v$last v$new | git-apply --stat > ../diffstat-$new" - -and when I want to do a new kernel release I literally first tag it, and -then do - - release-script 2.6.12 2.6.13-rc6 2.6.13-rc7 - -and check that things look sane, and then just cut-and-paste the commands. - -Yeah, it's stupid. - - Linus - diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index b89b9dbc0f..55d4d37b21 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -808,6 +808,48 @@ available Which shows that e05db0fd is reachable from itself, from v1.5.0-rc1, and from v1.5.0-rc2, but not from v1.5.0-rc0. +[[making-a-release]] +Creating a changelog and tarball for a software release +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The gitlink:git-archive[1] command can create a tar or zip archive from +any version of a project; for example: + +------------------------------------------------- +$ git archive --format=tar --prefix=project/ HEAD | gzip >latest.tar.gz +------------------------------------------------- + +will use HEAD to produce a tar archive in which each filename is +preceded by "prefix/". + +If you're releasing a new version of a software project, you may want +to simultaneously make a changelog to include in the release +announcement. + +Linus Torvalds, for example, makes new kernel releases by tagging them, +then running: + +------------------------------------------------- +$ release-script 2.6.12 2.6.13-rc6 2.6.13-rc7 +------------------------------------------------- + +where release-script is a shell script that looks like: + +------------------------------------------------- +#!/bin/sh +stable="$1" +last="$2" +new="$3" +echo "# git tag v$new" +echo "git archive --prefix=linux-$new/ v$new | gzip -9 > ../linux-$new.tar.gz" +echo "git diff v$stable v$new | gzip -9 > ../patch-$new.gz" +echo "git log --no-merges v$new ^v$last > ../ChangeLog-$new" +echo "git shortlog --no-merges v$new ^v$last > ../ShortLog" +echo "git diff --stat --summary -M v$last v$new > ../diffstat-$new" +------------------------------------------------- + +and then he just cut-and-pastes the output commands after verifying that +they look OK. [[Developing-with-git]] Developing with git From 9e2163ea45b688e9de4744ebb9b01ea7e1ed8d56 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" <bfields@citi.umich.edu> Date: Sun, 13 May 2007 01:48:47 -0400 Subject: [PATCH 62/86] user-manual: move howto/using-topic-branches into manual Move howto/using-topic-branches into the user manual as an example for the "sharing development" chapter. While we're at it, remove some discussion that's covered in earlier chapters, modernize somewhat (use separate-heads setup, remotes, replace "whatchanged" by "log", etc.), and replace syntax we'd need to explain by syntax we've already covered (e.g. old..new instead of new ^old). The result may not really describe what Tony Luck does any more.... Hope that's not annoying. Cc: Tony Luck <tony.luck@intel.com> Signed-off-by: "J. Bruce Fields" <bfields@citi.umich.edu> --- Documentation/howto/using-topic-branches.txt | 296 ------------------ Documentation/user-manual.txt | 297 ++++++++++++++++++- 2 files changed, 296 insertions(+), 297 deletions(-) delete mode 100644 Documentation/howto/using-topic-branches.txt diff --git a/Documentation/howto/using-topic-branches.txt b/Documentation/howto/using-topic-branches.txt deleted file mode 100644 index 2c98194cb8..0000000000 --- a/Documentation/howto/using-topic-branches.txt +++ /dev/null @@ -1,296 +0,0 @@ -Date: Mon, 15 Aug 2005 12:17:41 -0700 -From: tony.luck@intel.com -Subject: Some tutorial text (was git/cogito workshop/bof at linuxconf au?) -Abstract: In this article, Tony Luck discusses how he uses GIT - as a Linux subsystem maintainer. - -Here's something that I've been putting together on how I'm using -GIT as a Linux subsystem maintainer. - --Tony - -Last updated w.r.t. GIT 1.1 - -Linux subsystem maintenance using GIT -------------------------------------- - -My requirements here are to be able to create two public trees: - -1) A "test" tree into which patches are initially placed so that they -can get some exposure when integrated with other ongoing development. -This tree is available to Andrew for pulling into -mm whenever he wants. - -2) A "release" tree into which tested patches are moved for final -sanity checking, and as a vehicle to send them upstream to Linus -(by sending him a "please pull" request.) - -Note that the period of time that each patch spends in the "test" tree -is dependent on the complexity of the change. Since GIT does not support -cherry picking, it is not practical to simply apply all patches to the -test tree and then pull to the release tree as that would leave trivial -patches blocked in the test tree waiting for complex changes to accumulate -enough test time to graduate. - -Back in the BitKeeper days I achieved this by creating small forests of -temporary trees, one tree for each logical grouping of patches, and then -pulling changes from these trees first to the test tree, and then to the -release tree. At first I replicated this in GIT, but then I realised -that I could so this far more efficiently using branches inside a single -GIT repository. - -So here is the step-by-step guide how this all works for me. - -First create your work tree by cloning Linus's public tree: - - $ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git work - -Change directory into the cloned tree you just created - - $ cd work - -Set up a remotes file so that you can fetch the latest from Linus' master -branch into a local branch named "linus": - - $ cat > .git/remotes/linus - URL: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git - Pull: master:linus - ^D - -and create the linus branch: - - $ git branch linus - -The "linus" branch will be used to track the upstream kernel. To update it, -you simply run: - - $ git fetch linus - -you can do this frequently (and it should be safe to do so with pending -work in your tree, but perhaps not if you are in mid-merge). - -If you need to keep track of other public trees, you can add remote branches -for them too: - - $ git branch another - $ cat > .git/remotes/another - URL: ... insert URL here ... - Pull: name-of-branch-in-this-remote-tree:another - ^D - -and run: - - $ git fetch another - -Now create the branches in which you are going to work, these start -out at the current tip of the linus branch. - - $ git branch test linus - $ git branch release linus - -These can be easily kept up to date by merging from the "linus" branch: - - $ git checkout test && git merge "Auto-update from upstream" test linus - $ git checkout release && git merge "Auto-update from upstream" release linus - -Important note! If you have any local changes in these branches, then -this merge will create a commit object in the history (with no local -changes git will simply do a "Fast forward" merge). Many people dislike -the "noise" that this creates in the Linux history, so you should avoid -doing this capriciously in the "release" branch, as these noisy commits -will become part of the permanent history when you ask Linus to pull -from the release branch. - -Set up so that you can push upstream to your public tree (you need to -log-in to the remote system and create an empty tree there before the -first push). - - $ cat > .git/remotes/mytree - URL: master.kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git - Push: release - Push: test - ^D - -and the push both the test and release trees using: - - $ git push mytree - -or push just one of the test and release branches using: - - $ git push mytree test -or - $ git push mytree release - -Now to apply some patches from the community. Think of a short -snappy name for a branch to hold this patch (or related group of -patches), and create a new branch from the current tip of the -linus branch: - - $ git checkout -b speed-up-spinlocks linus - -Now you apply the patch(es), run some tests, and commit the change(s). If -the patch is a multi-part series, then you should apply each as a separate -commit to this branch. - - $ ... patch ... test ... commit [ ... patch ... test ... commit ]* - -When you are happy with the state of this change, you can pull it into the -"test" branch in preparation to make it public: - - $ git checkout test && git merge "Pull speed-up-spinlock changes" test speed-up-spinlocks - -It is unlikely that you would have any conflicts here ... but you might if you -spent a while on this step and had also pulled new versions from upstream. - -Some time later when enough time has passed and testing done, you can pull the -same branch into the "release" tree ready to go upstream. This is where you -see the value of keeping each patch (or patch series) in its own branch. It -means that the patches can be moved into the "release" tree in any order. - - $ git checkout release && git merge "Pull speed-up-spinlock changes" release speed-up-spinlocks - -After a while, you will have a number of branches, and despite the -well chosen names you picked for each of them, you may forget what -they are for, or what status they are in. To get a reminder of what -changes are in a specific branch, use: - - $ git-whatchanged branchname ^linus | git-shortlog - -To see whether it has already been merged into the test or release branches -use: - - $ git-rev-list branchname ^test -or - $ git-rev-list branchname ^release - -[If this branch has not yet been merged you will see a set of SHA1 values -for the commits, if it has been merged, then there will be no output] - -Once a patch completes the great cycle (moving from test to release, then -pulled by Linus, and finally coming back into your local "linus" branch) -the branch for this change is no longer needed. You detect this when the -output from: - - $ git-rev-list branchname ^linus - -is empty. At this point the branch can be deleted: - - $ git branch -d branchname - -Some changes are so trivial that it is not necessary to create a separate -branch and then merge into each of the test and release branches. For -these changes, just apply directly to the "release" branch, and then -merge that into the "test" branch. - -To create diffstat and shortlog summaries of changes to include in a "please -pull" request to Linus you can use: - - $ git-whatchanged -p release ^linus | diffstat -p1 -and - $ git-whatchanged release ^linus | git-shortlog - - -Here are some of the scripts that I use to simplify all this even further. - -==== update script ==== -# Update a branch in my GIT tree. If the branch to be updated -# is "linus", then pull from kernel.org. Otherwise merge local -# linus branch into test|release branch - -case "$1" in -test|release) - git checkout $1 && git merge "Auto-update from upstream" $1 linus - ;; -linus) - before=$(cat .git/refs/heads/linus) - git fetch linus - after=$(cat .git/refs/heads/linus) - if [ $before != $after ] - then - git-whatchanged $after ^$before | git-shortlog - fi - ;; -*) - echo "Usage: $0 linus|test|release" 1>&2 - exit 1 - ;; -esac - -==== merge script ==== -# Merge a branch into either the test or release branch - -pname=$0 - -usage() -{ - echo "Usage: $pname branch test|release" 1>&2 - exit 1 -} - -if [ ! -f .git/refs/heads/"$1" ] -then - echo "Can't see branch <$1>" 1>&2 - usage -fi - -case "$2" in -test|release) - if [ $(git-rev-list $1 ^$2 | wc -c) -eq 0 ] - then - echo $1 already merged into $2 1>&2 - exit 1 - fi - git checkout $2 && git merge "Pull $1 into $2 branch" $2 $1 - ;; -*) - usage - ;; -esac - -==== status script ==== -# report on status of my ia64 GIT tree - -gb=$(tput setab 2) -rb=$(tput setab 1) -restore=$(tput setab 9) - -if [ `git-rev-list release ^test | wc -c` -gt 0 ] -then - echo $rb Warning: commits in release that are not in test $restore - git-whatchanged release ^test -fi - -for branch in `ls .git/refs/heads` -do - if [ $branch = linus -o $branch = test -o $branch = release ] - then - continue - fi - - echo -n $gb ======= $branch ====== $restore " " - status= - for ref in test release linus - do - if [ `git-rev-list $branch ^$ref | wc -c` -gt 0 ] - then - status=$status${ref:0:1} - fi - done - case $status in - trl) - echo $rb Need to pull into test $restore - ;; - rl) - echo "In test" - ;; - l) - echo "Waiting for linus" - ;; - "") - echo $rb All done $restore - ;; - *) - echo $rb "<$status>" $restore - ;; - esac - git-whatchanged $branch ^linus | git-shortlog -done diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index 55d4d37b21..9cc5fc9db3 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -1789,7 +1789,302 @@ gitweb/INSTALL in the git source tree for instructions on setting it up. Examples -------- -TODO: topic branches, typical roles as in everyday.txt, ? +[[maintaining-topic-branches]] +Maintaining topic branches for a Linux subsystem maintainer +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This describes how Tony Luck uses git in his role as maintainer of the +IA64 architecture for the Linux kernel. + +He uses two public branches: + + - A "test" tree into which patches are initially placed so that they + can get some exposure when integrated with other ongoing development. + This tree is available to Andrew for pulling into -mm whenever he + wants. + + - A "release" tree into which tested patches are moved for final sanity + checking, and as a vehicle to send them upstream to Linus (by sending + him a "please pull" request.) + +He also uses a set of temporary branches ("topic branches"), each +containing a logical grouping of patches. + +To set this up, first create your work tree by cloning Linus's public +tree: + +------------------------------------------------- +$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git work +$ cd work +------------------------------------------------- + +Linus's tree will be stored in the remote branch named origin/master, +and can be updated using gitlink:git-fetch[1]; you can track other +public trees using gitlink:git-remote[1] to set up a "remote" and +git-fetch[1] to keep them up-to-date; see <<repositories-and-branches>>. + +Now create the branches in which you are going to work; these start out +at the current tip of origin/master branch, and should be set up (using +the --track option to gitlink:git-branch[1]) to merge changes in from +Linus by default. + +------------------------------------------------- +$ git branch --track test origin/master +$ git branch --track release origin/master +------------------------------------------------- + +These can be easily kept up to date using gitlink:git-pull[1] + +------------------------------------------------- +$ git checkout test && git pull +$ git checkout release && git pull +------------------------------------------------- + +Important note! If you have any local changes in these branches, then +this merge will create a commit object in the history (with no local +changes git will simply do a "Fast forward" merge). Many people dislike +the "noise" that this creates in the Linux history, so you should avoid +doing this capriciously in the "release" branch, as these noisy commits +will become part of the permanent history when you ask Linus to pull +from the release branch. + +A few configuration variables (see gitlink:git-config[1]) can +make it easy to push both branches to your public tree. (See +<<setting-up-a-public-repository>>.) + +------------------------------------------------- +$ cat >> .git/config <<EOF +[remote "mytree"] + url = master.kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git + push = release + push = test +EOF +------------------------------------------------- + +Then you can push both the test and release trees using +gitlink:git-push[1]: + +------------------------------------------------- +$ git push mytree +------------------------------------------------- + +or push just one of the test and release branches using: + +------------------------------------------------- +$ git push mytree test +------------------------------------------------- + +or + +------------------------------------------------- +$ git push mytree release +------------------------------------------------- + +Now to apply some patches from the community. Think of a short +snappy name for a branch to hold this patch (or related group of +patches), and create a new branch from the current tip of Linus's +branch: + +------------------------------------------------- +$ git checkout -b speed-up-spinlocks origin +------------------------------------------------- + +Now you apply the patch(es), run some tests, and commit the change(s). If +the patch is a multi-part series, then you should apply each as a separate +commit to this branch. + +------------------------------------------------- +$ ... patch ... test ... commit [ ... patch ... test ... commit ]* +------------------------------------------------- + +When you are happy with the state of this change, you can pull it into the +"test" branch in preparation to make it public: + +------------------------------------------------- +$ git checkout test && git pull . speed-up-spinlocks +------------------------------------------------- + +It is unlikely that you would have any conflicts here ... but you might if you +spent a while on this step and had also pulled new versions from upstream. + +Some time later when enough time has passed and testing done, you can pull the +same branch into the "release" tree ready to go upstream. This is where you +see the value of keeping each patch (or patch series) in its own branch. It +means that the patches can be moved into the "release" tree in any order. + +------------------------------------------------- +$ git checkout release && git pull . speed-up-spinlocks +------------------------------------------------- + +After a while, you will have a number of branches, and despite the +well chosen names you picked for each of them, you may forget what +they are for, or what status they are in. To get a reminder of what +changes are in a specific branch, use: + +------------------------------------------------- +$ git log linux..branchname | git-shortlog +------------------------------------------------- + +To see whether it has already been merged into the test or release branches +use: + +------------------------------------------------- +$ git log test..branchname +------------------------------------------------- + +or + +------------------------------------------------- +$ git log release..branchname +------------------------------------------------- + +(If this branch has not yet been merged you will see some log entries. +If it has been merged, then there will be no output.) + +Once a patch completes the great cycle (moving from test to release, +then pulled by Linus, and finally coming back into your local +"origin/master" branch) the branch for this change is no longer needed. +You detect this when the output from: + +------------------------------------------------- +$ git log origin..branchname +------------------------------------------------- + +is empty. At this point the branch can be deleted: + +------------------------------------------------- +$ git branch -d branchname +------------------------------------------------- + +Some changes are so trivial that it is not necessary to create a separate +branch and then merge into each of the test and release branches. For +these changes, just apply directly to the "release" branch, and then +merge that into the "test" branch. + +To create diffstat and shortlog summaries of changes to include in a "please +pull" request to Linus you can use: + +------------------------------------------------- +$ git diff --stat origin..release +------------------------------------------------- + +and + +------------------------------------------------- +$ git log -p origin..release | git shortlog +------------------------------------------------- + +Here are some of the scripts that simplify all this even further. + +------------------------------------------------- +==== update script ==== +# Update a branch in my GIT tree. If the branch to be updated +# is origin, then pull from kernel.org. Otherwise merge +# origin/master branch into test|release branch + +case "$1" in +test|release) + git checkout $1 && git pull . origin + ;; +origin) + before=$(cat .git/refs/remotes/origin/master) + git fetch origin + after=$(cat .git/refs/remotes/origin/master) + if [ $before != $after ] + then + git log $before..$after | git shortlog + fi + ;; +*) + echo "Usage: $0 origin|test|release" 1>&2 + exit 1 + ;; +esac +------------------------------------------------- + +------------------------------------------------- +==== merge script ==== +# Merge a branch into either the test or release branch + +pname=$0 + +usage() +{ + echo "Usage: $pname branch test|release" 1>&2 + exit 1 +} + +if [ ! -f .git/refs/heads/"$1" ] +then + echo "Can't see branch <$1>" 1>&2 + usage +fi + +case "$2" in +test|release) + if [ $(git log $2..$1 | wc -c) -eq 0 ] + then + echo $1 already merged into $2 1>&2 + exit 1 + fi + git checkout $2 && git pull . $1 + ;; +*) + usage + ;; +esac +------------------------------------------------- + +------------------------------------------------- +==== status script ==== +# report on status of my ia64 GIT tree + +gb=$(tput setab 2) +rb=$(tput setab 1) +restore=$(tput setab 9) + +if [ `git rev-list test..release | wc -c` -gt 0 ] +then + echo $rb Warning: commits in release that are not in test $restore + git log test..release +fi + +for branch in `ls .git/refs/heads` +do + if [ $branch = test -o $branch = release ] + then + continue + fi + + echo -n $gb ======= $branch ====== $restore " " + status= + for ref in test release origin/master + do + if [ `git rev-list $ref..$branch | wc -c` -gt 0 ] + then + status=$status${ref:0:1} + fi + done + case $status in + trl) + echo $rb Need to pull into test $restore + ;; + rl) + echo "In test" + ;; + l) + echo "Waiting for linus" + ;; + "") + echo $rb All done $restore + ;; + *) + echo $rb "<$status>" $restore + ;; + esac + git log origin/master..$branch | git shortlog +done +------------------------------------------------- [[cleaning-up-history]] From 46acd3fa32404a9373d48c9caba271c34357ec9f Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" <bfields@citi.umich.edu> Date: Sun, 13 May 2007 02:14:45 -0400 Subject: [PATCH 63/86] user-manual: add a "counting commits" example This is partly just an excuse to mention --pretty= and rev-list. Signed-off-by: "J. Bruce Fields" <bfields@citi.umich.edu> --- Documentation/user-manual.txt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index 9cc5fc9db3..242f5aa479 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -690,6 +690,25 @@ may be any path to a file tracked by git. Examples -------- +[[counting-commits-on-a-branch]] +Counting the number of commits on a branch +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Suppose you want to know how many commits you've made on "mybranch" +since it diverged from "origin": + +------------------------------------------------- +$ git log --pretty=oneline origin..mybranch | wc -l +------------------------------------------------- + +Alternatively, you may often see this sort of thing done with the +lower-level command gitlink:git-rev-list[1], which just lists the SHA1's +of all the given commits: + +------------------------------------------------- +$ git rev-list origin..mybranch | wc -l +------------------------------------------------- + [[checking-for-equal-branches]] Check whether two branches point at the same history ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 99eaefdd32f25a6b76b2bd52bb253e19a4a3cad4 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" <bfields@citi.umich.edu> Date: Sun, 13 May 2007 02:23:11 -0400 Subject: [PATCH 64/86] user-manual: introduce git Well, we should say at least something about what git is. Signed-off-by: "J. Bruce Fields" <bfields@citi.umich.edu> --- Documentation/user-manual.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index 242f5aa479..773ed36640 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -1,6 +1,9 @@ Git User's Manual (for version 1.5.1 or newer) ______________________________________________ + +Git is a fast distributed revision control system. + This manual is designed to be readable by someone with basic unix command-line skills, but no previous knowledge of git. From 629d9f785fecb964245dac52b422aec0bd00278e Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" <bfields@citi.umich.edu> Date: Sun, 13 May 2007 22:58:06 -0400 Subject: [PATCH 65/86] user-manual: listing commits reachable from some refs not others This is just an amusing example raised by someone in irc. Signed-off-by: "J. Bruce Fields" <bfields@citi.umich.edu> --- Documentation/user-manual.txt | 48 +++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index 773ed36640..735fea1621 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -830,6 +830,54 @@ available Which shows that e05db0fd is reachable from itself, from v1.5.0-rc1, and from v1.5.0-rc2, but not from v1.5.0-rc0. +[[showing-commits-unique-to-a-branch]] +Showing commits unique to a given branch +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Suppose you would like to see all the commits reachable from the branch +head named "master" but not from any other head in your repository. + +We can list all the heads in this repository with +gitlink:git-show-ref[1]: + +------------------------------------------------- +$ git show-ref --heads +bf62196b5e363d73353a9dcf094c59595f3153b7 refs/heads/core-tutorial +db768d5504c1bb46f63ee9d6e1772bd047e05bf9 refs/heads/maint +a07157ac624b2524a059a3414e99f6f44bebc1e7 refs/heads/master +24dbc180ea14dc1aebe09f14c8ecf32010690627 refs/heads/tutorial-2 +1e87486ae06626c2f31eaa63d26fc0fd646c8af2 refs/heads/tutorial-fixes +------------------------------------------------- + +We can get just the branch-head names, and remove "master", with +the help of the standard utilities cut and grep: + +------------------------------------------------- +$ git show-ref --heads | cut -d' ' -f2 | grep -v '^refs/heads/master' +refs/heads/core-tutorial +refs/heads/maint +refs/heads/tutorial-2 +refs/heads/tutorial-fixes +------------------------------------------------- + +And then we can ask to see all the commits reachable from master +but not from these other heads: + +------------------------------------------------- +$ gitk master --not $( git show-ref --heads | cut -d' ' -f2 | + grep -v '^refs/heads/master' ) +------------------------------------------------- + +Obviously, endless variations are possible; for example, to see all +commits reachable from some head but not from any tag in the repository: + +------------------------------------------------- +$ gitk ($ git show-ref --heads ) --not $( git show-ref --tags ) +------------------------------------------------- + +(See gitlink:git-rev-parse[1] for explanations of commit-selecting +syntax such as `--not`.) + [[making-a-release]] Creating a changelog and tarball for a software release ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From eda694491933ac5f209892f3e284b648bb0185a0 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" <bfields@citi.umich.edu> Date: Tue, 15 May 2007 00:00:29 -0400 Subject: [PATCH 66/86] user-manual: reorganize public git repo discussion Helping a couple people set up public repos recently, I wanted to point them at this piece of the user manual, but found it wasn't as helpful as it could be: - It starts with a big explanation of why you'd want a public repository, not necessary in their case since they already knew why they wanted that. So, separate that out. - It skimps on some of the git-daemon details, and puts the http export information first. Fix that. Also group all the public repo subsections into a single section, and do some miscellaneous related editing. Signed-off-by: "J. Bruce Fields" <bfields@citi.umich.edu> --- Documentation/user-manual.txt | 90 +++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 40 deletions(-) diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index 735fea1621..f4843f4e90 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -1674,31 +1674,30 @@ The final result will be a series of commits, one for each patch in the original mailbox, with authorship and commit log message each taken from the message containing each patch. -[[setting-up-a-public-repository]] -Setting up a public repository ------------------------------- +[[public-repositories]] +Public git repositories +----------------------- -Another way to submit changes to a project is to simply tell the -maintainer of that project to pull from your repository, exactly as -you did in the section "<<getting-updates-with-git-pull, Getting -updates with git pull>>". +Another way to submit changes to a project is to tell the maintainer of +that project to pull the changes from your repository using git-pull[1]. +In the section "<<getting-updates-with-git-pull, Getting updates with +git pull>>" we described this as a way to get updates from the "main" +repository, but it works just as well in the other direction. -If you and maintainer both have accounts on the same machine, then -then you can just pull changes from each other's repositories -directly; note that all of the commands (gitlink:git-clone[1], -git-fetch[1], git-pull[1], etc.) that accept a URL as an argument -will also accept a local directory name; so, for example, you can -use +If you and the maintainer both have accounts on the same machine, then +you can just pull changes from each other's repositories directly; +commands that accepts repository URLs as arguments will also accept a +local directory name: ------------------------------------------------- $ git clone /path/to/repository $ git pull /path/to/other/repository ------------------------------------------------- -If this sort of setup is inconvenient or impossible, another (more -common) option is to set up a public repository on a public server. -This also allows you to cleanly separate private work in progress -from publicly visible work. +However, the more common way to do this is to maintain a separate public +repository (usually on a different host) for others to pull changes +from. This is usually more convenient, and allows you to cleanly +separate private work in progress from publicly visible work. You will continue to do your day-to-day work in your personal repository, but periodically "push" changes from your personal @@ -1717,32 +1716,52 @@ like this: | they push V their public repo <------------------- their repo -Now, assume your personal repository is in the directory ~/proj. We -first create a new clone of the repository: +[[setting-up-a-public-repository]] +Setting up a public repository +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Assume your personal repository is in the directory ~/proj. We +first create a new clone of the repository and tell git-daemon that it +is meant to be public: ------------------------------------------------- $ git clone --bare ~/proj proj.git +$ touch proj.git/git-daemon-export-ok ------------------------------------------------- The resulting directory proj.git contains a "bare" git repository--it is -just the contents of the ".git" directory, without a checked-out copy of -a working directory. +just the contents of the ".git" directory, without any files checked out +around it. Next, copy proj.git to the server where you plan to host the public repository. You can use scp, rsync, or whatever is most convenient. -If somebody else maintains the public server, they may already have -set up a git service for you, and you may skip to the section +[[exporting-via-git]] +Exporting a git repository via the git protocol +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is the preferred method. + +If someone else administers the server, they should tell you what +directory to put the repository in, and what git:// url it will appear +at. You can then skip to the section "<<pushing-changes-to-a-public-repository,Pushing changes to a public repository>>", below. -Otherwise, the following sections explain how to export your newly -created public repository: +Otherwise, all you need to do is start gitlink:git-daemon[1]; it will +listen on port 9418. By default, it will allow access to any directory +that looks like a git directory and contains the magic file +git-daemon-export-ok. Passing some directory paths as git-daemon +arguments will further restrict the exports to those paths. + +You can also run git-daemon as an inetd service; see the +gitlink:git-daemon[1] man page for details. (See especially the +examples section.) [[exporting-via-http]] Exporting a git repository via http ------------------------------------ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The git protocol gives better performance and reliability, but on a host with a web server set up, http exports may be simpler to set up. @@ -1774,20 +1793,11 @@ link:howto/setup-git-server-over-http.txt[setup-git-server-over-http] for a slightly more sophisticated setup using WebDAV which also allows pushing over http.) -[[exporting-via-git]] -Exporting a git repository via the git protocol ------------------------------------------------ - -This is the preferred method. - -For now, we refer you to the gitlink:git-daemon[1] man page for -instructions. (See especially the examples section.) - [[pushing-changes-to-a-public-repository]] Pushing changes to a public repository --------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Note that the two techniques outline above (exporting via +Note that the two techniques outlined above (exporting via <<exporting-via-http,http>> or <<exporting-via-git,git>>) allow other maintainers to fetch your latest changes, but they do not allow write access, which you will need to update the public repository with the @@ -1839,7 +1849,7 @@ details. [[setting-up-a-shared-repository]] Setting up a shared repository ------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Another way to collaborate is by using a model similar to that commonly used in CVS, where several developers with special rights @@ -1848,8 +1858,8 @@ link:cvs-migration.txt[git for CVS users] for instructions on how to set this up. [[setting-up-gitweb]] -Allow web browsing of a repository ----------------------------------- +Allowing web browsing of a repository +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The gitweb cgi script provides users an easy way to browse your project's files and history without having to install git; see the file From 5e6cfc80e26a4d0ebac38cff74c2cdebbe66cd27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= <rene.scharfe@lsrfire.ath.cx> Date: Sat, 19 May 2007 00:09:41 +0200 Subject: [PATCH 67/86] git-archive: convert archive entries like checkouts do As noted by Johan Herland, git-archive is a kind of checkout and needs to apply any checkout filters that might be configured. This patch adds the convenience function convert_sha1_file which returns a buffer containing the object's contents, after converting, if necessary (i.e. it's a combination of read_sha1_file and convert_to_working_tree). Direct calls to read_sha1_file in git-archive are then replaced by calls to convert_sha1_file. Since convert_sha1_file expects its path argument to be NUL-terminated -- a convention it inherits from convert_to_working_tree -- the patch also changes the path handling in archive-tar.c to always NUL-terminate the string. It used to solely rely on the len field of struct strbuf before. archive-zip.c already NUL-terminates the path and thus needs no such change. Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx> Signed-off-by: Junio C Hamano <junkio@cox.net> --- archive-tar.c | 16 +++++++++------- archive-zip.c | 2 +- cache.h | 1 + convert.c | 15 +++++++++++++++ 4 files changed, 26 insertions(+), 8 deletions(-) diff --git a/archive-tar.c b/archive-tar.c index 56ff356966..33e76576f1 100644 --- a/archive-tar.c +++ b/archive-tar.c @@ -82,12 +82,13 @@ static void strbuf_append_string(struct strbuf *sb, const char *s) { int slen = strlen(s); int total = sb->len + slen; - if (total > sb->alloc) { - sb->buf = xrealloc(sb->buf, total); - sb->alloc = total; + if (total + 1 > sb->alloc) { + sb->buf = xrealloc(sb->buf, total + 1); + sb->alloc = total + 1; } memcpy(sb->buf + sb->len, s, slen); sb->len = total; + sb->buf[total] = '\0'; } /* @@ -270,20 +271,21 @@ static int write_tar_entry(const unsigned char *sha1, path.alloc = PATH_MAX; path.len = path.eof = 0; } - if (path.alloc < baselen + filenamelen) { + if (path.alloc < baselen + filenamelen + 1) { free(path.buf); - path.buf = xmalloc(baselen + filenamelen); - path.alloc = baselen + filenamelen; + path.buf = xmalloc(baselen + filenamelen + 1); + path.alloc = baselen + filenamelen + 1; } memcpy(path.buf, base, baselen); memcpy(path.buf + baselen, filename, filenamelen); path.len = baselen + filenamelen; + path.buf[path.len] = '\0'; if (S_ISDIR(mode) || S_ISDIRLNK(mode)) { strbuf_append_string(&path, "/"); buffer = NULL; size = 0; } else { - buffer = read_sha1_file(sha1, &type, &size); + buffer = convert_sha1_file(path.buf, sha1, mode, &type, &size); if (!buffer) die("cannot read %s", sha1_to_hex(sha1)); } diff --git a/archive-zip.c b/archive-zip.c index 1eaf262b74..3cbf6bb8ac 100644 --- a/archive-zip.c +++ b/archive-zip.c @@ -195,7 +195,7 @@ static int write_zip_entry(const unsigned char *sha1, if (S_ISREG(mode) && zlib_compression_level != 0) method = 8; result = 0; - buffer = read_sha1_file(sha1, &type, &size); + buffer = convert_sha1_file(path, sha1, mode, &type, &size); if (!buffer) die("cannot read %s", sha1_to_hex(sha1)); crc = crc32(crc, buffer, size); diff --git a/cache.h b/cache.h index aaeb04a1b9..4204bc168c 100644 --- a/cache.h +++ b/cache.h @@ -548,6 +548,7 @@ extern void trace_argv_printf(const char **argv, int count, const char *format, /* convert.c */ extern char *convert_to_git(const char *path, const char *src, unsigned long *sizep); extern char *convert_to_working_tree(const char *path, const char *src, unsigned long *sizep); +extern void *convert_sha1_file(const char *path, const unsigned char *sha1, unsigned int mode, enum object_type *type, unsigned long *size); /* match-trees.c */ void shift_tree(const unsigned char *, const unsigned char *, unsigned char *, int); diff --git a/convert.c b/convert.c index 12abdaf2a5..c64880bdf5 100644 --- a/convert.c +++ b/convert.c @@ -652,3 +652,18 @@ char *convert_to_working_tree(const char *path, const char *src, unsigned long * return buf; } + +void *convert_sha1_file(const char *path, const unsigned char *sha1, + unsigned int mode, enum object_type *type, + unsigned long *size) +{ + void *buffer = read_sha1_file(sha1, type, size); + if (S_ISREG(mode) && buffer) { + void *converted = convert_to_working_tree(path, buffer, size); + if (converted) { + free(buffer); + buffer = converted; + } + } + return buffer; +} From 760f0c62ef8980cc46422894791649b010cc480f Mon Sep 17 00:00:00 2001 From: Andy Parkins <andyparkins@gmail.com> Date: Fri, 18 May 2007 13:33:32 +0100 Subject: [PATCH 68/86] Fix crlf attribute handling to match documentation gitattributes.txt says, of the crlf attribute: Set:: Setting the `crlf` attribute on a path is meant to mark the path as a "text" file. 'core.autocrlf' conversion takes place without guessing the content type by inspection. That is to say that the crlf attribute does not force the file to have CRLF line endings, instead it removes the autocrlf guesswork and forces the file to be treated as text. Then, whatever line ending is defined by the autocrlf setting is applied. However, that is not what convert.c was doing. The conversion to CRLF was being skipped in crlf_to_worktree() when the following condition was true: action == CRLF_GUESS && auto_crlf <= 0 That is to say conversion took place when not in guess mode (crlf attribute not specified) or core.autocrlf set to true. This was wrong. It meant that the crlf attribute being on for a given file _forced_ CRLF conversion, when actually it should force the file to be treated as text, and converted accordingly. The real test should simply be auto_crlf <= 0 That is to say, if core.autocrlf is falsei (or input), conversion from LF to CRLF is never done. When core.autocrlf is true, conversion from LF to CRLF is done only when in CRLF_GUESS (and the guess is "text"), or CRLF_TEXT mode. Similarly for crlf_to_worktree(), if core.autocrlf is false, no conversion should _ever_ take place. In reality it was only not taking place if core.autocrlf was false _and_ the crlf attribute was unspecified. Signed-off-by: Andy Parkins <andyparkins@gmail.com> Signed-off-by: Junio C Hamano <junkio@cox.net> --- convert.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/convert.c b/convert.c index c64880bdf5..4b26b1a9b9 100644 --- a/convert.c +++ b/convert.c @@ -86,7 +86,7 @@ static char *crlf_to_git(const char *path, const char *src, unsigned long *sizep unsigned long size, nsize; struct text_stat stats; - if ((action == CRLF_BINARY) || (action == CRLF_GUESS && !auto_crlf)) + if ((action == CRLF_BINARY) || !auto_crlf) return NULL; size = *sizep; @@ -154,7 +154,7 @@ static char *crlf_to_worktree(const char *path, const char *src, unsigned long * unsigned char last; if ((action == CRLF_BINARY) || (action == CRLF_INPUT) || - (action == CRLF_GUESS && auto_crlf <= 0)) + auto_crlf <= 0) return NULL; size = *sizep; From a5c2d26a044af3899669b010a5b85801a8c2b6a7 Mon Sep 17 00:00:00 2001 From: Petr Baudis <pasky@suse.cz> Date: Sat, 19 May 2007 01:21:53 +0200 Subject: [PATCH 69/86] Documentation: git-rev-list's "patterns" git-rev-list(1) talks about patterns as values for the --grep, --committed etc. parameters, without going into detail. This patch mentions that these patterns are actually regexps. Signed-off-by: Petr Baudis <pasky@suse.cz> Signed-off-by: Junio C Hamano <junkio@cox.net> --- Documentation/git-rev-list.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt index 11ce395c98..fde9a7208d 100644 --- a/Documentation/git-rev-list.txt +++ b/Documentation/git-rev-list.txt @@ -193,12 +193,12 @@ limiting may be applied. --author='pattern', --committer='pattern':: Limit the commits output to ones with author/committer - header lines that match the specified pattern. + header lines that match the specified pattern (regular expression). --grep='pattern':: Limit the commits output to ones with log message that - matches the specified pattern. + matches the specified pattern (regular expression). --remove-empty:: From 7f79b0173d2464a31fcb69ff33df9821172b2219 Mon Sep 17 00:00:00 2001 From: Petr Baudis <pasky@suse.cz> Date: Sat, 19 May 2007 01:12:32 +0200 Subject: [PATCH 70/86] gitweb: Remove redundant $searchtype setup Sorry, this was inadverently introduced by my grep search patch. It causes annoying "redefined" warnings. Signed-off-by: Petr Baudis <pasky@suse.cz> Signed-off-by: Junio C Hamano <junkio@cox.net> --- gitweb/gitweb.perl | 7 ------- 1 file changed, 7 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 7c136ec0d3..17d8efb29c 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -408,13 +408,6 @@ if (defined $searchtext) { $search_regexp = quotemeta $searchtext; } -our $searchtype = $cgi->param('st'); -if (defined $searchtype) { - if ($searchtype =~ m/[^a-z]/) { - die_error(undef, "Invalid searchtype parameter"); - } -} - # now read PATH_INFO and use it as alternative to parameters sub evaluate_path_info { return if defined $project; From 6b68342edc392bb640b30c2115eb6585a3303e25 Mon Sep 17 00:00:00 2001 From: Junio C Hamano <junkio@cox.net> Date: Fri, 18 May 2007 17:21:31 -0700 Subject: [PATCH 71/86] GIT v1.5.1.5 Signed-off-by: Junio C Hamano <junkio@cox.net> --- Documentation/RelNotes-1.5.1.5.txt | 15 +++++++++++++-- GIT-VERSION-GEN | 2 +- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Documentation/RelNotes-1.5.1.5.txt b/Documentation/RelNotes-1.5.1.5.txt index 5cfe0b5b06..85e821c433 100644 --- a/Documentation/RelNotes-1.5.1.5.txt +++ b/Documentation/RelNotes-1.5.1.5.txt @@ -6,6 +6,17 @@ Fixes since v1.5.1.4 * Bugfixes + - git-send-email did not understand aliases file for mutt, which + allows leading whitespaces. + + - git-format-patch emitted Content-Type and Content-Transfer-Encoding + headers for non ASCII contents, but failed to add MIME-Version. + + - git-name-rev had a buffer overrun with a deep history. + + - contributed script import-tars did not get the directory in + tar archives interpreted correctly. + - git-svn was reported to segfault for many people on list and #git; hopefully this has been fixed. @@ -28,10 +39,10 @@ Fixes since v1.5.1.4 and extern, which caused trouble compiling with Forte12 compilers on Sun. - - Many documentation fixes. + - Many many documentation fixes and updates. -- exec >/var/tmp/1 -O=v1.5.1.4-26-gb4b20b2 +O=v1.5.1.4-48-gcecb98a echo O=`git describe refs/heads/maint` git shortlog --no-merges $O..refs/heads/maint diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 094a0d1b0e..2dbedf3d9d 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v1.5.1.4.GIT +DEF_VER=v1.5.1.5.GIT LF=' ' From b6e4db6a9974766ae8855501b63ec331a1c737da Mon Sep 17 00:00:00 2001 From: Junio C Hamano <junkio@cox.net> Date: Fri, 18 May 2007 17:28:24 -0700 Subject: [PATCH 72/86] Add link to 1.5.1.5 release notes. Signed-off-by: Junio C Hamano <junkio@cox.net> --- Documentation/git.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/git.txt b/Documentation/git.txt index 273ca173d4..99b8f52084 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -40,7 +40,9 @@ Documentation for older releases are available here: * link:RelNotes-1.5.1.txt[release notes for 1.5.1] -* link:v1.5.1.4/git.html[documentation for release 1.5.1.4] +* link:v1.5.1.5/git.html[documentation for release 1.5.1.5] + +* link:RelNotes-1.5.1.5.txt[release notes for 1.5.1.5] * link:RelNotes-1.5.1.4.txt[release notes for 1.5.1.4] From c906b18122af72a8219c76281473490f812e5a40 Mon Sep 17 00:00:00 2001 From: Jakub Narebski <jnareb@gmail.com> Date: Sat, 19 May 2007 02:47:51 +0200 Subject: [PATCH 73/86] gitweb: Fix "Use of uninitialized value" warning in git_feed Initial (root) commit has no parents, and $co{'parent'} is undefined. Use '--root' for initial commit. This fixes "Use of uninitialized value in open at gitweb/gitweb.perl line 4925." warning. Signed-off-by: Jakub Narebski <jnareb@gmail.com> Signed-off-by: Junio C Hamano <junkio@cox.net> --- gitweb/gitweb.perl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 17d8efb29c..5c7011a37b 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -5040,7 +5040,8 @@ XML # get list of changed files open my $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts, - $co{'parent'}, $co{'id'}, "--", (defined $file_name ? $file_name : ()) + $co{'parent'} || "--root", + $co{'id'}, "--", (defined $file_name ? $file_name : ()) or next; my @difftree = map { chomp; $_ } <$fd>; close $fd From 2ff3f61ab6125edc53e4da8065b787bd10d0fdbb Mon Sep 17 00:00:00 2001 From: Junio C Hamano <junkio@cox.net> Date: Fri, 18 May 2007 21:43:13 -0700 Subject: [PATCH 74/86] Documentation/git.txt: Update links to older documentation pages. It's starting to take too much space at the beginning of the main documentation page. Signed-off-by: Junio C Hamano <junkio@cox.net> --- Documentation/git.txt | 53 ++++++++++++++++++------------------------- 1 file changed, 22 insertions(+), 31 deletions(-) diff --git a/Documentation/git.txt b/Documentation/git.txt index 99b8f52084..157ef29131 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -35,44 +35,35 @@ documentation can be viewed at ifdef::stalenotes[] [NOTE] ============ -You are reading the documentation for the latest version of git. -Documentation for older releases are available here: -* link:RelNotes-1.5.1.txt[release notes for 1.5.1] +You are reading the documentation for the latest (possibly +unreleased) version of git, that is available from 'master' +branch of the `git.git` repository. +Documentation for older releases are available here: * link:v1.5.1.5/git.html[documentation for release 1.5.1.5] -* link:RelNotes-1.5.1.5.txt[release notes for 1.5.1.5] +* release notes for link:RelNotes-1.5.1.5.txt[1.5.1.5], + link:RelNotes-1.5.1.4.txt[1.5.1.4], + link:RelNotes-1.5.1.3.txt[1.5.1.3], + link:RelNotes-1.5.1.2.txt[1.5.1.2], + link:RelNotes-1.5.1.1.txt[1.5.1.1], + link:RelNotes-1.5.1.txt[1.5.1]. -* link:RelNotes-1.5.1.4.txt[release notes for 1.5.1.4] +* link:v1.5.0.7/git.html[documentation for release 1.5.0.7] -* link:RelNotes-1.5.1.3.txt[release notes for 1.5.1.3] +* release notes for link:RelNotes-1.5.0.7.txt[1.5.0.7], + link:RelNotes-1.5.0.6.txt[1.5.0.6], + link:RelNotes-1.5.0.5.txt[1.5.0.5], + link:RelNotes-1.5.0.3.txt[1.5.0.3], + link:RelNotes-1.5.0.2.txt[1.5.0.2], + link:RelNotes-1.5.0.1.txt[1.5.0.1], + link:RelNotes-1.5.0.txt[1.5.0]. -* link:RelNotes-1.5.1.2.txt[release notes for 1.5.1.2] - -* link:RelNotes-1.5.1.1.txt[release notes for 1.5.1.1] - -* link:RelNotes-1.5.0.7.txt[release notes for 1.5.0.7] - -* link:RelNotes-1.5.0.6.txt[release notes for 1.5.0.6] - -* link:RelNotes-1.5.0.5.txt[release notes for 1.5.0.5] - -* link:RelNotes-1.5.0.3.txt[release notes for 1.5.0.3] - -* link:RelNotes-1.5.0.2.txt[release notes for 1.5.0.2] - -* link:RelNotes-1.5.0.1.txt[release notes for 1.5.0.1] - -* link:RelNotes-1.5.0.txt[release notes for 1.5.0] - -* link:v1.4.4.4/git.html[documentation for release 1.4.4.4] - -* link:v1.3.3/git.html[documentation for release 1.3.3] - -* link:v1.2.6/git.html[documentation for release 1.2.6] - -* link:v1.0.13/git.html[documentation for release 1.0.13] +* documentation for release link:v1.4.4.4/git.html[1.4.4.4], + link:v1.3.3/git.html[1.3.3], + link:v1.2.6/git.html[1.2.6], + link:v1.0.13/git.html[1.0.13]. ============ From e448ff877b5bff0f2e6c5281652ed5183a41ed6c Mon Sep 17 00:00:00 2001 From: Matthias Kestenholz <matthias@spinlock.ch> Date: Fri, 18 May 2007 15:39:33 +0200 Subject: [PATCH 75/86] Documentation: Added [verse] to SYNOPSIS where necessary Signed-off-by: Matthias Kestenholz <matthias@spinlock.ch> Signed-off-by: Junio C Hamano <junkio@cox.net> --- Documentation/git-archive.txt | 1 + Documentation/git-bundle.txt | 1 + Documentation/git-fmt-merge-msg.txt | 1 + Documentation/git-name-rev.txt | 1 + Documentation/git-rebase.txt | 2 +- 5 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Documentation/git-archive.txt b/Documentation/git-archive.txt index 59dfabed23..5fd3b62cf1 100644 --- a/Documentation/git-archive.txt +++ b/Documentation/git-archive.txt @@ -8,6 +8,7 @@ git-archive - Creates an archive of files from a named tree SYNOPSIS -------- +[verse] 'git-archive' --format=<fmt> [--list] [--prefix=<prefix>/] [<extra>] [--remote=<repo>] <tree-ish> [path...] diff --git a/Documentation/git-bundle.txt b/Documentation/git-bundle.txt index 92e7a68722..5051e2bada 100644 --- a/Documentation/git-bundle.txt +++ b/Documentation/git-bundle.txt @@ -8,6 +8,7 @@ git-bundle - Move objects and refs by archive SYNOPSIS -------- +[verse] 'git-bundle' create <file> [git-rev-list args] 'git-bundle' verify <file> 'git-bundle' list-heads <file> [refname...] diff --git a/Documentation/git-fmt-merge-msg.txt b/Documentation/git-fmt-merge-msg.txt index e560b30c57..4913c2552f 100644 --- a/Documentation/git-fmt-merge-msg.txt +++ b/Documentation/git-fmt-merge-msg.txt @@ -8,6 +8,7 @@ git-fmt-merge-msg - Produce a merge commit message SYNOPSIS -------- +[verse] git-fmt-merge-msg [--summary | --no-summary] <$GIT_DIR/FETCH_HEAD git-fmt-merge-msg [--summary | --no-summray] -F <file> diff --git a/Documentation/git-name-rev.txt b/Documentation/git-name-rev.txt index 5b5c4c865f..d6c8bf800f 100644 --- a/Documentation/git-name-rev.txt +++ b/Documentation/git-name-rev.txt @@ -8,6 +8,7 @@ git-name-rev - Find symbolic names for given revs SYNOPSIS -------- +[verse] 'git-name-rev' [--tags] [--refs=<pattern>] ( --all | --stdin | <committish>... ) diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt index 2f417a8f85..753b275a0f 100644 --- a/Documentation/git-rebase.txt +++ b/Documentation/git-rebase.txt @@ -7,8 +7,8 @@ git-rebase - Forward-port local commits to the updated upstream head SYNOPSIS -------- +[verse] 'git-rebase' [-v] [--merge] [-C<n>] [--onto <newbase>] <upstream> [<branch>] - 'git-rebase' --continue | --skip | --abort DESCRIPTION From 97925fde00743e557fa5e792004483a27e31fbd8 Mon Sep 17 00:00:00 2001 From: Matthias Kestenholz <matthias@spinlock.ch> Date: Fri, 18 May 2007 15:39:34 +0200 Subject: [PATCH 76/86] Documentation: Reformatted SYNOPSIS for several commands Signed-off-by: Matthias Kestenholz <matthias@spinlock.ch> Signed-off-by: Junio C Hamano <junkio@cox.net> --- Documentation/git-for-each-ref.txt | 5 ++++- Documentation/git-index-pack.txt | 4 +++- Documentation/git-instaweb.txt | 5 +++-- Documentation/git-local-fetch.txt | 4 +++- Documentation/git-p4import.txt | 6 +++--- Documentation/git-push.txt | 4 +++- 6 files changed, 19 insertions(+), 9 deletions(-) diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt index f49b0d944c..6df8e85004 100644 --- a/Documentation/git-for-each-ref.txt +++ b/Documentation/git-for-each-ref.txt @@ -7,7 +7,10 @@ git-for-each-ref - Output information on each ref SYNOPSIS -------- -'git-for-each-ref' [--count=<count>]\* [--shell|--perl|--python|--tcl] [--sort=<key>]\* [--format=<format>] [<pattern>] +[verse] +'git-for-each-ref' [--count=<count>]\* + [--shell|--perl|--python|--tcl] + [--sort=<key>]\* [--format=<format>] [<pattern>] DESCRIPTION ----------- diff --git a/Documentation/git-index-pack.txt b/Documentation/git-index-pack.txt index 2229ee86b7..c498bed845 100644 --- a/Documentation/git-index-pack.txt +++ b/Documentation/git-index-pack.txt @@ -8,8 +8,10 @@ git-index-pack - Build pack index file for an existing packed archive SYNOPSIS -------- +[verse] 'git-index-pack' [-v] [-o <index-file>] <pack-file> -'git-index-pack' --stdin [--fix-thin] [--keep] [-v] [-o <index-file>] [<pack-file>] +'git-index-pack' --stdin [--fix-thin] [--keep] [-v] [-o <index-file>] + [<pack-file>] DESCRIPTION diff --git a/Documentation/git-instaweb.txt b/Documentation/git-instaweb.txt index 52a6aa6e82..9df0ab2d76 100644 --- a/Documentation/git-instaweb.txt +++ b/Documentation/git-instaweb.txt @@ -7,8 +7,9 @@ git-instaweb - Instantly browse your working repository in gitweb SYNOPSIS -------- -'git-instaweb' [--local] [--httpd=<httpd>] [--port=<port>] [--browser=<browser>] - +[verse] +'git-instaweb' [--local] [--httpd=<httpd>] [--port=<port>] + [--browser=<browser>] 'git-instaweb' [--start] [--stop] [--restart] DESCRIPTION diff --git a/Documentation/git-local-fetch.txt b/Documentation/git-local-fetch.txt index dd9e2387fc..51389ef37d 100644 --- a/Documentation/git-local-fetch.txt +++ b/Documentation/git-local-fetch.txt @@ -8,7 +8,9 @@ git-local-fetch - Duplicate another git repository on a local system SYNOPSIS -------- -'git-local-fetch' [-c] [-t] [-a] [-d] [-v] [-w filename] [--recover] [-l] [-s] [-n] commit-id path +[verse] +'git-local-fetch' [-c] [-t] [-a] [-d] [-v] [-w filename] [--recover] [-l] [-s] [-n] + commit-id path DESCRIPTION ----------- diff --git a/Documentation/git-p4import.txt b/Documentation/git-p4import.txt index 6edb9f12b8..714abbe28e 100644 --- a/Documentation/git-p4import.txt +++ b/Documentation/git-p4import.txt @@ -8,10 +8,10 @@ git-p4import - Import a Perforce repository into git SYNOPSIS -------- -`git-p4import` [-q|-v] [--notags] [--authors <file>] [-t <timezone>] <//p4repo/path> <branch> - +[verse] +`git-p4import` [-q|-v] [--notags] [--authors <file>] [-t <timezone>] + <//p4repo/path> <branch> `git-p4import` --stitch <//p4repo/path> - `git-p4import` diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt index f8cc2b5432..e9ad10672a 100644 --- a/Documentation/git-push.txt +++ b/Documentation/git-push.txt @@ -8,7 +8,9 @@ git-push - Update remote refs along with associated objects SYNOPSIS -------- -'git-push' [--all] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...] +[verse] +'git-push' [--all] [--tags] [--receive-pack=<git-receive-pack>] + [--repo=all] [-f | --force] [-v] [<repository> <refspec>...] DESCRIPTION ----------- From cd50aba918c2d801602278db7b461a92a811b430 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" <bfields@citi.umich.edu> Date: Thu, 17 May 2007 23:56:08 -0400 Subject: [PATCH 77/86] tutorials: add user-manual links Mention the user manual, especially as an alternative introduction for user's mainly interested in read-only operations. And fix a typo while we're there. Signed-off-by: "J. Bruce Fields" <bfields@citi.umich.edu> --- Documentation/tutorial-2.txt | 3 +++ Documentation/tutorial.txt | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Documentation/tutorial-2.txt b/Documentation/tutorial-2.txt index af8d43bd12..5c39a165f5 100644 --- a/Documentation/tutorial-2.txt +++ b/Documentation/tutorial-2.txt @@ -391,6 +391,9 @@ with the commands mentioned in link:everyday.html[Everyday git]. You should be able to find any unknown jargon in the link:glossary.html[Glossary]. +The link:user-manual.html[Git User's Manual] provides a more +comprehensive introduction to git. + The link:cvs-migration.html[CVS migration] document explains how to import a CVS repository into git, and shows how to use git in a CVS-like way. diff --git a/Documentation/tutorial.txt b/Documentation/tutorial.txt index 99efce4576..8094172316 100644 --- a/Documentation/tutorial.txt +++ b/Documentation/tutorial.txt @@ -4,6 +4,10 @@ A tutorial introduction to git (for version 1.5.1 or newer) This tutorial explains how to import a new project into git, make changes to it, and share changes with other developers. +If you are instead primarily interested in using git to fetch a project, +for example, to test the latest version, you may prefer to start with +the first two chapters of link:user-manual.html[The Git User's Manual]. + First, note that you can get documentation for a command such as "git diff" with: @@ -564,7 +568,7 @@ link:tutorial-2.html[Part two of this tutorial] explains the object database, the index file, and a few other odds and ends that you'll need to make the most of git. -If you don't want to consider with that right away, a few other +If you don't want to continue with that right away, a few other digressions that may be interesting at this point are: * gitlink:git-format-patch[1], gitlink:git-am[1]: These convert From 93f9cc675d6ca9d9170f72def005ecffd9590e9c Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" <bfields@citi.umich.edu> Date: Fri, 18 May 2007 00:51:42 -0400 Subject: [PATCH 78/86] tutorial: revise index introduction The embarassing history of this tutorial is that I started it without really understanding the index well, so I avoided mentioning it. And we all got the idea that "index" was a word to avoid using around newbies, but it was reluctantly mentioned that *something* had to be said. The result is a little awkward: the discussion of the index never actually uses that word, and isn't well-integrated into the surrounding material. Let's just go ahead and use the word "index" from the very start, and try to demonstrate its use with a minimum of lecturing. Also, remove discussion of using git-commit with explicit filenames. We're already a bit slow here to get people to their first commit, and I'm not convinced this is really so important. Signed-off-by: "J. Bruce Fields" <bfields@citi.umich.edu> --- Documentation/tutorial.txt | 100 ++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 52 deletions(-) diff --git a/Documentation/tutorial.txt b/Documentation/tutorial.txt index 8094172316..f55d4083ed 100644 --- a/Documentation/tutorial.txt +++ b/Documentation/tutorial.txt @@ -44,42 +44,67 @@ Initialized empty Git repository in .git/ ------------------------------------------------ You've now initialized the working directory--you may notice a new -directory created, named ".git". Tell git that you want it to track -every file under the current directory (note the '.') with: +directory created, named ".git". + +Next, tell git to take a snapshot of the contents of all files under the +current directory (note the '.'), with gitlink:git-add[1]: ------------------------------------------------ $ git add . ------------------------------------------------ -Finally, +This snapshot is now stored in a temporary staging area which git calls +the "index". You can permanently store the contents of the index in the +repository with gitlink:git-commit[1]: ------------------------------------------------ $ git commit ------------------------------------------------ -will prompt you for a commit message, then record the current state -of all the files to the repository. +This will prompt you for a commit message. You've now stored the first +version of your project in git. Making changes -------------- -Try modifying some files, then run - ------------------------------------------------- -$ git diff ------------------------------------------------- - -to review your changes. When you're done, tell git that you -want the updated contents of these files in the commit and then -make a commit, like this: +Modify some files, then add their updated contents to the index: ------------------------------------------------ $ git add file1 file2 file3 +------------------------------------------------ + +You are now ready to commit. You can see what is about to be committed +using gitlink:git-diff[1] with the --cached option: + +------------------------------------------------ +$ git diff --cached +------------------------------------------------ + +(Without --cached, gitlink:git-diff[1] will show you any changes that +you've made but not yet added to the index.) You can also get a brief +summary of the situation with gitlink:git-status[1]: + +------------------------------------------------ +$ git status +# On branch master +# Changes to be committed: +# (use "git reset HEAD <file>..." to unstage) +# +# modified: file1 +# modified: file2 +# modified: file3 +# +------------------------------------------------ + +If you need to make any further adjustments, do so now, and then add any +newly modified content to the index. Finally, commit your changes with: + +------------------------------------------------ $ git commit ------------------------------------------------ This will again prompt your for a message describing the change, and then -record the new versions of the files you listed. +record a new version of the project. Alternatively, instead of running `git add` beforehand, you can use @@ -87,7 +112,8 @@ Alternatively, instead of running `git add` beforehand, you can use $ git commit -a ------------------------------------------------ -which will automatically notice modified (but not new) files. +which will automatically notice any modified (but not new) files, add +them to the index, and commit, all in one step. A note on commit messages: Though not required, it's a good idea to begin the commit message with a single short (less than 50 character) @@ -96,45 +122,15 @@ thorough description. Tools that turn commits into email, for example, use the first line on the Subject: line and the rest of the commit in the body. - Git tracks content not files ---------------------------- -With git you have to explicitly "add" all the changed _content_ you -want to commit together. This can be done in a few different ways: - -1) By using 'git add <file_spec>...' - -This can be performed multiple times before a commit. Note that this -is not only for adding new files. Even modified files must be -added to the set of changes about to be committed. The "git status" -command gives you a summary of what is included so far for the -next commit. When done you should use the 'git commit' command to -make it real. - -Note: don't forget to 'add' a file again if you modified it after the -first 'add' and before 'commit'. Otherwise only the previous added -state of that file will be committed. This is because git tracks -content, so what you're really 'adding' to the commit is the *content* -of the file in the state it is in when you 'add' it. - -2) By using 'git commit -a' directly - -This is a quick way to automatically 'add' the content from all files -that were modified since the previous commit, and perform the actual -commit without having to separately 'add' them beforehand. This will -not add content from new files i.e. files that were never added before. -Those files still have to be added explicitly before performing a -commit. - -But here's a twist. If you do 'git commit <file1> <file2> ...' then only -the changes belonging to those explicitly specified files will be -committed, entirely bypassing the current "added" changes. Those "added" -changes will still remain available for a subsequent commit though. - -However, for normal usage you only have to remember 'git add' + 'git commit' -and/or 'git commit -a'. - +Many revision control systems provide an "add" command that tells the +system to start tracking changes to a new file. Git's "add" command +does something simpler and more powerful: `git add` is used both for new +and newly modified files, and in both cases it takes a snapshot of the +given files and stages that content in the index, ready for inclusion in +the next commit. Viewing the changelog --------------------- From 8fae22250fab25bc59efe24e849a7e9f20e3386c Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" <bfields@citi.umich.edu> Date: Tue, 15 May 2007 00:30:58 -0400 Subject: [PATCH 79/86] user-manual: discourage shared repository I don't really want to look like we're encouraging the shared repository thing. Take down some of the argument for using purely single-developer-owned repositories and collaborating using patches and pulls instead. Signed-off-by: "J. Bruce Fields" <bfields@citi.umich.edu> --- Documentation/user-manual.txt | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index f4843f4e90..1ab3d4b87f 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -1857,6 +1857,27 @@ all push to and pull from a single shared repository. See link:cvs-migration.txt[git for CVS users] for instructions on how to set this up. +However, while there is nothing wrong with git's support for shared +repositories, this mode of operation is not generally recommended, +simply because the mode of collaboration that git supports--by +exchanging patches and pulling from public repositories--has so many +advantages over the central shared repository: + + - Git's ability to quickly import and merge patches allows a + single maintainer to process incoming changes even at very + high rates. And when that becomes too much, git-pull provides + an easy way for that maintainer to delegate this job to other + maintainers while still allowing optional review of incoming + changes. + - Since every developer's repository has the same complete copy + of the project history, no repository is special, and it is + trivial for another developer to take over maintenance of a + project, either by mutual agreement, or because a maintainer + becomes unresponsive or difficult to work with. + - The lack of a central group of "committers" means there is + less need for formal decisions about who is "in" and who is + "out". + [[setting-up-gitweb]] Allowing web browsing of a repository ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 187b0d80dfad2f51df580bffbbc1e7bc2103f6d4 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" <bfields@citi.umich.edu> Date: Sat, 19 May 2007 00:37:25 -0400 Subject: [PATCH 80/86] user-manual: finding commits referencing given file content Another amusing git exploration example brought up in irc. (Credit to aeruder for the complete solution.) Signed-off-by: "J. Bruce Fields" <bfields@citi.umich.edu> --- Documentation/user-manual.txt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index 1ab3d4b87f..222171be30 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -921,6 +921,22 @@ echo "git diff --stat --summary -M v$last v$new > ../diffstat-$new" and then he just cut-and-pastes the output commands after verifying that they look OK. +Finding commits referencing a file with given content +----------------------------------------------------- + +Somebody hands you a copy of a file, and asks which commits modified a +file such that it contained the given content either before or after the +commit. You can find out with this: + +------------------------------------------------- +$ git log --raw -r --abbrev=40 --pretty=oneline -- filename | + grep -B 1 `git hash-object filename` +------------------------------------------------- + +Figuring out why this works is left as an exercise to the (advanced) +student. The gitlink:git-log[1], gitlink:git-diff-tree[1], and +gitlink:git-hash-object[1] man pages may prove helpful. + [[Developing-with-git]] Developing with git =================== From 2dc53617a43fda3df12e51e765fe4043935cfc22 Mon Sep 17 00:00:00 2001 From: Johan Herland <johan@herland.net> Date: Wed, 16 May 2007 02:31:40 +0200 Subject: [PATCH 81/86] user-manual: Add section on ignoring files The todo list at the end of the user manual says that something must be said about .gitignore. Also, there seems to be a lack of documentation on how to choose between the various types of ignore files (.gitignore vs. .git/info/exclude, etc.). This patch adds a section on ignoring files which try to introduce how to tell git about ignored files, and how the different strategies complement eachother. The syntax of exclude patterns is explained in a simplified manner, with a reference to git-ls-files(1) which already contains a more thorough explanation. Signed-off-by: Johan Herland <johan@herland.net> --- Documentation/user-manual.txt | 71 ++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index 222171be30..534ece464b 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -1089,6 +1089,75 @@ description. Tools that turn commits into email, for example, use the first line on the Subject line and the rest of the commit in the body. +[[ignoring-files]] +Ignoring files +-------------- + +A project will often generate files that you do 'not' want to track with git. +This typically includes files generated by a build process or temporary +backup files made by your editor. Of course, 'not' tracking files with git +is just a matter of 'not' calling "`git add`" on them. But it quickly becomes +annoying to have these untracked files lying around; e.g. they make +"`git add .`" and "`git commit -a`" practically useless, and they keep +showing up in the output of "`git status`", etc. + +Git therefore provides "exclude patterns" for telling git which files to +actively ignore. Exclude patterns are thoroughly explained in the +"Exclude Patterns" section of the gitlink:git-ls-files[1] manual page, +but the heart of the concept is simply a list of files which git should +ignore. Entries in the list may contain globs to specify multiple files, +or may be prefixed by "`!`" to explicitly include (un-ignore) a previously +excluded (ignored) file (i.e. later exclude patterns override earlier ones). +The following example should illustrate such patterns: + +------------------------------------------------- +# Lines starting with '#' are considered comments. +# Ignore foo.txt. +foo.txt +# Ignore (generated) html files, +*.html +# except foo.html which is maintained by hand. +!foo.html +# Ignore objects and archives. +*.[oa] +------------------------------------------------- + +The next question is where to put these exclude patterns so that git can +find them. Git looks for exclude patterns in the following files: + +`.gitignore` files in your working tree::: + You may store multiple `.gitignore` files at various locations in your + working tree. Each `.gitignore` file is applied to the directory where + it's located, including its subdirectories. Furthermore, the + `.gitignore` files can be tracked like any other files in your working + tree; just do a "`git add .gitignore`" and commit. `.gitignore` is + therefore the right place to put exclude patterns that are meant to + be shared between all project participants, such as build output files + (e.g. `\*.o`), etc. +`.git/info/exclude` in your repo::: + Exclude patterns in this file are applied to the working tree as a + whole. Since the file is not located in your working tree, it does + not follow push/pull/clone like `.gitignore` can do. This is therefore + the place to put exclude patterns that are local to your copy of the + repo (i.e. 'not' shared between project participants), such as + temporary backup files made by your editor (e.g. `\*~`), etc. +The file specified by the `core.excludesfile` config directive::: + By setting the `core.excludesfile` config directive you can tell git + where to find more exclude patterns (see gitlink:git-config[1] for + more information on configuration options). This config directive + can be set in the per-repo `.git/config` file, in which case the + exclude patterns will apply to that repo only. Alternatively, you + can set the directive in the global `~/.gitconfig` file to apply + the exclude pattern to all your git repos. As with the above + `.git/info/exclude` (and, indeed, with git config directives in + general), this directive does not follow push/pull/clone, but remain + local to your repo(s). + +[NOTE] +In addition to the above alternatives, there are git commands that can take +exclude patterns directly on the command line. See gitlink:git-ls-files[1] +for an example of this. + [[how-to-merge]] How to merge ------------ @@ -3853,8 +3922,6 @@ Think about how to create a clear chapter dependency graph that will allow people to get to important topics without necessarily reading everything in between. -Say something about .gitignore. - Scan Documentation/ for other stuff left out; in particular: howto's some of technical/? From 6442754d6cc0056cf5b69b43d218f8b6d317e7f5 Mon Sep 17 00:00:00 2001 From: Eric Wong <normalperson@yhbt.net> Date: Sat, 19 May 2007 02:58:37 -0700 Subject: [PATCH 82/86] git-svn: avoid crashing svnserve when creating new directories When sorting directory names by depth (slash ("/") count) and closing the deepest directories first (as the protocol requires), we failed to put the root baton (with an empty string as its key "") after top-level directories (which did not have any slashes). This resulted in svnserve being in a situation it couldn't handle and caused a segmentation fault on the remote server. This bug did not affect users of DAV and filesystem repositories. Signed-off-by: Eric Wong <normalperson@yhbt.net> Confirmed-by: Matthieu Moy <Matthieu.Moy@imag.fr> Signed-off-by: Junio C Hamano <junkio@cox.net> --- git-svn.perl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/git-svn.perl b/git-svn.perl index f4c9ff1b85..b87dedc99c 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -2841,8 +2841,10 @@ sub close_edit { my ($self) = @_; my ($p,$bat) = ($self->{pool}, $self->{bat}); foreach (sort { $b =~ tr#/#/# <=> $a =~ tr#/#/# } keys %$bat) { + next if $_ eq ''; $self->close_directory($bat->{$_}, $p); } + $self->close_directory($bat->{''}, $p); $self->SUPER::close_edit($p); $p->clear; } From dc431666d3a54a84ac32b6007f020fb13062345b Mon Sep 17 00:00:00 2001 From: Eric Wong <normalperson@yhbt.net> Date: Sat, 19 May 2007 03:59:02 -0700 Subject: [PATCH 83/86] git-svn: don't minimize-url when doing an init that tracks multiple paths I didn't have a chance to test the off-by-default minimize-url stuff enough before, but it's quite broken for people passing the --trunk/-T, --tags/-t, --branches/-b switches to "init" or "clone" commands. Additionally, follow-parent functionality seems broken when we're not connected to the root of the repository. Default behavior for "traditional" git-svn users who only track one directory (without needing follow-parent) should be reasonable, as those users started using things before minimize-url functionality existed. Behavior for users more used to the git-svnimport-like command line will also benefit from a more-flexible command-line than svnimport given the assumption they're working with non-restrictive read permissions on the repository. I hope to properly fix these bugs when I get a chance to in the next week or so, but I would like to get this stopgap measure of reverting to the old behavior as soon as possible. Signed-off-by: Eric Wong <normalperson@yhbt.net> Signed-off-by: Junio C Hamano <junkio@cox.net> --- git-svn.perl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/git-svn.perl b/git-svn.perl index b87dedc99c..eda9969f50 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -485,6 +485,11 @@ sub cmd_multi_init { unless (defined $_trunk || defined $_branches || defined $_tags) { usage(1); } + + # there are currently some bugs that prevent multi-init/multi-fetch + # setups from working well without this. + $Git::SVN::_minimize_url = 1; + $_prefix = '' unless defined $_prefix; if (defined $url) { $url =~ s#/+$##; From f7b47b273ed2c9e9b298c4f5dd02884b46dfbced Mon Sep 17 00:00:00 2001 From: Junio C Hamano <junkio@cox.net> Date: Sat, 19 May 2007 18:18:24 -0700 Subject: [PATCH 84/86] GIT 1.5.1.6 Signed-off-by: Junio C Hamano <junkio@cox.net> --- Documentation/RelNotes-1.5.1.5.txt | 8 +----- Documentation/RelNotes-1.5.1.6.txt | 45 ++++++++++++++++++++++++++++++ GIT-VERSION-GEN | 2 +- RelNotes | 2 +- 4 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 Documentation/RelNotes-1.5.1.6.txt diff --git a/Documentation/RelNotes-1.5.1.5.txt b/Documentation/RelNotes-1.5.1.5.txt index 85e821c433..b0ab8eb371 100644 --- a/Documentation/RelNotes-1.5.1.5.txt +++ b/Documentation/RelNotes-1.5.1.5.txt @@ -1,4 +1,4 @@ -GIT v1.5.1.5 Release Notes (draft) +GIT v1.5.1.5 Release Notes ========================== Fixes since v1.5.1.4 @@ -40,9 +40,3 @@ Fixes since v1.5.1.4 compilers on Sun. - Many many documentation fixes and updates. - --- -exec >/var/tmp/1 -O=v1.5.1.4-48-gcecb98a -echo O=`git describe refs/heads/maint` -git shortlog --no-merges $O..refs/heads/maint diff --git a/Documentation/RelNotes-1.5.1.6.txt b/Documentation/RelNotes-1.5.1.6.txt new file mode 100644 index 0000000000..55f3ac13e3 --- /dev/null +++ b/Documentation/RelNotes-1.5.1.6.txt @@ -0,0 +1,45 @@ +GIT v1.5.1.6 Release Notes +========================== + +Fixes since v1.5.1.4 +-------------------- + +* Bugfixes + + - git-send-email did not understand aliases file for mutt, which + allows leading whitespaces. + + - git-format-patch emitted Content-Type and Content-Transfer-Encoding + headers for non ASCII contents, but failed to add MIME-Version. + + - git-name-rev had a buffer overrun with a deep history. + + - contributed script import-tars did not get the directory in + tar archives interpreted correctly. + + - git-svn was reported to segfault for many people on list and + #git; hopefully this has been fixed. + + - git-svn also had a bug to crash svnserve by sending a bad + sequence of requests. + + - "git-svn clone" does not try to minimize the URL + (i.e. connect to higher level hierarchy) by default, as this + can prevent clone to fail if only part of the repository + (e.g. 'trunk') is open to public. + + - "git checkout branch^0" did not detach the head when you are + already on 'branch'; backported the fix from the 'master'. + + - "git-config section.var" did not correctly work when + existing configuration file had both [section] and [section "name"] + next to each other. + + - "git clone ../other-directory" was fooled if the current + directory $PWD points at is a symbolic link. + + - (build) tree_entry_extract() function was both static inline + and extern, which caused trouble compiling with Forte12 + compilers on Sun. + + - Many many documentation fixes and updates. diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 2dbedf3d9d..582f423e9e 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v1.5.1.5.GIT +DEF_VER=v1.5.1.6.GIT LF=' ' diff --git a/RelNotes b/RelNotes index 8abe4c292b..e5de2fa02b 120000 --- a/RelNotes +++ b/RelNotes @@ -1 +1 @@ -Documentation/RelNotes-1.5.1.5.txt \ No newline at end of file +Documentation/RelNotes-1.5.1.6.txt \ No newline at end of file From e40a30452d3ab024b06238abab3968b872dd5e1c Mon Sep 17 00:00:00 2001 From: Junio C Hamano <junkio@cox.net> Date: Sat, 19 May 2007 17:53:45 -0700 Subject: [PATCH 85/86] git-cvsserver: exit with 1 upon "I HATE YOU" Signed-off-by: Junio C Hamano <junkio@cox.net> --- git-cvsserver.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-cvsserver.perl b/git-cvsserver.perl index ac88625fc2..fcfb99db65 100755 --- a/git-cvsserver.perl +++ b/git-cvsserver.perl @@ -105,7 +105,7 @@ if (@ARGV && $ARGV[0] eq 'pserver') { unless ($line eq 'anonymous') { print "E Only anonymous user allowed via pserver\n"; print "I HATE YOU\n"; - exit; + exit 1; } $line = <STDIN>; chomp $line; # validate the password? $line = <STDIN>; chomp $line; From aba170cdb4874b72dd619e6f7bbc13c33295f831 Mon Sep 17 00:00:00 2001 From: Junio C Hamano <junkio@cox.net> Date: Sun, 20 May 2007 00:30:39 -0700 Subject: [PATCH 86/86] GIT 1.5.2 Signed-off-by: Junio C Hamano <junkio@cox.net> --- Documentation/RelNotes-1.5.2.txt | 32 ++++++++++++++------------------ Documentation/git.txt | 14 +++++++++++--- GIT-VERSION-GEN | 2 +- 3 files changed, 26 insertions(+), 22 deletions(-) diff --git a/Documentation/RelNotes-1.5.2.txt b/Documentation/RelNotes-1.5.2.txt index 7dbdb26988..6195715dc7 100644 --- a/Documentation/RelNotes-1.5.2.txt +++ b/Documentation/RelNotes-1.5.2.txt @@ -1,18 +1,18 @@ -GIT v1.5.2 Release Notes (draft) +GIT v1.5.2 Release Notes ======================== Updates since v1.5.1 -------------------- -* Plumbing level subproject support. +* Plumbing level superproject support. You can include a subdirectory that has an independent git - repository in your index and tree objects as a - "subproject". This plumbing (i.e. "core") level subproject - support explicitly excludes recursive behaviour. + repository in your index and tree objects of your project + ("superproject"). This plumbing (i.e. "core") level + superproject support explicitly excludes recursive behaviour. - The "subproject" entries in the index and trees are - incompatible with older versions of git. Experimenting with + The "subproject" entries in the index and trees of a superproject + are incompatible with older versions of git. Experimenting with the plumbing level support is encouraged, but be warned that unless everybody in your project updates to this release or later, using this feature would make your project @@ -33,7 +33,8 @@ Updates since v1.5.1 but this feature is an extremely sharp-edged razor and needs to be handled with caution (do not use it unless you understand the earlier mailing list discussion on keyword - expansion). + expansion). These conversions apply when checking files in + or out, and exporting via git-archive. * The packfile format now optionally suports 64-bit index. @@ -42,12 +43,13 @@ Updates since v1.5.1 needs more than 32-bit to express offsets of objects in the pack. -* Comes with an updated git-gui 0.7.0 +* Comes with an updated git-gui 0.7.1 * Updated gitweb: - can show combined diff for merges; - uses font size of user's preference, not hardcoded in pixels; + - can now 'grep'; * New commands and options. @@ -190,12 +192,6 @@ this release, unless otherwise noted. - "git clean -d -X" now does not remove non-excluded directories. -* Documentation updates - -* Performance Tweaks - --- -exec >/var/tmp/1 -O=v1.5.2-rc3 -echo O=`git describe refs/heads/master` -git shortlog --no-merges $O..refs/heads/master ^refs/heads/maint + - rebasing (without -m) a series that changes a symlink to a directory + in the middle of a path confused git-apply greatly and refused to + operate. diff --git a/Documentation/git.txt b/Documentation/git.txt index 157ef29131..98860af045 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -41,9 +41,16 @@ unreleased) version of git, that is available from 'master' branch of the `git.git` repository. Documentation for older releases are available here: -* link:v1.5.1.5/git.html[documentation for release 1.5.1.5] +* link:v1.5.2/git.html[documentation for release 1.5.2] -* release notes for link:RelNotes-1.5.1.5.txt[1.5.1.5], +* release notes for + link:RelNotes-1.5.2.txt[1.5.2]. + +* link:v1.5.1.6/git.html[documentation for release 1.5.1.6] + +* release notes for + link:RelNotes-1.5.1.6.txt[1.5.1.6], + link:RelNotes-1.5.1.5.txt[1.5.1.5], link:RelNotes-1.5.1.4.txt[1.5.1.4], link:RelNotes-1.5.1.3.txt[1.5.1.3], link:RelNotes-1.5.1.2.txt[1.5.1.2], @@ -52,7 +59,8 @@ Documentation for older releases are available here: * link:v1.5.0.7/git.html[documentation for release 1.5.0.7] -* release notes for link:RelNotes-1.5.0.7.txt[1.5.0.7], +* release notes for + link:RelNotes-1.5.0.7.txt[1.5.0.7], link:RelNotes-1.5.0.6.txt[1.5.0.6], link:RelNotes-1.5.0.5.txt[1.5.0.5], link:RelNotes-1.5.0.3.txt[1.5.0.3], diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index bd4a0443c4..06c360b267 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v1.5.2-rc3.GIT +DEF_VER=v1.5.2.GIT LF=' '
description" . esc_html($descr) . "
owner$owner
last change$cd{'rfc2822'}
owner$owner
last change$cd{'rfc2822'}