summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--Documentation/Makefile31
-rw-r--r--Documentation/RelNotes-1.5.0.6.txt22
-rw-r--r--Documentation/RelNotes-1.5.0.7.txt18
-rw-r--r--Documentation/RelNotes-1.5.1.txt258
-rw-r--r--Documentation/asciidoc.conf19
-rw-r--r--Documentation/diff-options.txt3
-rw-r--r--Documentation/git-am.txt27
-rw-r--r--Documentation/git-cvsserver.txt8
-rw-r--r--Documentation/git-log.txt5
-rw-r--r--Documentation/git-mergetool.txt10
-rw-r--r--Documentation/git-rev-parse.txt16
-rw-r--r--Documentation/git-svnimport.txt2
-rw-r--r--Documentation/git.txt18
-rw-r--r--Documentation/glossary.txt742
-rw-r--r--Documentation/sort_glossary.pl69
-rw-r--r--Documentation/user-manual.txt68
-rwxr-xr-xGIT-VERSION-GEN2
-rw-r--r--Makefile86
-rw-r--r--README6
-rw-r--r--builtin-add.c2
-rw-r--r--builtin-bundle.c4
-rw-r--r--builtin-ls-files.c2
-rw-r--r--builtin-mailinfo.c23
-rw-r--r--builtin-read-tree.c2
-rw-r--r--builtin-rerere.c9
-rw-r--r--builtin-revert.c10
-rw-r--r--builtin-rm.c18
-rw-r--r--commit.c24
-rw-r--r--config.mak.in1
-rw-r--r--configure.ac24
-rw-r--r--connect.c4
-rw-r--r--contrib/emacs/git-blame.el138
-rw-r--r--contrib/emacs/git.el22
-rw-r--r--contrib/hooks/post-receieve-email588
-rwxr-xr-xcontrib/workdir/git-new-workdir57
-rw-r--r--dir.c96
-rw-r--r--dir.h2
-rw-r--r--fast-import.c6
-rwxr-xr-xgit-am.sh18
-rwxr-xr-xgit-bisect.sh14
-rwxr-xr-xgit-clone.sh2
-rwxr-xr-xgit-commit.sh2
-rw-r--r--git-compat-util.h2
-rwxr-xr-xgit-fetch.sh2
-rwxr-xr-xgit-merge-ours.sh2
-rwxr-xr-xgit-mergetool.sh158
-rwxr-xr-xgit-quiltimport.sh2
-rwxr-xr-xgit-rebase.sh10
-rwxr-xr-xgit-remote.perl16
-rwxr-xr-xgit-svn.perl25
-rw-r--r--git.c2
-rw-r--r--git.spec.in34
-rw-r--r--gitweb/INSTALL225
-rw-r--r--gitweb/gitweb.css2
-rwxr-xr-xgitweb/gitweb.perl10
-rw-r--r--help.c14
-rw-r--r--http-fetch.c37
-rw-r--r--index-pack.c5
-rw-r--r--merge-recursive.c37
-rw-r--r--revision.c16
-rw-r--r--revision.h3
-rw-r--r--sha1_file.c11
-rwxr-xr-xt/t4200-rerere.sh21
-rw-r--r--t/t5100/patch00052
-rwxr-xr-xt/t6006-rev-list-format.sh150
-rw-r--r--templates/hooks--post-receive17
-rw-r--r--templates/hooks--update225
-rw-r--r--upload-pack.c1
-rw-r--r--usage.c2
-rw-r--r--wt-status.c2
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='
'
diff --git a/Makefile b/Makefile
index 51c1fed711..ad321b35bf 100644
--- a/Makefile
+++ b/Makefile
@@ -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" || \
diff --git a/README b/README
index 441167cb8a..548142c327 100644
--- a/README
+++ b/README
@@ -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);
}
diff --git a/commit.c b/commit.c
index 718e568855..754d1b8a0b 100644
--- a/commit.c
+++ b/commit.c
@@ -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])
diff --git a/connect.c b/connect.c
index 5048653639..da89c9cfcf 100644
--- a/connect.c
+++ b/connect.c
@@ -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
diff --git a/dir.c b/dir.c
index b48e19dc09..7426fde330 100644
--- a/dir.c
+++ b/dir.c
@@ -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;
}
diff --git a/dir.h b/dir.h
index 7233d65bbd..33c31f25fb 100644
--- a/dir.h
+++ b/dir.h
@@ -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;
diff --git a/git-am.sh b/git-am.sh
index 88af8dd256..e69ecbfdb1 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -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";
diff --git a/git.c b/git.c
index ed1c65e309..5b1bc2a895 100644
--- a/git.c
+++ b/git.c
@@ -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");
}
diff --git a/help.c b/help.c
index 0893fea025..6a9af4d175 100644
--- a/help.c
+++ b/help.c
@@ -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
+foobarbazxyzzy
+commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+foobarbazxyzzy
+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)
diff --git a/usage.c b/usage.c
index 4dc5c77633..f5e652cc76 100644
--- a/usage.c
+++ b/usage.c
@@ -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 */