diff options
71 files changed, 2483 insertions, 1030 deletions
diff --git a/.gitignore b/.gitignore index e8d2731ee5..b39f78fcdf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ GIT-CFLAGS +GIT-GUI-VARS GIT-VERSION-FILE git git-add @@ -141,6 +142,7 @@ git-verify-tag git-whatchanged git-write-tree git-core-*/?* +gitk-wish gitweb/gitweb.cgi test-chmtime test-date diff --git a/Documentation/Makefile b/Documentation/Makefile index 7c1c9e1918..e82596dcdf 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -16,8 +16,9 @@ ARTICLES += repository-layout ARTICLES += hooks ARTICLES += everyday ARTICLES += git-tools +ARTICLES += glossary # with their own formatting rules. -SP_ARTICLES = glossary howto/revert-branch-rebase user-manual +SP_ARTICLES = howto/revert-branch-rebase user-manual DOC_HTML += $(patsubst %,%.html,$(ARTICLES) $(SP_ARTICLES)) @@ -64,6 +65,11 @@ install: man $(INSTALL) -m644 $(DOC_MAN7) $(DESTDIR)$(man7dir) +../GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE + $(MAKE) -C ../ GIT-VERSION-FILE + +-include ../GIT-VERSION-FILE + # # Determine "include::" file references in asciidoc files. # @@ -90,32 +96,35 @@ $(cmds_txt): cmd-list.perl $(MAN1_TXT) git.7 git.html: git.txt core-intro.txt clean: - rm -f *.xml *.html *.1 *.7 howto-index.txt howto/*.html doc.dep + rm -f *.xml *.xml+ *.html *.html+ *.1 *.7 howto-index.txt howto/*.html doc.dep rm -f $(cmds_txt) %.html : %.txt - $(ASCIIDOC) -b xhtml11 -d manpage -f asciidoc.conf $(ASCIIDOC_EXTRA) $< + rm -f $@+ $@ + $(ASCIIDOC) -b xhtml11 -d manpage -f asciidoc.conf \ + $(ASCIIDOC_EXTRA) -o - $< | \ + sed -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' >$@+ + mv $@+ $@ %.1 %.7 : %.xml xmlto -m callouts.xsl man $< %.xml : %.txt - $(ASCIIDOC) -b docbook -d manpage -f asciidoc.conf $< + rm -f $@+ $@ + $(ASCIIDOC) -b docbook -d manpage -f asciidoc.conf \ + $(ASCIIDOC_EXTRA) -o - $< | \ + sed -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' >$@+ + mv $@+ $@ user-manual.xml: user-manual.txt user-manual.conf $(ASCIIDOC) -b docbook -d book $< XSLT = http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl -XSLTOPTS = --nonet --xinclude --stringparam html.stylesheet docbook-xsl.css +XSLTOPTS = --xinclude --stringparam html.stylesheet docbook-xsl.css user-manual.html: user-manual.xml xsltproc $(XSLTOPTS) -o $@ $(XSLT) $< -glossary.html : glossary.txt sort_glossary.pl - cat $< | \ - perl sort_glossary.pl | \ - $(ASCIIDOC) -b xhtml11 - > glossary.html - howto-index.txt: howto-index.sh $(wildcard howto/*.txt) rm -f $@+ $@ sh ./howto-index.sh $(wildcard howto/*.txt) >$@+ @@ -136,3 +145,5 @@ install-webdoc : html quick-install: sh ./install-doc-quick.sh $(DOC_REF) $(mandir) + +.PHONY: .FORCE-GIT-VERSION-FILE diff --git a/Documentation/RelNotes-1.5.0.6.txt b/Documentation/RelNotes-1.5.0.6.txt new file mode 100644 index 0000000000..e15447ffdb --- /dev/null +++ b/Documentation/RelNotes-1.5.0.6.txt @@ -0,0 +1,22 @@ +GIT v1.5.0.6 Release Notes +========================== + +Fixes since v1.5.0.5 +-------------------- + +* Bugfixes + + - a handful small fixes to gitweb. + + - build procedure for user-manual is fixed not to require locally + installed stylesheets. + + - "git commit $paths" on paths whose earlier contents were + already updated in the index were failing out. + +* Documentation + + - user-manual has better cross references. + + - gitweb installation/deployment procedure is now documented. + diff --git a/Documentation/RelNotes-1.5.0.7.txt b/Documentation/RelNotes-1.5.0.7.txt new file mode 100644 index 0000000000..670ad32b85 --- /dev/null +++ b/Documentation/RelNotes-1.5.0.7.txt @@ -0,0 +1,18 @@ +GIT v1.5.0.7 Release Notes +========================== + +Fixes since v1.5.0.6 +-------------------- + +* Bugfixes + + - git-upload-pack failed to close unused pipe ends, resulting + in many zombies to hang around. + + - git-rerere was recording the contents of earlier hunks + duplicated in later hunks. This prevented resolving the same + conflict when performing the same merge the other way around. + +* Documentation + + - a few documentation fixes from Debian package maintainer. diff --git a/Documentation/RelNotes-1.5.1.txt b/Documentation/RelNotes-1.5.1.txt index f78cf56bc8..daed367270 100644 --- a/Documentation/RelNotes-1.5.1.txt +++ b/Documentation/RelNotes-1.5.1.txt @@ -10,11 +10,15 @@ Updates since v1.5.0 * New commands and options. - - "git log" and friends take --reverse. This makes output - that typically goes reverse order in chronological order. - "git shortlog" usually lists commits in chronological order, - but with "--reverse", they are shown in reverse - chronological order. + - "git log" and friends take --reverse, which instructs them + to give their output in the order opposite from their usual. + They typically output from new to old, but with this option + their output would read from old to new. "git shortlog" + usually lists older commits first, but with this option, + they are shown from new to old. + + - "git log --pretty=format:<string>" to allow more flexible + custom log output. - "git diff" learned --ignore-space-at-eol. This is a weaker form of --ignore-space-change. @@ -22,9 +26,6 @@ Updates since v1.5.0 - "git diff --no-index pathA pathB" can be used as diff replacement with git specific enhancements. - - "git diff --pretty=format:<string>" to allow more flexible - custom log output. - - "git diff --no-index" can read from '-' (standard input). - "git diff" also learned --exit-code to exit with non-zero @@ -33,6 +34,17 @@ Updates since v1.5.0 backward incompatible change; it will stay as an option for now. + - "git diff --quiet" is --exit-code with output turned off, + meant for scripted use to quickly determine if there is any + tree-level difference. + + - Textual patch generation with "git diff" without -w/-b + option has been significantly optimized. "git blame" got + faster because of the same change. + + - "git log" and "git rev-list" has been optimized + significantly when they are used with pathspecs. + - "git branch --track" can be used to set up configuration variables to help it easier to base your work on branches you track from a remote site. @@ -61,11 +73,33 @@ Updates since v1.5.0 symlinks on filesystems that do not support them; they are checked out as regular files instead. + - You can name a commit object with its first line of the + message. The syntax to use is ':/message text'. E.g. + + $ git show ":/object name: introduce ':/<oneline prefix>' notation" + + means the same thing as: + + $ git show 28a4d940443806412effa246ecc7768a21553ec7 + + - "git bisect" learned a new command "run" that takes a script + to run after each revision is checked out to determine if it + is good or bad, to automate the bisection process. -* Updated behaviour of existing commands. + - "git log" family learned a new traversal option --first-parent, + which does what the name suggests. + + +* Updated behavior of existing commands. + + - "git-merge-recursive" used to barf when there are more than + one common ancestors for the merge, and merging them had a + rename/rename conflict. This has been fixed. - "git fsck" does not barf on corrupt loose objects. + - "git rm" does not remove newly added files without -f. + - "git archimport" allows remapping when coming up with git branch names from arch names. @@ -83,10 +117,10 @@ Updates since v1.5.0 allow users to explicitly override this heuristic based on paths. - - The behaviour of 'git-apply', when run in a subdirectory, + - The behavior of 'git-apply', when run in a subdirectory, without --index nor --cached were inconsistent with that of the command with these options. This was fixed to match the - behaviour with --index. A patch that is meant to be applied + behavior with --index. A patch that is meant to be applied with -p1 from the toplevel of the project tree can be applied with any custom -p<n> option. A patch that is not relative to the toplevel needs to be applied with -p<n> @@ -128,12 +162,17 @@ Updates since v1.5.0 the heaviest parts in C. - "git mailinfo" which splits an e-mail into a patch and the - metainformation was rewritten, thanks to Don Zickus. It - handles nested multipart better. + meta-information was rewritten, thanks to Don Zickus. It + handles nested multipart better. The command was broken for + a brief period on 'master' branch since 1.5.0 but the + breakage is fixed now. - send-email learned configurable bcc and chain-reply-to. - - Using objects from packs is now seriouly optimized by clever + - "git remote show $remote" also talks about branches that + would be pushed if you run "git push remote". + + - Using objects from packs is now seriously optimized by clever use of a cache. This should be most noticeable in git-log family of commands that involve reading many tree objects. In addition, traversing revisions while filtering changes @@ -143,23 +182,190 @@ Updates since v1.5.0 * Hooks - - The sample update hook to show how to send out notification - e-mail was updated to show only new commits that appeared in - the repository. Earlier, it showed new commits that appeared - on the branch. + - The part to send out notification e-mails was removed from + the sample update hook, as it was not an appropriate place + to do so. The proper place to do this is the new post-receive + hook. An example hook has been added to contrib/hooks/. * Others - git-revert, git-gc and git-cherry-pick are now built-ins. +Fixes since v1.5.0 +------------------ + +These are all in v1.5.0.x series. + +* Documentation updates + + - Clarifications and corrections to 1.5.0 release notes. + + - The main documentation did not link to git-remote documentation. + + - Clarified introductory text of git-rebase documentation. + + - Converted remaining mentions of update-index on Porcelain + documents to git-add/git-rm. + + - Some i18n.* configuration variables were incorrectly + described as core.*; fixed. + + - added and clarified core.bare, core.legacyheaders configurations. + + - updated "git-clone --depth" documentation. + + - user-manual updates. + + - Options to 'git remote add' were described insufficiently. + + - Configuration format.suffix was not documented. + + - Other formatting and spelling fixes. + + - user-manual has better cross references. + + - gitweb installation/deployment procedure is now documented. + + +* Bugfixes + + - git-upload-pack closes unused pipe ends; earlier this caused + many zombies to hang around. + + - git-rerere was recording the contents of earlier hunks + duplicated in later hunks. This prevented resolving the same + conflict when performing the same merge the other way around. + + - git-add and git-update-index on a filesystem on which + executable bits are unreliable incorrectly reused st_mode + bits even when the path changed between symlink and regular + file. + + - git-daemon marks the listening sockets with FD_CLOEXEC so + that it won't be leaked into the children. + + - segfault from git-blame when the mandatory pathname + parameter was missing was fixed; usage() message is given + instead. + + - git-rev-list did not read $GIT_DIR/config file, which means + that did not honor i18n.logoutputencoding correctly. + + - Automated merge conflict handling when changes to symbolic + links conflicted were completely broken. The merge-resolve + strategy created a regular file with conflict markers in it + in place of the symbolic link. The default strategy, + merge-recursive was even more broken. It removed the path + that was pointed at by the symbolic link. Both of these + problems have been fixed. + + - 'git diff maint master next' did not correctly give combined + diff across three trees. + + - 'git fast-import' portability fix for Solaris. + + - 'git show-ref --verify' without arguments did not error out + but segfaulted. + + - 'git diff :tracked-file `pwd`/an-untracked-file' gave an extra + slashes after a/ and b/. + + - 'git format-patch' produced too long filenames if the commit + message had too long line at the beginning. + + - Running 'make all' and then without changing anything + running 'make install' still rebuilt some files. This + was inconvenient when building as yourself and then + installing as root (especially problematic when the source + directory is on NFS and root is mapped to nobody). + + - 'git-rerere' failed to deal with two unconflicted paths that + sorted next to each other. + + - 'git-rerere' attempted to open(2) a symlink and failed if + there was a conflict. Since a conflicting change to a + symlink would not benefit from rerere anyway, the command + now ignores conflicting changes to symlinks. + + - 'git-repack' did not like to pass more than 64 arguments + internally to underlying 'rev-list' logic, which made it + impossible to repack after accumulating many (small) packs + in the repository. + + - 'git-diff' to review the combined diff during a conflicted + merge were not reading the working tree version correctly + when changes to a symbolic link conflicted. It should have + read the data using readlink(2) but read from the regular + file the symbolic link pointed at. + + - 'git-remote' did not like period in a remote's name. + + - 'git.el' honors the commit coding system from the configuration. + + - 'blameview' in contrib/ correctly digs deeper when a line is + clicked. + + - 'http-push' correctly makes sure the remote side has leading + path. Earlier it started in the middle of the path, and + incorrectly. + + - 'git-merge' did not exit with non-zero status when the + working tree was dirty and cannot fast forward. It does + now. + + - 'cvsexportcommit' does not lose yet-to-be-used message file. + + - int-vs-size_t typefix when running combined diff on files + over 2GB long. + + - 'git apply --whitespace=strip' should not touch unmodified + lines. + + - 'git-mailinfo' choke when a logical header line was too long. + + - 'git show A..B' did not error out. Negative ref ("not A" in + this example) does not make sense for the purpose of the + command, so now it errors out. + + - 'git fmt-merge-msg --file' without file parameter did not + correctly error out. + + - 'git archimport' barfed upon encountering a commit without + summary. + + - 'git index-pack' did not protect itself from getting a short + read out of pread(2). + + - 'git http-push' had a few buffer overruns. + + - Build dependency fixes to rebuild fetch.o when other headers + change. + + - git.el does not add duplicate sign-off lines. + + - git-commit shows the full stat of the resulting commit, not + just about the files in the current directory, when run from + a subdirectory. + + - "git-checkout -m '@{8 hours ago}'" had a funny failure from + eval; fixed. + + - git-merge (hence git-pull) did not refuse fast-forwarding + when the working tree had local changes that would have + conflicted with it. + + - a handful small fixes to gitweb. + + - build procedure for user-manual is fixed not to require locally + installed stylesheets. + + - "git commit $paths" on paths whose earlier contents were + already updated in the index were failing out. + --- -exec >/var/tmp/1 -O=v1.5.0.5-446-g5d86501 -echo O=`git describe master` -git shortlog --no-merges $O..master ^maint +* Tweaks -# Local Variables: -# mode: text -# End: + - sliding mmap() inefficiently mmaped the same region of a + packfile with an access pattern that used objects in the + reverse order. This has been made more efficient. diff --git a/Documentation/asciidoc.conf b/Documentation/asciidoc.conf index 44b1ce4c6b..fa7dc94845 100644 --- a/Documentation/asciidoc.conf +++ b/Documentation/asciidoc.conf @@ -31,6 +31,25 @@ ifdef::backend-docbook[] {title#}</example> endif::backend-docbook[] +ifdef::doctype-manpage[] +ifdef::backend-docbook[] +[header] +template::[header-declarations] +<refentry> +<refmeta> +<refentrytitle>{mantitle}</refentrytitle> +<manvolnum>{manvolnum}</manvolnum> +<refmiscinfo class="source">Git</refmiscinfo> +<refmiscinfo class="version">@@GIT_VERSION@@</refmiscinfo> +<refmiscinfo class="manual">Git Manual</refmiscinfo> +</refmeta> +<refnamediv> + <refname>{manname}</refname> + <refpurpose>{manpurpose}</refpurpose> +</refnamediv> +endif::backend-docbook[] +endif::doctype-manpage[] + ifdef::backend-xhtml11[] [gitlink-inlinemacro] <a href="{target}.html">{target}{0?({0})}</a> diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 77a3f78dd7..1689c74817 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -164,5 +164,8 @@ That is, it exits with 1 if there were differences and 0 means no differences. +--quiet:: + Disable all output of the program. Implies --exit-code. + For more detailed explanation on these common options, see also link:diffcore.html[diffcore documentation]. diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt index 13a7389867..148ce40568 100644 --- a/Documentation/git-am.txt +++ b/Documentation/git-am.txt @@ -87,6 +87,33 @@ default. You could use `--no-utf8` to override this. DISCUSSION ---------- +The commit author name is taken from the "From: " line of the +message, and commit author time is taken from the "Date: " line +of the message. The "Subject: " line is used as the title of +the commit, after stripping common prefix "[PATCH <anything>]". +It is supposed to describe what the commit is about concisely as +a one line text. + +The body of the message (iow, after a blank line that terminates +RFC2822 headers) can begin with "Subject: " and "From: " lines +that are different from those of the mail header, to override +the values of these fields. + +The commit message is formed by the title taken from the +"Subject: ", a blank line and the body of the message up to +where the patch begins. Excess whitespaces at the end of the +lines are automatically stripped. + +The patch is expected to be inline, directly following the +message. Any line that is of form: + +* three-dashes and end-of-line, or +* a line that begins with "diff -", or +* a line that begins with "Index: " + +is taken as the beginning of a patch, and the commit log message +is terminated before the first occurrence of such a line. + When initially invoking it, you give it names of the mailboxes to crunch. Upon seeing the first patch that does not apply, it aborts in the middle, just like 'git-applymbox' does. You can diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt index 1c6f6a7e27..85d0950cf4 100644 --- a/Documentation/git-cvsserver.txt +++ b/Documentation/git-cvsserver.txt @@ -134,9 +134,11 @@ checkout, diff, status, update, log, add, remove, commit. Legacy monitoring operations are not supported (edit, watch and related). Exports and tagging (tags and branches) are not supported at this stage. -The server will set the -k mode to binary when relevant. In proper GIT -tradition, the contents of the files are always respected. -No keyword expansion or newline munging is supported. +The server should set the -k mode to binary when relevant, however, +this is not really implemented yet. For now, you can force the server +to set `-kb` for all files by setting the `gitcvs.allbinary` config +variable. In proper GIT tradition, the contents of the files are +always respected. No keyword expansion or newline munging is supported. Dependencies ------------ diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt index 361eaec700..030edaf305 100644 --- a/Documentation/git-log.txt +++ b/Documentation/git-log.txt @@ -38,6 +38,11 @@ include::pretty-formats.txt[] and <until>, see "SPECIFYING REVISIONS" section in gitlink:git-rev-parse[1]. +--first-parent:: + Follow only the first parent commit upon seeing a merge + commit. This option gives a better overview of the + evolution of a particular branch. + -p:: Show the change the commit introduces in a patch form. diff --git a/Documentation/git-mergetool.txt b/Documentation/git-mergetool.txt index 5baaaca0b5..34288fe08b 100644 --- a/Documentation/git-mergetool.txt +++ b/Documentation/git-mergetool.txt @@ -26,11 +26,11 @@ OPTIONS Use the merge resolution program specified by <tool>. Valid merge tools are: kdiff3, tkdiff, meld, xxdiff, emerge, and vimdiff. - - If a merge resolution program is not specified, 'git mergetool' - will use the configuration variable merge.tool. If the - configuration variable merge.tool is not set, 'git mergetool' - will pick a suitable default. ++ +If a merge resolution program is not specified, 'git mergetool' +will use the configuration variable merge.tool. If the +configuration variable merge.tool is not set, 'git mergetool' +will pick a suitable default. Author ------ diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt index ccc66aae7f..a8bf6561e1 100644 --- a/Documentation/git-rev-parse.txt +++ b/Documentation/git-rev-parse.txt @@ -265,14 +265,14 @@ its all parents. Here are a handful examples: - D A B D - D F A B C D F - ^A G B D - ^A F B C F - G...I C D F G I - ^B G I C D F G I - F^@ A B C - F^! H D F H + D G H D + D F G H I J D F + ^G D H D + ^D B E I J F B + B...C G H D E B C + ^D B C E I J F B C + C^@ I J F + F^! D G H D F Author ------ diff --git a/Documentation/git-svnimport.txt b/Documentation/git-svnimport.txt index b166cf3327..bdae7d87dc 100644 --- a/Documentation/git-svnimport.txt +++ b/Documentation/git-svnimport.txt @@ -27,7 +27,7 @@ repository, or incrementally import into an existing one. SVN access is done by the SVN::Perl module. git-svnimport assumes that SVN repositories are organized into one -"trunk" directory where the main development happens, "branch/FOO" +"trunk" directory where the main development happens, "branches/FOO" directories for branches, and "/tags/FOO" directories for tags. Other subdirectories are ignored. diff --git a/Documentation/git.txt b/Documentation/git.txt index 31397dc539..9defc33273 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -35,17 +35,23 @@ ifdef::stalenotes[] You are reading the documentation for the latest version of git. Documentation for older releases are available here: -* link:v1.5.0.5/git.html[documentation for release 1.5.0.5] +* link:RelNotes-1.5.1.txt[release notes for 1.5.1] -* link:v1.5.0.5/RelNotes-1.5.0.5.txt[release notes for 1.5.0.5] +* link:v1.5.0.7/git.html[documentation for release 1.5.0.7] -* link:v1.5.0.3/RelNotes-1.5.0.3.txt[release notes for 1.5.0.3] +* link:RelNotes-1.5.0.7.txt[release notes for 1.5.0.7] -* link:v1.5.0.2/RelNotes-1.5.0.2.txt[release notes for 1.5.0.2] +* link:RelNotes-1.5.0.6.txt[release notes for 1.5.0.6] -* link:v1.5.0.1/RelNotes-1.5.0.1.txt[release notes for 1.5.0.1] +* link:RelNotes-1.5.0.5.txt[release notes for 1.5.0.5] -* link:v1.5.0/RelNotes-1.5.0.txt[release notes for 1.5.0] +* 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] diff --git a/Documentation/glossary.txt b/Documentation/glossary.txt index 9f446241e2..2465514e46 100644 --- a/Documentation/glossary.txt +++ b/Documentation/glossary.txt @@ -1,365 +1,405 @@ -alternate object database:: - Via the alternates mechanism, a repository can inherit part of its - object database from another object database, which is called - "alternate". - -bare repository:: - A bare repository is normally an appropriately named - directory with a `.git` suffix that does not have a - locally checked-out copy of any of the files under revision - control. That is, all of the `git` administrative and - control files that would normally be present in the - hidden `.git` sub-directory are directly present in - the `repository.git` directory instead, and no other files - are present and checked out. Usually publishers of public - repositories make bare repositories available. - -blob object:: - Untyped object, e.g. the contents of a file. - -branch:: - A non-cyclical graph of revisions, i.e. the complete history of - a particular revision, which is called the branch head. The - branch heads are stored in `$GIT_DIR/refs/heads/`. - -cache:: - Obsolete for: index. - -chain:: - A list of objects, where each object in the list contains a - reference to its successor (for example, the successor of a commit - could be one of its parents). - -changeset:: - BitKeeper/cvsps speak for "commit". Since git does not store - changes, but states, it really does not make sense to use - the term "changesets" with git. - -checkout:: - The action of updating the working tree to a revision which was - stored in the object database. - -cherry-picking:: - In SCM jargon, "cherry pick" means to choose a subset of - changes out of a series of changes (typically commits) - and record them 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 commit and to record it based - on the tip of the current branch as a new commit. - -clean:: - A working tree is clean, if it corresponds to the revision - referenced by the current head. Also see "dirty". - -commit:: - As a verb: The action of storing the current state of the index in the - object database. The result is a revision. - As a noun: Short hand for commit object. - -commit object:: - An object which contains the information about a particular - revision, such as parents, committer, author, date and the - tree object which corresponds to the top directory of the - stored revision. - -core git:: - Fundamental data structures and utilities of git. Exposes only - limited source code management tools. - -DAG:: - Directed acyclic graph. The commit objects form a directed acyclic - graph, because they have parents (directed), and the graph of commit - objects is acyclic (there is no chain which begins and ends with the - same object). - -dangling object:: - An unreachable object which is not reachable even from other - unreachable objects; a dangling object has no references to it - from any reference or object in the repository. - -dircache:: +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". + +[[def_bare_repository]]bare repository:: + A <<def_bare_repository,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` + administrative and control files that would normally be present in the + hidden `.git` sub-directory are directly present in the + `repository.git` directory instead, + and no other files are present and checked out. Usually publishers of + public repositories make bare repositories available. + +[[def_blob_object]]blob object:: + 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/`. + +[[def_cache]]cache:: + Obsolete for: <<def_index,index>>. + +[[def_chain]]chain:: + A list of objects, where each <<def_object,object>> in the list contains + a reference to its successor (for example, the successor of a + <<def_commit,commit>> could be one of its parents). + +[[def_changeset]]changeset:: + BitKeeper/cvsps speak for "<<def_commit,commit>>". Since git does not + store changes, but states, it really does not make sense to use the term + "changesets" with git. + +[[def_checkout]]checkout:: + The action of updating the <<def_working_tree,working tree>> to a + <<def_revision,revision>> which was stored in the + <<def_object_database,object database>>. + +[[def_cherry-picking]]cherry-picking:: + In <<def_SCM,SCM>> jargon, "cherry pick" means to choose a subset of + changes out of a series of changes (typically commits) and record them + 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>>. + +[[def_clean]]clean:: + A <<def_working_tree,working tree>> is <<def_clean,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>>. + +[[def_commit_object]]commit object:: + An <<def_object,object>> which contains the information about a + particular <<def_revision,revision>>, such as parents, committer, + author, date and the <<def_tree_object,tree object>> which corresponds + to the top <<def_directory,directory>> of the stored + <<def_revision,revision>>. + +[[def_core_git]]core git:: + Fundamental data structures and utilities of git. Exposes only limited + source code management tools. + +[[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 + <<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 + reference or <<def_object,object>> in the <<def_repository,repository>>. + +[[def_dircache]]dircache:: You are *waaaaay* behind. -dirty:: - A working tree is said to be dirty if it contains modifications - which have not been committed to the current branch. - -directory:: +[[def_directory]]directory:: The list you get with "ls" :-) -ent:: - Favorite synonym to "tree-ish" by some total geeks. See +[[def_dirty]]dirty:: + A <<def_working_tree,working tree>> is said to be <<def_dirty,dirty>> if + it contains modifications which have not been committed to the current + <<def_branch,branch>>. + +[[def_ent]]ent:: + Favorite synonym to "<<def_tree-ish,tree-ish>>" by some total geeks. See `http://en.wikipedia.org/wiki/Ent_(Middle-earth)` for an in-depth - explanation. Avoid this term, not to confuse people. - -fast forward:: - A fast-forward is a special type of merge where you have - a revision and you are "merging" another branch's changes - that happen to be a descendant of what you have. - In such these cases, you do not make a new merge commit but - instead just update to his revision. This will happen - frequently on a tracking branch of a remote repository. - -fetch:: - Fetching a branch means to get the branch's head ref from a - remote repository, to find out which objects are missing from - the local object database, and to get them, too. - -file system:: - Linus Torvalds originally designed git to be a user space file - system, i.e. the infrastructure to hold files and directories. - That ensured the efficiency and speed of git. - -git archive:: - Synonym for repository (for arch people). - -grafts:: - 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 commit - has is different from what was recorded when the commit was created. - Configured via the `.git/info/grafts` file. - -hash:: - In git's context, synonym to object name. - -head:: - The top of a branch. It contains a ref to the corresponding - commit object. - -head ref:: - A ref pointing to a head. Often, this is abbreviated to "head". - Head refs are stored in `$GIT_DIR/refs/heads/`. - -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 hook scripts are found in the `$GIT_DIR/hooks/` directory, - and are enabled by simply making them executable. - -index:: - A collection of files with stat information, whose contents are - stored as objects. The index is a stored version of your working - tree. Truth be told, it can also contain a second, and even a third - version of a working tree, which are used when merging. - -index entry:: - The information regarding a particular file, stored in the index. - An index entry can be unmerged, if a merge was started, but not - yet finished (i.e. if the index contains multiple versions of - that file). - -master:: - The default development branch. Whenever you create a git - repository, a branch named "master" is created, and becomes - the active branch. In most cases, this contains the local + explanation. Avoid this term, not to confuse people. + +[[def_fast_forward]]fast forward:: + A fast-forward is a special type of <<def_merge,merge>> where you have a + <<def_revision,revision>> and you are "merging" another + <<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 + <<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. + +[[def_file_system]]file system:: + Linus Torvalds originally designed git to be a user space file system, + i.e. the infrastructure to hold files and directories. That ensured the + efficiency and speed of git. + +[[def_git_archive]]git archive:: + Synonym for <<def_repository,repository>> (for arch people). + +[[def_grafts]]grafts:: + 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 + 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>>. + +[[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/`. + +[[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 + `$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 + <<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_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. -merge:: - To merge branches means to try to accumulate the changes since a - common ancestor and apply them to the first branch. An automatic - merge uses heuristics to accomplish that. Evidently, an automatic - merge can fail. - -object:: - The unit of storage in git. It is uniquely identified by - the SHA1 of its contents. Consequently, an object can not - be changed. - -object database:: - Stores a set of "objects", and an individual object is identified - by its object name. The objects usually live in `$GIT_DIR/objects/`. - -object identifier:: - Synonym for object name. - -object name:: - The unique identifier of an object. The hash of the object's contents - using the Secure Hash Algorithm 1 and usually represented by the 40 - character hexadecimal encoding of the hash of the object (possibly - followed by a white space). - -object type:: - One of the identifiers "commit","tree","tag" and "blob" describing - the type of an object. - -octopus:: - To merge more than two branches. Also denotes an intelligent - predator. - -origin:: - The default upstream repository. Most projects have at - least one upstream project which they track. By default - 'origin' is used for that purpose. New upstream updates +[[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. + +[[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. + +[[def_object_database]]object database:: + Stores a set of "objects", and an individual <<def_object,object>> is + identified by its <<def_object_name,object name>>. The objects usually + live in `$GIT_DIR/objects/`. + +[[def_object_identifier]]object identifier:: + Synonym for <<def_object_name,object name>>. + +[[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 + 1 and usually represented by the 40 character hexadecimal encoding of + the <<def_hash,hash>> of the <<def_object,object>> (possibly followed by + a white space). + +[[def_object_type]]object type:: + One of the identifiers + "<<def_commit,commit>>","<<def_tree,tree>>","<<def_tag,tag>>" or "<<def_blob_object,blob>>" + describing the type of an <<def_object,object>>. + +[[def_octopus]]octopus:: + To <<def_merge,merge>> more than two branches. Also denotes an + intelligent predator. + +[[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 will be fetched into remote tracking branches named origin/name-of-upstream-branch, which you can see using - "git branch -r". + "git <<def_branch,branch>> -r". -pack:: - A set of objects which have been compressed into one file (to save - space or to transmit them efficiently). +[[def_pack]]pack:: + A set of objects which have been compressed into one file (to save space + or to transmit them efficiently). -pack index:: +[[def_pack_index]]pack index:: The list of identifiers, and other information, of the objects in a - pack, to assist in efficiently accessing the contents of a pack. - -parent:: - A commit object contains a (possibly empty) list of the logical - predecessor(s) in the line of development, i.e. its parents. - -pickaxe:: - The term pickaxe refers to an option to the diffcore routines - that help select changes that add or delete a given text string. - With the --pickaxe-all option, it can be used to view the - full changeset that introduced or removed, say, a particular - line of text. See gitlink:git-diff[1]. - -plumbing:: - Cute name for core git. - -porcelain:: - Cute name for programs and program suites depending on core git, - presenting a high level access to core git. Porcelains expose - more of a SCM interface than the plumbing. - -pull:: - Pulling a branch means to fetch it and merge it. - -push:: - Pushing a branch means to get the branch's head ref from a remote - repository, 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 reachable from the local head ref, and which are missing from - the remote repository, into the remote object database, and updating - the remote head ref. If the remote head is not an ancestor to the - local head, the push fails. - -reachable:: - All of the ancestors of a given commit are said to be reachable from - that commit. More generally, one object is reachable from another if - we can reach the one from the other by a chain that follows tags to - whatever they tag, commits to their parents or trees, and trees to the - trees or blobs that they contain. - -rebase:: - To clean a branch by starting from the head of the main line of - development ("master"), and reapply the (possibly cherry-picked) - changes from that branch. - -ref:: - A 40-byte hex representation of a SHA1 or a name that denotes - a particular object. These may be stored in `$GIT_DIR/refs/`. - -refspec:: - A refspec is used by fetch and push to describe the mapping - between remote 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 branch 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] - -repository:: - A collection of refs together with an object database containing - all objects, which are reachable from the refs, possibly accompanied - by meta data from one or more porcelains. A repository can - share an object database with other repositories. - -resolve:: - The action of fixing up manually what a failed automatic merge - left behind. - -revision:: - A particular state of files and directories which was stored in - the object database. It is referenced by a commit object. - -rewind:: - To throw away part of the development, i.e. to assign the head to - an earlier revision. - -SCM:: + <<def_pack,pack>>, to assist in efficiently accessing the contents of a + <<def_pack,pack>>. + +[[def_parent]]parent:: + A <<def_commit_object,commit object>> contains a (possibly empty) list + of the logical predecessor(s) in the line of development, i.e. its + parents. + +[[def_pickaxe]]pickaxe:: + The term <<def_pickaxe,pickaxe>> refers to an option to the diffcore + routines that help select changes that add or delete a given text + string. With the --pickaxe-all option, it can be used to view the full + <<def_changeset,changeset>> that introduced or removed, say, a + particular line of text. See gitlink:git-diff[1]. + +[[def_plumbing]]plumbing:: + Cute name for <<def_core_git,core git>>. + +[[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>> + 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_push]]push:: + Pushing a <<def_branch,branch>> means to get the <<def_branch,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 + 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 + <<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. + +[[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 + 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 + <<def_tree_object,trees>> to the trees or <<def_blob_object,blobs>> + that they contain. + +[[def_rebase]]rebase:: + To reapply a series of changes from a <<def_branch,branch>> to a + different base, and reset the <<def_head,head>> of that branch + to the result. + +[[def_ref]]ref:: + A 40-byte hex representation of a <<def_SHA1,SHA1>> or a name that + denotes a particular <<def_object,object>>. These may be stored in + `$GIT_DIR/refs/`. + +[[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_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. + +[[def_resolve]]resolve:: + The action of fixing up manually what a failed automatic + <<def_merge,merge>> left behind. + +[[def_revision]]revision:: + A particular state of files and directories which was stored in the + <<def_object_database,object database>>. It is referenced by a + <<def_commit_object,commit object>>. + +[[def_rewind]]rewind:: + To throw away part of the development, i.e. to assign the + <<def_head,head>> to an earlier <<def_revision,revision>>. + +[[def_SCM]]SCM:: Source code management (tool). -SHA1:: - Synonym for object name. - -shallow repository:: - 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 - 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 shallow repository is created by giving - `--depth` option to gitlink:git-clone[1], and its - history can be later deepened with gitlink:git-fetch[1]. - -symref:: - Symbolic reference: instead of containing the 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 symref. Symbolic references are manipulated with - the gitlink:git-symbolic-ref[1] command. - -topic branch:: - A regular git branch that is used by a developer to - identify a conceptual line of development. Since branches - are very easy and inexpensive, it is often desirable to - have several small branches that each contain very well - defined concepts or small incremental yet related changes. - -tracking branch:: - A regular git branch that is used to follow changes from - another 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 ref in a Pull: refspec. - -tree object:: - An object containing a list of file names and modes along with refs - to the associated blob and/or tree objects. A tree is equivalent - to a directory. - -tree:: - Either a working tree, or a tree object together with the - dependent blob and tree objects (i.e. a stored representation - of a working tree). - -tree-ish:: - A ref pointing to either a commit object, a tree object, or a - tag object pointing to a tag or commit or tree object. - -tag object:: - An object containing a ref pointing to another object, which can - contain a message just like a commit object. It can also - contain a (PGP) signature, in which case it is called a "signed - tag object". - -tag:: - A ref pointing to a tag or commit object. In contrast to a head, - a tag is not changed by a commit. Tags (not tag objects) are - stored in `$GIT_DIR/refs/tags/`. A git tag has nothing to do with - a Lisp tag (which is called object type in git's context). - A tag is most typically used to mark a particular point in the - commit ancestry chain. - -unmerged index:: - An index which contains unmerged index entries. - -unreachable object:: - An object which is not reachable from a branch, tag, or any - other reference. - -working tree:: - The set of files and directories currently being worked on, - i.e. you can work in your working tree without using git at all. - +[[def_SHA1]]SHA1:: + Synonym for <<def_object_name,object name>>. + +[[def_shallow_repository]]shallow repository:: + A <<def_shallow_repository,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>> + 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. + +[[def_tag]]tag:: + A <<def_ref,ref>> pointing to a <<def_tag,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>>. + +[[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 + <<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>>". + +[[def_topic_branch]]topic branch:: + A regular git <<def_branch,branch>> that is used by a developer to + identify a conceptual line of development. Since branches are very easy + and inexpensive, it is often desirable to have several small branches + that each contain very well defined concepts or small incremental yet + related changes. + +[[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 + 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>>). + +[[def_tree_object]]tree object:: + An <<def_object,object>> containing a list of file names and modes along + with refs to the associated blob and/or tree objects. A + <<def_tree,tree>> is equivalent to a <<def_directory,directory>>. + +[[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>>. + +[[def_unmerged_index]]unmerged index:: + An <<def_index,index>> which contains unmerged + <<def_index_entry,index entries>>. + +[[def_unreachable_object]]unreachable object:: + An <<def_object,object>> which is not <<def_reachable,reachable>> from a + <<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. diff --git a/Documentation/sort_glossary.pl b/Documentation/sort_glossary.pl deleted file mode 100644 index 05dc7b2c7b..0000000000 --- a/Documentation/sort_glossary.pl +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/perl - -%terms=(); - -while(<>) { - if(/^(\S.*)::$/) { - my $term=$1; - if(defined($terms{$term})) { - die "$1 defined twice\n"; - } - $terms{$term}=""; - LOOP: while(<>) { - if(/^$/) { - last LOOP; - } - if(/^ \S/) { - $terms{$term}.=$_; - } else { - die "Error 1: $_"; - } - } - } -} - -sub format_tab_80 ($) { - my $text=$_[0]; - my $result=""; - $text=~s/\s+/ /g; - $text=~s/^\s+//; - while($text=~/^(.{1,72})(|\s+(\S.*)?)$/) { - $result.=" ".$1."\n"; - $text=$3; - } - return $result; -} - -sub no_spaces ($) { - my $result=$_[0]; - $result=~tr/ /_/; - return $result; -} - -print 'GIT Glossary -============ - -This list is sorted alphabetically: - -'; - -@keys=sort {uc($a) cmp uc($b)} keys %terms; -$pattern='(\b(?<!link:git-)'.join('\b|\b(?<!-)',reverse @keys).'\b)'; -foreach $key (@keys) { - $terms{$key}=~s/$pattern/sprintf "<<ref_".no_spaces($1).",$1>>";/eg; - print '[[ref_'.no_spaces($key).']]'.$key."::\n" - .format_tab_80($terms{$key})."\n"; -} - -print ' - -Author ------- -Written by Johannes Schindelin <Johannes.Schindelin@gmx.de> and -the git-list <git@vger.kernel.org>. - -GIT ---- -Part of the link:git.html[git] suite -'; - diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index d7b227e647..574e9c0e50 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -84,7 +84,7 @@ $ git branch -r # list origin/master origin/next ... -$ git branch checkout -b masterwork origin/master +$ git checkout -b masterwork origin/master ----------------------------------------------- Fetch a branch from a different repository, and give it a new @@ -155,8 +155,8 @@ Make sure git knows who to blame: ------------------------------------------------ $ cat >~/.gitconfig <<\EOF [user] -name = Your Name Comes Here -email = you@yourdomain.example.com + name = Your Name Comes Here + email = you@yourdomain.example.com EOF ------------------------------------------------ @@ -195,7 +195,7 @@ 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" +$ git am mbox # import patches from the mailbox "mbox" ----------------------------------------------- Fetch a branch in a different git repository, then merge into the @@ -288,21 +288,22 @@ collection of files. It stores the history as a compressed collection of interrelated snapshots (versions) of the project's contents. -A single git repository may contain multiple branches. Each branch -is a bookmark referencing a particular point in the project history. -The gitlink:git-branch[1] command shows you the list of branches: +A single git repository may contain multiple branches. It keeps track +of them by keeping a list of <<def_head,heads>> which reference the +latest version on each branch; the gitlink:git-branch[1] command shows +you the list of branch heads: ------------------------------------------------ $ git branch * master ------------------------------------------------ -A freshly cloned repository contains a single branch, named "master", -and the working directory contains the version of the project -referred to by the master branch. +A freshly cloned repository contains a single branch head, named +"master", and working directory is initialized to the state of +the project referred to by "master". -Most projects also use tags. Tags, like branches, are references -into the project's history, and can be listed using the +Most projects also use <<def_tag,tags>>. Tags, like heads, are +references into the project's history, and can be listed using the gitlink:git-tag[1] command: ------------------------------------------------ @@ -320,9 +321,9 @@ v2.6.13 ------------------------------------------------ Tags are expected to always point at the same version of a project, -while branches are expected to advance as development progresses. +while heads are expected to advance as development progresses. -Create a new branch pointing to one of these versions and check it +Create a new branch head pointing to one of these versions and check it out using gitlink:git-checkout[1]: ------------------------------------------------ @@ -346,10 +347,10 @@ the current branch to point at v2.6.17 instead, with $ git reset --hard v2.6.17 ------------------------------------------------ -Note that if the current branch was your only reference to a +Note that if the current branch head was your only reference to a particular point in history, then resetting that branch may leave you -with no way to find the history it used to point to; so use this -command carefully. +with no way to find the history it used to point to; so use this command +carefully. Understanding History: Commits ------------------------------ @@ -452,17 +453,15 @@ be replaced with another letter or number. Understanding history: What is a branch? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Though we've been using the word "branch" to mean a kind of reference -to a particular commit, the word branch is also commonly used to -refer to the line of commits leading up to that point. In the -example above, git may think of the branch named "A" as just a -pointer to one particular commit, but we may refer informally to the -line of three commits leading up to that point as all being part of +When we need to be precise, we will use the word "branch" to mean a line +of development, and "branch head" (or just "head") to mean a reference +to the most recent commit on a branch. In the example above, the branch +head named "A" is a pointer to one particular commit, but we refer to +the line of three commits leading up to that point as all being part of "branch A". -If we need to make it clear that we're just talking about the most -recent commit on the branch, we may refer to that commit as the -"head" of the branch. +However, when no confusion will result, we often just use the term +"branch" both for branches and for branch heads. Manipulating branches --------------------- @@ -580,7 +579,7 @@ cloned from, using gitlink:git-remote[1]: ------------------------------------------------- $ git remote add linux-nfs git://linux-nfs.org/pub/nfs-2.6.git -$ git fetch +$ git fetch linux-nfs * refs/remotes/linux-nfs/master: storing branch 'master' ... commit: bf81b46 ------------------------------------------------- @@ -681,7 +680,7 @@ occasionally you may land on a commit that broke something unrelated; run ------------------------------------------------- -$ git bisect-visualize +$ git bisect visualize ------------------------------------------------- which will run gitk and label the commit it chose with a marker that @@ -766,7 +765,7 @@ We can also create a tag to refer to a particular commit; after running ------------------------------------------------- -$ git-tag stable-1 1b2e1d63ff +$ git tag stable-1 1b2e1d63ff ------------------------------------------------- You can use stable-1 to refer to the commit 1b2e1d63ff. @@ -910,7 +909,7 @@ name based on any tag it finds pointing to one of the commit's descendants: ------------------------------------------------- -$ git name-rev e05db0fd +$ git name-rev --tags e05db0fd e05db0fd tags/v1.5.0-rc1^0~23 ------------------------------------------------- @@ -919,7 +918,7 @@ revision using a tag on which the given commit is based: ------------------------------------------------- $ git describe e05db0fd -v1.5.0-rc0-ge05db0f +v1.5.0-rc0-260-ge05db0f ------------------------------------------------- but that may sometimes help you guess which tags might come after the @@ -1698,7 +1697,7 @@ 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 file patch; so, for example, you can +will also accept a local directory name; so, for example, you can use ------------------------------------------------- @@ -1862,7 +1861,7 @@ Allow 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 -gitweb/README in the git source tree for instructions on setting it up. +gitweb/INSTALL in the git source tree for instructions on setting it up. Examples -------- @@ -3013,9 +3012,6 @@ 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). -Glossary of git terms -===================== - include::glossary.txt[] Notes and todo list for this manual diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 39ba8d135c..48715012be 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v1.5.1-rc1.GIT +DEF_VER=v1.5.1.GIT LF=' ' @@ -110,6 +110,14 @@ all:: # Define NO_PERL_MAKEMAKER if you cannot use Makefiles generated by perl's # MakeMaker (e.g. using ActiveState under Cygwin). # +# Define WITH_P4IMPORT to build and install Python git-p4import script. +# +# Define NO_TCLTK if you do not want Tcl/Tk GUI. +# +# The TCLTK_PATH variable governs the location of the Tck/Tk interpreter. +# If not set it defaults to the bare 'wish'. If it is set to the empty +# string then NO_TCLTK will be forced (this is used by configure script). +# GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE @$(SHELL_PATH) ./GIT-VERSION-GEN @@ -159,6 +167,7 @@ AR = ar TAR = tar INSTALL = install RPMBUILD = rpmbuild +TCLTK_PATH = wish # sparse is architecture-neutral, which means that we need to tell it # explicitly what architecture to check for. Fix this up for yours.. @@ -196,9 +205,20 @@ SCRIPT_PERL = \ git-svnimport.perl git-cvsexportcommit.perl \ git-send-email.perl git-svn.perl +SCRIPT_PYTHON = \ + git-p4import.py + +ifdef WITH_P4IMPORT +SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \ + $(patsubst %.perl,%,$(SCRIPT_PERL)) \ + $(patsubst %.py,%,$(SCRIPT_PYTHON)) \ + git-status git-instaweb +else SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \ $(patsubst %.perl,%,$(SCRIPT_PERL)) \ git-status git-instaweb +endif + # ... and all the rest that could be moved out of bindir to gitexecdir PROGRAMS = \ @@ -231,6 +251,12 @@ BUILT_INS = \ # what 'all' will build and 'install' will install, in gitexecdir ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS) +# what 'all' will build but not install in gitexecdir +OTHER_PROGRAMS = git$X gitweb/gitweb.cgi +ifndef NO_TCLTK +OTHER_PROGRAMS += gitk-wish +endif + # Backward compatibility -- to be removed after 1.0 PROGRAMS += git-ssh-pull$X git-ssh-push$X @@ -241,6 +267,9 @@ endif ifndef PERL_PATH PERL_PATH = /usr/bin/perl endif +ifndef PYTHON_PATH + PYTHON_PATH = /usr/local/bin/python +endif export PERL_PATH @@ -608,6 +637,10 @@ ifdef NO_PERL_MAKEMAKER export NO_PERL_MAKEMAKER endif +ifeq ($(TCLTK_PATH),) +NO_TCLTK=NoThanks +endif + QUIET_SUBDIR0 = $(MAKE) -C # space to separate -C and subdir QUIET_SUBDIR1 = @@ -646,6 +679,8 @@ prefix_SQ = $(subst ','\'',$(prefix)) SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH)) +PYTHON_PATH_SQ = $(subst ','\'',$(PYTHON_PATH)) +TCLTK_PATH_SQ = $(subst ','\'',$(TCLTK_PATH)) LIBS = $(GITLIBS) $(EXTLIBS) @@ -661,19 +696,27 @@ export prefix gitexecdir TAR INSTALL DESTDIR SHELL_PATH template_dir ### Build rules -all:: $(ALL_PROGRAMS) $(BUILT_INS) git$X gitk gitweb/gitweb.cgi +all:: $(ALL_PROGRAMS) $(BUILT_INS) $(OTHER_PROGRAMS) ifneq (,$X) $(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) git$X)), rm -f '$p';) endif all:: - $(QUIET_SUBDIR0)git-gui $(QUIET_SUBDIR1) all +ifndef NO_TCLTK + $(QUIET_SUBDIR0)git-gui TCLTK_PATH='$(TCLTK_PATH_SQ)' $(QUIET_SUBDIR1) all +endif $(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' all $(QUIET_SUBDIR0)templates $(QUIET_SUBDIR1) strip: $(PROGRAMS) git$X $(STRIP) $(STRIP_OPTS) $(PROGRAMS) git$X +gitk-wish: gitk GIT-GUI-VARS + $(QUIET_GEN)rm -f $@ $@+ && \ + sed -e '1,3s|^exec .* "$$0"|exec $(subst |,'\|',$(TCLTK_PATH_SQ)) "$$0"|' <gitk >$@+ && \ + chmod +x $@+ && \ + mv -f $@+ $@ + git$X: git.c common-cmds.h $(BUILTIN_OBJS) $(GITLIBS) GIT-CFLAGS $(QUIET_LINK)$(CC) -DGIT_VERSION='"$(GIT_VERSION)"' \ $(ALL_CFLAGS) -o $@ $(filter %.c,$^) \ @@ -699,6 +742,15 @@ $(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh $(patsubst %.perl,%,$(SCRIPT_PERL)): perl/perl.mak +$(patsubst %.py,%,$(SCRIPT_PYTHON)) : % : %.py + rm -f $@ $@+ + sed -e '1s|#!.*/python|#!$(PYTHON_PATH_SQ)|' \ + -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \ + -e 's/@@NO_CURL@@/$(NO_CURL)/g' \ + $@.py >$@+ + chmod +x $@+ + mv $@+ $@ + perl/perl.mak: GIT-CFLAGS $(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' $(@F) @@ -852,6 +904,20 @@ GIT-CFLAGS: .FORCE-GIT-CFLAGS echo "$$FLAGS" >GIT-CFLAGS; \ fi +### Detect Tck/Tk interpreter path changes +ifndef NO_TCLTK +TRACK_VARS = $(subst ','\'',-DTCLTK_PATH='$(TCLTK_PATH_SQ)') + +GIT-GUI-VARS: .FORCE-GIT-GUI-VARS + @VARS='$(TRACK_VARS)'; \ + if test x"$$VARS" != x"`cat $@ 2>/dev/null`" ; then \ + echo 1>&2 " * new Tcl/Tk interpreter location"; \ + echo "$$VARS" >$@; \ + fi + +.PHONY: .FORCE-GIT-GUI-VARS +endif + ### Testing rules # GNU make supports exporting all variables by "export" without parameters. @@ -892,10 +958,13 @@ install: all $(INSTALL) -d -m755 '$(DESTDIR_SQ)$(bindir_SQ)' $(INSTALL) -d -m755 '$(DESTDIR_SQ)$(gitexecdir_SQ)' $(INSTALL) $(ALL_PROGRAMS) '$(DESTDIR_SQ)$(gitexecdir_SQ)' - $(INSTALL) git$X gitk '$(DESTDIR_SQ)$(bindir_SQ)' + $(INSTALL) git$X '$(DESTDIR_SQ)$(bindir_SQ)' $(MAKE) -C templates DESTDIR='$(DESTDIR_SQ)' install $(MAKE) -C perl prefix='$(prefix_SQ)' install +ifndef NO_TCLTK + $(INSTALL) gitk-wish '$(DESTDIR_SQ)$(bindir_SQ)'/gitk $(MAKE) -C git-gui install +endif if test 'z$(bindir_SQ)' != 'z$(gitexecdir_SQ)'; \ then \ ln -f '$(DESTDIR_SQ)$(bindir_SQ)/git$X' \ @@ -963,7 +1032,7 @@ dist-doc: clean: rm -f *.o mozilla-sha1/*.o arm/*.o ppc/*.o compat/*.o xdiff/*.o \ - $(LIB_FILE) $(XDIFF_LIB) + test-chmtime$X $(LIB_FILE) $(XDIFF_LIB) rm -f $(ALL_PROGRAMS) $(BUILT_INS) git$X rm -f *.spec *.pyc *.pyo */*.pyc */*.pyo common-cmds.h TAGS tags rm -rf autom4te.cache @@ -974,10 +1043,13 @@ clean: rm -f gitweb/gitweb.cgi $(MAKE) -C Documentation/ clean $(MAKE) -C perl clean - $(MAKE) -C git-gui clean $(MAKE) -C templates/ clean $(MAKE) -C t/ clean - rm -f GIT-VERSION-FILE GIT-CFLAGS +ifndef NO_TCLTK + rm -f gitk-wish + $(MAKE) -C git-gui clean +endif + rm -f GIT-VERSION-FILE GIT-CFLAGS GIT-GUI-VARS .PHONY: all install clean strip .PHONY: .FORCE-GIT-VERSION-FILE TAGS tags .FORCE-GIT-CFLAGS @@ -991,7 +1063,7 @@ check-docs:: git-merge-octopus | git-merge-ours | git-merge-recursive | \ git-merge-resolve | git-merge-stupid | \ git-add--interactive | git-fsck-objects | git-init-db | \ - git-repo-config | \ + git-repo-config | git-fetch--tool | \ git-ssh-pull | git-ssh-push ) continue ;; \ esac ; \ test -f "Documentation/$$v.txt" || \ @@ -38,3 +38,9 @@ requests, comments and patches to git@vger.kernel.org. To subscribe to the list, send an email with just "subscribe git" in the body to majordomo@vger.kernel.org. The mailing list archives are available at http://marc.theaimsgroup.com/?l=git and other archival sites. + +The messages titled "A note from the maintainer", "What's in +git.git (stable)" and "What's cooking in git.git (topics)" and +the discussion following them on the mailing list give a good +reference for project status, development direction and +remaining tasks. diff --git a/builtin-add.c b/builtin-add.c index 9fcf514dbc..871e23f0f6 100644 --- a/builtin-add.c +++ b/builtin-add.c @@ -87,7 +87,7 @@ static void fill_directory(struct dir_struct *dir, const char **pathspec) } /* Read the directory and prune it */ - read_directory(dir, path, base, baselen); + read_directory(dir, path, base, baselen, pathspec); if (pathspec) prune_directory(dir, pathspec, baselen); } diff --git a/builtin-bundle.c b/builtin-bundle.c index 0a9b73867f..d1635a0a6b 100644 --- a/builtin-bundle.c +++ b/builtin-bundle.c @@ -87,7 +87,7 @@ static int read_header(const char *path, struct bundle_header *header) { if (buffer[len - 1] == '\n') buffer[len - 1] = '\0'; if (get_sha1_hex(buffer + offset, sha1)) { - warn("unrecognized header: %s", buffer); + warning("unrecognized header: %s", buffer); continue; } delim = buffer[40 + offset]; @@ -268,7 +268,7 @@ static int create_bundle(struct bundle_header *header, const char *path, * from getting output. */ if (!(e->item->flags & SHOWN)) { - warn("ref '%s' is excluded by the rev-list options", + warning("ref '%s' is excluded by the rev-list options", e->name); continue; } diff --git a/builtin-ls-files.c b/builtin-ls-files.c index 4e1d5af634..74a6acacc1 100644 --- a/builtin-ls-files.c +++ b/builtin-ls-files.c @@ -216,7 +216,7 @@ static void show_files(struct dir_struct *dir, const char *prefix) if (baselen) path = base = prefix; - read_directory(dir, path, base, baselen); + read_directory(dir, path, base, baselen, pathspec); if (show_others) show_other_files(dir); if (show_killed) diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c index d94578cb4a..c95e477e83 100644 --- a/builtin-mailinfo.c +++ b/builtin-mailinfo.c @@ -294,14 +294,14 @@ static char *header[MAX_HDR_PARSED] = { "From","Subject","Date", }; -static int check_header(char *line, char **hdr_data) +static int check_header(char *line, char **hdr_data, int overwrite) { int i; /* search for the interesting parts */ for (i = 0; header[i]; i++) { int len = strlen(header[i]); - if (!hdr_data[i] && + if ((!hdr_data[i] || overwrite) && !strncasecmp(line, header[i], len) && line[len] == ':' && isspace(line[len + 1])) { /* Unwrap inline B and Q encoding, and optionally @@ -614,6 +614,7 @@ static int find_boundary(void) static int handle_boundary(void) { + char newline[]="\n"; again: if (!memcmp(line+content_top->boundary_len, "--", 2)) { /* we hit an end boundary */ @@ -628,7 +629,7 @@ again: "can't recover\n"); exit(1); } - handle_filter("\n"); + handle_filter(newline); /* skip to the next boundary */ if (!find_boundary()) @@ -643,7 +644,7 @@ again: /* slurp in this section's info */ while (read_one_header_line(line, sizeof(line), fin)) - check_header(line, p_hdr_data); + check_header(line, p_hdr_data, 0); /* eat the blank line after section info */ return (fgets(line, sizeof(line), fin) != NULL); @@ -699,10 +700,14 @@ static int handle_commit_msg(char *line) if (!*cp) return 0; } - if ((still_looking = check_header(cp, s_hdr_data)) != 0) + if ((still_looking = check_header(cp, s_hdr_data, 0)) != 0) return 0; } + /* normalize the log message to UTF-8. */ + if (metainfo_charset) + convert_to_utf8(line, charset); + if (patchbreak(line)) { fclose(cmitmsg); cmitmsg = NULL; @@ -767,12 +772,8 @@ static void handle_body(void) return; } - /* Unwrap transfer encoding and optionally - * normalize the log message to UTF-8. - */ + /* Unwrap transfer encoding */ decode_transfer_encoding(line); - if (metainfo_charset) - convert_to_utf8(line, charset); switch (transfer_encoding) { case TE_BASE64: @@ -875,7 +876,7 @@ int mailinfo(FILE *in, FILE *out, int ks, const char *encoding, /* process the email header */ while (read_one_header_line(line, sizeof(line), fin)) - check_header(line, p_hdr_data); + check_header(line, p_hdr_data, 1); handle_body(); handle_info(); diff --git a/builtin-read-tree.c b/builtin-read-tree.c index 82df94101a..793eae0a5f 100644 --- a/builtin-read-tree.c +++ b/builtin-read-tree.c @@ -184,7 +184,7 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix) if (opts.dir) die("more than one --exclude-per-directory are given."); - dir = calloc(1, sizeof(*opts.dir)); + dir = xcalloc(1, sizeof(*opts.dir)); dir->show_ignored = 1; dir->exclude_per_dir = arg + 24; opts.dir = dir; diff --git a/builtin-rerere.c b/builtin-rerere.c index b8867ab4ad..b463c07f04 100644 --- a/builtin-rerere.c +++ b/builtin-rerere.c @@ -78,6 +78,13 @@ static void append_line(struct buffer *buffer, const char *line) buffer->nr += len; } +static void clear_buffer(struct buffer *buffer) +{ + free(buffer->ptr); + buffer->ptr = NULL; + buffer->nr = buffer->alloc = 0; +} + static int handle_file(const char *path, unsigned char *sha1, const char *output) { @@ -131,6 +138,8 @@ static int handle_file(const char *path, SHA1_Update(&ctx, two->ptr, two->nr); SHA1_Update(&ctx, "\0", 1); } + clear_buffer(one); + clear_buffer(two); } else if (hunk == 1) append_line(one, buf); else if (hunk == 2) diff --git a/builtin-revert.c b/builtin-revert.c index f3f3f5c6ee..4ba0ee63ab 100644 --- a/builtin-revert.c +++ b/builtin-revert.c @@ -294,13 +294,13 @@ static int revert_or_cherry_pick(int argc, const char **argv) oneline = get_oneline(message); if (action == REVERT) { + char *oneline_body = strchr(oneline, ' '); + base = commit; next = commit->parents->item; - add_to_msg("Revert "); - add_to_msg(find_unique_abbrev(commit->object.sha1, - DEFAULT_ABBREV)); - add_to_msg(oneline); - add_to_msg("\nThis reverts commit "); + add_to_msg("Revert \""); + add_to_msg(oneline_body + 1); + add_to_msg("\"\n\nThis reverts commit "); add_to_msg(sha1_to_hex(commit->object.sha1)); add_to_msg(".\n"); } else { diff --git a/builtin-rm.c b/builtin-rm.c index 00dbe39960..bf42003a7e 100644 --- a/builtin-rm.c +++ b/builtin-rm.c @@ -89,20 +89,10 @@ static int check_local_mod(unsigned char *head) if (ce_match_stat(ce, &st, 0)) errs = error("'%s' has local modifications " "(hint: try -f)", ce->name); - if (no_head) - continue; - /* - * It is Ok to remove a newly added path, as long as - * it is cache-clean. - */ - if (get_tree_entry(head, name, sha1, &mode)) - continue; - /* - * Otherwise make sure the version from the HEAD - * matches the index. - */ - if (ce->ce_mode != create_ce_mode(mode) || - hashcmp(ce->sha1, sha1)) + if (no_head + || get_tree_entry(head, name, sha1, &mode) + || ce->ce_mode != create_ce_mode(mode) + || hashcmp(ce->sha1, sha1)) errs = error("'%s' has changes staged in the index " "(hint: try -f)", name); } @@ -654,6 +654,7 @@ static char *get_header(const struct commit *commit, const char *key) static char *replace_encoding_header(char *buf, const char *encoding) { char *encoding_header = strstr(buf, "\nencoding "); + char *header_end = strstr(buf, "\n\n"); char *end_of_encoding_header; int encoding_header_pos; int encoding_header_len; @@ -661,8 +662,10 @@ static char *replace_encoding_header(char *buf, const char *encoding) int need_len; int buflen = strlen(buf) + 1; - if (!encoding_header) - return buf; /* should not happen but be defensive */ + if (!header_end) + header_end = buf + buflen; + if (!encoding_header || encoding_header >= header_end) + return buf; encoding_header++; end_of_encoding_header = strchr(encoding_header, '\n'); if (!end_of_encoding_header) @@ -760,7 +763,7 @@ static void fill_person(struct interp *table, const char *msg, int len) if (msg + start == ep) return; - table[5].value = xstrndup(msg + start, ep - msg + start); + table[5].value = xstrndup(msg + start, ep - (msg + start)); /* parse tz */ for (start = ep - msg + 1; start < len && isspace(msg[start]); start++) @@ -849,19 +852,23 @@ static long format_commit_message(const struct commit *commit, interp_set_entry(table, ITREE_ABBREV, find_unique_abbrev(commit->tree->object.sha1, DEFAULT_ABBREV)); + + parents[1] = 0; for (i = 0, p = commit->parents; p && i < sizeof(parents) - 1; p = p->next) - i += snprintf(parents + i, sizeof(parents) - i - 1, "%s ", + i += snprintf(parents + i, sizeof(parents) - i - 1, " %s", sha1_to_hex(p->item->object.sha1)); - interp_set_entry(table, IPARENTS, parents); + interp_set_entry(table, IPARENTS, parents + 1); + + parents[1] = 0; for (i = 0, p = commit->parents; p && i < sizeof(parents) - 1; p = p->next) - i += snprintf(parents + i, sizeof(parents) - i - 1, "%s ", + i += snprintf(parents + i, sizeof(parents) - i - 1, " %s", find_unique_abbrev(p->item->object.sha1, DEFAULT_ABBREV)); - interp_set_entry(table, IPARENTS_ABBREV, parents); + interp_set_entry(table, IPARENTS_ABBREV, parents + 1); for (i = 0, state = HEADER; msg[i] && state < BODY; i++) { int eol; @@ -884,7 +891,8 @@ static long format_commit_message(const struct commit *commit, fill_person(table + ICOMMITTER_NAME, msg + i + 10, eol - i - 10); else if (!prefixcmp(msg + i, "encoding ")) - table[IENCODING].value = xstrndup(msg + i, eol - i); + table[IENCODING].value = + xstrndup(msg + i + 9, eol - i - 9); i = eol; } if (msg[i]) diff --git a/config.mak.in b/config.mak.in index 9a578405d8..eb9d7a5549 100644 --- a/config.mak.in +++ b/config.mak.in @@ -6,6 +6,7 @@ CFLAGS = @CFLAGS@ AR = @AR@ TAR = @TAR@ #INSTALL = @INSTALL@ # needs install-sh or install.sh in sources +TCLTK_PATH = @TCLTK_PATH@ prefix = @prefix@ exec_prefix = @exec_prefix@ diff --git a/configure.ac b/configure.ac index 3a8e778def..50d2b85ace 100644 --- a/configure.ac +++ b/configure.ac @@ -75,6 +75,14 @@ GIT_ARG_SET_PATH(shell) # Define PERL_PATH to provide path to Perl. GIT_ARG_SET_PATH(perl) # +# Declare the with-tcltk/without-tcltk options. +AC_ARG_WITH(tcltk, +AS_HELP_STRING([--with-tcltk],[use Tcl/Tk GUI (default is YES)]) +AS_HELP_STRING([],[ARG is the full path to the Tcl/Tk interpreter.]) +AS_HELP_STRING([],[Bare --with-tcltk will make the GUI part only if]) +AS_HELP_STRING([],[Tcl/Tk interpreter will be found in a system.]),\ +GIT_PARSE_WITH(tcltk)) +# ## Checks for programs. @@ -84,6 +92,22 @@ AC_PROG_CC([cc gcc]) #AC_PROG_INSTALL # needs install-sh or install.sh in sources AC_CHECK_TOOL(AR, ar, :) AC_CHECK_PROGS(TAR, [gtar tar]) +# TCLTK_PATH will be set to some value if we want Tcl/Tk +# or will be empty otherwise. +if test -z "$NO_TCLTK"; then + if test "$with_tcltk" = ""; then + # No Tcl/Tk switches given. Do not check for Tcl/Tk, use bare 'wish'. + TCLTK_PATH=wish + AC_SUBST(TCLTK_PATH) + elif test "$with_tcltk" = "yes"; then + # Tcl/Tk check requested. + AC_CHECK_PROGS(TCLTK_PATH, [wish], ) + else + AC_MSG_RESULT([Using Tcl/Tk interpreter $with_tcltk]) + TCLTK_PATH="$with_tcltk" + AC_SUBST(TCLTK_PATH) + fi +fi ## Checks for libraries. AC_MSG_NOTICE([CHECKS for libraries]) @@ -417,6 +417,8 @@ static int git_tcp_connect_sock(char *host) if (colon) { *colon = 0; port = colon + 1; + if (!*port) + port = "<none>"; } memset(&hints, 0, sizeof(hints)); @@ -425,7 +427,7 @@ static int git_tcp_connect_sock(char *host) gai = getaddrinfo(host, port, &hints, &ai); if (gai) - die("Unable to look up %s (%s)", host, gai_strerror(gai)); + die("Unable to look up %s (port %s) (%s)", host, port, gai_strerror(gai)); for (ai0 = ai; ai; ai = ai->ai_next) { sockfd = socket(ai->ai_family, diff --git a/contrib/emacs/git-blame.el b/contrib/emacs/git-blame.el index 64ad50b327..bb671d561e 100644 --- a/contrib/emacs/git-blame.el +++ b/contrib/emacs/git-blame.el @@ -8,8 +8,8 @@ ;; License: GPL ;; Keywords: git, version control, release management ;; -;; Compatibility: Emacs21 - +;; Compatibility: Emacs21, Emacs22 and EmacsCVS +;; Git 1.5 and up ;; This file is *NOT* part of GNU Emacs. ;; This file is distributed under the same terms as GNU Emacs. @@ -61,8 +61,9 @@ ;;; Compatibility: ;; -;; It requires GNU Emacs 21. If you'are using Emacs 20, try -;; changing this: +;; It requires GNU Emacs 21 or later and Git 1.5.0 and up +;; +;; If you'are using Emacs 20, try changing this: ;; ;; (overlay-put ovl 'face (list :background ;; (cdr (assq 'color (cddddr info))))) @@ -77,30 +78,51 @@ ;; ;;; Code: -(require 'cl) ; to use `push', `pop' - -(defun color-scale (l) - (let* ((colors ()) - r g b) - (setq r l) - (while r - (setq g l) - (while g - (setq b l) - (while b - (push (concat "#" (car r) (car g) (car b)) colors) - (pop b)) - (pop g)) - (pop r)) - colors)) +(eval-when-compile (require 'cl)) ; to use `push', `pop' + + +(defun git-blame-color-scale (&rest elements) + "Given a list, returns a list of triples formed with each +elements of the list. + +a b => bbb bba bab baa abb aba aaa aab" + (let (result) + (dolist (a elements) + (dolist (b elements) + (dolist (c elements) + (setq result (cons (format "#%s%s%s" a b c) result))))) + result)) + +;; (git-blame-color-scale "0c" "04" "24" "1c" "2c" "34" "14" "3c") => +;; ("#3c3c3c" "#3c3c14" "#3c3c34" "#3c3c2c" "#3c3c1c" "#3c3c24" +;; "#3c3c04" "#3c3c0c" "#3c143c" "#3c1414" "#3c1434" "#3c142c" ...) + +(defmacro git-blame-random-pop (l) + "Select a random element from L and returns it. Also remove +selected element from l." + ;; only works on lists with unique elements + `(let ((e (elt ,l (random (length ,l))))) + (setq ,l (remove e ,l)) + e)) (defvar git-blame-dark-colors - (color-scale '("0c" "04" "24" "1c" "2c" "34" "14" "3c"))) + (git-blame-color-scale "0c" "04" "24" "1c" "2c" "34" "14" "3c") + "*List of colors (format #RGB) to use in a dark environment. + +To check out the list, evaluate (list-colors-display git-blame-dark-colors).") (defvar git-blame-light-colors - (color-scale '("c4" "d4" "cc" "dc" "f4" "e4" "fc" "ec"))) + (git-blame-color-scale "c4" "d4" "cc" "dc" "f4" "e4" "fc" "ec") + "*List of colors (format #RGB) to use in a light environment. + +To check out the list, evaluate (list-colors-display git-blame-light-colors).") -(defvar git-blame-ancient-color "dark green") +(defvar git-blame-colors '() + "Colors used by git-blame. The list is built once when activating git-blame +minor mode.") + +(defvar git-blame-ancient-color "dark green" + "*Color to be used for ancient commit.") (defvar git-blame-autoupdate t "*Automatically update the blame display while editing") @@ -125,41 +147,64 @@ "A queue of update requests") (make-variable-buffer-local 'git-blame-update-queue) +;; FIXME: docstrings +(defvar git-blame-file nil) +(defvar git-blame-current nil) + (defvar git-blame-mode nil) (make-variable-buffer-local 'git-blame-mode) -(unless (assq 'git-blame-mode minor-mode-alist) - (setq minor-mode-alist - (cons (list 'git-blame-mode " blame") - minor-mode-alist))) + +(defvar git-blame-mode-line-string " blame" + "String to display on the mode line when git-blame is active.") + +(or (assq 'git-blame-mode minor-mode-alist) + (setq minor-mode-alist + (cons '(git-blame-mode git-blame-mode-line-string) minor-mode-alist))) ;;;###autoload (defun git-blame-mode (&optional arg) - "Minor mode for displaying Git blame" + "Toggle minor mode for displaying Git blame + +With prefix ARG, turn the mode on if ARG is positive." (interactive "P") - (if arg - (setq git-blame-mode (eq arg 1)) - (setq git-blame-mode (not git-blame-mode))) + (cond + ((null arg) + (if git-blame-mode (git-blame-mode-off) (git-blame-mode-on))) + ((> (prefix-numeric-value arg) 0) (git-blame-mode-on)) + (t (git-blame-mode-off)))) + +(defun git-blame-mode-on () + "Turn on git-blame mode. + +See also function `git-blame-mode'." (make-local-variable 'git-blame-colors) (if git-blame-autoupdate (add-hook 'after-change-functions 'git-blame-after-change nil t) (remove-hook 'after-change-functions 'git-blame-after-change t)) (git-blame-cleanup) - (if git-blame-mode - (progn - (let ((bgmode (cdr (assoc 'background-mode (frame-parameters))))) - (if (eq bgmode 'dark) - (setq git-blame-colors git-blame-dark-colors) - (setq git-blame-colors git-blame-light-colors))) - (setq git-blame-cache (make-hash-table :test 'equal)) - (git-blame-run)) - (cancel-timer git-blame-idle-timer))) + (let ((bgmode (cdr (assoc 'background-mode (frame-parameters))))) + (if (eq bgmode 'dark) + (setq git-blame-colors git-blame-dark-colors) + (setq git-blame-colors git-blame-light-colors))) + (setq git-blame-cache (make-hash-table :test 'equal)) + (setq git-blame-mode t) + (git-blame-run)) + +(defun git-blame-mode-off () + "Turn off git-blame mode. + +See also function `git-blame-mode'." + (git-blame-cleanup) + (if git-blame-idle-timer (cancel-timer git-blame-idle-timer)) + (setq git-blame-mode nil)) ;;;###autoload (defun git-reblame () "Recalculate all blame information in the current buffer" - (unless git-blame-mode - (error "git-blame is not active")) (interactive) + (unless git-blame-mode + (error "Git-blame is not active")) + (git-blame-cleanup) (git-blame-run)) @@ -275,7 +320,6 @@ (t nil))) - (defun git-blame-new-commit (hash src-line res-line num-lines) (save-excursion (set-buffer git-blame-file) @@ -283,9 +327,11 @@ (inhibit-point-motion-hooks t) (inhibit-modification-hooks t)) (when (not info) - (let ((color (pop git-blame-colors))) - (unless color - (setq color git-blame-ancient-color)) + ;; Assign a random color to each new commit info + ;; Take care not to select the same color multiple times + (let ((color (if git-blame-colors + (git-blame-random-pop git-blame-colors) + git-blame-ancient-color))) (setq info (list hash src-line res-line num-lines (git-describe-commit hash) (cons 'color color)))) diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el index 5f22dec5f7..2f9995ea39 100644 --- a/contrib/emacs/git.el +++ b/contrib/emacs/git.el @@ -263,6 +263,16 @@ and returns the process output as a string." (locale-charset-to-coding-system repo-config)) 'utf-8))) +(defun git-get-logoutput-coding-system () + "Return the coding system used for git-log output." + (let ((repo-config (or (git-config "i18n.logoutputencoding") + (git-config "i18n.commitencoding")))) + (or git-commits-coding-system + (and repo-config + (fboundp 'locale-charset-to-coding-system) + (locale-charset-to-coding-system repo-config)) + 'utf-8))) + (defun git-escape-file-name (name) "Escape a file name if necessary." (if (string-match "[\n\t\"\\]" name) @@ -406,6 +416,14 @@ and returns the process output as a string." (push (match-string 0) heads)))) (nreverse heads))) +(defun git-get-commit-description (commit) + "Get a one-line description of COMMIT." + (let ((coding-system-for-read (git-get-logoutput-coding-system))) + (let ((descr (git-call-process-env-string nil "log" "--max-count=1" "--pretty=oneline" commit))) + (if (and descr (string-match "\\`\\([0-9a-f]\\{40\\}\\) *\\(.*\\)$" descr)) + (concat (substring (match-string 1 descr) 0 10) " - " (match-string 2 descr)) + descr)))) + ;;;; File info structure ;;;; ------------------------------------------------------------ @@ -573,7 +591,7 @@ and returns the process output as a string." "Refresh the ewoc header and footer." (let ((branch (git-symbolic-ref "HEAD")) (head (if (git-empty-db-p) "Nothing committed yet" - (substring (git-rev-parse "HEAD") 0 10))) + (git-get-commit-description "HEAD"))) (merge-heads (git-get-merge-heads))) (ewoc-set-hf status (format "Directory: %s\nBranch: %s\nHead: %s%s\n" @@ -584,7 +602,7 @@ and returns the process output as a string." head (if merge-heads (concat "\nMerging: " - (mapconcat (lambda (str) (substring str 0 10)) merge-heads " ")) + (mapconcat (lambda (str) (git-get-commit-description str)) merge-heads "\n ")) "")) (if (ewoc-nth status 0) "" " No changes.")))) diff --git a/contrib/hooks/post-receieve-email b/contrib/hooks/post-receieve-email new file mode 100644 index 0000000000..65160153ee --- /dev/null +++ b/contrib/hooks/post-receieve-email @@ -0,0 +1,588 @@ +#!/bin/sh +# +# Copyright (c) 2007 Andy Parkins +# +# An example hook script to mail out commit update information. This hook sends emails +# listing new revisions to the repository introduced by the change being reported. The +# rule is that (for branch updates) each commit will appear on one email and one email +# only. +# +# This hook is stored in the contrib/hooks directory. Your distribution will have put +# this somewhere standard. You should make this script executable then link to it in +# the repository you would like to use it in. For example, on debian the hook is stored +# in /usr/share/doc/git-core/contrib/hooks/post-receive-email: +# +# chmod a+x post-receive-email +# cd /path/to/your/repository.git +# ln -sf /usr/share/doc/git-core/contrib/hooks/post-receive-email hooks/post-receive +# +# This hook script assumes it is enabled on the central repository of a project, with +# all users pushing only to it and not between each other. It will still work if you +# don't operate in that style, but it would become possible for the email to be from +# someone other than the person doing the push. +# +# Config +# ------ +# hooks.mailinglist +# This is the list that all pushes will go to; leave it blank to not send +# emails for every ref update. +# hooks.announcelist +# This is the list that all pushes of annotated tags will go to. Leave it +# blank to default to the mailinglist field. The announce emails lists the +# short log summary of the changes since the last annotated tag. +# hook.envelopesender +# If set then the -f option is passed to sendmail to allow the envelope sender +# address to be set +# +# Notes +# ----- +# All emails have their subjects prefixed with "[SCM]" to aid filtering. +# All emails include the headers "X-Git-Refname", "X-Git-Oldrev", +# "X-Git-Newrev", and "X-Git-Reftype" to enable fine tuned filtering and +# give information for debugging. +# + +# ---------------------------- Functions + +# +# Top level email generation function. This decides what type of update +# this is and calls the appropriate body-generation routine after outputting +# the common header +# +# Note this function doesn't actually generate any email output, that is taken +# care of by the functions it calls: +# - generate_email_header +# - generate_create_XXXX_email +# - generate_update_XXXX_email +# - generate_delete_XXXX_email +# - generate_email_footer +# +generate_email() +{ + # --- Arguments + oldrev=$(git rev-parse $1) + newrev=$(git rev-parse $2) + refname="$3" + + # --- Interpret + # 0000->1234 (create) + # 1234->2345 (update) + # 2345->0000 (delete) + if expr "$oldrev" : '0*$' >/dev/null + then + change_type="create" + else + if expr "$newrev" : '0*$' >/dev/null + then + change_type="delete" + else + change_type="update" + fi + fi + + # --- Get the revision types + newrev_type=$(git cat-file -t $newrev 2> /dev/null) + oldrev_type=$(git cat-file -t "$oldrev" 2> /dev/null) + case "$change_type" in + create|update) + rev="$newrev" + rev_type="$newrev_type" + ;; + delete) + rev="$oldrev" + rev_type="$oldrev_type" + ;; + esac + + # The revision type tells us what type the commit is, combined with + # the location of the ref we can decide between + # - working branch + # - tracking branch + # - unannoted tag + # - annotated tag + case "$refname","$rev_type" in + refs/tags/*,commit) + # un-annotated tag + refname_type="tag" + short_refname=${refname##refs/tags/} + ;; + refs/tags/*,tag) + # annotated tag + refname_type="annotated tag" + short_refname=${refname##refs/tags/} + # change recipients + if [ -n "$announcerecipients" ]; then + recipients="$announcerecipients" + fi + ;; + refs/heads/*,commit) + # branch + refname_type="branch" + short_refname=${refname##refs/heads/} + ;; + refs/remotes/*,commit) + # tracking branch + refname_type="tracking branch" + short_refname=${refname##refs/remotes/} + echo >&2 "*** Push-update of tracking branch, $refname" + echo >&2 "*** - no email generated." + exit 0 + ;; + *) + # Anything else (is there anything else?) + echo >&2 "*** Unknown type of update to $refname ($rev_type)" + echo >&2 "*** - no email generated" + exit 1 + ;; + esac + + # Check if we've got anyone to send to + if [ -z "$recipients" ]; then + echo >&2 "*** hooks.recipients is not set so no email will be sent" + echo >&2 "*** for $refname update $oldrev->$newrev" + exit 0 + fi + + # Email parameters + # The committer will be obtained from the latest existing rev; so + # for a deletion it will be the oldrev, for the others, then newrev + committer=$(git show --pretty=full -s $rev | sed -ne "s/^Commit: //p" | + sed -ne 's/\(.*\) </"\1" </p') + # The email subject will contain the best description of the ref + # that we can build from the parameters + describe=$(git describe $rev 2>/dev/null) + if [ -z "$describe" ]; then + describe=$rev + fi + + generate_email_header + + # Call the correct body generation function + fn_name=general + case "$refname_type" in + "tracking branch"|branch) + fn_name=branch + ;; + "annotated tag") + fn_name=atag + ;; + esac + generate_${change_type}_${fn_name}_email + + generate_email_footer +} + +generate_email_header() +{ + # --- Email (all stdout will be the email) + # Generate header + cat <<-EOF + From: $committer + To: $recipients + Subject: ${EMAILPREFIX}$projectdesc $refname_type, $short_refname, ${change_type}d. $describe + X-Git-Refname: $refname + X-Git-Reftype: $refname_type + X-Git-Oldrev: $oldrev + X-Git-Newrev: $newrev + + This is an automated email from the git hooks/post-receive script. It was + generated because a ref change was pushed to the repository containing + the project "$projectdesc". + + The $refname_type, $short_refname has been ${change_type}d + EOF +} + +generate_email_footer() +{ + cat <<-EOF + + + hooks/post-receive + -- + $projectdesc + EOF +} + +# --------------- Branches + +# +# Called for the creation of a branch +# +generate_create_branch_email() +{ + # This is a new branch and so oldrev is not valid + echo " at $newrev ($newrev_type)" + echo "" + + echo $LOGBEGIN + # This shows all log entries that are not already covered by + # another ref - i.e. commits that are now accessible from this + # ref that were previously not accessible (see generate_update_branch_email + # for the explanation of this command) + git rev-parse --not --branches | grep -v $(git rev-parse $refname) | + git rev-list --pretty --stdin $newrev + echo $LOGEND +} + +# +# Called for the change of a pre-existing branch +# +generate_update_branch_email() +{ + # Consider this: + # 1 --- 2 --- O --- X --- 3 --- 4 --- N + # + # O is $oldrev for $refname + # N is $newrev for $refname + # X is a revision pointed to by some other ref, for which we may + # assume that an email has already been generated. + # In this case we want to issue an email containing only revisions + # 3, 4, and N. Given (almost) by + # + # git-rev-list N ^O --not --all + # + # The reason for the "almost", is that the "--not --all" will take + # precedence over the "N", and effectively will translate to + # + # git-rev-list N ^O ^X ^N + # + # So, we need to build up the list more carefully. git-rev-parse will + # generate a list of revs that may be fed into git-rev-list. We can get + # it to make the "--not --all" part and then filter out the "^N" with: + # + # git-rev-parse --not --all | grep -v N + # + # Then, using the --stdin switch to git-rev-list we have effectively + # manufactured + # + # git-rev-list N ^O ^X + # + # This leaves a problem when someone else updates the repository + # while this script is running. Their new value of the ref we're working + # on would be included in the "--not --all" output; and as our $newrev + # would be an ancestor of that commit, it would exclude all of our + # commits. What we really want is to exclude the current value of + # $refname from the --not list, rather than N itself. So: + # + # git-rev-parse --not --all | grep -v $(git-rev-parse $refname) + # + # Get's us to something pretty safe (apart from the small time between + # refname being read, and git-rev-parse running - for that, I give up) + # + # + # Next problem, consider this: + # * --- B --- * --- O ($oldrev) + # \ + # * --- X --- * --- N ($newrev) + # + # That is to say, there is no guarantee that oldrev is a strict subset of + # newrev (it would have required a --force, but that's allowed). So, we + # can't simply say rev-list $oldrev..$newrev. Instead we find the common + # base of the two revs and list from there. + # + # As above, we need to take into account the presence of X; if another + # branch is already in the repository and points at some of the revisions + # that we are about to output - we don't want them. The solution is as + # before: git-rev-parse output filtered. + # + # Finally, tags: + # 1 --- 2 --- O --- T --- 3 --- 4 --- N + # + # Tags pushed into the repository generate nice shortlog emails that + # summarise the commits between them and the previous tag. However, + # those emails don't include the full commit messages that we output + # for a branch update. Therefore we still want to output revisions + # that have been output on a tag email. + # + # Luckily, git-rev-parse includes just the tool. Instead of using "--all" + # we use "--branches"; this has the added benefit that "remotes/" will + # be ignored as well. + + # List all of the revisions that were removed by this update, in a fast forward + # update, this list will be empty, because rev-list O ^N is empty. For a non + # fast forward, O ^N is the list of removed revisions + fastforward="" + rev="" + for rev in $(git rev-list $newrev..$oldrev) + do + revtype=$(git cat-file -t "$rev") + echo " discards $rev ($revtype)" + done + if [ -z "$rev" ]; then + fast_forward=1 + fi + + # List all the revisions from baserev to newrev in a kind of + # "table-of-contents"; note this list can include revisions that have + # already had notification emails and is present to show the full detail + # of the change from rolling back the old revision to the base revision and + # then forward to the new revision + for rev in $(git rev-list $oldrev..$newrev) + do + revtype=$(git cat-file -t "$rev") + echo " via $rev ($revtype)" + done + + if [ -z "$fastforward" ]; then + echo " from $oldrev ($oldrev_type)" + else + echo "" + echo "This update added new revisions after undoing old revisions. That is to" + echo "say, the old revision is not a strict subset of the new revision. This" + echo "situation occurs when you --force push a change and generate a" + echo "repository containing something like this:" + echo "" + echo " * -- * -- B -- O -- O -- O ($oldrev)" + echo " \\" + echo " N -- N -- N ($newrev)" + echo "" + echo "When this happens we assume that you've already had alert emails for all" + echo "of the O revisions, and so we here report only the revisions in the N" + echo "branch from the common base, B." + fi + + echo "" + echo "Those revisions listed above that are new to this repository have" + echo "not appeared on any other notification email; so we list those" + echo "revisions in full, below." + + echo "" + echo $LOGBEGIN + git rev-parse --not --branches | grep -v $(git rev-parse $refname) | + git rev-list --pretty --stdin $oldrev..$newrev + + # XXX: Need a way of detecting whether git rev-list actually outputted + # anything, so that we can issue a "no new revisions added by this + # update" message + + echo $LOGEND + + # The diffstat is shown from the old revision to the new revision. This + # is to show the truth of what happened in this change. There's no point + # showing the stat from the base to the new revision because the base + # is effectively a random revision at this point - the user will be + # interested in what this revision changed - including the undoing of + # previous revisions in the case of non-fast forward updates. + echo "" + echo "Summary of changes:" + git diff-tree --stat --summary --find-copies-harder $oldrev..$newrev +} + +# +# Called for the deletion of a branch +# +generate_delete_branch_email() +{ + echo " was $oldrev" + echo "" + echo $LOGEND + git show -s --pretty=oneline $oldrev + echo $LOGEND +} + +# --------------- Annotated tags + +# +# Called for the creation of an annotated tag +# +generate_create_atag_email() +{ + echo " at $newrev ($newrev_type)" + + generate_atag_email +} + +# +# Called for the update of an annotated tag (this is probably a rare event +# and may not even be allowed) +# +generate_update_atag_email() +{ + echo " to $newrev ($newrev_type)" + echo " from $oldrev (which is now obsolete)" + + generate_atag_email +} + +# +# Called when an annotated tag is created or changed +# +generate_atag_email() +{ + # Use git-for-each-ref to pull out the individual fields from the tag + eval $(git for-each-ref --shell --format=' + tagobject=%(*objectname) + tagtype=%(*objecttype) + tagger=%(taggername) + tagged=%(taggerdate)' $refname + ) + + echo " tagging $tagobject ($tagtype)" + case "$tagtype" in + commit) + # If the tagged object is a commit, then we assume this is a + # release, and so we calculate which tag this tag is replacing + prevtag=$(git describe --abbrev=0 $newrev^ 2>/dev/null) + + if [ -n "$prevtag" ]; then + echo " replaces $prevtag" + fi + ;; + *) + echo " length $(git cat-file -s $tagobject) bytes" + ;; + esac + echo " tagged by $tagger" + echo " on $tagged" + + echo "" + echo $LOGBEGIN + + # Show the content of the tag message; this might contain a change log + # or release notes so is worth displaying. + git cat-file tag $newrev | sed -e '1,/^$/d' + + echo "" + case "$tagtype" in + commit) + # Only commit tags make sense to have rev-list operations performed + # on them + if [ -n "$prevtag" ]; then + # Show changes since the previous release + git rev-list --pretty=short "$prevtag..$newrev" | git shortlog + else + # No previous tag, show all the changes since time began + git rev-list --pretty=short $newrev | git shortlog + fi + ;; + *) + # XXX: Is there anything useful we can do for non-commit objects? + ;; + esac + + echo $LOGEND +} + +# +# Called for the deletion of an annotated tag +# +generate_delete_atag_email() +{ + echo " was $oldrev" + echo "" + echo $LOGEND + git show -s --pretty=oneline $oldrev + echo $LOGEND +} + +# --------------- General references + +# +# Called when any other type of reference is created (most likely a +# non-annotated tag) +# +generate_create_general_email() +{ + echo " at $newrev ($newrev_type)" + + generate_general_email +} + +# +# Called when any other type of reference is updated (most likely a +# non-annotated tag) +# +generate_update_general_email() +{ + echo " to $newrev ($newrev_type)" + echo " from $oldrev" + + generate_general_email +} + +# +# Called for creation or update of any other type of reference +# +generate_general_email() +{ + # Unannotated tags are more about marking a point than releasing a version; + # therefore we don't do the shortlog summary that we do for annotated tags + # above - we simply show that the point has been marked, and print the log + # message for the marked point for reference purposes + # + # Note this section also catches any other reference type (although there + # aren't any) and deals with them in the same way. + + echo "" + if [ "$newrev_type" = "commit" ]; then + echo $LOGBEGIN + git show --no-color --root -s $newrev + echo $LOGEND + else + # What can we do here? The tag marks an object that is not a commit, + # so there is no log for us to display. It's probably not wise to + # output git-cat-file as it could be a binary blob. We'll just say how + # big it is + echo "$newrev is a $newrev_type, and is $(git cat-file -s $newrev) bytes long." + fi +} + +# +# Called for the deletion of any other type of reference +# +generate_delete_general_email() +{ + echo " was $oldrev" + echo "" + echo $LOGEND + git show -s --pretty=oneline $oldrev + echo $LOGEND +} + +# ---------------------------- main() + +# --- Constants +EMAILPREFIX="[SCM] " +LOGBEGIN="- Log -----------------------------------------------------------------" +LOGEND="-----------------------------------------------------------------------" + +# --- Config +# Set GIT_DIR either from the working directory, or from the environment +# variable. +GIT_DIR=$(git rev-parse --git-dir 2>/dev/null) +if [ -z "$GIT_DIR" ]; then + echo >&2 "fatal: post-receive: GIT_DIR not set" + exit 1 +fi + +projectdesc=$(sed -e '1p' "$GIT_DIR/description") +# Check if the description is unchanged from it's default, and shorten it to a +# more manageable length if it is +if expr "$projectdesc" : "Unnamed repository.*$" >/dev/null +then + projectdesc="UNNAMED PROJECT" +fi + +recipients=$(git repo-config hooks.mailinglist) +announcerecipients=$(git repo-config hooks.announcelist) +envelopesender=$(git-repo-config hooks.envelopesender) + +# --- Main loop +# Allow dual mode: run from the command line just like the update hook, or if +# no arguments are given then run as a hook script +if [ -n "$1" -a -n "$2" -a -n "$3" ]; then + # Output to the terminal in command line mode - if someone wanted to + # resend an email; they could redirect the output to sendmail themselves + PAGER= generate_email $2 $3 $1 +else + if [ -n "$envelopesender" ]; then + envelopesender="-f '$envelopesender'" + fi + + while read oldrev newrev refname + do + generate_email $oldrev $newrev $refname | + /usr/sbin/sendmail -t $envelopesender + done +fi diff --git a/contrib/workdir/git-new-workdir b/contrib/workdir/git-new-workdir new file mode 100755 index 0000000000..9877b98508 --- /dev/null +++ b/contrib/workdir/git-new-workdir @@ -0,0 +1,57 @@ +#!/bin/sh + +usage () { + echo "usage:" $@ + exit 127 +} + +die () { + echo $@ + exit 128 +} + +if test $# -lt 2 || test $# -gt 3 +then + usage "$0 <repository> <new_workdir> [<branch>]" +fi + +orig_git=$1 +new_workdir=$2 +branch=$3 + +# want to make sure that what is pointed to has a .git directory ... +test -d "$orig_git/.git" || die "\"$orig_git\" is not a git repository!" + +# don't link to a workdir +if test -L "$orig_git/.git/config" +then + die "\"$orig_git\" is a working directory only, please specify" \ + "a complete repository." +fi + +# make sure the the links use full paths +orig_git=$(cd "$orig_git"; pwd) + +# create the workdir +mkdir -p "$new_workdir/.git" || die "unable to create \"$new_workdir\"!" + +# create the links to the original repo. explictly exclude index, HEAD and +# logs/HEAD from the list since they are purely related to the current working +# directory, and should not be shared. +for x in config refs logs/refs objects info hooks packed-refs remotes rr-cache +do + case $x in + */*) + mkdir -p "$(dirname "$new_workdir/.git/$x")" + ;; + esac + ln -s "$orig_git/.git/$x" "$new_workdir/.git/$x" +done + +# now setup the workdir +cd "$new_workdir" +# copy the HEAD from the original repository as a default branch +cp "$orig_git/.git/HEAD" .git/HEAD +# checkout the branch (either the same as HEAD from the original repository, or +# the one that was asked for) +git checkout -f $branch @@ -8,6 +8,11 @@ #include "cache.h" #include "dir.h" +struct path_simplify { + int len; + const char *path; +}; + int common_prefix(const char **pathspec) { const char *path, *slash, *next; @@ -293,6 +298,31 @@ static int dir_exists(const char *dirname, int len) } /* + * This is an inexact early pruning of any recursive directory + * reading - if the path cannot possibly be in the pathspec, + * return true, and we'll skip it early. + */ +static int simplify_away(const char *path, int pathlen, const struct path_simplify *simplify) +{ + if (simplify) { + for (;;) { + const char *match = simplify->path; + int len = simplify->len; + + if (!match) + break; + if (len > pathlen) + len = pathlen; + if (!memcmp(path, match, len)) + return 0; + simplify++; + } + return 1; + } + return 0; +} + +/* * Read a directory tree. We currently ignore anything but * directories, regular files and symlinks. That's because git * doesn't handle them at all yet. Maybe that will change some @@ -301,7 +331,7 @@ static int dir_exists(const char *dirname, int len) * Also, we ignore the name ".git" (even if it is not a directory). * That likely will not change. */ -static int read_directory_recursive(struct dir_struct *dir, const char *path, const char *base, int baselen, int check_only) +static int read_directory_recursive(struct dir_struct *dir, const char *path, const char *base, int baselen, int check_only, const struct path_simplify *simplify) { DIR *fdir = opendir(path); int contents = 0; @@ -324,6 +354,8 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co continue; len = strlen(de->d_name); memcpy(fullname + baselen, de->d_name, len+1); + if (simplify_away(fullname, baselen + len, simplify)) + continue; if (excluded(dir, fullname) != dir->show_ignored) { if (!dir->show_ignored || DTYPE(de) != DT_DIR) { continue; @@ -350,13 +382,13 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co if (dir->hide_empty_directories && !read_directory_recursive(dir, fullname, fullname, - baselen + len, 1)) + baselen + len, 1, simplify)) continue; break; } contents += read_directory_recursive(dir, - fullname, fullname, baselen + len, 0); + fullname, fullname, baselen + len, 0, simplify); continue; case DT_REG: case DT_LNK: @@ -386,8 +418,61 @@ static int cmp_name(const void *p1, const void *p2) e2->name, e2->len); } -int read_directory(struct dir_struct *dir, const char *path, const char *base, int baselen) +/* + * Return the length of the "simple" part of a path match limiter. + */ +static int simple_length(const char *match) { + const char special[256] = { + [0] = 1, ['?'] = 1, + ['\\'] = 1, ['*'] = 1, + ['['] = 1 + }; + int len = -1; + + for (;;) { + unsigned char c = *match++; + len++; + if (special[c]) + return len; + } +} + +static struct path_simplify *create_simplify(const char **pathspec) +{ + int nr, alloc = 0; + struct path_simplify *simplify = NULL; + + if (!pathspec) + return NULL; + + for (nr = 0 ; ; nr++) { + const char *match; + if (nr >= alloc) { + alloc = alloc_nr(alloc); + simplify = xrealloc(simplify, alloc * sizeof(*simplify)); + } + match = *pathspec++; + if (!match) + break; + simplify[nr].path = match; + simplify[nr].len = simple_length(match); + } + simplify[nr].path = NULL; + simplify[nr].len = 0; + return simplify; +} + +static void free_simplify(struct path_simplify *simplify) +{ + if (simplify) + free(simplify); +} + +int read_directory(struct dir_struct *dir, const char *path, const char *base, int baselen, const char **pathspec) +{ + struct path_simplify *simplify = create_simplify(pathspec); + /* * Make sure to do the per-directory exclude for all the * directories leading up to our base. @@ -414,7 +499,8 @@ int read_directory(struct dir_struct *dir, const char *path, const char *base, i } } - read_directory_recursive(dir, path, base, baselen, 0); + read_directory_recursive(dir, path, base, baselen, 0, simplify); + free_simplify(simplify); qsort(dir->entries, dir->nr, sizeof(struct dir_entry *), cmp_name); return dir->nr; } @@ -48,7 +48,7 @@ extern int common_prefix(const char **pathspec); #define MATCHED_EXACTLY 3 extern int match_pathspec(const char **pathspec, const char *name, int namelen, int prefix, char *seen); -extern int read_directory(struct dir_struct *, const char *path, const char *base, int baselen); +extern int read_directory(struct dir_struct *, const char *path, const char *base, int baselen, const char **pathspec); extern int push_exclude_per_directory(struct dir_struct *, const char *, int); extern void pop_exclude_per_directory(struct dir_struct *, int); diff --git a/fast-import.c b/fast-import.c index 55ffae4fa6..cdd629d6bc 100644 --- a/fast-import.c +++ b/fast-import.c @@ -630,7 +630,7 @@ static void start_packfile(void) int pack_fd; snprintf(tmpfile, sizeof(tmpfile), - "%s/pack_XXXXXX", get_object_directory()); + "%s/tmp_pack_XXXXXX", get_object_directory()); pack_fd = mkstemp(tmpfile); if (pack_fd < 0) die("Can't create %s: %s", tmpfile, strerror(errno)); @@ -730,7 +730,7 @@ static char *create_index(void) } snprintf(tmpfile, sizeof(tmpfile), - "%s/index_XXXXXX", get_object_directory()); + "%s/tmp_idx_XXXXXX", get_object_directory()); idx_fd = mkstemp(tmpfile); if (idx_fd < 0) die("Can't create %s: %s", tmpfile, strerror(errno)); @@ -1312,7 +1312,7 @@ static int update_branch(struct branch *b) if (!in_merge_bases(old_cmit, &new_cmit, 1)) { unlock_ref(lock); - warn("Not updating %s" + warning("Not updating %s" " (new tip %s does not contain %s)", b->name, sha1_to_hex(b->sha1), sha1_to_hex(old_sha1)); return -1; @@ -408,12 +408,10 @@ do # trust what the user has in the index file and the # working tree. resolved= - changed="$(git-diff-index --cached --name-only HEAD)" - if test '' = "$changed" - then + git-diff-index --quiet --cached HEAD && { echo "No changes - did you forget to use 'git add'?" stop_here_user_resolve $this - fi + } unmerged=$(git-ls-files -u) if test -n "$unmerged" then @@ -435,13 +433,11 @@ do then # Applying the patch to an earlier tree and merging the # result may have produced the same tree as ours. - changed="$(git-diff-index --cached --name-only HEAD)" - if test '' = "$changed" - then - echo No changes -- Patch already applied. - go_next - continue - fi + git-diff-index --quiet --cached HEAD && { + echo No changes -- Patch already applied. + go_next + continue + } # clear apply_status -- we have successfully merged. apply_status=0 fi diff --git a/git-bisect.sh b/git-bisect.sh index 936b4a4b83..11313a7949 100755 --- a/git-bisect.sh +++ b/git-bisect.sh @@ -123,7 +123,15 @@ bisect_next_check() { case "$next_ok,$1" in no,) false ;; no,fail) - echo >&2 'You need to give me at least one good and one bad revisions.' + THEN='' + test -d "$GIT_DIR/refs/bisect" || { + echo >&2 'You need to start by "git bisect start".' + THEN='then ' + } + echo >&2 'You '$THEN'need to give me at least one good' \ + 'and one bad revisions.' + echo >&2 '(You can use "git bisect bad" and' \ + '"git bisect good" for that.)' exit 1 ;; *) true ;; @@ -173,7 +181,7 @@ bisect_reset() { else branch=master fi ;; - 1) test -f "$GIT_DIR/refs/heads/$1" || { + 1) git-show-ref --verify --quiet -- "refs/heads/$1" || { echo >&2 "$1 does not seem to be a valid branch" exit 1 } @@ -223,6 +231,8 @@ bisect_replay () { } bisect_run () { + bisect_next_check fail + while true do echo "running $@" diff --git a/git-clone.sh b/git-clone.sh index 6ba477d1f4..513b574d13 100755 --- a/git-clone.sh +++ b/git-clone.sh @@ -60,7 +60,7 @@ Perhaps git-update-server-info needs to be run there?" else tname=$name fi - git-http-fetch $v -a -w "$tname" "$name" "$1/" || exit 1 + git-http-fetch $v -a -w "$tname" "$name" "$1" || exit 1 done <"$clone_tmp/refs" rm -fr "$clone_tmp" http_fetch "$1/HEAD" "$GIT_DIR/REMOTE_HEAD" || diff --git a/git-commit.sh b/git-commit.sh index 3656d607d5..292cf967e3 100755 --- a/git-commit.sh +++ b/git-commit.sh @@ -371,7 +371,7 @@ t,) if test -z "$initial_commit" then cp "$THIS_INDEX" "$TMP_INDEX" - GIT_INDEX_FILE="$TMP_INDEX" git-read-tree -m HEAD + GIT_INDEX_FILE="$TMP_INDEX" git-read-tree -i -m HEAD else rm -f "$TMP_INDEX" fi || exit diff --git a/git-compat-util.h b/git-compat-util.h index 7534db1267..139fc19108 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -87,7 +87,7 @@ extern void usage(const char *err) NORETURN; extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2))); extern int error(const char *err, ...) __attribute__((format (printf, 1, 2))); -extern void warn(const char *err, ...) __attribute__((format (printf, 1, 2))); +extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2))); extern void set_usage_routine(void (*routine)(const char *err) NORETURN); extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN); diff --git a/git-fetch.sh b/git-fetch.sh index 93349330d4..fd70696b74 100755 --- a/git-fetch.sh +++ b/git-fetch.sh @@ -248,7 +248,7 @@ fetch_per_ref () { expr "z$head" : "z$_x40\$" >/dev/null || die "No such ref $remote_name at $remote" echo >&2 "Fetching $remote_name from $remote using $proto" - git-http-fetch -v -a "$head" "$remote/" || exit + git-http-fetch -v -a "$head" "$remote" || exit ;; rsync://*) test -n "$shallow_depth" && diff --git a/git-merge-ours.sh b/git-merge-ours.sh index 4f3d053889..2b6a5c0d10 100755 --- a/git-merge-ours.sh +++ b/git-merge-ours.sh @@ -9,6 +9,6 @@ # because the current index is what we will be committing as the # merge result. -test "$(git-diff-index --cached --name-status HEAD)" = "" || exit 2 +git-diff-index --quiet --cached HEAD || exit 2 exit 0 diff --git a/git-mergetool.sh b/git-mergetool.sh index 7942fd0b64..e62351bcba 100755 --- a/git-mergetool.sh +++ b/git-mergetool.sh @@ -14,19 +14,19 @@ SUBDIRECTORY_OK=Yes require_work_tree # Returns true if the mode reflects a symlink -function is_symlink () { +is_symlink () { test "$1" = 120000 } -function local_present () { +local_present () { test -n "$local_mode" } -function remote_present () { +remote_present () { test -n "$remote_mode" } -function base_present () { +base_present () { test -n "$base_mode" } @@ -39,32 +39,29 @@ cleanup_temp_files () { fi } -function describe_file () { +describe_file () { mode="$1" branch="$2" file="$3" - echo -n " " + printf " {%s}: " "$branch" if test -z "$mode"; then - echo -n "'$path' was deleted" + echo "deleted" elif is_symlink "$mode" ; then - echo -n "'$path' is a symlink containing '" - cat "$file" - echo -n "'" + echo "a symbolic link -> '$(cat "$file")'" else if base_present; then - echo -n "'$path' was created" + echo "modified" else - echo -n "'$path' was modified" + echo "created" fi fi - echo " in the $branch branch" } resolve_symlink_merge () { - while /bin/true; do - echo -n "Use (r)emote or (l)ocal, or (a)bort? " + while true; do + printf "Use (l)ocal or (r)emote, or (a)bort? " read ans case "$ans" in [lL]*) @@ -73,13 +70,13 @@ resolve_symlink_merge () { cleanup_temp_files --save-backup return ;; - [rR]*) + [rR]*) git-checkout-index -f --stage=3 -- "$path" git-add -- "$path" cleanup_temp_files --save-backup return ;; - [qQ]*) + [aA]*) exit 1 ;; esac @@ -87,38 +84,69 @@ resolve_symlink_merge () { } resolve_deleted_merge () { - while /bin/true; do - echo -n "Use (m)odified or (d)eleted file, or (a)bort? " + while true; do + if base_present; then + printf "Use (m)odified or (d)eleted file, or (a)bort? " + else + printf "Use (c)reated or (d)eleted file, or (a)bort? " + fi read ans case "$ans" in - [mM]*) + [mMcC]*) git-add -- "$path" cleanup_temp_files --save-backup return ;; - [dD]*) - git-rm -- "$path" + [dD]*) + git-rm -- "$path" > /dev/null cleanup_temp_files return ;; - [qQ]*) + [aA]*) exit 1 ;; esac done } -merge_file () { - path="$1" +check_unchanged () { + if test "$path" -nt "$BACKUP" ; then + status=0; + else + while true; do + echo "$path seems unchanged." + printf "Was the merge successful? [y/n] " + read answer < /dev/tty + case "$answer" in + y*|Y*) status=0; break ;; + n*|N*) status=1; break ;; + esac + done + fi +} - if test ! -f "$path" ; then - echo "$path: file not found" - exit 1 +save_backup () { + if test "$status" -eq 0; then + mv -- "$BACKUP" "$path.orig" + fi +} + +remove_backup () { + if test "$status" -eq 0; then + rm "$BACKUP" fi +} + +merge_file () { + path="$1" f=`git-ls-files -u -- "$path"` if test -z "$f" ; then - echo "$path: file does not need merging" + if test ! -f "$path" ; then + echo "$path: file not found" + else + echo "$path: file does not need merging" + fi exit 1 fi @@ -139,7 +167,7 @@ merge_file () { remote_present && git cat-file blob ":3:$path" > "$REMOTE" 2>/dev/null if test -z "$local_mode" -o -z "$remote_mode"; then - echo "Deleted merge conflict for $path:" + echo "Deleted merge conflict for '$path':" describe_file "$local_mode" "local" "$LOCAL" describe_file "$remote_mode" "remote" "$REMOTE" resolve_deleted_merge @@ -147,17 +175,17 @@ merge_file () { fi if is_symlink "$local_mode" || is_symlink "$remote_mode"; then - echo "Symlink merge conflict for $path:" + echo "Symbolic link merge conflict for '$path':" describe_file "$local_mode" "local" "$LOCAL" describe_file "$remote_mode" "remote" "$REMOTE" resolve_symlink_merge return fi - echo "Normal merge conflict for $path:" + echo "Normal merge conflict for '$path':" describe_file "$local_mode" "local" "$LOCAL" describe_file "$remote_mode" "remote" "$REMOTE" - echo -n "Hit return to start merge resolution tool ($merge_tool): " + printf "Hit return to start merge resolution tool (%s): " "$merge_tool" read ans case "$merge_tool" in @@ -170,9 +198,7 @@ merge_file () { -o "$path" -- "$LOCAL" "$REMOTE" > /dev/null 2>&1) fi status=$? - if test "$status" -eq 0; then - rm "$BACKUP" - fi + remove_backup ;; tkdiff) if base_present ; then @@ -181,29 +207,13 @@ merge_file () { tkdiff -o "$path" -- "$LOCAL" "$REMOTE" fi status=$? - if test "$status" -eq 0; then - mv -- "$BACKUP" "$path.orig" - fi + save_backup ;; meld|vimdiff) touch "$BACKUP" $merge_tool -- "$LOCAL" "$path" "$REMOTE" - if test "$path" -nt "$BACKUP" ; then - status=0; - else - while true; do - echo "$path seems unchanged." - echo -n "Was the merge successful? [y/n] " - read answer < /dev/tty - case "$answer" in - y*|Y*) status=0; break ;; - n*|N*) status=1; break ;; - esac - done - fi - if test "$status" -eq 0; then - mv -- "$BACKUP" "$path.orig" - fi + check_unchanged + save_backup ;; xxdiff) touch "$BACKUP" @@ -220,22 +230,18 @@ merge_file () { -R 'Accel.SearchForward: "Ctrl-G"' \ --merged-file "$path" -- "$LOCAL" "$REMOTE" fi - if test "$path" -nt "$BACKUP" ; then - status=0; + check_unchanged + save_backup + ;; + opendiff) + touch "$BACKUP" + if base_present; then + opendiff "$LOCAL" "$REMOTE" -ancestor "$BASE" -merge "$path" | cat else - while true; do - echo "$path seems unchanged." - echo -n "Was the merge successful? [y/n] " - read answer < /dev/tty - case "$answer" in - y*|Y*) status=0; break ;; - n*|N*) status=1; break ;; - esac - done - fi - if test "$status" -eq 0; then - mv -- "$BACKUP" "$path.orig" + opendiff "$LOCAL" "$REMOTE" -merge "$path" | cat fi + check_unchanged + save_backup ;; emerge) if base_present ; then @@ -244,9 +250,7 @@ merge_file () { emacs -f emerge-files-command "$LOCAL" "$REMOTE" "$path" fi status=$? - if test "$status" -eq 0; then - mv -- "$BACKUP" "$path.orig" - fi + save_backup ;; esac if test "$status" -ne 0; then @@ -289,7 +293,7 @@ done if test -z "$merge_tool"; then merge_tool=`git-config merge.tool` case "$merge_tool" in - kdiff3 | tkdiff | xxdiff | meld | emerge | vimdiff) + kdiff3 | tkdiff | xxdiff | meld | opendiff | emerge | vimdiff | "") ;; # happy *) echo >&2 "git config option merge.tool set to unknown tool: $merge_tool" @@ -308,6 +312,8 @@ if test -z "$merge_tool" ; then merge_tool=xxdiff elif type meld >/dev/null 2>&1 && test -n "$DISPLAY"; then merge_tool=meld + elif type opendiff >/dev/null 2>&1; then + merge_tool=opendiff elif type emacs >/dev/null 2>&1; then merge_tool=emerge elif type vimdiff >/dev/null 2>&1; then @@ -319,7 +325,7 @@ if test -z "$merge_tool" ; then fi case "$merge_tool" in - kdiff3|tkdiff|meld|xxdiff|vimdiff) + kdiff3|tkdiff|meld|xxdiff|vimdiff|opendiff) if ! type "$merge_tool" > /dev/null 2>&1; then echo "The merge tool $merge_tool is not available" exit 1 @@ -346,12 +352,12 @@ if test $# -eq 0 ; then echo Merging the files: $files git ls-files -u | sed -e 's/^[^ ]* //' | sort -u | while read i do - echo "" + printf "\n" merge_file "$i" < /dev/tty > /dev/tty done else while test $# -gt 0; do - echo "" + printf "\n" merge_file "$1" shift done diff --git a/git-quiltimport.sh b/git-quiltimport.sh index 08ac9bb729..edccd82755 100755 --- a/git-quiltimport.sh +++ b/git-quiltimport.sh @@ -115,7 +115,7 @@ for patch_name in $(cat "$QUILT_PATCHES/series" | grep -v '^#'); do if [ -z "$dry_run" ] ; then git-apply --index -C1 "$tmp_patch" && tree=$(git-write-tree) && - commit=$((echo "$SUBJECT"; echo; cat "$tmp_msg") | git-commit-tree $tree -p $commit) && + commit=$( (echo "$SUBJECT"; echo; cat "$tmp_msg") | git-commit-tree $tree -p $commit) && git-update-ref -m "quiltimport: $patch_name" HEAD $commit || exit 4 fi done diff --git a/git-rebase.sh b/git-rebase.sh index aadd580f8d..1d96f32685 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -59,7 +59,7 @@ continue_merge () { die "$RESOLVEMSG" fi - if test -n "`git-diff-index HEAD`" + if ! git-diff-index --quiet HEAD then if ! git-commit -C "`cat $dotest/current`" then @@ -124,13 +124,11 @@ while case "$#" in 0) break ;; esac do case "$1" in --continue) - diff=$(git-diff-files) - case "$diff" in - ?*) echo "You must edit all merge conflicts and then" + git-diff-files --quiet || { + echo "You must edit all merge conflicts and then" echo "mark them as resolved using git update-index" exit 1 - ;; - esac + } if test -d "$dotest" then prev_head="`cat $dotest/prev_head`" diff --git a/git-remote.perl b/git-remote.perl index bd70bf1ddd..52013fe76d 100755 --- a/git-remote.perl +++ b/git-remote.perl @@ -15,6 +15,10 @@ sub add_remote_config { $hash->{$name}{'FETCH'} ||= []; push @{$hash->{$name}{'FETCH'}}, $value; } + elsif ($what eq 'push') { + $hash->{$name}{'PUSH'} ||= []; + push @{$hash->{$name}{'PUSH'}}, $value; + } if (!exists $hash->{$name}{'SOURCE'}) { $hash->{$name}{'SOURCE'} = 'config'; } @@ -44,7 +48,8 @@ sub add_remote_remotes { } } elsif (/^Push:\s*(.*)$/) { - ; # later + $it->{'PUSH'} ||= []; + push @{$it->{'PUSH'}}, $1; } elsif (/^Pull:\s*(.*)$/) { $it->{'FETCH'} ||= []; @@ -250,6 +255,15 @@ sub show_remote { if ($info->{'LS_REMOTE'}) { show_mapping($name, $info); } + if ($info->{'PUSH'}) { + my @pushed = map { + s|^refs/heads/||; + s|:refs/heads/|:|; + $_; + } @{$info->{'PUSH'}}; + print " Local branch(es) pushed with 'git push'\n"; + print " @pushed\n"; + } } sub add_remote { diff --git a/git-svn.perl b/git-svn.perl index e8457893db..d307d430f3 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -435,6 +435,9 @@ sub cmd_rebase { } my $gs = Git::SVN->find_by_url($url); + unless ($gs) { + die "Unable to determine remote information from URL: $url\n"; + } if (command(qw/diff-index HEAD --/)) { print STDERR "Cannot rebase with uncommited changes:\n"; command_noisy('status'); @@ -1327,8 +1330,10 @@ sub rel_path { my ($self) = @_; my $repos_root = $self->ra->{repos_root}; return $self->{path} if ($self->{url} eq $repos_root); - die "BUG: rel_path failed! repos_root: $repos_root, Ra URL: ", - $self->ra->{url}, " path: $self->{path}, URL: $self->{url}\n"; + my $url = $self->{url} . + (length $self->{path} ? "/$self->{path}" : $self->{path}); + $url =~ s!^\Q$repos_root\E(?:/+|$)!!g; + $url; } sub traverse_ignore { @@ -2838,8 +2843,7 @@ package Git::SVN::Ra; use vars qw/@ISA $config_dir $_log_window_size/; use strict; use warnings; -my ($can_do_switch); -my $RA; +my ($can_do_switch, %ignored_err, $RA); BEGIN { # enforce temporary pool usage for some simple functions @@ -3211,9 +3215,16 @@ sub skip_unknown_revs { # 175007 - http(s):// (this repo required authorization, too...) # More codes may be discovered later... if ($errno == 175007 || $errno == 175002 || $errno == 160013) { - warn "W: Ignoring error from SVN, path probably ", - "does not exist: ($errno): ", - $err->expanded_message,"\n"; + my $err_key = $err->expanded_message; + # revision numbers change every time, filter them out + $err_key =~ s/\d+/\0/g; + $err_key = "$errno\0$err_key"; + unless ($ignored_err{$err_key}) { + warn "W: Ignoring error from SVN, path probably ", + "does not exist: ($errno): ", + $err->expanded_message,"\n"; + $ignored_err{$err_key} = 1; + } return; } die "Error from SVN, ($errno): ", $err->expanded_message,"\n"; @@ -99,7 +99,7 @@ static int split_cmdline(char *cmdline, const char ***argv) int src, dst, count = 0, size = 16; char quoted = 0; - *argv = malloc(sizeof(char*) * size); + *argv = xmalloc(sizeof(char*) * size); /* split alias_string */ (*argv)[count++] = cmdline; diff --git a/git.spec.in b/git.spec.in index 46aee88fd1..1d3934bba5 100644 --- a/git.spec.in +++ b/git.spec.in @@ -1,4 +1,7 @@ # Pass --without docs to rpmbuild if you don't want the documentation + +%define python_path /usr/bin/python + Name: git Version: @@VERSION@@ Release: 1%{?dist} @@ -50,6 +53,13 @@ Requires: git-core = %{version}-%{release}, tla %description arch Git tools for importing Arch repositories. +%package p4 +Summary: Git tools for importing Perforce repositories +Group: Development/Tools +Requires: git-core = %{version}-%{release}, python +%description p4 +Git tools for importing Perforce repositories. + %package email Summary: Git tools for sending email Group: Development/Tools @@ -85,23 +95,23 @@ Perl interface to Git %setup -q %build -make %{_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" WITH_OWN_SUBPROCESS_PY=YesPlease \ - prefix=%{_prefix} all %{!?_without_docs: doc} +make %{_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" WITH_P4IMPORT=YesPlease \ + prefix=%{_prefix} PYTHON_PATH=%{python_path} all %{!?_without_docs: doc} %install rm -rf $RPM_BUILD_ROOT make %{_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" DESTDIR=$RPM_BUILD_ROOT \ - WITH_OWN_SUBPROCESS_PY=YesPlease \ - prefix=%{_prefix} mandir=%{_mandir} INSTALLDIRS=vendor \ - install %{!?_without_docs: install-doc} + WITH_P4IMPORT=YesPlease prefix=%{_prefix} mandir=%{_mandir} \ + PYTHON_PATH=%{python_path} \ + INSTALLDIRS=vendor install %{!?_without_docs: install-doc} find $RPM_BUILD_ROOT -type f -name .packlist -exec rm -f {} ';' find $RPM_BUILD_ROOT -type f -name '*.bs' -empty -exec rm -f {} ';' find $RPM_BUILD_ROOT -type f -name perllocal.pod -exec rm -f {} ';' -(find $RPM_BUILD_ROOT%{_bindir} -type f | grep -vE "archimport|svn|cvs|email|gitk|git-gui|git-citool" | sed -e s@^$RPM_BUILD_ROOT@@) > bin-man-doc-files +(find $RPM_BUILD_ROOT%{_bindir} -type f | grep -vE "p4import|archimport|svn|cvs|email|gitk|git-gui|git-citool" | sed -e s@^$RPM_BUILD_ROOT@@) > bin-man-doc-files (find $RPM_BUILD_ROOT%{perl_vendorlib} -type f | sed -e s@^$RPM_BUILD_ROOT@@) >> perl-files %if %{!?_without_docs:1}0 -(find $RPM_BUILD_ROOT%{_mandir} $RPM_BUILD_ROOT/Documentation -type f | grep -vE "archimport|svn|git-cvs|email|gitk|git-gui|git-citool" | sed -e s@^$RPM_BUILD_ROOT@@ -e 's/$/*/' ) >> bin-man-doc-files +(find $RPM_BUILD_ROOT%{_mandir} $RPM_BUILD_ROOT/Documentation -type f | grep -vE "p4import|archimport|svn|git-cvs|email|gitk|git-gui|git-citool" | sed -e s@^$RPM_BUILD_ROOT@@ -e 's/$/*/' ) >> bin-man-doc-files %else rm -rf $RPM_BUILD_ROOT%{_mandir} %endif @@ -133,6 +143,13 @@ rm -rf $RPM_BUILD_ROOT %{!?_without_docs: %{_mandir}/man1/git-archimport.1*} %{!?_without_docs: %doc Documentation/git-archimport.html } +%files p4 +%defattr(-,root,root) +%doc Documentation/git-p4import.txt +%{_bindir}/git-p4import +%{!?_without_docs: %{_mandir}/man1/git-p4import.1*} +%{!?_without_docs: %doc Documentation/git-p4import.html } + %files email %defattr(-,root,root) %doc Documentation/*email*.txt @@ -167,6 +184,9 @@ rm -rf $RPM_BUILD_ROOT %{!?_without_docs: %doc Documentation/*.html } %changelog +* Tue Mar 27 2007 Eygene Ryabinkin <rea-git@codelabs.ru> +- Added the git-p4 package: Perforce import stuff. + * Mon Feb 13 2007 Nicolas Pitre <nico@cam.org> - Update core package description (Git isn't as stupid as it used to be) diff --git a/gitweb/INSTALL b/gitweb/INSTALL new file mode 100644 index 0000000000..6328e26f56 --- /dev/null +++ b/gitweb/INSTALL @@ -0,0 +1,225 @@ +GIT web Interface (gitweb) Installation +======================================= + +First you have to generate gitweb.cgi from gitweb.perl using +"make gitweb/gitweb.cgi", then copy appropriate files (gitweb.cgi, +gitweb.css, git-logo.png and git-favicon.png) to their destination. +For example if git was (or is) installed with /usr prefix, you can do + + $ make prefix=/usr gitweb/gitweb.cgi ;# as yourself + # cp gitweb/git* /var/www/cgi-bin/ ;# as root + +Alternatively you can use autoconf generated ./configure script to +set up path to git binaries (via config.mak.autogen), so you can write +instead + + $ make configure ;# as yourself + $ ./configure --prefix=/usr ;# as yourself + $ make gitweb/gitweb.cgi ;# as yourself + # cp gitweb/git* /var/www/cgi-bin/ ;# as root + +The above example assumes that your web server is configured to run +[executable] files in /var/www/cgi-bin/ as server scripts (as CGI +scripts). + + +Build time configuration +------------------------ + +See also "How to configure gitweb for your local system" in README +file for gitweb (in gitweb/README). + +- There are many configuration variables which affects building of + gitweb.cgi; see "default configuration for gitweb" section in main + (top dir) Makefile, and instructions for building gitweb/gitweb.cgi + target. + + One of most important is where to find git wrapper binary. Gitweb + tries to find git wrapper at $(bindir)/git, so you have to set $bindir + when building gitweb.cgi, or $prefix from which $bindir is derived. If + you build and install gitweb together with the rest of git suite, + there should be no problems. Otherwise, if git was for example + installed from a binary package, you have to set $prefix (or $bindir) + accordingly. + +- Another important issue is where are git repositories you want to make + available to gitweb. By default gitweb search for repositories under + /pub/git; if you want to have projects somewhere else, like /home/git, + use GITWEB_PROJECTROOT build configuration variable. + + By default all git repositories under projectroot are visible and + available to gitweb. List of projects is generated by default by + scanning the projectroot directory for git repositories. This can be + changed (configured) as described in "Gitweb repositories" section + below. + + Note that gitweb deals directly with object database, and does not + need working directory; the name of the project is the name of its + repository object database, usually projectname.git for bare + repositories. If you want to provide gitweb access to non-bare (live) + repository, you can make projectname.git symbolic link under + projectroot linking to projectname/.git (but it is just + a suggestion). + +- You can control where gitweb tries to find its main CSS style file, + its favicon and logo with GITWEB_CSS, GITWEB_FAVICON and GITWEB_LOGO + build configuration variables. By default gitweb tries to find them + in the same directory as gitweb.cgi script. + +Build example +~~~~~~~~~~~~~ + +- To install gitweb to /var/www/cgi-bin/gitweb/ when git wrapper + is installed at /usr/local/bin/git and the repositories (projects) + we want to display are under /home/local/scm, you can do + + make GITWEB_PROJECTROOT="/home/local/scm" \ + GITWEB_CSS="/gitweb/gitweb.css" \ + GITWEB_LOGO="/gitweb/git-logo.png" \ + GITWEB_FAVICON="/gitweb/git-favicon.png" \ + bindir=/usr/local/bin \ + gitweb/gitweb.cgi + + cp -fv ~/git/gitweb/gitweb.{cgi,css} \ + ~/git/gitweb/git-{favicon,logo}.png \ + /var/www/cgi-bin/gitweb/ + + +Gitweb config file +------------------ + +See also "Runtime gitweb configuration" section in README file +for gitweb (in gitweb/README). + +- You can configure gitweb further using gitweb configuration file; + by default it is file named gitweb_config.perl in the same place as + gitweb.cgi script. You can control default place for config file + using GITWEB_CONFIG build configuration variable, and you can set it + using GITWEB_CONFIG environmental variable. + +- Gitweb config file is [fragment] of perl code. You can set variables + using "our $variable = value"; text from "#" character until the end + of a line is ignored. See perlsyn(1) for details. + + See the top of gitweb.perl file for examples of customizable options. + +Config file example +~~~~~~~~~~~~~~~~~~~ + +To enable blame, pickaxe search, and snapshot support, while allowing +individual projects to turn them off, put the following in your +GITWEB_CONFIG file: + + $feature{'blame'}{'default'} = [1]; + $feature{'blame'}{'override'} = 1; + + $feature{'pickaxe'}{'default'} = [1]; + $feature{'pickaxe'}{'override'} = 1; + + $feature{'snapshot'}{'default'} = ['x-gzip', 'gz', 'gzip']; + $feature{'snapshot'}{'override'} = 1; + + +Gitweb repositories +------------------- + +- By default all git repositories under projectroot are visible and + available to gitweb. List of projects is generated by default by + scanning the projectroot directory for git repositories (for object + databases to be more exact). + + You can provide pre-generated list of [visible] repositories, + together with information about their owners (the project ownership + is taken from owner of repository directory otherwise), by setting + GITWEB_LIST build configuration variable (or $projects_list variable + in gitweb config file) to point to a plain file. + + Each line of projects list file should consist of url-encoded path + to project repository database (relative to projectroot) separated + by space from url-encoded project owner; spaces in both project path + and project owner have to be encoded as either '%20' or '+'. + + You can generate projects list index file using project_index action + (the 'TXT' link on projects list page) directly from gitweb. + +- By default even if project is not visible on projects list page, you + can view it nevertheless by hand-crafting gitweb URL. You can set + GITWEB_STRICT_EXPORT build configuration variable (or $strict_export + variable in gitweb config file) to only allow viewing of + repositories also shown on the overview page. + +- Alternatively, you can configure gitweb to only list and allow + viewing of the explicitly exported repositories, via + GITWEB_EXPORT_OK build configuration variable (or $export_ok + variable in gitweb config file). If it evaluates to true, gitweb + show repository only if this file exists in its object database + (if directory has the magic file $export_ok). + +Generating projects list using gitweb +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +We assume that GITWEB_CONFIG has its default Makefile value, namely +gitweb_config.perl. Put the following in gitweb_make_index.perl file: + + $GITWEB_CONFIG = "gitweb_config.perl"; + do $GITWEB_CONFIG if -e $GITWEB_CONFIG; + + $projects_list = $projectroot; + +Then create the following script to get list of project in the format +suitable for GITWEB_LIST build configuration variable (or +$projects_list variable in gitweb config): + + #!/bin/sh + + export GITWEB_CONFIG="gitweb_make_index.perl" + export GATEWAY_INTERFACE="CGI/1.1" + export HTTP_ACCEPT="*/*" + export REQUEST_METHOD="GET" + export QUERY_STRING="a=project_index" + + perl -- /var/www/cgi-bin/gitweb.cgi + + +Requirements +------------ + + - Core git tools + - Perl + - Perl modules: CGI, Encode, Fcntl, File::Find, File::Basename. + - web server + + +Example web server configuration +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +See also "Webserver configuration" section in README file for gitweb +(in gitweb/README). + + +- Apache2, gitweb installed as CGI script, + under /var/www/cgi-bin/ + + ScriptAlias /cgi-bin/ "/var/www/cgi-bin/" + + <Directory "/var/www/cgi-bin"> + Options Indexes FollowSymlinks ExecCGI + AllowOverride None + Order allow,deny + Allow from all + </Directory> + +- Apache2, gitweb installed as mod_perl legacy script, + under /var/www/perl/ + + Alias /perl "/var/www/perl" + + <Directory "/var/www/perl"> + SetHandler perl-script + PerlResponseHandler ModPerl::Registry + PerlOptions +ParseHeaders + Options Indexes FollowSymlinks +ExecCGI + AllowOverride None + Order allow,deny + Allow from all + </Directory> diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css index 7177c6e86b..5e40292404 100644 --- a/gitweb/gitweb.css +++ b/gitweb/gitweb.css @@ -107,7 +107,7 @@ span.age { font-style: italic; } -div.page_body span.signoff { +span.signoff { color: #888888; } diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 5214050a88..3786955fca 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3154,7 +3154,7 @@ sub git_blame2 { } $ftype = git_get_type($hash); if ($ftype !~ "blob") { - die_error("400 Bad Request", "Object is not a blob"); + die_error('400 Bad Request', "Object is not a blob"); } open ($fd, "-|", git_cmd(), "blame", '-p', '--', $file_name, $hash_base) @@ -3220,7 +3220,7 @@ HTML print "</td>\n"; } open (my $dd, "-|", git_cmd(), "rev-parse", "$full_rev^") - or die_error("could not open git-rev-parse"); + or die_error(undef, "Open git-rev-parse failed"); my $parent_commit = <$dd>; close $dd; chomp($parent_commit); @@ -3622,7 +3622,7 @@ sub git_snapshot { $name =~ s/\047/\047\\\047\047/g; open my $fd, "-|", "$git archive --format=tar --prefix=\'$name\'/ $hash | $command" - or die_error(undef, "Execute git-tar-tree failed."); + or die_error(undef, "Execute git-tar-tree failed"); binmode STDOUT, ':raw'; print <$fd>; binmode STDOUT, ':utf8'; # as set at the beginning of gitweb.cgi @@ -3885,7 +3885,7 @@ sub git_blobdiff { # read raw output open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts, $hash_parent_base, $hash_base, - "--", $file_name + "--", (defined $file_parent ? $file_parent : ()), $file_name or die_error(undef, "Open git-diff-tree failed"); @difftree = map { chomp; $_ } <$fd>; close $fd @@ -3935,7 +3935,7 @@ sub git_blobdiff { # open patch output open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts, '-p', $hash_parent_base, $hash_base, - "--", $file_name + "--", (defined $file_parent ? $file_parent : ()), $file_name or die_error(undef, "Open git-diff-tree failed"); } @@ -31,12 +31,6 @@ static int term_columns(void) return 80; } -static void oom(void) -{ - fprintf(stderr, "git: out of memory\n"); - exit(1); -} - static inline void mput_char(char c, unsigned int num) { while(num--) @@ -54,13 +48,9 @@ static void add_cmdname(const char *name, int len) struct cmdname *ent; if (cmdname_alloc <= cmdname_cnt) { cmdname_alloc = cmdname_alloc + 200; - cmdname = realloc(cmdname, cmdname_alloc * sizeof(*cmdname)); - if (!cmdname) - oom(); + cmdname = xrealloc(cmdname, cmdname_alloc * sizeof(*cmdname)); } - ent = malloc(sizeof(*ent) + len); - if (!ent) - oom(); + ent = xmalloc(sizeof(*ent) + len); ent->len = len; memcpy(ent->name, name, len); ent->name[len] = 0; diff --git a/http-fetch.c b/http-fetch.c index e6cd11db73..557b40322f 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -16,8 +16,7 @@ static struct curl_slist *no_pragma_header; struct alt_base { - const char *base; - int path_len; + char *base; int got_indices; struct packed_git *packs; struct alt_base *next; @@ -158,12 +157,12 @@ static void start_object_request(struct object_request *obj_req) SHA1_Init(&obj_req->c); - url = xmalloc(strlen(obj_req->repo->base) + 50); - obj_req->url = xmalloc(strlen(obj_req->repo->base) + 50); + url = xmalloc(strlen(obj_req->repo->base) + 51); + obj_req->url = xmalloc(strlen(obj_req->repo->base) + 51); strcpy(url, obj_req->repo->base); posn = url + strlen(obj_req->repo->base); - strcpy(posn, "objects/"); - posn += 8; + strcpy(posn, "/objects/"); + posn += 9; memcpy(posn, hex, 2); posn += 2; *(posn++) = '/'; @@ -515,7 +514,6 @@ static void process_alternates_response(void *callback_data) int serverlen = 0; struct alt_base *newalt; char *target = NULL; - char *path; if (data[i] == '/') { /* This counts * http://git.host/pub/scm/linux.git/ @@ -583,12 +581,6 @@ static void process_alternates_response(void *callback_data) newalt->base = target; newalt->got_indices = 0; newalt->packs = NULL; - path = strstr(target, "//"); - if (path) { - path = strchr(path+2, '/'); - if (path) - newalt->path_len = strlen(path); - } while (tail->next != NULL) tail = tail->next; @@ -938,14 +930,14 @@ static char *quote_ref_url(const char *base, const char *ref) int len, baselen, ch; baselen = strlen(base); - len = baselen + 6; /* "refs/" + NUL */ + len = baselen + 7; /* "/refs/" + NUL */ for (cp = ref; (ch = *cp) != 0; cp++, len++) if (needs_quote(ch)) len += 2; /* extra two hex plus replacement % */ qref = xmalloc(len); memcpy(qref, base, baselen); - memcpy(qref + baselen, "refs/", 5); - for (cp = ref, dp = qref + baselen + 5; (ch = *cp) != 0; cp++) { + memcpy(qref + baselen, "/refs/", 6); + for (cp = ref, dp = qref + baselen + 6; (ch = *cp) != 0; cp++) { if (needs_quote(ch)) { *dp++ = '%'; *dp++ = hex((ch >> 4) & 0xF); @@ -999,7 +991,7 @@ int main(int argc, const char **argv) const char **write_ref = NULL; char **commit_id; const char *url; - char *path; + char *s; int arg = 1; int rc = 0; @@ -1044,16 +1036,13 @@ int main(int argc, const char **argv) no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:"); alt = xmalloc(sizeof(*alt)); - alt->base = url; + alt->base = xmalloc(strlen(url) + 1); + strcpy(alt->base, url); + for (s = alt->base + strlen(alt->base) - 1; *s == '/'; --s) + *s = 0; alt->got_indices = 0; alt->packs = NULL; alt->next = NULL; - path = strstr(url, "//"); - if (path) { - path = strchr(path+2, '/'); - if (path) - alt->path_len = strlen(path); - } if (pull(commits, commit_id, write_ref, url)) rc = 1; diff --git a/index-pack.c b/index-pack.c index 61eb20e45b..3c768fbc63 100644 --- a/index-pack.c +++ b/index-pack.c @@ -139,7 +139,7 @@ static const char *open_pack_file(const char *pack_name) if (!pack_name) { static char tmpfile[PATH_MAX]; snprintf(tmpfile, sizeof(tmpfile), - "%s/pack_XXXXXX", get_object_directory()); + "%s/tmp_pack_XXXXXX", get_object_directory()); output_fd = mkstemp(tmpfile); pack_name = xstrdup(tmpfile); } else @@ -358,6 +358,7 @@ static void sha1_object(const void *data, unsigned long size, if (size != has_size || type != has_type || memcmp(data, has_data, size) != 0) die("SHA1 COLLISION FOUND WITH %s !", sha1_to_hex(sha1)); + free(has_data); } } @@ -690,7 +691,7 @@ static const char *write_index_file(const char *index_name, unsigned char *sha1) if (!index_name) { static char tmpfile[PATH_MAX]; snprintf(tmpfile, sizeof(tmpfile), - "%s/index_XXXXXX", get_object_directory()); + "%s/tmp_idx_XXXXXX", get_object_directory()); fd = mkstemp(tmpfile); index_name = xstrdup(tmpfile); } else { diff --git a/merge-recursive.c b/merge-recursive.c index c96e1a734c..e1aebd7727 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -278,8 +278,16 @@ static struct tree *git_write_tree(void) { struct tree *result = NULL; - if (unmerged_index()) + if (unmerged_index()) { + int i; + output(0, "There are unmerged index entries:"); + for (i = 0; i < active_nr; i++) { + struct cache_entry *ce = active_cache[i]; + if (ce_stage(ce)) + output(0, "%d %.*s", ce_stage(ce), ce_namelen(ce), ce->name); + } return NULL; + } if (!active_cache_tree) active_cache_tree = cache_tree(); @@ -735,8 +743,19 @@ static void conflict_rename_rename(struct rename *ren1, ren2_dst, branch1, dst_name2); remove_file(0, ren2_dst, 0); } - update_stages(dst_name1, NULL, ren1->pair->two, NULL, 1); - update_stages(dst_name2, NULL, NULL, ren2->pair->two, 1); + if (index_only) { + remove_file_from_cache(dst_name1); + remove_file_from_cache(dst_name2); + /* + * Uncomment to leave the conflicting names in the resulting tree + * + * update_file(0, ren1->pair->two->sha1, ren1->pair->two->mode, dst_name1); + * update_file(0, ren2->pair->two->sha1, ren2->pair->two->mode, dst_name2); + */ + } else { + update_stages(dst_name1, NULL, ren1->pair->two, NULL, 1); + update_stages(dst_name2, NULL, NULL, ren2->pair->two, 1); + } while (delp--) free(del[delp]); } @@ -852,10 +871,16 @@ static int process_renames(struct path_list *a_renames, if (strcmp(ren1_dst, ren2_dst) != 0) { clean_merge = 0; output(1, "CONFLICT (rename/rename): " - "Rename %s->%s in branch %s " - "rename %s->%s in %s", + "Rename \"%s\"->\"%s\" in branch \"%s\" " + "rename \"%s\"->\"%s\" in \"%s\"%s", src, ren1_dst, branch1, - src, ren2_dst, branch2); + src, ren2_dst, branch2, + index_only ? " (left unresolved)": ""); + if (index_only) { + remove_file_from_cache(src); + update_file(0, ren1->pair->one->sha1, + ren1->pair->one->mode, src); + } conflict_rename_rename(ren1, branch1, ren2, branch2); } else { struct merge_file_info mfi; diff --git a/revision.c b/revision.c index adc381c268..486393cb08 100644 --- a/revision.c +++ b/revision.c @@ -360,6 +360,7 @@ static void add_parents_to_list(struct rev_info *revs, struct commit *commit, st { struct commit_list *parent = commit->parents; unsigned left_flag; + int add, rest; if (commit->object.flags & ADDED) return; @@ -405,18 +406,19 @@ static void add_parents_to_list(struct rev_info *revs, struct commit *commit, st return; left_flag = (commit->object.flags & SYMMETRIC_LEFT); - parent = commit->parents; - while (parent) { + + rest = !revs->first_parent_only; + for (parent = commit->parents, add = 1; parent; add = rest) { struct commit *p = parent->item; parent = parent->next; - parse_commit(p); p->object.flags |= left_flag; if (p->object.flags & SEEN) continue; p->object.flags |= SEEN; - insert_by_date(p, list); + if (add) + insert_by_date(p, list); } } @@ -484,7 +486,7 @@ static void handle_one_reflog_commit(unsigned char *sha1, void *cb_data) add_pending_object(cb->all_revs, o, ""); } else if (!cb->warned_bad_reflog) { - warn("reflog of '%s' references pruned commits", + warning("reflog of '%s' references pruned commits", cb->name_for_errormsg); cb->warned_bad_reflog = 1; } @@ -847,6 +849,10 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch handle_all(revs, flags); continue; } + if (!strcmp(arg, "--first-parent")) { + revs->first_parent_only = 1; + continue; + } if (!strcmp(arg, "--reflog")) { handle_reflog(revs, flags); continue; diff --git a/revision.h b/revision.h index 6ae39e6bec..55e6b531ce 100644 --- a/revision.h +++ b/revision.h @@ -46,7 +46,8 @@ struct rev_info { boundary:2, left_right:1, parents:1, - reverse:1; + reverse:1, + first_parent_only:1; /* Diff flags */ unsigned int diff:1, diff --git a/sha1_file.c b/sha1_file.c index 940bab5612..9c26038420 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -1979,7 +1979,7 @@ int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned cha return error("sha1 file %s: %s\n", filename, strerror(errno)); } - snprintf(tmpfile, sizeof(tmpfile), "%s/obj_XXXXXX", get_object_directory()); + snprintf(tmpfile, sizeof(tmpfile), "%s/tmp_obj_XXXXXX", get_object_directory()); fd = mkstemp(tmpfile); if (fd < 0) { @@ -2020,7 +2020,8 @@ int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned cha if (write_buffer(fd, compressed, size) < 0) die("unable to write sha1 file"); fchmod(fd, 0444); - close(fd); + if (close(fd)) + die("unable to write sha1 file"); free(compressed); return move_temp_to_file(tmpfile, filename); @@ -2105,7 +2106,7 @@ int write_sha1_from_fd(const unsigned char *sha1, int fd, char *buffer, int ret; SHA_CTX c; - snprintf(tmpfile, sizeof(tmpfile), "%s/obj_XXXXXX", get_object_directory()); + snprintf(tmpfile, sizeof(tmpfile), "%s/tmp_obj_XXXXXX", get_object_directory()); local = mkstemp(tmpfile); if (local < 0) { @@ -2154,7 +2155,9 @@ int write_sha1_from_fd(const unsigned char *sha1, int fd, char *buffer, } while (1); inflateEnd(&stream); - close(local); + fchmod(local, 0444); + if (close(local) != 0) + die("unable to write sha1 file"); SHA1_Final(real_sha1, &c); if (ret != Z_STREAM_END) { unlink(tmpfile); diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh index e081b32aff..8b611bbea2 100755 --- a/t/t4200-rerere.sh +++ b/t/t4200-rerere.sh @@ -34,7 +34,8 @@ EOF git commit -q -a -m first git checkout -b second master -git show first:a1 | sed 's/To die, t/To die! T/' > a1 +git show first:a1 | +sed -e 's/To die, t/To die! T/' -e 's/life;$/life./' > a1 git commit -q -a -m second # activate rerere @@ -42,19 +43,26 @@ mkdir .git/rr-cache test_expect_failure 'conflicting merge' 'git pull . first' -sha1=4f58849a60b4f969a2848966b6d02893b783e8fb +sha1=$(sed -e 's/\t.*//' .git/rr-cache/MERGE_RR) rr=.git/rr-cache/$sha1 test_expect_success 'recorded preimage' "grep ======= $rr/preimage" test_expect_success 'no postimage or thisimage yet' \ "test ! -f $rr/postimage -a ! -f $rr/thisimage" +test_expect_success 'preimage have right number of lines' ' + + cnt=$(sed -ne "/^<<<<<<</,/^>>>>>>>/p" $rr/preimage | wc -l) && + test "$cnt" = 10 + +' + git show first:a1 > a1 cat > expect << EOF --- a/a1 +++ b/a1 -@@ -6,11 +6,7 @@ +@@ -6,17 +6,9 @@ The heart-ache and the thousand natural shocks That flesh is heir to, 'tis a consummation Devoutly to be wish'd. @@ -66,8 +74,13 @@ cat > expect << EOF To sleep: perchance to dream: ay, there's the rub; For in that sleep of death what dreams may come When we have shuffled off this mortal coil, + Must give us pause: there's the respect +-<<<<<<< +-That makes calamity of so long life. +-======= + That makes calamity of so long life; +->>>>>>> EOF - git rerere diff > out test_expect_success 'rerere diff' 'git diff expect out' diff --git a/t/t5100/patch0005 b/t/t5100/patch0005 index e7d6f66608..7d24b24af8 100644 --- a/t/t5100/patch0005 +++ b/t/t5100/patch0005 @@ -61,7 +61,7 @@ diff --git a/git-cvsimport-script b/git-cvsimport-script push(@old,$fn); -- -David KÃ¥gedal +David Kågedal - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@vger.kernel.org diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh new file mode 100755 index 0000000000..aab17face8 --- /dev/null +++ b/t/t6006-rev-list-format.sh @@ -0,0 +1,150 @@ +#!/bin/sh + +test_description='git-rev-list --pretty=format test' + +. ./test-lib.sh + +test_tick +test_expect_success 'setup' ' +touch foo && git-add foo && git-commit -m "added foo" && + echo changed >foo && git-commit -a -m "changed foo" +' + +# usage: test_format name format_string <expected_output +test_format() { + cat >expect.$1 + test_expect_success "format $1" " +git-rev-list --pretty=format:$2 master >output.$1 && +git-diff expect.$1 output.$1 +" +} + +test_format hash %H%n%h <<'EOF' +commit 131a310eb913d107dd3c09a65d1651175898735d +131a310eb913d107dd3c09a65d1651175898735d +131a310 +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +86c75cf +EOF + +test_format tree %T%n%t <<'EOF' +commit 131a310eb913d107dd3c09a65d1651175898735d +fe722612f26da5064c32ca3843aa154bdb0b08a0 +fe72261 +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +4d5fcadc293a348e88f777dc0920f11e7d71441c +4d5fcad +EOF + +test_format parents %P%n%p <<'EOF' +commit 131a310eb913d107dd3c09a65d1651175898735d +86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +86c75cf +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 + + +EOF + +# we don't test relative here +test_format author %an%n%ae%n%ad%n%aD%n%at <<'EOF' +commit 131a310eb913d107dd3c09a65d1651175898735d +A U Thor +author@example.com +Thu Apr 7 15:13:13 2005 -0700 +Thu, 7 Apr 2005 15:13:13 -0700 +1112911993 +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +A U Thor +author@example.com +Thu Apr 7 15:13:13 2005 -0700 +Thu, 7 Apr 2005 15:13:13 -0700 +1112911993 +EOF + +test_format committer %cn%n%ce%n%cd%n%cD%n%ct <<'EOF' +commit 131a310eb913d107dd3c09a65d1651175898735d +C O Mitter +committer@example.com +Thu Apr 7 15:13:13 2005 -0700 +Thu, 7 Apr 2005 15:13:13 -0700 +1112911993 +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +C O Mitter +committer@example.com +Thu Apr 7 15:13:13 2005 -0700 +Thu, 7 Apr 2005 15:13:13 -0700 +1112911993 +EOF + +test_format encoding %e <<'EOF' +commit 131a310eb913d107dd3c09a65d1651175898735d +<unknown> +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +<unknown> +EOF + +test_format subject %s <<'EOF' +commit 131a310eb913d107dd3c09a65d1651175898735d +changed foo +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +added foo +EOF + +test_format body %b <<'EOF' +commit 131a310eb913d107dd3c09a65d1651175898735d +<unknown> +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +<unknown> +EOF + +test_format colors %Credfoo%Cgreenbar%Cbluebaz%Cresetxyzzy <<'EOF' +commit 131a310eb913d107dd3c09a65d1651175898735d +[31mfoo[32mbar[34mbaz[mxyzzy +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +[31mfoo[32mbar[34mbaz[mxyzzy +EOF + +cat >commit-msg <<'EOF' +Test printing of complex bodies + +This commit message is much longer than the others, +and it will be encoded in iso8859-1. We should therefore +include an iso8859 character: ¡bueno! +EOF +test_expect_success 'setup complex body' ' +git-config i18n.commitencoding iso8859-1 && + echo change2 >foo && git-commit -a -F commit-msg +' + +test_format complex-encoding %e <<'EOF' +commit f58db70b055c5718631e5c61528b28b12090cdea +iso8859-1 +commit 131a310eb913d107dd3c09a65d1651175898735d +<unknown> +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +<unknown> +EOF + +test_format complex-subject %s <<'EOF' +commit f58db70b055c5718631e5c61528b28b12090cdea +Test printing of complex bodies +commit 131a310eb913d107dd3c09a65d1651175898735d +changed foo +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +added foo +EOF + +test_format complex-body %b <<'EOF' +commit f58db70b055c5718631e5c61528b28b12090cdea +This commit message is much longer than the others, +and it will be encoded in iso8859-1. We should therefore +include an iso8859 character: ¡bueno! + +commit 131a310eb913d107dd3c09a65d1651175898735d +<unknown> +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +<unknown> +EOF + +test_done diff --git a/templates/hooks--post-receive b/templates/hooks--post-receive new file mode 100644 index 0000000000..190de2688c --- /dev/null +++ b/templates/hooks--post-receive @@ -0,0 +1,17 @@ +#!/bin/sh +# +# An example hook script for the post-receive event +# +# This script is run after receive-pack has accepted a pack and the +# repository has been updated. It is passed arguments in through stdin +# in the form +# <oldrev> <newrev> <refname> +# For example: +# aa453216d1b3e49e7f6f98441fa56946ddcd6a20 68f7abf4e6f922807889f52bc043ecd31b79f814 refs/heads/master +# +# see contrib/hooks/ for an sample, or uncomment the next line (on debian) +# + + +#. /usr/share/doc/git-core/contrib/hooks/post-receive-email + diff --git a/templates/hooks--update b/templates/hooks--update index 1a60773890..0ff03309e6 100644 --- a/templates/hooks--update +++ b/templates/hooks--update @@ -1,36 +1,16 @@ #!/bin/sh # -# An example hook script to mail out commit update information. -# It can also blocks tags that aren't annotated. +# An example hook script to blocks unannotated tags from entering. # Called by git-receive-pack with arguments: refname sha1-old sha1-new # # To enable this hook, make this file executable by "chmod +x update". # # Config # ------ -# hooks.mailinglist -# This is the list that all pushes will go to; leave it blank to not send -# emails frequently. The log email will list every log entry in full between -# the old ref value and the new ref value. -# hooks.announcelist -# This is the list that all pushes of annotated tags will go to. Leave it -# blank to just use the mailinglist field. The announce emails list the -# short log summary of the changes since the last annotated tag # hooks.allowunannotated # This boolean sets whether unannotated tags will be allowed into the # repository. By default they won't be. # -# Notes -# ----- -# All emails have their subjects prefixed with "[SCM]" to aid filtering. -# All emails include the headers "X-Git-Refname", "X-Git-Oldrev", -# "X-Git-Newrev", and "X-Git-Reftype" to enable fine tuned filtering and info. - -# --- Constants -EMAILPREFIX="[SCM] " -LOGBEGIN="- Log -----------------------------------------------------------------" -LOGEND="-----------------------------------------------------------------------" -DATEFORMAT="%F %R %z" # --- Command line refname="$1" @@ -51,9 +31,6 @@ if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then fi # --- Config -projectdesc=$(cat $GIT_DIR/description) -recipients=$(git-repo-config hooks.mailinglist) -announcerecipients=$(git-repo-config hooks.announcelist) allowunannotated=$(git-repo-config --bool hooks.allowunannotated) # check for no description @@ -68,224 +45,28 @@ newrev_type=$(git-cat-file -t $newrev) case "$refname","$newrev_type" in refs/tags/*,commit) # un-annotated tag - refname_type="tag" short_refname=${refname##refs/tags/} if [ "$allowunannotated" != "true" ]; then - echo "*** The un-annotated tag, $short_refname is not allowed in this repository" >&2 + echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2 echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 exit 1 fi ;; refs/tags/*,tag) # annotated tag - refname_type="annotated tag" - short_refname=${refname##refs/tags/} - # change recipients - if [ -n "$announcerecipients" ]; then - recipients="$announcerecipients" - fi ;; refs/heads/*,commit) # branch - refname_type="branch" - short_refname=${refname##refs/heads/} ;; refs/remotes/*,commit) # tracking branch - refname_type="tracking branch" - short_refname=${refname##refs/remotes/} - # Should this even be allowed? - echo "*** Push-update of tracking branch, $refname. No email generated." >&2 - exit 0 ;; *) # Anything else (is there anything else?) - echo "*** Update hook: unknown type of update, \"$newrev_type\", to ref $refname" >&2 + echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 exit 1 ;; esac -# Check if we've got anyone to send to -if [ -z "$recipients" ]; then - # If the email isn't sent, then at least give the user some idea of what command - # would generate the email at a later date - echo "*** No recipients found - no email will be sent, but the push will continue" >&2 - echo "*** for $0 $1 $2 $3" >&2 - exit 0 -fi - -# --- Email parameters -committer=$(git show --pretty=full -s $newrev | grep "^Commit: " | sed -e "s/^Commit: //") -describe=$(git describe $newrev 2>/dev/null) -if [ -z "$describe" ]; then - describe=$newrev -fi - -# --- Email (all stdout will be the email) -( -# Generate header -cat <<-EOF -From: $committer -To: $recipients -Subject: ${EMAILPREFIX}$projectdesc $refname_type, $short_refname now at $describe -X-Git-Refname: $refname -X-Git-Reftype: $refname_type -X-Git-Oldrev: $oldrev -X-Git-Newrev: $newrev - -Hello, - -This is an automated email from the git hooks/update script, it was -generated because a ref change was pushed to the repository. - -Updating $refname_type, $short_refname, -EOF - -case "$refname_type" in - "tracking branch"|branch) - if expr "$oldrev" : '0*$' >/dev/null - then - # If the old reference is "0000..0000" then this is a new branch - # and so oldrev is not valid - echo " as a new $refname_type" - echo " to $newrev ($newrev_type)" - echo "" - echo $LOGBEGIN - # This shows all log entries that are not already covered by - # another ref - i.e. commits that are now accessible from this - # ref that were previously not accessible - git log $newrev --not --all - echo $LOGEND - else - # oldrev is valid - oldrev_type=$(git-cat-file -t "$oldrev") - - # Now the problem is for cases like this: - # * --- * --- * --- * (oldrev) - # \ - # * --- * --- * (newrev) - # i.e. there is no guarantee that newrev is a strict subset - # of oldrev - (would have required a force, but that's allowed). - # So, we can't simply say rev-list $oldrev..$newrev. Instead - # we find the common base of the two revs and list from there - baserev=$(git-merge-base $oldrev $newrev) - - # Commit with a parent - for rev in $(git-rev-list $newrev --not $baserev --all) - do - revtype=$(git-cat-file -t "$rev") - echo " via $rev ($revtype)" - done - if [ "$baserev" = "$oldrev" ]; then - echo " from $oldrev ($oldrev_type)" - else - echo " based on $baserev" - echo " from $oldrev ($oldrev_type)" - echo "" - echo "This ref update crossed a branch point; i.e. the old rev is not a strict subset" - echo "of the new rev. This occurs, when you --force push a change in a situation" - echo "like this:" - echo "" - echo " * -- * -- B -- O -- O -- O ($oldrev)" - echo " \\" - echo " N -- N -- N ($newrev)" - echo "" - echo "Therefore, we assume that you've already had alert emails for all of the O" - echo "revisions, and now give you all the revisions in the N branch from the common" - echo "base, B ($baserev), up to the new revision." - fi - echo "" - echo $LOGBEGIN - git log $newrev --not $baserev --all - echo $LOGEND - echo "" - echo "Diffstat:" - git-diff-tree --no-color --stat -M -C --find-copies-harder $baserev..$newrev - fi - ;; - "annotated tag") - # Should we allow changes to annotated tags? - if expr "$oldrev" : '0*$' >/dev/null - then - # If the old reference is "0000..0000" then this is a new atag - # and so oldrev is not valid - echo " to $newrev ($newrev_type)" - else - echo " to $newrev ($newrev_type)" - echo " from $oldrev" - fi - - # If this tag succeeds another, then show which tag it replaces - prevtag=$(git describe --abbrev=0 $newrev^ 2>/dev/null) - if [ -n "$prevtag" ]; then - echo " replaces $prevtag" - fi - - # Read the tag details - eval $(git cat-file tag $newrev | \ - sed -n '4s/tagger \([^>]*>\)[^0-9]*\([0-9]*\).*/tagger="\1" ts="\2"/p') - tagged=$(date --date="1970-01-01 00:00:00 +0000 $ts seconds" +"$DATEFORMAT") - - echo " tagged by $tagger" - echo " on $tagged" - - echo "" - echo $LOGBEGIN - echo "" - - if [ -n "$prevtag" ]; then - git rev-list --pretty=short "$prevtag..$newrev" | git shortlog - else - git rev-list --pretty=short $newrev | git shortlog - fi - - echo $LOGEND - echo "" - ;; - *) - # By default, unannotated tags aren't allowed in; if - # they are though, it's debatable whether we would even want an - # email to be generated; however, I don't want to add another config - # option just for that. - # - # Unannotated tags are more about marking a point than releasing - # a version; therefore we don't do the shortlog summary that we - # do for annotated tags above - we simply show that the point has - # been marked, and print the log message for the marked point for - # reference purposes - # - # Note this section also catches any other reference type (although - # there aren't any) and deals with them in the same way. - if expr "$oldrev" : '0*$' >/dev/null - then - # If the old reference is "0000..0000" then this is a new tag - # and so oldrev is not valid - echo " as a new $refname_type" - echo " to $newrev ($newrev_type)" - else - echo " to $newrev ($newrev_type)" - echo " from $oldrev" - fi - echo "" - echo $LOGBEGIN - git-show --no-color --root -s $newrev - echo $LOGEND - echo "" - ;; -esac - -# Footer -cat <<-EOF - -hooks/update ---- -Git Source Code Management System -$0 $1 \\ - $2 \\ - $3 -EOF -#) | cat >&2 -) | /usr/sbin/sendmail -t - # --- Finished exit 0 diff --git a/upload-pack.c b/upload-pack.c index 498bf50eb8..d3a09e78d5 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -119,6 +119,7 @@ static void create_pack_file(void) int i; struct rev_info revs; + close(lp_pipe[0]); pack_pipe = fdopen(lp_pipe[1], "w"); if (create_full_pack) @@ -86,7 +86,7 @@ int error(const char *err, ...) return -1; } -void warn(const char *warn, ...) +void warning(const char *warn, ...) { va_list params; diff --git a/wt-status.c b/wt-status.c index a25632bc87..a0559905a0 100644 --- a/wt-status.c +++ b/wt-status.c @@ -260,7 +260,7 @@ static void wt_status_print_untracked(struct wt_status *s) if (file_exists(x)) add_excludes_from_file(&dir, x); - read_directory(&dir, ".", "", 0); + read_directory(&dir, ".", "", 0, NULL); for(i = 0; i < dir.nr; i++) { /* check for matching entry, which is unmerged; lifted from * builtin-ls-files:show_other_files */ |