Merge branch 'rj/maint-simplify-cygwin-makefile'
authorJunio C Hamano <gitster@pobox.com>
Sat, 21 Nov 2009 07:47:43 +0000 (23:47 -0800)
committerJunio C Hamano <gitster@pobox.com>
Sat, 21 Nov 2009 07:47:43 +0000 (23:47 -0800)
* rj/maint-simplify-cygwin-makefile:
  Makefile: merge two Cygwin configuration sections into one

219 files changed:
.gitignore
Documentation/Makefile
Documentation/RelNotes-1.6.5.1.txt [new file with mode: 0644]
Documentation/RelNotes-1.6.5.2.txt [new file with mode: 0644]
Documentation/RelNotes-1.6.5.3.txt [new file with mode: 0644]
Documentation/RelNotes-1.6.6.txt [new file with mode: 0644]
Documentation/config.txt
Documentation/diff-options.txt
Documentation/fetch-options.txt
Documentation/git-add.txt
Documentation/git-bisect.txt
Documentation/git-check-ref-format.txt
Documentation/git-clone.txt
Documentation/git-describe.txt
Documentation/git-difftool.txt
Documentation/git-fetch.txt
Documentation/git-filter-branch.txt
Documentation/git-format-patch.txt
Documentation/git-fsck.txt
Documentation/git-gc.txt
Documentation/git-http-push.txt
Documentation/git-ls-files.txt
Documentation/git-merge.txt
Documentation/git-mergetool.txt
Documentation/git-pull.txt
Documentation/git-push.txt
Documentation/git-read-tree.txt
Documentation/git-rebase.txt
Documentation/git-receive-pack.txt
Documentation/git-replace.txt
Documentation/git-reset.txt
Documentation/git-send-pack.txt
Documentation/git-show-ref.txt
Documentation/git-submodule.txt
Documentation/git-svn.txt
Documentation/git-update-index.txt
Documentation/git.txt
Documentation/gitattributes.txt
Documentation/gitcore-tutorial.txt
Documentation/githooks.txt
Documentation/gitworkflows.txt
Documentation/glossary-content.txt
Documentation/howto/maintain-git.txt
Documentation/howto/revert-branch-rebase.txt
Documentation/howto/update-hook-example.txt
Documentation/manpage-quote-apos.xsl [new file with mode: 0644]
Documentation/merge-config.txt
Documentation/merge-options.txt
Documentation/pretty-formats.txt
Documentation/pt_BR/gittutorial.txt
Documentation/pull-fetch-param.txt
Documentation/technical/pack-protocol.txt
Documentation/technical/protocol-capabilities.txt [new file with mode: 0644]
Documentation/technical/protocol-common.txt [new file with mode: 0644]
Documentation/user-manual.txt
GIT-VERSION-GEN
Makefile
RelNotes
archive.c
builtin-apply.c
builtin-blame.c
builtin-branch.c
builtin-check-ref-format.c
builtin-checkout.c
builtin-clone.c
builtin-commit-tree.c
builtin-commit.c
builtin-describe.c
builtin-fetch.c
builtin-fsck.c
builtin-gc.c
builtin-grep.c
builtin-help.c
builtin-log.c
builtin-ls-files.c
builtin-ls-remote.c
builtin-ls-tree.c
builtin-mailsplit.c
builtin-merge-ours.c
builtin-merge-recursive.c
builtin-merge.c
builtin-mv.c
builtin-pack-objects.c
builtin-push.c
builtin-read-tree.c
builtin-receive-pack.c
builtin-reflog.c
builtin-remote.c
builtin-rerere.c
builtin-rev-list.c
builtin-rev-parse.c
builtin-send-pack.c
builtin-shortlog.c
builtin-show-branch.c
builtin-show-ref.c
builtin-stripspace.c
builtin-tar-tree.c
builtin-upload-archive.c
builtin.h
cache.h
command-list.txt
commit.c
commit.h
compat/bswap.h
compat/mingw.h
compat/vcbuild/scripts/clink.pl
contrib/buildsystems/Generators/Vcproj.pm
contrib/buildsystems/engine.pl
contrib/completion/git-completion.bash
contrib/emacs/git-blame.el
contrib/examples/builtin-fetch--tool.c [moved from builtin-fetch--tool.c with 98% similarity]
contrib/examples/git-merge.sh
contrib/examples/git-resolve.sh
contrib/fast-import/import-tars.perl
contrib/hooks/post-receive-email
diff-no-index.c
diff.c
diff.h
fast-import.c
git-add--interactive.perl
git-bisect.sh
git-compat-util.h
git-cvsimport.perl
git-filter-branch.sh
git-gui/git-gui.sh
git-gui/lib/diff.tcl
git-gui/lib/remote_branch_delete.tcl
git-gui/po/el.po [new file with mode: 0644]
git-gui/po/git-gui.pot
git-gui/po/glossary/el.po [new file with mode: 0644]
git-gui/po/ru.po
git-instaweb.sh
git-merge-octopus.sh
git-merge-one-file.sh
git-mergetool--lib.sh
git-pull.sh
git-rebase--interactive.sh
git-rebase.sh
git-send-email.perl
git-stash.sh
git-submodule.sh
git-svn.perl
git.c
gitweb/gitweb.css
gitweb/gitweb.perl
http-fetch.c
http-push.c
imap-send.c
index-pack.c
log-tree.c
pack-redundant.c
pretty.c
progress.c
reflog-walk.c
reflog-walk.h
remote-curl.c
remote.c
revision.c
revision.h
setup.c
sha1_file.c
show-index.c
submodule.c [new file with mode: 0644]
submodule.h [new file with mode: 0644]
t/lib-git-svn.sh
t/lib-rebase.sh
t/t1001-read-tree-m-2way.sh
t/t1200-tutorial.sh
t/t1402-check-ref-format.sh [new file with mode: 0755]
t/t3003-ls-files-exclude.sh [new file with mode: 0755]
t/t3101-ls-tree-dirname.sh
t/t3404-rebase-interactive.sh
t/t3701-add-interactive.sh
t/t4013/diff.log_--decorate=full_--all
t/t4013/diff.log_--decorate_--all
t/t4014-format-patch.sh
t/t4015-diff-whitespace.sh
t/t4019-diff-wserror.sh
t/t4034-diff-words.sh
t/t4041-diff-submodule.sh [new file with mode: 0755]
t/t4124-apply-ws-rule.sh
t/t5100/.gitattributes [new file with mode: 0644]
t/t5100/0010 [deleted file]
t/t5303-pack-corruption-resilience.sh
t/t5505-remote.sh
t/t5510-fetch.sh
t/t5518-fetch-exit-status.sh
t/t6006-rev-list-format.sh
t/t6028-merge-up-to-date.sh
t/t6050-replace.sh
t/t6120-describe.sh
t/t7002-grep.sh
t/t7003-filter-branch.sh
t/t7400-submodule-basic.sh
t/t7501-commit.sh
t/t7502-commit.sh
t/t7600-merge.sh
t/t7800-difftool.sh
t/t9001-send-email.sh
t/t9115-git-svn-dcommit-funky-renames.sh
t/t9130-git-svn-authors-file.sh
t/t9146-git-svn-empty-dirs.sh [new file with mode: 0755]
t/t9150-svk-mergetickets.sh [new file with mode: 0755]
t/t9150/make-svk-dump [new file with mode: 0644]
t/t9150/svk-merge.dump [new file with mode: 0644]
t/t9151-svn-mergeinfo.sh [new file with mode: 0755]
t/t9151/.gitignore [new file with mode: 0644]
t/t9151/make-svnmerge-dump [new file with mode: 0644]
t/t9151/svn-mergeinfo.dump [new file with mode: 0644]
templates/Makefile
templates/hooks--pre-commit.sample
transport.c
unpack-file.c
unpack-trees.c
upload-pack.c
usage.c
utf8.c
utf8.h
ws.c

index 51a37b1af7ab927b98e2764e755b130080bfc9e3..338c6d888123f326ce7b82a4c9c0459d618bef3d 100644 (file)
-GIT-BUILD-OPTIONS
-GIT-CFLAGS
-GIT-GUI-VARS
-GIT-VERSION-FILE
-git
-git-add
-git-add--interactive
-git-am
-git-annotate
-git-apply
-git-archimport
-git-archive
-git-bisect
-git-bisect--helper
-git-blame
-git-branch
-git-bundle
-git-cat-file
-git-check-attr
-git-check-ref-format
-git-checkout
-git-checkout-index
-git-cherry
-git-cherry-pick
-git-clean
-git-clone
-git-commit
-git-commit-tree
-git-config
-git-count-objects
-git-cvsexportcommit
-git-cvsimport
-git-cvsserver
-git-daemon
-git-diff
-git-diff-files
-git-diff-index
-git-diff-tree
-git-difftool
-git-difftool--helper
-git-describe
-git-fast-export
-git-fast-import
-git-fetch
-git-fetch--tool
-git-fetch-pack
-git-filter-branch
-git-fmt-merge-msg
-git-for-each-ref
-git-format-patch
-git-fsck
-git-fsck-objects
-git-gc
-git-get-tar-commit-id
-git-grep
-git-hash-object
-git-help
-git-http-fetch
-git-http-push
-git-imap-send
-git-index-pack
-git-init
-git-init-db
-git-instaweb
-git-log
-git-lost-found
-git-ls-files
-git-ls-remote
-git-ls-tree
-git-mailinfo
-git-mailsplit
-git-merge
-git-merge-base
-git-merge-index
-git-merge-file
-git-merge-tree
-git-merge-octopus
-git-merge-one-file
-git-merge-ours
-git-merge-recursive
-git-merge-resolve
-git-merge-subtree
-git-mergetool
-git-mergetool--lib
-git-mktag
-git-mktree
-git-name-rev
-git-mv
-git-pack-redundant
-git-pack-objects
-git-pack-refs
-git-parse-remote
-git-patch-id
-git-peek-remote
-git-prune
-git-prune-packed
-git-pull
-git-push
-git-quiltimport
-git-read-tree
-git-rebase
-git-rebase--interactive
-git-receive-pack
-git-reflog
-git-relink
-git-remote
-git-remote-curl
-git-repack
-git-replace
-git-repo-config
-git-request-pull
-git-rerere
-git-reset
-git-rev-list
-git-rev-parse
-git-revert
-git-rm
-git-send-email
-git-send-pack
-git-sh-setup
-git-shell
-git-shortlog
-git-show
-git-show-branch
-git-show-index
-git-show-ref
-git-stage
-git-stash
-git-status
-git-stripspace
-git-submodule
-git-svn
-git-symbolic-ref
-git-tag
-git-tar-tree
-git-unpack-file
-git-unpack-objects
-git-update-index
-git-update-ref
-git-update-server-info
-git-upload-archive
-git-upload-pack
-git-var
-git-verify-pack
-git-verify-tag
-git-web--browse
-git-whatchanged
-git-write-tree
-git-core-*/?*
-gitk-wish
-gitweb/gitweb.cgi
-test-chmtime
-test-ctype
-test-date
-test-delta
-test-dump-cache-tree
-test-genrandom
-test-match-trees
-test-parse-options
-test-path-utils
-test-sha1
-test-sigchain
-common-cmds.h
+/GIT-BUILD-OPTIONS
+/GIT-CFLAGS
+/GIT-GUI-VARS
+/GIT-VERSION-FILE
+/git
+/git-add
+/git-add--interactive
+/git-am
+/git-annotate
+/git-apply
+/git-archimport
+/git-archive
+/git-bisect
+/git-bisect--helper
+/git-blame
+/git-branch
+/git-bundle
+/git-cat-file
+/git-check-attr
+/git-check-ref-format
+/git-checkout
+/git-checkout-index
+/git-cherry
+/git-cherry-pick
+/git-clean
+/git-clone
+/git-commit
+/git-commit-tree
+/git-config
+/git-count-objects
+/git-cvsexportcommit
+/git-cvsimport
+/git-cvsserver
+/git-daemon
+/git-diff
+/git-diff-files
+/git-diff-index
+/git-diff-tree
+/git-difftool
+/git-difftool--helper
+/git-describe
+/git-fast-export
+/git-fast-import
+/git-fetch
+/git-fetch--tool
+/git-fetch-pack
+/git-filter-branch
+/git-fmt-merge-msg
+/git-for-each-ref
+/git-format-patch
+/git-fsck
+/git-fsck-objects
+/git-gc
+/git-get-tar-commit-id
+/git-grep
+/git-hash-object
+/git-help
+/git-http-fetch
+/git-http-push
+/git-imap-send
+/git-index-pack
+/git-init
+/git-init-db
+/git-instaweb
+/git-log
+/git-lost-found
+/git-ls-files
+/git-ls-remote
+/git-ls-tree
+/git-mailinfo
+/git-mailsplit
+/git-merge
+/git-merge-base
+/git-merge-index
+/git-merge-file
+/git-merge-tree
+/git-merge-octopus
+/git-merge-one-file
+/git-merge-ours
+/git-merge-recursive
+/git-merge-resolve
+/git-merge-subtree
+/git-mergetool
+/git-mergetool--lib
+/git-mktag
+/git-mktree
+/git-name-rev
+/git-mv
+/git-pack-redundant
+/git-pack-objects
+/git-pack-refs
+/git-parse-remote
+/git-patch-id
+/git-peek-remote
+/git-prune
+/git-prune-packed
+/git-pull
+/git-push
+/git-quiltimport
+/git-read-tree
+/git-rebase
+/git-rebase--interactive
+/git-receive-pack
+/git-reflog
+/git-relink
+/git-remote
+/git-remote-curl
+/git-repack
+/git-replace
+/git-repo-config
+/git-request-pull
+/git-rerere
+/git-reset
+/git-rev-list
+/git-rev-parse
+/git-revert
+/git-rm
+/git-send-email
+/git-send-pack
+/git-sh-setup
+/git-shell
+/git-shortlog
+/git-show
+/git-show-branch
+/git-show-index
+/git-show-ref
+/git-stage
+/git-stash
+/git-status
+/git-stripspace
+/git-submodule
+/git-svn
+/git-symbolic-ref
+/git-tag
+/git-tar-tree
+/git-unpack-file
+/git-unpack-objects
+/git-update-index
+/git-update-ref
+/git-update-server-info
+/git-upload-archive
+/git-upload-pack
+/git-var
+/git-verify-pack
+/git-verify-tag
+/git-web--browse
+/git-whatchanged
+/git-write-tree
+/git-core-*/?*
+/gitk-git/gitk-wish
+/gitweb/gitweb.cgi
+/test-chmtime
+/test-ctype
+/test-date
+/test-delta
+/test-dump-cache-tree
+/test-genrandom
+/test-match-trees
+/test-parse-options
+/test-path-utils
+/test-sha1
+/test-sigchain
+/common-cmds.h
 *.tar.gz
 *.dsc
 *.deb
-git.spec
+/git.spec
 *.exe
 *.[aos]
 *.py[co]
-config.mak
-autom4te.cache
-config.cache
-config.log
-config.status
-config.mak.autogen
-config.mak.append
-configure
-tags
-TAGS
-cscope*
+*+
+/config.mak
+/autom4te.cache
+/config.cache
+/config.log
+/config.status
+/config.mak.autogen
+/config.mak.append
+/configure
+/tags
+/TAGS
+/cscope*
 *.obj
 *.lib
 *.sln
@@ -188,5 +189,5 @@ cscope*
 *.user
 *.idb
 *.pdb
-Debug/
-Release/
+/Debug/
+/Release/
index 06b0c57b95057b3df4f215f3191fd8e9fc473e6f..cd5b4396dbc174edbba3eb42bb285eefc57f9caf 100644 (file)
@@ -103,6 +103,14 @@ ifdef DOCBOOK_SUPPRESS_SP
 XMLTO_EXTRA += -m manpage-suppress-sp.xsl
 endif
 
+# If your target system uses GNU groff, it may try to render
+# apostrophes as a "pretty" apostrophe using unicode.  This breaks
+# cut&paste, so you should set GNU_ROFF to force them to be ASCII
+# apostrophes.  Unfortunately does not work with non-GNU roff.
+ifdef GNU_ROFF
+XMLTO_EXTRA += -m manpage-quote-apos.xsl
+endif
+
 SHELL_PATH ?= $(SHELL)
 # Shell quote;
 SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
diff --git a/Documentation/RelNotes-1.6.5.1.txt b/Documentation/RelNotes-1.6.5.1.txt
new file mode 100644 (file)
index 0000000..309ba18
--- /dev/null
@@ -0,0 +1,20 @@
+GIT v1.6.5.1 Release Notes
+==========================
+
+Fixes since v1.6.5
+------------------
+
+ * An corrupt pack could make codepath to read objects into an
+   infinite loop.
+
+ * Download throughput display was always shown in KiB/s but on fast links
+   it is more appropriate to show it in MiB/s.
+
+ * "git grep -f filename" used uninitialized variable and segfaulted.
+
+ * "git clone -b branch" gave a wrong commit object name to post-checkout
+   hook.
+
+ * "git pull" over http did not work on msys.
+
+Other minor documentation updates are included.
diff --git a/Documentation/RelNotes-1.6.5.2.txt b/Documentation/RelNotes-1.6.5.2.txt
new file mode 100644 (file)
index 0000000..aa7ccce
--- /dev/null
@@ -0,0 +1,19 @@
+GIT v1.6.5.2 Release Notes
+==========================
+
+Fixes since v1.6.5.1
+--------------------
+
+ * Installation of templates triggered a bug in busybox when using tar
+   implementation from it.
+
+ * "git add -i" incorrectly ignored paths that are already in the index
+   if they matched .gitignore patterns.
+
+ * "git describe --always" should have produced some output even there
+   were no tags in the repository, but it didn't.
+
+ * "git ls-files" when showing tracked files incorrectly paid attention
+   to the exclude patterns.
+
+Other minor documentation updates are included.
diff --git a/Documentation/RelNotes-1.6.5.3.txt b/Documentation/RelNotes-1.6.5.3.txt
new file mode 100644 (file)
index 0000000..b2fad1b
--- /dev/null
@@ -0,0 +1,63 @@
+Git v1.6.5.3 Release Notes
+==========================
+
+Fixes since v1.6.5.2
+--------------------
+
+ * info/grafts file didn't ignore trailing CR at the end of lines.
+
+ * Packages generated on newer FC were unreadable by older versions of
+   RPM as the new default is to use stronger hash.
+
+ * output from "git blame" was unreadable when the file ended in an
+   incomplete line.
+
+ * "git add -i/-p" didn't handle deletion of empty files correctly.
+
+ * "git clone" takes up to two parameters, but did not complain when
+   given more arguments than necessary and silently ignored them.
+
+ * "git cvsimport" did not read files given as command line arguments
+   correctly when it is run from a subdirectory.
+
+ * "git diff --color-words -U0" didn't work correctly.
+
+ * The handling of blank lines at the end of file by "git diff/apply
+   --whitespace" was inconsistent with the other kinds of errors.
+   They are now colored, warned against, and fixed the same way as others.
+
+ * There was no way to allow blank lines at the end of file without
+   allowing extra blanks at the end of lines.  You can use blank-at-eof
+   and blank-at-eol whitespace error class to specify them separately.
+   The old trailing-space error class is now a short-hand to set both.
+
+ * "-p" option to "git format-patch" was supposed to suppress diffstat
+   generation, but it was broken since 1.6.1.
+
+ * "git imap-send" did not compile cleanly with newer OpenSSL.
+
+ * "git help -a" outside of a git repository was broken.
+
+ * "git ls-files -i" was supposed to be inverse of "git ls-files" without -i
+   with respect to exclude patterns, but it was broken since 1.6.5.2.
+
+ * "git ls-remote" outside of a git repository over http was broken.
+
+ * "git rebase -i" gave bogus error message when the command word was
+   misspelled.
+
+ * "git receive-pack" that is run in response to "git push" did not run
+   garbage collection nor update-server-info, but in larger hosting sites,
+   these almost always need to be run.  To help site administrators, the
+   command now runs "gc --auto" and "u-s-i" by setting receive.autogc
+   and receive.updateserverinfo configuration variables, respectively.
+
+ * Release notes spelled the package name with incorrect capitalization.
+
+ * "gitweb" did not escape non-ascii characters correctly in the URL.
+
+ * "gitweb" showed "patch" link even for merge commits.
+
+ * "gitweb" showed incorrect links for blob line numbers in pathinfo mode.
+
+Other minor documentation updates are included.
diff --git a/Documentation/RelNotes-1.6.6.txt b/Documentation/RelNotes-1.6.6.txt
new file mode 100644 (file)
index 0000000..2f9c254
--- /dev/null
@@ -0,0 +1,108 @@
+Git v1.6.6 Release Notes
+========================
+
+In this release, "git fsck" defaults to "git fsck --full" and checks
+packfiles, and because of this it will take much longer to complete
+than before.  If you prefer a quicker check only on loose objects (the
+old default), you can say "git fsck --no-full".  This has been
+supported by 1.5.4 and newer versions of git, so it is safe to write
+it in your script even if you use slightly older git on some of your
+machines.
+
+In git 1.7.0, which is planned to be the release after 1.6.6, "git
+push" into a branch that is currently checked out will be refused by
+default.
+
+You can choose what should happen upon such a push by setting the
+configuration variable receive.denyCurrentBranch in the receiving
+repository.
+
+Also, "git push $there :$killed" to delete the branch $killed in a remote
+repository $there, when $killed branch is the current branch pointed at by
+its HEAD, will be refused by default.
+
+You can choose what should happen upon such a push by setting the
+configuration variable receive.denyDeleteCurrent in the receiving
+repository.
+
+To ease the transition plan, the receiving repository of such a
+push running this release will issue a big warning when the
+configuration variable is missing.  Please refer to:
+
+  http://git.or.cz/gitwiki/GitFaq#non-bare
+  http://thread.gmane.org/gmane.comp.version-control.git/107758/focus=108007
+
+for more details on the reason why this change is needed and the
+transition plan.
+
+Updates since v1.6.5
+--------------------
+
+(subsystems)
+
+ * various git-gui updates including new translations, wm states, etc.
+
+(portability)
+
+(performance)
+
+(usability, bells and whistles)
+
+ * The object replace mechanism can be bypassed with --no-replace-objects
+   global option given to the "git" program.
+
+ * "git bisect reset" can reset to an arbitrary commit.
+
+ * "git checkout frotz" when there is no local branch "frotz" but there
+   is only one remote tracking branch "frotz" is taken as a request to
+   start the named branch at the corresponding remote tracking branch.
+
+ * "git describe" can be told to add "-dirty" suffix with "--dirty" option.
+
+ * "git diff" learned --submodule option to show a list of one-line logs
+   instead of differences between the commit object names.
+
+ * "git fsck" by default checks the packfiles (i.e. "--full" is the
+   default); you can turn it off with "git fsck --no-full".
+
+ * import-tars contributed fast-import frontend learned more types of
+   compressed tarballs.
+
+ * "git instaweb" knows how to talk with mod_cgid to apache2.
+
+ * "git log --decorate" shows the location of HEAD as well.
+
+ * "--pretty=format" option to "log" family of commands learned:
+
+   . to wrap text with the "%w()" specifier.
+   . to show reflog information with "%g[sdD]" specifier.
+
+ * "git merge" (and "git pull") learned --ff-only option to make it fail
+   if the merge does not result in a fast-forward.
+
+ * "git mergetool" learned to use p4merge.
+
+ * "git rebase -i" learned "reword" that acts like "edit" but immediately
+   starts an editor to tweak the log message without returning control to
+   the shell, which is done by "edit" to give an opportunity to tweak the
+   contents.
+
+ * "git svn" learned to read SVN 1.5+ and SVK merge tickets.
+
+ * Author names shown in gitweb output are links to search commits by the
+   author.
+
+
+(developers)
+
+Fixes since v1.6.5
+------------------
+
+All of the fixes in v1.6.5.X maintenance series are included in this
+release, unless otherwise noted.
+
+---
+exec >/var/tmp/1
+echo O=$(git describe master)
+O=v1.6.5.3-152-g122d0f6
+git shortlog --no-merges $O..master --not maint
index cd1781498eb92d7dd0d3648a8fe188fc75a6df8c..cb73d7571f25deffb061441577ce1ae531fdf5d9 100644 (file)
@@ -416,13 +416,17 @@ core.whitespace::
        consider them as errors.  You can prefix `-` to disable
        any of them (e.g. `-trailing-space`):
 +
-* `trailing-space` treats trailing whitespaces at the end of the line
+* `blank-at-eol` treats trailing whitespaces at the end of the line
   as an error (enabled by default).
 * `space-before-tab` treats a space character that appears immediately
   before a tab character in the initial indent part of the line as an
   error (enabled by default).
 * `indent-with-non-tab` treats a line that is indented with 8 or more
   space characters as an error (not enabled by default).
+* `blank-at-eof` treats blank lines added at the end of file as an error
+  (enabled by default).
+* `trailing-space` is a short-hand to cover both `blank-at-eol` and
+  `blank-at-eof`.
 * `cr-at-eol` treats a carriage-return at the end of line as
   part of the line terminator, i.e. with it, `trailing-space`
   does not trigger if the character before such a carriage-return
@@ -1320,6 +1324,11 @@ rebase.stat::
        Whether to show a diffstat of what changed upstream since the last
        rebase. False by default.
 
+receive.autogc::
+       By default, git-receive-pack will run "git-gc --auto" after
+       receiving data from git-push and updating refs.  You can stop
+       it by setting this variable to false.
+
 receive.fsckObjects::
        If it is set to true, git-receive-pack will check all received
        objects. It will abort in the case of a malformed object or a
@@ -1351,10 +1360,14 @@ receive.denyCurrentBranch::
 
 receive.denyNonFastForwards::
        If set to true, git-receive-pack will deny a ref update which is
-       not a fast forward. Use this to prevent such an update via a push,
+       not a fast-forward. Use this to prevent such an update via a push,
        even if that push is forced. This configuration variable is
        set when initializing a shared repository.
 
+receive.updateserverinfo::
+       If set to true, git-receive-pack will run git-update-server-info
+       after receiving data from git-push and updating refs.
+
 remote.<name>.url::
        The URL of a remote repository.  See linkgit:git-fetch[1] or
        linkgit:git-push[1].
index 9276faeb11aec2650393c56fe5edf2b571692dbd..2b37193a37da9715b0ae4b8aa47c85064694ef8e 100644 (file)
@@ -14,7 +14,8 @@ endif::git-format-patch[]
 
 ifdef::git-format-patch[]
 -p::
-       Generate patches without diffstat.
+--no-stat::
+       Generate plain patches without any diffstats.
 endif::git-format-patch[]
 
 ifndef::git-format-patch[]
@@ -27,33 +28,40 @@ endif::git-format-patch[]
 -U<n>::
 --unified=<n>::
        Generate diffs with <n> lines of context instead of
-       the usual three. Implies "-p".
+       the usual three.
+ifndef::git-format-patch[]
+       Implies `-p`.
+endif::git-format-patch[]
 
+ifndef::git-format-patch[]
 --raw::
        Generate the raw format.
        {git-diff-core? This is the default.}
+endif::git-format-patch[]
 
+ifndef::git-format-patch[]
 --patch-with-raw::
-       Synonym for "-p --raw".
+       Synonym for `-p --raw`.
+endif::git-format-patch[]
 
 --patience::
        Generate a diff using the "patience diff" algorithm.
 
 --stat[=width[,name-width]]::
        Generate a diffstat.  You can override the default
-       output width for 80-column terminal by "--stat=width".
+       output width for 80-column terminal by `--stat=width`.
        The width of the filename part can be controlled by
        giving another width to it separated by a comma.
 
 --numstat::
-       Similar to \--stat, but shows number of added and
+       Similar to `\--stat`, but shows number of added and
        deleted lines in decimal notation and pathname without
        abbreviation, to make it more machine friendly.  For
        binary files, outputs two `-` instead of saying
        `0 0`.
 
 --shortstat::
-       Output only the last line of the --stat format containing total
+       Output only the last line of the `--stat` format containing total
        number of modified files, as well as number of added and deleted
        lines.
 
@@ -61,24 +69,26 @@ endif::git-format-patch[]
        Output the distribution of relative amount of changes (number of lines added or
        removed) for each sub-directory. Directories with changes below
        a cut-off percent (3% by default) are not shown. The cut-off percent
-       can be set with "--dirstat=limit". Changes in a child directory is not
-       counted for the parent directory, unless "--cumulative" is used.
+       can be set with `--dirstat=limit`. Changes in a child directory is not
+       counted for the parent directory, unless `--cumulative` is used.
 
 --dirstat-by-file[=limit]::
-       Same as --dirstat, but counts changed files instead of lines.
+       Same as `--dirstat`, but counts changed files instead of lines.
 
 --summary::
        Output a condensed summary of extended header information
        such as creations, renames and mode changes.
 
+ifndef::git-format-patch[]
 --patch-with-stat::
-       Synonym for "-p --stat".
-       {git-format-patch? This is the default.}
+       Synonym for `-p --stat`.
+endif::git-format-patch[]
 
+ifndef::git-format-patch[]
 -z::
-       NUL-line termination on output.  This affects the --raw
+       NUL-line termination on output.  This affects the `--raw`
        output field terminator.  Also output from commands such
-       as "git-log" will be delimited with NUL between commits.
+       as `git-log` will be delimited with NUL between commits.
 
 --name-only::
        Show only names of changed files.
@@ -87,6 +97,13 @@ endif::git-format-patch[]
        Show only names and status of changed files. See the description
        of the `--diff-filter` option on what the status letters mean.
 
+--submodule[=<format>]::
+       Chose the output format for submodule differences. <format> can be one of
+       'short' and 'log'. 'short' just shows pairs of commit names, this format
+       is used when this option is not given. 'log' is the default value for this
+       option and lists the commits in that commit range like the 'summary'
+       option of linkgit:git-submodule[1] does.
+
 --color::
        Show colored diff.
 
@@ -110,16 +127,19 @@ The regex can also be set via a diff driver or configuration option, see
 linkgit:gitattributes[1] or linkgit:git-config[1].  Giving it explicitly
 overrides any diff driver or configuration setting.  Diff drivers
 override configuration settings.
+endif::git-format-patch[]
 
 --no-renames::
        Turn off rename detection, even when the configuration
        file gives the default to do so.
 
+ifndef::git-format-patch[]
 --check::
        Warn if changes introduce trailing whitespace
        or an indent that uses a space before a tab. Exits with
        non-zero status if problems are found. Not compatible with
        --exit-code.
+endif::git-format-patch[]
 
 --full-index::
        Instead of the first handful of characters, show the full
@@ -127,16 +147,16 @@ override configuration settings.
        line when generating patch format output.
 
 --binary::
-       In addition to --full-index, output "binary diff" that
-       can be applied with "git apply".
+       In addition to `--full-index`, output a binary diff that
+       can be applied with `git-apply`.
 
 --abbrev[=<n>]::
        Instead of showing the full 40-byte hexadecimal object
        name in diff-raw format output and diff-tree header
        lines, show only a partial prefix.  This is
-       independent of --full-index option above, which controls
+       independent of the `--full-index` option above, which controls
        the diff-patch output format.  Non default number of
-       digits can be specified with --abbrev=<n>.
+       digits can be specified with `--abbrev=<n>`.
 
 -B::
        Break complete rewrite changes into pairs of delete and create.
@@ -147,6 +167,7 @@ override configuration settings.
 -C::
        Detect copies as well as renames.  See also `--find-copies-harder`.
 
+ifndef::git-format-patch[]
 --diff-filter=[ACDMRTUXB*]::
        Select only files that are Added (`A`), Copied (`C`),
        Deleted (`D`), Modified (`M`), Renamed (`R`), have their
@@ -158,6 +179,7 @@ override configuration settings.
        paths are selected if there is any file that matches
        other criteria in the comparison; if there is no file
        that matches other criteria, nothing is selected.
+endif::git-format-patch[]
 
 --find-copies-harder::
        For performance reasons, by default, `-C` option finds copies only
@@ -169,12 +191,13 @@ override configuration settings.
        `-C` option has the same effect.
 
 -l<num>::
-       -M and -C options require O(n^2) processing time where n
+       The `-M` and `-C` options require O(n^2) processing time where n
        is the number of potential rename/copy targets.  This
        option prevents rename/copy detection from running if
        the number of rename/copy targets exceeds the specified
        number.
 
+ifndef::git-format-patch[]
 -S<string>::
        Look for differences that introduce or remove an instance of
        <string>. Note that this is different than the string simply
@@ -182,18 +205,20 @@ override configuration settings.
        linkgit:gitdiffcore[7] for more details.
 
 --pickaxe-all::
-       When -S finds a change, show all the changes in that
+       When `-S` finds a change, show all the changes in that
        changeset, not just the files that contain the change
        in <string>.
 
 --pickaxe-regex::
        Make the <string> not a plain string but an extended POSIX
        regex to match.
+endif::git-format-patch[]
 
 -O<orderfile>::
        Output the patch in the order specified in the
        <orderfile>, which has one shell glob pattern per line.
 
+ifndef::git-format-patch[]
 -R::
        Swap two inputs; that is, show differences from index or
        on-disk file to tree contents.
@@ -205,6 +230,7 @@ override configuration settings.
        not in a subdirectory (e.g. in a bare repository), you
        can name which subdirectory to make the output relative
        to by giving a <path> as an argument.
+endif::git-format-patch[]
 
 -a::
 --text::
@@ -229,13 +255,15 @@ override configuration settings.
        Show the context between diff hunks, up to the specified number
        of lines, thereby fusing hunks that are close to each other.
 
+ifndef::git-format-patch[]
 --exit-code::
        Make the program exit with codes similar to diff(1).
        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.
+       Disable all output of the program. Implies `--exit-code`.
+endif::git-format-patch[]
 
 --ext-diff::
        Allow an external diff helper to be executed. If you set an
index 5eb2b0ee07b2f4e81e909a103f486c1a6d2dc6cb..28868747dac778dd1c527f3e40446edd739a5ba9 100644 (file)
@@ -1,25 +1,13 @@
-ifndef::git-pull[]
--q::
---quiet::
-       Pass --quiet to git-fetch-pack and silence any other internally
-       used git commands.
-
--v::
---verbose::
-       Be verbose.
-endif::git-pull[]
-
 -a::
 --append::
        Append ref names and object names of fetched refs to the
        existing contents of `.git/FETCH_HEAD`.  Without this
        option old data in `.git/FETCH_HEAD` will be overwritten.
 
---upload-pack <upload-pack>::
-       When given, and the repository to fetch from is handled
-       by 'git-fetch-pack', '--exec=<upload-pack>' is passed to
-       the command to specify non-default path for the command
-       run on the other end.
+--depth=<depth>::
+       Deepen the history of a 'shallow' repository created by
+       `git clone` with `--depth=<depth>` option (see linkgit:git-clone[1])
+       by the specified number of commits.
 
 -f::
 --force::
@@ -29,6 +17,10 @@ endif::git-pull[]
        fetches is a descendant of `<lbranch>`.  This option
        overrides that check.
 
+-k::
+--keep::
+       Keep downloaded pack.
+
 ifdef::git-pull[]
 --no-tags::
 endif::git-pull[]
@@ -49,10 +41,6 @@ endif::git-pull[]
        flag lets all tags and their associated objects be
        downloaded.
 
--k::
---keep::
-       Keep downloaded pack.
-
 -u::
 --update-head-ok::
        By default 'git-fetch' refuses to update the head which
@@ -62,7 +50,19 @@ endif::git-pull[]
        implementing your own Porcelain you are not supposed to
        use it.
 
---depth=<depth>::
-       Deepen the history of a 'shallow' repository created by
-       `git clone` with `--depth=<depth>` option (see linkgit:git-clone[1])
-       by the specified number of commits.
+--upload-pack <upload-pack>::
+       When given, and the repository to fetch from is handled
+       by 'git-fetch-pack', '--exec=<upload-pack>' is passed to
+       the command to specify non-default path for the command
+       run on the other end.
+
+ifndef::git-pull[]
+-q::
+--quiet::
+       Pass --quiet to git-fetch-pack and silence any other internally
+       used git commands.
+
+-v::
+--verbose::
+       Be verbose.
+endif::git-pull[]
index 45ebf87ca3c31bce8645a0130625f4b653929e5c..e93e606f458356275964d0d7b438ca772abba47c 100644 (file)
@@ -76,10 +76,10 @@ OPTIONS
        work tree and add them to the index. This gives the user a chance
        to review the difference before adding modified contents to the
        index.
-
-       This effectively runs ``add --interactive``, but bypasses the
-       initial command menu and directly jumps to `patch` subcommand.
-       See ``Interactive mode'' for details.
++
+This effectively runs `add --interactive`, but bypasses the
+initial command menu and directly jumps to the `patch` subcommand.
+See ``Interactive mode'' for details.
 
 -e, \--edit::
        Open the diff vs. the index in an editor and let the user
index 63e7a42cb353e2cd0c8bbb6e83927bd1863a32cb..d2ffae0c10176a412202d381a9c7beb2b21979ef 100644 (file)
@@ -20,7 +20,7 @@ on the subcommand:
  git bisect bad [<rev>]
  git bisect good [<rev>...]
  git bisect skip [(<rev>|<range>)...]
- git bisect reset [<branch>]
+ git bisect reset [<commit>]
  git bisect visualize
  git bisect replay <logfile>
  git bisect log
@@ -81,16 +81,27 @@ will have been left with the first bad kernel revision in "refs/bisect/bad".
 Bisect reset
 ~~~~~~~~~~~~
 
-To return to the original head after a bisect session, issue the
-following command:
+After a bisect session, to clean up the bisection state and return to
+the original HEAD, issue the following command:
 
 ------------------------------------------------
 $ git bisect reset
 ------------------------------------------------
 
-This resets the tree to the original branch instead of being on the
-bisection commit ("git bisect start" will also do that, as it resets
-the bisection state).
+By default, this will return your tree to the commit that was checked
+out before `git bisect start`.  (A new `git bisect start` will also do
+that, as it cleans up the old bisection state.)
+
+With an optional argument, you can return to a different commit
+instead:
+
+------------------------------------------------
+$ git bisect reset <commit>
+------------------------------------------------
+
+For example, `git bisect reset HEAD` will leave you on the current
+bisection commit and avoid switching commits at all, while `git bisect
+reset bisect/bad` will check out the first bad revision.
 
 Bisect visualize
 ~~~~~~~~~~~~~~~~
index 0b7982ea76633e45b8d3073cd275ea74a757c0eb..0aeef24780f07e5d5fa021f6ebdaa7090a3dcdb7 100644 (file)
@@ -9,7 +9,8 @@ SYNOPSIS
 --------
 [verse]
 'git check-ref-format' <refname>
-'git check-ref-format' [--branch] <branchname-shorthand>
+'git check-ref-format' --print <refname>
+'git check-ref-format' --branch <branchname-shorthand>
 
 DESCRIPTION
 -----------
@@ -63,16 +64,31 @@ reference name expressions (see linkgit:git-rev-parse[1]):
 
 . at-open-brace `@{` is used as a notation to access a reflog entry.
 
-With the `--branch` option, it expands a branch name shorthand and
-prints the name of the branch the shorthand refers to.
+With the `--print` option, if 'refname' is acceptable, it prints the
+canonicalized name of a hypothetical reference with that name.  That is,
+it prints 'refname' with any extra `/` characters removed.
 
-EXAMPLE
--------
+With the `--branch` option, it expands the ``previous branch syntax''
+`@{-n}`.  For example, `@{-1}` is a way to refer the last branch you
+were on.  This option should be used by porcelains to accept this
+syntax anywhere a branch name is expected, so they can act as if you
+typed the branch name.
 
-git check-ref-format --branch @{-1}::
-
-Print the name of the previous branch.
+EXAMPLES
+--------
 
+* Print the name of the previous branch:
++
+------------
+$ git check-ref-format --branch @{-1}
+------------
+
+* Determine the reference name to use for a new branch:
++
+------------
+$ ref=$(git check-ref-format --print "refs/heads/$newbranch") ||
+die "we do not like '$newbranch' as a branch name."
+------------
 
 GIT
 ---
index 5ebcba1c7c6e749e2d80e7f98804be600fd548b3..7e7d9fcf508eed3cbc984fec3aabc5d351943a32 100644 (file)
@@ -39,7 +39,7 @@ OPTIONS
 --local::
 -l::
        When the repository to clone from is on a local machine,
-       this flag bypasses normal "git aware" transport
+       this flag bypasses the normal "git aware" transport
        mechanism and clones the repository by making a copy of
        HEAD and everything under objects and refs directories.
        The files under `.git/objects/` directory are hardlinked
@@ -60,7 +60,7 @@ OPTIONS
 -s::
        When the repository to clone is on the local machine,
        instead of using hard links, automatically setup
-       .git/objects/info/alternates to share the objects
+       `.git/objects/info/alternates` to share the objects
        with the source repository.  The resulting repository
        starts out without any object of its own.
 +
@@ -69,7 +69,7 @@ it unless you understand what it does. If you clone your
 repository using this option and then delete branches (or use any
 other git command that makes any existing commit unreferenced) in the
 source repository, some objects may become unreferenced (or dangling).
-These objects may be removed by normal git operations (such as 'git-commit')
+These objects may be removed by normal git operations (such as `git commit`)
 which automatically call `git gc --auto`. (See linkgit:git-gc[1].)
 If these objects are removed and were referenced by the cloned repository,
 then the cloned repository will become corrupt.
@@ -86,13 +86,13 @@ objects from the source repository into a pack in the cloned repository.
 
 --reference <repository>::
        If the reference repository is on the local machine,
-       automatically setup .git/objects/info/alternates to
+       automatically setup `.git/objects/info/alternates` to
        obtain objects from the reference repository.  Using
        an already existing repository as an alternate will
        require fewer objects to be copied from the repository
        being cloned, reducing network and local storage costs.
 +
-*NOTE*: see NOTE to --shared option.
+*NOTE*: see the NOTE for the `--shared` option.
 
 --quiet::
 -q::
@@ -101,7 +101,7 @@ objects from the source repository into a pack in the cloned repository.
 
 --verbose::
 -v::
-       Display the progressbar, even in case the standard output is not
+       Display the progress bar, even in case the standard output is not
        a terminal.
 
 --no-checkout::
@@ -121,17 +121,17 @@ objects from the source repository into a pack in the cloned repository.
        configuration variables are created.
 
 --mirror::
-       Set up a mirror of the remote repository.  This implies --bare.
+       Set up a mirror of the remote repository.  This implies `--bare`.
 
 --origin <name>::
 -o <name>::
-       Instead of using the remote name 'origin' to keep track
-       of the upstream repository, use <name>.
+       Instead of using the remote name `origin` to keep track
+       of the upstream repository, use `<name>`.
 
 --branch <name>::
 -b <name>::
        Instead of pointing the newly created HEAD to the branch pointed
-       to by the cloned repository's HEAD, point to <name> branch
+       to by the cloned repository's HEAD, point to `<name>` branch
        instead. In a non-bare repository, this is the branch that will
        be checked out.
 
@@ -158,7 +158,7 @@ objects from the source repository into a pack in the cloned repository.
 --recursive::
        After the clone is created, initialize all submodules within,
        using their default settings. This is equivalent to running
-       'git submodule update --init --recursive' immediately after
+       `git submodule update --init --recursive` immediately after
        the clone is finished. This option is ignored if the cloned
        repository does not have a worktree/checkout (i.e. if any of
        `--no-checkout`/`-n`, `--bare`, or `--mirror` is given)
@@ -171,8 +171,8 @@ objects from the source repository into a pack in the cloned repository.
 <directory>::
        The name of a new directory to clone into.  The "humanish"
        part of the source repository is used if no directory is
-       explicitly given ("repo" for "/path/to/repo.git" and "foo"
-       for "host.xz:foo/.git").  Cloning into an existing directory
+       explicitly given (`repo` for `/path/to/repo.git` and `foo`
+       for `host.xz:foo/.git`).  Cloning into an existing directory
        is only allowed if the directory is empty.
 
 :git-clone: 1
index b231dbb947791bb4fc5cde552e8c736b3558ca0a..78b9808aa3a2f5fe2435ea188ac4e73508c2720a 100644 (file)
@@ -8,7 +8,9 @@ git-describe - Show the most recent tag that is reachable from a commit
 
 SYNOPSIS
 --------
+[verse]
 'git describe' [--all] [--tags] [--contains] [--abbrev=<n>] <committish>...
+'git describe' [--all] [--tags] [--contains] [--abbrev=<n>] --dirty[=<mark>]
 
 DESCRIPTION
 -----------
@@ -27,6 +29,11 @@ OPTIONS
 <committish>...::
        Committish object names to describe.
 
+--dirty[=<mark>]::
+       Describe the working tree.
+       It means describe HEAD and appends <mark> (`-dirty` by
+       default) if the working tree is dirty.
+
 --all::
        Instead of using only the annotated tags, use any ref
        found in `.git/refs/`.  This option enables matching
@@ -44,7 +51,9 @@ OPTIONS
 
 --abbrev=<n>::
        Instead of using the default 7 hexadecimal digits as the
-       abbreviated object name, use <n> digits.
+       abbreviated object name, use <n> digits, or as many digits
+       as needed to form a unique object name.  An <n> of 0
+       will suppress long format, only showing the closest tag.
 
 --candidates=<n>::
        Instead of considering only the 10 most recent tags as
@@ -68,8 +77,8 @@ OPTIONS
        This is useful when you want to see parts of the commit object name
        in "describe" output, even when the commit in question happens to be
        a tagged version.  Instead of just emitting the tag name, it will
-       describe such a commit as v1.2-0-deadbeef (0th commit since tag v1.2
-       that points at object deadbeef....).
+       describe such a commit as v1.2-0-gdeadbee (0th commit since tag v1.2
+       that points at object deadbee....).
 
 --match <pattern>::
        Only consider tags matching the given pattern (can be used to avoid
@@ -108,7 +117,7 @@ the output shows the reference path as well:
        [torvalds@g5 git]$ git describe --all --abbrev=4 v1.0.5^2
        tags/v1.0.0-21-g975b
 
-       [torvalds@g5 git]$ git describe --all HEAD^
+       [torvalds@g5 git]$ git describe --all --abbrev=4 HEAD^
        heads/lt/describe-7-g975b
 
 With --abbrev set to 0, the command can be used to find the
@@ -117,6 +126,13 @@ closest tagname without any suffix:
        [torvalds@g5 git]$ git describe --abbrev=0 v1.0.5^2
        tags/v1.0.0
 
+Note that the suffix you get if you type these commands today may be
+longer than what Linus saw above when he ran these commands, as your
+git repository may have new commits whose object names begin with
+975b that did not exist back then, and "-g975b" suffix alone may not
+be sufficient to disambiguate these commits.
+
+
 SEARCH STRATEGY
 ---------------
 
index 96a6c51a4b83207fa23fc8f09cb02f57b1085ea4..8e9aed67d7f68c0234ee47dc147736bf3b8e5c4f 100644 (file)
@@ -31,7 +31,7 @@ OPTIONS
        Use the diff tool specified by <tool>.
        Valid merge tools are:
        kdiff3, kompare, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff,
-       ecmerge, diffuse, opendiff and araxis.
+       ecmerge, diffuse, opendiff, p4merge and araxis.
 +
 If a diff tool is not specified, 'git-difftool'
 will use the configuration variable `diff.tool`.  If the
index d3164c5c88db6b9e02a4186c398e19c425bc204b..f2483d624ead24031ef3cf320a0c151cc6f6cb2b 100644 (file)
@@ -37,6 +37,35 @@ include::pull-fetch-param.txt[]
 
 include::urls-remotes.txt[]
 
+
+EXAMPLES
+--------
+
+* Update the remote-tracking branches:
++
+------------------------------------------------
+$ git fetch origin
+------------------------------------------------
++
+The above command copies all branches from the remote refs/heads/
+namespace and stores them to the local refs/remotes/origin/ namespace,
+unless the branch.<name>.fetch option is used to specify a non-default
+refspec.
+
+* Using refspecs explicitly:
++
+------------------------------------------------
+$ git fetch origin +pu:pu maint:tmp
+------------------------------------------------
++
+This updates (or creates, as necessary) branches `pu` and `tmp` in
+the local repository by fetching from the branches (respectively)
+`pu` and `maint` from the remote repository.
++
+The `pu` branch will be updated even if it is does not fast-forward,
+because it is prefixed with a plus sign; `tmp` will not be.
+
+
 SEE ALSO
 --------
 linkgit:git-pull[1]
index 2b40babb6ba1c5eb99ae2cc7748854f5e4dcd864..394a77a35f2019f5c86f9e90e94b88cf56da04ae 100644 (file)
@@ -159,7 +159,18 @@ to other tags will be rewritten to point to the underlying commit.
 --subdirectory-filter <directory>::
        Only look at the history which touches the given subdirectory.
        The result will contain that directory (and only that) as its
-       project root.
+       project root.  Implies --remap-to-ancestor.
+
+--remap-to-ancestor::
+       Rewrite refs to the nearest rewritten ancestor instead of
+       ignoring them.
++
+Normally, positive refs on the command line are only changed if the
+commit they point to was rewritten.  However, you can limit the extent
+of this rewriting by using linkgit:rev-list[1] arguments, e.g., path
+limiters.  Refs pointing to such excluded commits would then normally
+be ignored.  With this option, they are instead rewritten to point at
+the nearest ancestor that was not excluded.
 
 --prune-empty::
        Some kind of filters will generate empty commits, that left the tree
index 687e66759817bc2f349e8a5a89aa2c6731237b23..f1fd0df08ae3067f8f5b41797e5575d465a859af 100644 (file)
@@ -43,28 +43,28 @@ There are two ways to specify which commits to operate on.
 
 The first rule takes precedence in the case of a single <commit>.  To
 apply the second rule, i.e., format everything since the beginning of
-history up until <commit>, use the '\--root' option: "git format-patch
-\--root <commit>".  If you want to format only <commit> itself, you
-can do this with "git format-patch -1 <commit>".
+history up until <commit>, use the '\--root' option: `git format-patch
+\--root <commit>`.  If you want to format only <commit> itself, you
+can do this with `git format-patch -1 <commit>`.
 
 By default, each output file is numbered sequentially from 1, and uses the
 first line of the commit message (massaged for pathname safety) as
-the filename. With the --numbered-files option, the output file names
+the filename. With the `--numbered-files` option, the output file names
 will only be numbers, without the first line of the commit appended.
 The names of the output files are printed to standard
-output, unless the --stdout option is specified.
+output, unless the `--stdout` option is specified.
 
-If -o is specified, output files are created in <dir>.  Otherwise
+If `-o` is specified, output files are created in <dir>.  Otherwise
 they are created in the current working directory.
 
 By default, the subject of a single patch is "[PATCH] First Line" and
 the subject when multiple patches are output is "[PATCH n/m] First
-Line". To force 1/1 to be added for a single patch, use -n.  To omit
-patch numbers from the subject, use -N
+Line". To force 1/1 to be added for a single patch, use `-n`.  To omit
+patch numbers from the subject, use `-N`.
 
-If given --thread, 'git-format-patch' will generate In-Reply-To and
-References headers to make the second and subsequent patch mails appear
-as replies to the first mail; this also generates a Message-Id header to
+If given `--thread`, `git-format-patch` will generate `In-Reply-To` and
+`References` headers to make the second and subsequent patch mails appear
+as replies to the first mail; this also generates a `Message-Id` header to
 reference.
 
 OPTIONS
@@ -112,7 +112,7 @@ include::diff-options.txt[]
 --attach[=<boundary>]::
        Create multipart/mixed attachment, the first part of
        which is the commit message and the patch itself in the
-       second part, with "Content-Disposition: attachment".
+       second part, with `Content-Disposition: attachment`.
 
 --no-attach::
        Disable the creation of an attachment, overriding the
@@ -121,13 +121,13 @@ include::diff-options.txt[]
 --inline[=<boundary>]::
        Create multipart/mixed attachment, the first part of
        which is the commit message and the patch itself in the
-       second part, with "Content-Disposition: inline".
+       second part, with `Content-Disposition: inline`.
 
 --thread[=<style>]::
 --no-thread::
-       Controls addition of In-Reply-To and References headers to
+       Controls addition of `In-Reply-To` and `References` headers to
        make the second and subsequent mails appear as replies to the
-       first.  Also controls generation of the Message-Id header to
+       first.  Also controls generation of the `Message-Id` header to
        reference.
 +
 The optional <style> argument can be either `shallow` or `deep`.
@@ -136,16 +136,16 @@ series, where the head is chosen from the cover letter, the
 `\--in-reply-to`, and the first patch mail, in this order.  'deep'
 threading makes every mail a reply to the previous one.
 +
-The default is --no-thread, unless the 'format.thread' configuration
-is set.  If --thread is specified without a style, it defaults to the
+The default is `--no-thread`, unless the 'format.thread' configuration
+is set.  If `--thread` is specified without a style, it defaults to the
 style specified by 'format.thread' if any, or else `shallow`.
 +
 Beware that the default for 'git send-email' is to thread emails
-itself.  If you want 'git format-patch' to take care of hreading, you
-will want to ensure that threading is disabled for 'git send-email'.
+itself.  If you want `git format-patch` to take care of threading, you
+will want to ensure that threading is disabled for `git send-email`.
 
 --in-reply-to=Message-Id::
-       Make the first mail (or all the mails with --no-thread) appear as a
+       Make the first mail (or all the mails with `--no-thread`) appear as a
        reply to the given Message-Id, which avoids breaking threads to
        provide a new patch series.
 
@@ -160,16 +160,16 @@ will want to ensure that threading is disabled for 'git send-email'.
        Instead of the standard '[PATCH]' prefix in the subject
        line, instead use '[<Subject-Prefix>]'. This
        allows for useful naming of a patch series, and can be
-       combined with the --numbered option.
+       combined with the `--numbered` option.
 
 --cc=<email>::
-       Add a "Cc:" header to the email headers. This is in addition
+       Add a `Cc:` header to the email headers. This is in addition
        to any configured headers, and may be used multiple times.
 
 --add-header=<header>::
        Add an arbitrary header to the email headers.  This is in addition
        to any configured headers, and may be used multiple times.
-       For example, --add-header="Organization: git-foo"
+       For example, `--add-header="Organization: git-foo"`
 
 --cover-letter::
        In addition to the patches, generate a cover letter file
index 287c4fc5e07ea753c2a3d93bf6480f41aac8c9af..6fe9484da325fa1f72809937df263574ffe6fb9b 100644 (file)
@@ -10,7 +10,7 @@ SYNOPSIS
 --------
 [verse]
 'git fsck' [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]
-        [--full] [--strict] [--verbose] [--lost-found] [<object>*]
+        [--[no-]full] [--strict] [--verbose] [--lost-found] [<object>*]
 
 DESCRIPTION
 -----------
@@ -52,7 +52,8 @@ index file, all SHA1 references in .git/refs/*, and all reflogs (unless
        or $GIT_DIR/objects/info/alternates,
        and in packed git archives found in $GIT_DIR/objects/pack
        and corresponding pack subdirectories in alternate
-       object pools.
+       object pools.  This is now default; you can turn it off
+       with --no-full.
 
 --strict::
        Enable more strict checking, namely to catch a file mode
index 1f6df6ad6b374ee92952221856953d2c960a7f7e..4cd9cdf9056fe78b3acbbf62aa080b1e47907b0a 100644 (file)
@@ -120,7 +120,7 @@ Notes
 particular, it will keep not only objects referenced by your current set
 of branches and tags, but also objects referenced by the index, remote
 tracking branches, refs saved by 'git-filter-branch' in
-refs/original/, or reflogs (which may references commits in branches
+refs/original/, or reflogs (which may reference commits in branches
 that were later amended or rewound).
 
 If you are expecting some objects to be collected and they aren't, check
index aef383e0b142bd603b77620cad720c102d70c4b7..ddf7a18dc42ef4d5f8ad44aed89ee5b17bb0e9a6 100644 (file)
@@ -82,11 +82,11 @@ destination side.
 
 Without '--force', the <src> ref is stored at the remote only if
 <dst> does not exist, or <dst> is a proper subset (i.e. an
-ancestor) of <src>.  This check, known as "fast forward check",
+ancestor) of <src>.  This check, known as "fast-forward check",
 is performed in order to avoid accidentally overwriting the
 remote ref and lose other peoples' commits from there.
 
-With '--force', the fast forward check is disabled for all refs.
+With '--force', the fast-forward check is disabled for all refs.
 
 Optionally, a <ref> parameter can be prefixed with a plus '+' sign
 to disable the fast-forward check only on that ref.
index 021066e95d88624d2ec6c90a9218a4fd70ec17b7..625723e41fa072523fa850e37534677cfe8af631 100644 (file)
@@ -48,8 +48,10 @@ OPTIONS
 
 -i::
 --ignored::
-       Show ignored files in the output.
-       Note that this also reverses any exclude list present.
+       Show only ignored files in the output. When showing files in the
+       index, print only those matched by an exclude pattern. When
+       showing "other" files, show only those matched by an exclude
+       pattern.
 
 -s::
 --stage::
index d05f324462d23f64ba9563666e555a9eee3c443f..e886c2ef543501deea84909b2e88fb163a1c9d2b 100644 (file)
@@ -212,6 +212,39 @@ You can work through the conflict with a number of tools:
    common ancestor, 'git show :2:filename' shows the HEAD
    version and 'git show :3:filename' shows the remote version.
 
+
+EXAMPLES
+--------
+
+* Merge branches `fixes` and `enhancements` on top of
+  the current branch, making an octopus merge:
++
+------------------------------------------------
+$ git merge fixes enhancements
+------------------------------------------------
+
+* Merge branch `obsolete` into the current branch, using `ours`
+  merge strategy:
++
+------------------------------------------------
+$ git merge -s ours obsolete
+------------------------------------------------
+
+* Merge branch `maint` into the current branch, but do not make
+  a new commit automatically:
++
+------------------------------------------------
+$ git merge --no-commit maint
+------------------------------------------------
++
+This can be used when you want to include further changes to the
+merge, or want to write your own merge commit message.
++
+You should refrain from abusing this option to sneak substantial
+changes into a merge commit.  Small fixups like bumping
+release/version name would be acceptable.
+
+
 SEE ALSO
 --------
 linkgit:git-fmt-merge-msg[1], linkgit:git-pull[1],
index 68ed6c095664b8f06635ba7eaa85b85086b24280..4a6f7f3a2d189c40e4abfe4f74178f79d1c563fd 100644 (file)
@@ -27,7 +27,7 @@ OPTIONS
        Use the merge resolution program specified by <tool>.
        Valid merge tools are:
        kdiff3, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff, ecmerge,
-       diffuse, tortoisemerge, opendiff and araxis.
+       diffuse, tortoisemerge, opendiff, p4merge and araxis.
 +
 If a merge resolution program is not specified, 'git-mergetool'
 will use the configuration variable `merge.tool`.  If the
index 7578623edba9e2ddc5232f1a981bcb297182638d..b93201158fa6fda914b6093af5911b7884328838 100644 (file)
@@ -26,6 +26,10 @@ Also note that options meant for 'git-pull' itself and underlying
 
 OPTIONS
 -------
+
+Options related to merging
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
 include::merge-options.txt[]
 
 :git-pull: 1
@@ -47,6 +51,9 @@ unless you have read linkgit:git-rebase[1] carefully.
 --no-rebase::
        Override earlier --rebase.
 
+Options related to fetching
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
 include::fetch-options.txt[]
 
 include::pull-fetch-param.txt[]
@@ -131,54 +138,13 @@ $ git pull origin next
 ------------------------------------------------
 +
 This leaves a copy of `next` temporarily in FETCH_HEAD, but
-does not update any remote-tracking branches.
-
-* Bundle local branch `fixes` and `enhancements` on top of
-  the current branch, making an Octopus merge:
-+
-------------------------------------------------
-$ git pull . fixes enhancements
-------------------------------------------------
-+
-This `git pull .` syntax is equivalent to `git merge`.
-
-* Merge local branch `obsolete` into the current branch, using `ours`
-  merge strategy:
-+
-------------------------------------------------
-$ git pull -s ours . obsolete
-------------------------------------------------
-
-* Merge local branch `maint` into the current branch, but do not make
-  a commit automatically:
+does not update any remote-tracking branches. Using remote-tracking
+branches, the same can be done by invoking fetch and merge:
 +
 ------------------------------------------------
-$ git pull --no-commit . maint
+$ git fetch origin
+$ git merge origin/next
 ------------------------------------------------
-+
-This can be used when you want to include further changes to the
-merge, or want to write your own merge commit message.
-+
-You should refrain from abusing this option to sneak substantial
-changes into a merge commit.  Small fixups like bumping
-release/version name would be acceptable.
-
-* Command line pull of multiple branches from one repository:
-+
-------------------------------------------------
-$ git checkout master
-$ git fetch origin +pu:pu maint:tmp
-$ git pull . tmp
-------------------------------------------------
-+
-This updates (or creates, as necessary) branches `pu` and `tmp` in
-the local repository by fetching from the branches (respectively)
-`pu` and `maint` from the remote repository.
-+
-The `pu` branch will be updated even if it is does not fast-forward;
-the others will not be.
-+
-The final command then merges the newly fetched `tmp` into master.
 
 
 If you tried a pull which resulted in a complex conflicts and
index ba6a8a2fb21128fc90ca0364a0760700c4fb1658..52c0538df528ecbb5b755a2e75fc1715762bfc00 100644 (file)
@@ -50,9 +50,9 @@ updated.
 +
 The object referenced by <src> is used to update the <dst> reference
 on the remote side, but by default this is only allowed if the
-update can fast forward <dst>.  By having the optional leading `{plus}`,
+update can fast-forward <dst>.  By having the optional leading `{plus}`,
 you can tell git to update the <dst> ref even when the update is not a
-fast forward.  This does *not* attempt to merge <src> into <dst>.  See
+fast-forward.  This does *not* attempt to merge <src> into <dst>.  See
 EXAMPLES below for details.
 +
 `tag <tag>` means the same as `refs/tags/<tag>:refs/tags/<tag>`.
@@ -60,7 +60,7 @@ EXAMPLES below for details.
 Pushing an empty <src> allows you to delete the <dst> ref from
 the remote repository.
 +
-The special refspec `:` (or `{plus}:` to allow non-fast forward updates)
+The special refspec `:` (or `{plus}:` to allow non-fast-forward updates)
 directs git to push "matching" branches: for every branch that exists on
 the local side, the remote side is updated if a branch of the same name
 already exists on the remote side.  This is the default operation mode
@@ -138,6 +138,11 @@ useful if you write an alias or script around 'git-push'.
 --verbose::
        Run verbosely.
 
+-q::
+--quiet::
+       Suppress all output, including the listing of updated refs,
+       unless an error occurs.
+
 include::urls-remotes.txt[]
 
 OUTPUT
@@ -171,10 +176,10 @@ summary::
        For a successfully pushed ref, the summary shows the old and new
        values of the ref in a form suitable for using as an argument to
        `git log` (this is `<old>..<new>` in most cases, and
-       `<old>...<new>` for forced non-fast forward updates). For a
+       `<old>...<new>` for forced non-fast-forward updates). For a
        failed update, more details are given for the failure.
        The string `rejected` indicates that git did not try to send the
-       ref at all (typically because it is not a fast forward). The
+       ref at all (typically because it is not a fast-forward). The
        string `remote rejected` indicates that the remote end refused
        the update; this rejection is typically caused by a hook on the
        remote side. The string `remote failure` indicates that the
@@ -342,9 +347,9 @@ git push origin :experimental::
 
 git push origin {plus}dev:master::
        Update the origin repository's master branch with the dev branch,
-       allowing non-fast forward updates.  *This can leave unreferenced
+       allowing non-fast-forward updates.  *This can leave unreferenced
        commits dangling in the origin repository.*  Consider the
-       following situation, where a fast forward is not possible:
+       following situation, where a fast-forward is not possible:
 +
 ----
            o---o---o---A---B  origin/master
index 4a932b08c6ed4f1de46d51fd92046d5190f831a7..a10ce4ba40cc509a0f3a8f39551310fdd9231e71 100644 (file)
@@ -144,7 +144,7 @@ Two Tree Merge
 Typically, this is invoked as `git read-tree -m $H $M`, where $H
 is the head commit of the current repository, and $M is the head
 of a foreign tree, which is simply ahead of $H (i.e. we are in a
-fast forward situation).
+fast-forward situation).
 
 When two trees are specified, the user is telling 'git-read-tree'
 the following:
index 0aefc34d0d311030687563c56eaf3ac85a687e28..33e0ef1f6d48c22eddb2b1a7273065a4269924ae 100644 (file)
@@ -368,14 +368,17 @@ By replacing the command "pick" with the command "edit", you can tell
 the files and/or the commit message, amend the commit, and continue
 rebasing.
 
+If you just want to edit the commit message for a commit, replace the
+command "pick" with the command "reword".
+
 If you want to fold two or more commits into one, replace the command
 "pick" with "squash" for the second and subsequent commit.  If the
 commits had different authors, it will attribute the squashed commit to
 the author of the first commit.
 
-In both cases, or when a "pick" does not succeed (because of merge
-errors), the loop will stop to let you fix things, and you can continue
-the loop with `git rebase --continue`.
+'git-rebase' will stop when "pick" has been replaced with "edit" or
+when a command fails due to merge errors. When you are done editing
+and/or resolving conflicts you can continue with `git rebase --continue`.
 
 For example, if you want to reorder the last 5 commits, such that what
 was HEAD~4 becomes the new HEAD. To achieve that, you would call
index 514f03c97903aa0be41a4a8f0df236ccb68280b0..cb5f4052806d81b04d4a096d3697e0230d13e8ed 100644 (file)
@@ -20,7 +20,7 @@ The UI for the protocol is on the 'git-send-pack' side, and the
 program pair is meant to be used to push updates to remote
 repository.  For pull operations, see linkgit:git-fetch-pack[1].
 
-The command allows for creation and fast forwarding of sha1 refs
+The command allows for creation and fast-forwarding of sha1 refs
 (heads/tags) on the remote end (strictly speaking, it is the
 local end 'git-receive-pack' runs, but to the user who is sitting at
 the send-pack end, it is updating the remote.  Confused?)
index 915cb77b29f9d0fa71a288cace435e73637e1283..8adc1ef55c620d04fc10b8d6ccb0b9c90765a753 100644 (file)
@@ -23,6 +23,26 @@ replacement object.
 Unless `-f` is given, the replace reference must not yet exist in
 `.git/refs/replace/` directory.
 
+Replace references will be used by default by all git commands except
+those doing reachability traversal (prune, pack transfer and fsck).
+
+It is possible to disable use of replacement refs for any command
+using the --no-replace-objects option just after "git".
+
+For example if commit "foo" has been replaced by commit "bar":
+
+------------------------------------------------
+$ git --no-replace-object cat-file commit foo
+------------------------------------------------
+
+show information about commit "foo", while:
+
+------------------------------------------------
+$ git cat-file commit foo
+------------------------------------------------
+
+show information about commit "bar".
+
 OPTIONS
 -------
 -f::
@@ -54,6 +74,7 @@ SEE ALSO
 --------
 linkgit:git-tag[1]
 linkgit:git-branch[1]
+linkgit:git[1]
 
 Author
 ------
index 469cf6dbacb8de24b5dd0dd78d63dd9ecc8fbd01..2d27e405a39c77f1a7d7507db2f063a4819bec47 100644 (file)
@@ -150,7 +150,7 @@ Automatic merge failed; fix conflicts and then commit the result.
 $ git reset --hard                 <2>
 $ git pull . topic/branch          <3>
 Updating from 41223... to 13134...
-Fast forward
+Fast-forward
 $ git reset --hard ORIG_HEAD       <4>
 ------------
 +
@@ -161,7 +161,7 @@ right now, so you decide to do that later.
 which is a synonym for "git reset --hard HEAD" clears the mess
 from the index file and the working tree.
 <3> Merge a topic branch into the current branch, which resulted
-in a fast forward.
+in a fast-forward.
 <4> But you decided that the topic branch is not ready for public
 consumption yet.  "pull" or "merge" always leaves the original
 tip of the current branch in ORIG_HEAD, so resetting hard to it
index 399821832c2a5cd6a718a7dc37a87e6b5bc0b213..5a04c6eaf78adb8c6ccff573d873392e19640fdd 100644 (file)
@@ -105,11 +105,11 @@ name. See linkgit:git-rev-parse[1].
 
 Without '--force', the <src> ref is stored at the remote only if
 <dst> does not exist, or <dst> is a proper subset (i.e. an
-ancestor) of <src>.  This check, known as "fast forward check",
+ancestor) of <src>.  This check, known as "fast-forward check",
 is performed in order to avoid accidentally overwriting the
 remote ref and lose other peoples' commits from there.
 
-With '--force', the fast forward check is disabled for all refs.
+With '--force', the fast-forward check is disabled for all refs.
 
 Optionally, a <ref> parameter can be prefixed with a plus '+' sign
 to disable the fast-forward check only on that ref.
index f4429bdc6863ce1d115b47282f2c04a4d9093d29..70f400b2664df422160195a9615d566152a1b877 100644 (file)
@@ -8,7 +8,7 @@ git-show-ref - List references in a local repository
 SYNOPSIS
 --------
 [verse]
-'git show-ref' [-q|--quiet] [--verify] [-h|--head] [-d|--dereference]
+'git show-ref' [-q|--quiet] [--verify] [--head] [-d|--dereference]
             [-s|--hash[=<n>]] [--abbrev[=<n>]] [--tags]
             [--heads] [--] <pattern>...
 'git show-ref' --exclude-existing[=<pattern>] < ref-list
@@ -30,7 +30,6 @@ the `.git` directory.
 OPTIONS
 -------
 
--h::
 --head::
 
        Show the HEAD reference.
index 5ccdd18c89381e81fc616facb22bd7fee6faf964..4ef70c42ebf512ee6dc946ca2ceee284b3211b54 100644 (file)
@@ -10,7 +10,7 @@ SYNOPSIS
 --------
 [verse]
 'git submodule' [--quiet] add [-b branch]
-             [--reference <repository>] [--] <repository> <path>
+             [--reference <repository>] [--] <repository> [<path>]
 'git submodule' [--quiet] status [--cached] [--recursive] [--] [<path>...]
 'git submodule' [--quiet] init [--] [<path>...]
 'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--rebase]
@@ -69,7 +69,11 @@ add::
        to the changeset to be committed next to the current
        project: the current project is termed the "superproject".
 +
-This requires two arguments: <repository> and <path>.
+This requires at least one argument: <repository>. The optional
+argument <path> is the relative location for the cloned submodule
+to exist in the superproject. If <path> is not given, the
+"humanish" part of the source repository is used ("repo" for
+"/path/to/repo.git" and "foo" for "host.xz:foo/.git").
 +
 <repository> is the URL of the new submodule's origin repository.
 This may be either an absolute URL, or (if it begins with ./
index 1812890a7e986b2632972390ea4646331c0c922b..4cdca0d87435b4995e5c051750a6dd02720006f8 100644 (file)
@@ -320,6 +320,13 @@ Any other arguments are passed directly to 'git log'
        directories.  The output is suitable for appending to
        the $GIT_DIR/info/exclude file.
 
+'mkdirs'::
+       Attempts to recreate empty directories that core git cannot track
+       based on information in $GIT_DIR/svn/<refname>/unhandled.log files.
+       Empty directories are automatically recreated when using
+       "git svn clone" and "git svn rebase", so "mkdirs" is intended
+       for use after commands like "git checkout" or "git reset".
+
 'commit-diff'::
        Commits the diff of two tree-ish arguments from the
        command-line.  This command does not rely on being inside an `git svn
@@ -735,6 +742,16 @@ merges you've made.  Furthermore, if you merge or pull from a git branch
 that is a mirror of an SVN branch, 'dcommit' may commit to the wrong
 branch.
 
+If you do merge, note the following rule: 'git svn dcommit' will
+attempt to commit on top of the SVN commit named in
+------------------------------------------------------------------------
+git log --grep=^git-svn-id: --first-parent -1
+------------------------------------------------------------------------
+You 'must' therefore ensure that the most recent commit of the branch
+you want to dcommit to is the 'first' parent of the merge.  Chaos will
+ensue otherwise, especially if the first parent is an older commit on
+the same SVN branch.
+
 'git clone' does not clone branches under the refs/remotes/ hierarchy or
 any 'git svn' metadata, or config.  So repositories created and managed with
 using 'git svn' should use 'rsync' for cloning, if cloning is to be done
index 25e0bbea86caf1234da1746d4a2082cfb80129bd..6052484ab9e28d5565067885b1c4ed5667e8e90f 100644 (file)
@@ -99,6 +99,10 @@ in the index e.g. when merging in a commit;
 thus, in case the assumed-untracked file is changed upstream,
 you will need to handle the situation manually.
 
+--really-refresh::
+       Like '--refresh', but checks stat information unconditionally,
+       without regard to the "assume unchanged" setting.
+
 -g::
 --again::
        Runs 'git-update-index' itself on the paths whose index
@@ -308,7 +312,7 @@ Configuration
 -------------
 
 The command honors `core.filemode` configuration variable.  If
-your repository is on an filesystem whose executable bits are
+your repository is on a filesystem whose executable bits are
 unreliable, this should be set to 'false' (see linkgit:git-config[1]).
 This causes the command to ignore differences in file modes recorded
 in the index and the file mode on the filesystem if they differ only on
index d97aaf5bf8a2973f68e8bad308ae7a7fba1bf36b..8e577cc4fe2fd445ef238efc812d12b58156fec4 100644 (file)
@@ -10,7 +10,7 @@ SYNOPSIS
 --------
 [verse]
 'git' [--version] [--exec-path[=GIT_EXEC_PATH]] [--html-path]
-    [-p|--paginate|--no-pager]
+    [-p|--paginate|--no-pager] [--no-replace-objects]
     [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE]
     [--help] COMMAND [ARGS]
 
@@ -43,9 +43,12 @@ unreleased) version of git, that is available from 'master'
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
-* link:v1.6.5/git.html[documentation for release 1.6.5]
+* link:v1.6.5.3/git.html[documentation for release 1.6.5.3]
 
 * release notes for
+  link:RelNotes-1.6.5.3.txt[1.6.5.3],
+  link:RelNotes-1.6.5.2.txt[1.6.5.2],
+  link:RelNotes-1.6.5.1.txt[1.6.5.1],
   link:RelNotes-1.6.5.txt[1.6.5].
 
 * link:v1.6.4.4/git.html[documentation for release 1.6.4.4]
@@ -237,6 +240,10 @@ help ...`.
        environment is not set, it is set to the current working
        directory.
 
+--no-replace-objects::
+       Do not use replacement refs to replace git objects. See
+       linkgit:git-replace[1] for more information.
+
 
 FURTHER DOCUMENTATION
 ---------------------
index 1195e83b6e65b5cf7926c973c730ffe19ff92202..1f472cea59a64023d91d25b09cc4d6f0aa39bc28 100644 (file)
@@ -560,6 +560,16 @@ in the file.  E.g. the string `$Format:%H$` will be replaced by the
 commit hash.
 
 
+Packing objects
+~~~~~~~~~~~~~~~
+
+`delta`
+^^^^^^^
+
+Delta compression will not be attempted for blobs for paths with the
+attribute `delta` set to false.
+
+
 Viewing files in GUI tools
 ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
index b3640c4e64494689841e598cf17741ea8620af12..b7380b069ac35ed72f3673add60ce4566823b7aa 100644 (file)
@@ -185,7 +185,7 @@ object is. git will tell you that you have a "blob" object (i.e., just a
 regular file), and you can see the contents with
 
 ----------------
-$ git cat-file "blob" 557db03
+$ git cat-file blob 557db03
 ----------------
 
 which will print out "Hello World". The object `557db03` is nothing
@@ -993,7 +993,7 @@ would be different)
 
 ----------------
 Updating from ae3a2da... to a80b4aa....
-Fast forward (no commit created; -m option ignored)
+Fast-forward (no commit created; -m option ignored)
  example |    1 +
  hello   |    1 +
  2 files changed, 2 insertions(+), 0 deletions(-)
@@ -1003,7 +1003,7 @@ Because your branch did not contain anything more than what had
 already been merged into the `master` branch, the merge operation did
 not actually do a merge. Instead, it just updated the top of
 the tree of your branch to that of the `master` branch. This is
-often called 'fast forward' merge.
+often called 'fast-forward' merge.
 
 You can run `gitk \--all` again to see how the commit ancestry
 looks like, or run 'show-branch', which tells you this.
@@ -1188,7 +1188,7 @@ $ git show-branch
 --
  + [mybranch] Some work.
 *  [master] Some fun.
-*+ [mybranch^] New day.
+*+ [mybranch^] Initial commit
 ------------
 
 Now we are ready to experiment with the merge by hand.
@@ -1204,11 +1204,11 @@ $ mb=$(git merge-base HEAD mybranch)
 The command writes the commit object name of the common ancestor
 to the standard output, so we captured its output to a variable,
 because we will be using it in the next step.  By the way, the common
-ancestor commit is the "New day." commit in this case.  You can
+ancestor commit is the "Initial commit" commit in this case.  You can
 tell it by:
 
 ------------
-$ git name-rev $mb
+$ git name-rev --name-only --tags $mb
 my-first-tag
 ------------
 
@@ -1237,8 +1237,8 @@ inspect the index file with this command:
 ------------
 $ git ls-files --stage
 100644 7f8b141b65fdcee47321e399a2598a235a032422 0      example
-100644 263414f423d0e4d70dae8fe53fa34614ff3e2860 1      hello
-100644 06fa6a24256dc7e560efa5687fa84b51f0263c3a 2      hello
+100644 557db03de997c86a4a028e1ebd3a1ceb225be238 1      hello
+100644 ba42a2a96e3027f3333e13ede4ccf4498c3ae942 2      hello
 100644 cc44c73eb783565da5831b4d820c962954019b69 3      hello
 ------------
 
@@ -1253,8 +1253,8 @@ To look at only non-zero stages, use `\--unmerged` flag:
 
 ------------
 $ git ls-files --unmerged
-100644 263414f423d0e4d70dae8fe53fa34614ff3e2860 1      hello
-100644 06fa6a24256dc7e560efa5687fa84b51f0263c3a 2      hello
+100644 557db03de997c86a4a028e1ebd3a1ceb225be238 1      hello
+100644 ba42a2a96e3027f3333e13ede4ccf4498c3ae942 2      hello
 100644 cc44c73eb783565da5831b4d820c962954019b69 3      hello
 ------------
 
@@ -1283,8 +1283,8 @@ the working tree..  This can be seen if you run `ls-files
 ------------
 $ git ls-files --stage
 100644 7f8b141b65fdcee47321e399a2598a235a032422 0      example
-100644 263414f423d0e4d70dae8fe53fa34614ff3e2860 1      hello
-100644 06fa6a24256dc7e560efa5687fa84b51f0263c3a 2      hello
+100644 557db03de997c86a4a028e1ebd3a1ceb225be238 1      hello
+100644 ba42a2a96e3027f3333e13ede4ccf4498c3ae942 2      hello
 100644 cc44c73eb783565da5831b4d820c962954019b69 3      hello
 ------------
 
index 06e0f315c3bb5bb6ef3320b8b1922b76480f9646..4cc3d1387fbdb60a2134a2e399fa46140939fe2f 100644 (file)
@@ -229,7 +229,7 @@ from updating that ref.
 This hook can be used to prevent 'forced' update on certain refs by
 making sure that the object name is a commit object that is a
 descendant of the commit object named by the old object name.
-That is, to enforce a "fast forward only" policy.
+That is, to enforce a "fast-forward only" policy.
 
 It could also be used to log the old..new status.  However, it
 does not know the entire set of branches, so it would end up
index 2b021e3c155013965a383a2188fd1c380d379b62..91c0eea8904b520bf3d3b6295e50a4ebfac44e86 100644 (file)
@@ -209,6 +209,121 @@ chance to see if their in-progress work will be compatible.  `git.git`
 has such an official throw-away integration branch called 'pu'.
 
 
+Branch management for a release
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Assuming you are using the merge approach discussed above, when you
+are releasing your project you will need to do some additional branch
+management work.
+
+A feature release is created from the 'master' branch, since 'master'
+tracks the commits that should go into the next feature release.
+
+The 'master' branch is supposed to be a superset of 'maint'. If this
+condition does not hold, then 'maint' contains some commits that
+are not included on 'master'. The fixes represented by those commits
+will therefore not be included in your feature release.
+
+To verify that 'master' is indeed a superset of 'maint', use git log:
+
+.Verify 'master' is a superset of 'maint'
+[caption="Recipe: "]
+=====================================
+git log master..maint
+=====================================
+
+This command should not list any commits.  Otherwise, check out
+'master' and merge 'maint' into it.
+
+Now you can proceed with the creation of the feature release. Apply a
+tag to the tip of 'master' indicating the release version:
+
+.Release tagging
+[caption="Recipe: "]
+=====================================
+`git tag -s -m "GIT X.Y.Z" vX.Y.Z master`
+=====================================
+
+You need to push the new tag to a public git server (see
+"DISTRIBUTED WORKFLOWS" below). This makes the tag available to
+others tracking your project. The push could also trigger a
+post-update hook to perform release-related items such as building
+release tarballs and preformatted documentation pages.
+
+Similarly, for a maintenance release, 'maint' is tracking the commits
+to be released. Therefore, in the steps above simply tag and push
+'maint' rather than 'master'.
+
+
+Maintenance branch management after a feature release
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+After a feature release, you need to manage your maintenance branches.
+
+First, if you wish to continue to release maintenance fixes for the
+feature release made before the recent one, then you must create
+another branch to track commits for that previous release.
+
+To do this, the current maintenance branch is copied to another branch
+named with the previous release version number (e.g. maint-X.Y.(Z-1)
+where X.Y.Z is the current release).
+
+.Copy maint
+[caption="Recipe: "]
+=====================================
+`git branch maint-X.Y.(Z-1) maint`
+=====================================
+
+The 'maint' branch should now be fast-forwarded to the newly released
+code so that maintenance fixes can be tracked for the current release:
+
+.Update maint to new release
+[caption="Recipe: "]
+=====================================
+* `git checkout maint`
+* `git merge --ff-only master`
+=====================================
+
+If the merge fails because it is not a fast-forward, then it is
+possible some fixes on 'maint' were missed in the feature release.
+This will not happen if the content of the branches was verified as
+described in the previous section.
+
+
+Branch management for next and pu after a feature release
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+After a feature release, the integration branch 'next' may optionally be
+rewound and rebuilt from the tip of 'master' using the surviving
+topics on 'next':
+
+.Rewind and rebuild next
+[caption="Recipe: "]
+=====================================
+* `git checkout next`
+* `git reset --hard master`
+* `git merge ai/topic_in_next1`
+* `git merge ai/topic_in_next2`
+* ...
+=====================================
+
+The advantage of doing this is that the history of 'next' will be
+clean. For example, some topics merged into 'next' may have initially
+looked promising, but were later found to be undesirable or premature.
+In such a case, the topic is reverted out of 'next' but the fact
+remains in the history that it was once merged and reverted. By
+recreating 'next', you give another incarnation of such topics a clean
+slate to retry, and a feature release is a good point in history to do
+so.
+
+If you do this, then you should make a public announcement indicating
+that 'next' was rewound and rebuilt.
+
+The same rewind and rebuild process may be followed for 'pu'. A public
+announcement is not necessary since 'pu' is a throw-away branch, as
+described above.
+
+
 DISTRIBUTED WORKFLOWS
 ---------------------
 
index 43d84d15e921435ba4629a7d8c18021d16f89223..1f029f8aa080c4de6323e8b4905a81fa7e8e2046 100644 (file)
@@ -124,7 +124,7 @@ to point at the new commit.
        An evil merge is a <<def_merge,merge>> that introduces changes that
        do not appear in any <<def_parent,parent>>.
 
-[[def_fast_forward]]fast forward::
+[[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
@@ -220,7 +220,7 @@ to point at the new commit.
        conflict, manual intervention may be required to complete the
        merge.
 +
-As a noun: unless it is a <<def_fast_forward,fast forward>>, a
+As a noun: unless it is a <<def_fast_forward,fast-forward>>, a
 successful merge results in the creation of a new <<def_commit,commit>>
 representing the result of the merge, and having as
 <<def_parent,parents>> the tips of the merged <<def_branch,branches>>.
index 4357e269131fad960367534ae4161fe078fee30a..d527b307707c676e82a08f18cb9fdd7d3abcb228 100644 (file)
@@ -59,7 +59,7 @@ The policy.
    not yet pass the criteria set for 'next'.
 
  - The tips of 'master', 'maint' and 'next' branches will always
-   fast forward, to allow people to build their own
+   fast-forward, to allow people to build their own
    customization on top of them.
 
  - Usually 'master' contains all of 'maint', 'next' contains all
index e70d8a31e7b05e8efc70c6a56f476324065d57a6..8c32da6deb05b5da700a5bd0a4281bf862b23f2c 100644 (file)
@@ -85,7 +85,7 @@ Fortunately I did not have to; what I have in the current branch
 
 ------------------------------------------------
 $ git checkout master
-$ git merge revert-c99 ;# this should be a fast forward
+$ git merge revert-c99 ;# this should be a fast-forward
 Updating from 10d781b9caa4f71495c7b34963bef137216f86a8 to e3a693c...
  cache.h        |    8 ++++----
  commit.c       |    2 +-
@@ -95,7 +95,7 @@ Updating from 10d781b9caa4f71495c7b34963bef137216f86a8 to e3a693c...
  5 files changed, 8 insertions(+), 8 deletions(-)
 ------------------------------------------------
 
-There is no need to redo the test at this point.  We fast forwarded
+There is no need to redo the test at this point.  We fast-forwarded
 and we know 'master' matches 'revert-c99' exactly.  In fact:
 
 ------------------------------------------------
index 697d9188850e9a685045da5bd37844b02978752d..b7f8d416d65ca1cf17d6348e858a13f6ed72c7fe 100644 (file)
@@ -76,7 +76,7 @@ case "$1" in
     if expr "$2" : '0*$' >/dev/null; then
       info "The branch '$1' is new..."
     else
-      # updating -- make sure it is a fast forward
+      # updating -- make sure it is a fast-forward
       mb=$(git-merge-base "$2" "$3")
       case "$mb,$2" in
         "$2,$mb") info "Update is fast-forward" ;;
diff --git a/Documentation/manpage-quote-apos.xsl b/Documentation/manpage-quote-apos.xsl
new file mode 100644 (file)
index 0000000..aeb8839
--- /dev/null
@@ -0,0 +1,16 @@
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+               version="1.0">
+
+<!-- work around newer groff/man setups using a prettier apostrophe
+     that unfortunately does not quote anything when cut&pasting
+     examples to the shell -->
+<xsl:template name="escape.apostrophe">
+  <xsl:param name="content"/>
+  <xsl:call-template name="string.subst">
+    <xsl:with-param name="string" select="$content"/>
+    <xsl:with-param name="target">'</xsl:with-param>
+    <xsl:with-param name="replacement">\(aq</xsl:with-param>
+  </xsl:call-template>
+</xsl:template>
+
+</xsl:stylesheet>
index c0f96e70708cab74a13ec8696db003289f99b455..a403155052299dd0aaafd6bdfe0fec92d0d0ac7c 100644 (file)
@@ -23,7 +23,7 @@ merge.tool::
        Controls which merge resolution program is used by
        linkgit:git-mergetool[1].  Valid built-in values are: "kdiff3",
        "tkdiff", "meld", "xxdiff", "emerge", "vimdiff", "gvimdiff",
-       "diffuse", "ecmerge", "tortoisemerge", "araxis", and
+       "diffuse", "ecmerge", "tortoisemerge", "p4merge", "araxis" and
        "opendiff".  Any other value is treated is custom merge tool
        and there must be a corresponding mergetool.<tool>.cmd option.
 
index adadf8e4bf309a2fd2ec8efbeff09b410ca7b041..fec33943058ea3e139aff0b898ef55a677d4067e 100644 (file)
@@ -1,43 +1,42 @@
--q::
---quiet::
-       Operate quietly.
-
--v::
---verbose::
-       Be verbose.
-
---stat::
-       Show a diffstat at the end of the merge. The diffstat is also
-       controlled by the configuration option merge.stat.
-
--n::
---no-stat::
-       Do not show a diffstat at the end of the merge.
+--commit::
+--no-commit::
+       Perform the merge and commit the result. This option can
+       be used to override --no-commit.
++
+With --no-commit perform the merge but pretend the merge
+failed and do not autocommit, to give the user a chance to
+inspect and further tweak the merge result before committing.
 
---summary::
---no-summary::
-       Synonyms to --stat and --no-stat; these are deprecated and will be
-       removed in the future.
+--ff::
+--no-ff::
+       Do not generate a merge commit if the merge resolved as
+       a fast-forward, only update the branch pointer. This is
+       the default behavior of git-merge.
++
+With --no-ff Generate a merge commit even if the merge
+resolved as a fast-forward.
 
 --log::
+--no-log::
        In addition to branch names, populate the log message with
        one-line descriptions from the actual commits that are being
        merged.
++
+With --no-log do not list one-line descriptions from the
+actual commits being merged.
 
---no-log::
-       Do not list one-line descriptions from the actual commits being
-       merged.
-
---no-commit::
-       Perform the merge but pretend the merge failed and do
-       not autocommit, to give the user a chance to inspect and
-       further tweak the merge result before committing.
 
---commit::
-       Perform the merge and commit the result. This option can
-       be used to override --no-commit.
+--stat::
+-n::
+--no-stat::
+       Show a diffstat at the end of the merge. The diffstat is also
+       controlled by the configuration option merge.stat.
++
+With -n or --no-stat do not show a diffstat at the end of the
+merge.
 
 --squash::
+--no-squash::
        Produce the working tree and index state as if a real
        merge happened (except for the merge information),
        but do not actually make a commit or
        commit.  This allows you to create a single commit on
        top of the current branch whose effect is the same as
        merging another branch (or more in case of an octopus).
++
+With --no-squash perform the merge and commit the result. This
+option can be used to override --squash.
 
---no-squash::
-       Perform the merge and commit the result. This option can
-       be used to override --squash.
-
---no-ff::
-       Generate a merge commit even if the merge resolved as a
-       fast-forward.
-
---ff::
-       Do not generate a merge commit if the merge resolved as
-       a fast-forward, only update the branch pointer. This is
-       the default behavior of git-merge.
+--ff-only::
+       Refuse to merge and exit with a non-zero status unless the
+       current `HEAD` is already up-to-date or the merge can be
+       resolved as a fast-forward.
 
 -s <strategy>::
 --strategy=<strategy>::
        If there is no `-s` option, a built-in list of strategies
        is used instead ('git-merge-recursive' when merging a single
        head, 'git-merge-octopus' otherwise).
+
+--summary::
+--no-summary::
+       Synonyms to --stat and --no-stat; these are deprecated and will be
+       removed in the future.
+
+-q::
+--quiet::
+       Operate quietly.
+
+-v::
+--verbose::
+       Be verbose.
index 2a845b1e57590a6f18f05fd3efa858b736c1071a..38b9904791466152a98ab3df7c5b84ac66dbac73 100644 (file)
@@ -123,6 +123,9 @@ The placeholders are:
 - '%s': subject
 - '%f': sanitized subject line, suitable for a filename
 - '%b': body
+- '%gD': reflog selector, e.g., `refs/stash@\{1\}`
+- '%gd': shortened reflog selector, e.g., `stash@\{1\}`
+- '%gs': reflog subject
 - '%Cred': switch color to red
 - '%Cgreen': switch color to green
 - '%Cblue': switch color to blue
@@ -132,6 +135,12 @@ The placeholders are:
 - '%n': newline
 - '%x00': print a byte from a hex code
 
+NOTE: Some placeholders may depend on other options given to the
+revision traversal engine. For example, the `%g*` reflog options will
+insert an empty string unless we are traversing reflog entries (e.g., by
+`git log -g`). The `%d` placeholder will use the "short" decoration
+format if `--decorate` was not already provided on the command line.
+
 * 'tformat:'
 +
 The 'tformat:' format works exactly like 'format:', except that it
index 81e7ad7df4d4f7e2dc2e1f31109f28b3b9627860..beba065252f4b0fb375632a6027a45d74d1a12b9 100644 (file)
@@ -1,15 +1,15 @@
 gittutorial(7)
 ==============
 
-NAME
+NOME
 ----
 gittutorial - Um tutorial de introdução ao git (para versão 1.5.1 ou mais nova)
 
-SYNOPSIS
+SINOPSE
 --------
 git *
 
-DESCRIPTION
+DESCRIÇÃO
 -----------
 
 Este tutorial explica como importar um novo projeto para o git,
@@ -64,11 +64,11 @@ Git irá responder
 Initialized empty Git repository in .git/
 ------------------------------------------------
 
-Você agora iniciou seu diretório de trabalho--você deve ter notado um
-novo diretório criado, com o nome de ".git".
+Agora que você iniciou seu diretório de trabalho, você deve ter notado que um
+novo diretório foi criado com o nome de ".git".
 
 A seguir, diga ao git para gravar um instantâneo do conteúdo de todos os
-arquivos sob o diretório corrente (note o '.'), com 'git-add':
+arquivos sob o diretório atual (note o '.'), com 'git-add':
 
 ------------------------------------------------
 $ git add .
@@ -126,8 +126,8 @@ mudanças com:
 $ git commit
 ------------------------------------------------
 
-Isto irá novamente te pedir por uma mensagem descrevendo a mudança, e,
-então, gravar a nova versão do projeto.
+Ao executar esse comando, ele irá te pedir uma mensagem descrevendo a mudança,
+e, então, irá gravar a nova versão do projeto.
 
 Alternativamente, ao invés de executar 'git-add' antes, você pode usar
 
@@ -143,7 +143,7 @@ idéia começar a mensagem com uma simples e curta (menos de 50
 caracteres) linha sumarizando a mudança, seguida de uma linha em branco
 e, então, uma descrição mais detalhada. Ferramentas que transformam
 commits em email, por exemplo, usam a primeira linha no campo de
-cabeçalho Subject: e o resto no corpo.
+cabeçalho "Subject:" e o resto no corpo.
 
 Git rastreia conteúdo, não arquivos
 ----------------------------
@@ -155,7 +155,7 @@ usado tanto para arquivos novos e arquivos recentemente modificados, e
 em ambos os casos, ele tira o instantâneo dos arquivos dados e armazena
 o conteúdo no índice, pronto para inclusão do próximo commit.
 
-Visualizando história do projeto
+Visualizando história do projeto
 -----------------------
 
 Em qualquer ponto você pode visualizar a história das suas mudanças
@@ -165,7 +165,7 @@ usando
 $ git log
 ------------------------------------------------
 
-Se você também quer ver a diferença completa a cada passo, use
+Se você também quiser ver a diferença completa a cada passo, use
 
 ------------------------------------------------
 $ git log -p
index f9811f24733bde97b76dc8e695bad82eace5586b..44d936341fffe12d74b0ae6ec005f559f1de2af7 100644 (file)
@@ -11,9 +11,9 @@
 +
 The remote ref that matches <src>
 is fetched, and if <dst> is not empty string, the local
-ref that matches it is fast forwarded using <src>.
+ref that matches it is fast-forwarded using <src>.
 If the optional plus `+` is used, the local ref
-is updated even if it does not result in a fast forward
+is updated even if it does not result in a fast-forward
 update.
 +
 [NOTE]
index 9cd48b48597f9b7e822fc3d81e0bc556d6631b02..7950eeeda4447808c937b6ddcaa9ae1686e2ed5c 100644 (file)
-Pack transfer protocols
-=======================
-
-There are two Pack push-pull protocols.
-
-upload-pack (S) | fetch/clone-pack (C) protocol:
-
-       # Tell the puller what commits we have and what their names are
-       S: SHA1 name
-       S: ...
-       S: SHA1 name
-       S: # flush -- it's your turn
-       # Tell the pusher what commits we want, and what we have
-       C: want name
-       C: ..
-       C: want name
-       C: have SHA1
-       C: have SHA1
-       C: ...
-       C: # flush -- occasionally ask "had enough?"
-       S: NAK
-       C: have SHA1
-       C: ...
-       C: have SHA1
-       S: ACK
-       C: done
-       S: XXXXXXX -- packfile contents.
-
-send-pack | receive-pack protocol.
-
-       # Tell the pusher what commits we have and what their names are
-       C: SHA1 name
-       C: ...
-       C: SHA1 name
-       C: # flush -- it's your turn
-       # Tell the puller what the pusher has
-       S: old-SHA1 new-SHA1 name
-       S: old-SHA1 new-SHA1 name
-       S: ...
-       S: # flush -- done with the list
-       S: XXXXXXX --- packfile contents.
+Packfile transfer protocols
+===========================
+
+Git supports transferring data in packfiles over the ssh://, git:// and
+file:// transports.  There exist two sets of protocols, one for pushing
+data from a client to a server and another for fetching data from a
+server to a client.  All three transports (ssh, git, file) use the same
+protocol to transfer data.
+
+The processes invoked in the canonical Git implementation are 'upload-pack'
+on the server side and 'fetch-pack' on the client side for fetching data;
+then 'receive-pack' on the server and 'send-pack' on the client for pushing
+data.  The protocol functions to have a server tell a client what is
+currently on the server, then for the two to negotiate the smallest amount
+of data to send in order to fully update one or the other.
+
+Transports
+----------
+There are three transports over which the packfile protocol is
+initiated.  The Git transport is a simple, unauthenticated server that
+takes the command (almost always 'upload-pack', though Git
+servers can be configured to be globally writable, in which 'receive-
+pack' initiation is also allowed) with which the client wishes to
+communicate and executes it and connects it to the requesting
+process.
+
+In the SSH transport, the client just runs the 'upload-pack'
+or 'receive-pack' process on the server over the SSH protocol and then
+communicates with that invoked process over the SSH connection.
+
+The file:// transport runs the 'upload-pack' or 'receive-pack'
+process locally and communicates with it over a pipe.
+
+Git Transport
+-------------
+
+The Git transport starts off by sending the command and repository
+on the wire using the pkt-line format, followed by a NUL byte and a
+hostname paramater, terminated by a NUL byte.
+
+   0032git-upload-pack /project.git\0host=myserver.com\0
+
+--
+   git-proto-request = request-command SP pathname NUL [ host-parameter NUL ]
+   request-command   = "git-upload-pack" / "git-receive-pack" /
+                      "git-upload-archive"   ; case sensitive
+   pathname          = *( %x01-ff ) ; exclude NUL
+   host-parameter    = "host=" hostname [ ":" port ]
+--
+
+Only host-parameter is allowed in the git-proto-request. Clients
+MUST NOT attempt to send additional parameters. It is used for the
+git-daemon name based virtual hosting.  See --interpolated-path
+option to git daemon, with the %H/%CH format characters.
+
+Basically what the Git client is doing to connect to an 'upload-pack'
+process on the server side over the Git protocol is this:
+
+   $ echo -e -n \
+     "0039git-upload-pack /schacon/gitbook.git\0host=example.com\0" |
+     nc -v example.com 9418
+
+
+SSH Transport
+-------------
+
+Initiating the upload-pack or receive-pack processes over SSH is
+executing the binary on the server via SSH remote execution.
+It is basically equivalent to running this:
+
+   $ ssh git.example.com "git-upload-pack '/project.git'"
+
+For a server to support Git pushing and pulling for a given user over
+SSH, that user needs to be able to execute one or both of those
+commands via the SSH shell that they are provided on login.  On some
+systems, that shell access is limited to only being able to run those
+two commands, or even just one of them.
+
+In an ssh:// format URI, it's absolute in the URI, so the '/' after
+the host name (or port number) is sent as an argument, which is then
+read by the remote git-upload-pack exactly as is, so it's effectively
+an absolute path in the remote filesystem.
+
+       git clone ssh://user@example.com/project.git
+                   |
+                   v
+    ssh user@example.com "git-upload-pack '/project.git'"
+
+In a "user@host:path" format URI, its relative to the user's home
+directory, because the Git client will run:
+
+     git clone user@example.com:project.git
+                   |
+                   v
+  ssh user@example.com "git-upload-pack 'project.git'"
+
+The exception is if a '~' is used, in which case
+we execute it without the leading '/'.
+
+      ssh://user@example.com/~alice/project.git,
+                    |
+                    v
+   ssh user@example.com "git-upload-pack '~alice/project.git'"
+
+A few things to remember here:
+
+- The "command name" is spelled with dash (e.g. git-upload-pack), but
+  this can be overridden by the client;
+
+- The repository path is always quoted with single quotes.
+
+Fetching Data From a Server
+===========================
+
+When one Git repository wants to get data that a second repository
+has, the first can 'fetch' from the second.  This operation determines
+what data the server has that the client does not then streams that
+data down to the client in packfile format.
+
+
+Reference Discovery
+-------------------
+
+When the client initially connects the server will immediately respond
+with a listing of each reference it has (all branches and tags) along
+with the object name that each reference currently points to.
+
+   $ echo -e -n "0039git-upload-pack /schacon/gitbook.git\0host=example.com\0" |
+      nc -v example.com 9418
+   00887217a7c7e582c46cec22a130adf4b9d7d950fba0 HEAD\0multi_ack thin-pack side-band side-band-64k ofs-delta shallow no-progress include-tag
+   00441d3fcd5ced445d1abc402225c0b8a1299641f497 refs/heads/integration
+   003f7217a7c7e582c46cec22a130adf4b9d7d950fba0 refs/heads/master
+   003cb88d2441cac0977faf98efc80305012112238d9d refs/tags/v0.9
+   003c525128480b96c89e6418b1e40909bf6c5b2d580f refs/tags/v1.0
+   003fe92df48743b7bc7d26bcaabfddde0a1e20cae47c refs/tags/v1.0^{}
+   0000
+
+Server SHOULD terminate each non-flush line using LF ("\n") terminator;
+client MUST NOT complain if there is no terminator.
+
+The returned response is a pkt-line stream describing each ref and
+its current value.  The stream MUST be sorted by name according to
+the C locale ordering.
+
+If HEAD is a valid ref, HEAD MUST appear as the first advertised
+ref.  If HEAD is not a valid ref, HEAD MUST NOT appear in the
+advertisement list at all, but other refs may still appear.
+
+The stream MUST include capability declarations behind a NUL on the
+first ref. The peeled value of a ref (that is "ref^{}") MUST be
+immediately after the ref itself, if presented. A conforming server
+MUST peel the ref if its an annotated tag.
+
+----
+  advertised-refs  =  (no-refs / list-of-refs)
+                     flush-pkt
+
+  no-refs          =  PKT-LINE(zero-id SP "capabilities^{}"
+                     NUL capability-list LF)
+
+  list-of-refs     =  first-ref *other-ref
+  first-ref        =  PKT-LINE(obj-id SP refname
+                     NUL capability-list LF)
+
+  other-ref        =  PKT-LINE(other-tip / other-peeled)
+  other-tip        =  obj-id SP refname LF
+  other-peeled     =  obj-id SP refname "^{}" LF
+
+  capability-list  =  capability *(SP capability)
+  capability       =  1*(LC_ALPHA / DIGIT / "-" / "_")
+  LC_ALPHA         =  %x61-7A
+----
+
+Server and client MUST use lowercase for obj-id, both MUST treat obj-id
+as case-insensitive.
+
+See protocol-capabilities.txt for a list of allowed server capabilities
+and descriptions.
+
+Packfile Negotiation
+--------------------
+After reference and capabilities discovery, the client can decide
+to terminate the connection by sending a flush-pkt, telling the
+server it can now gracefully terminate (as happens with the ls-remote
+command) or it can enter the negotiation phase, where the client and
+server determine what the minimal packfile necessary for transport is.
+
+Once the client has the initial list of references that the server
+has, as well as the list of capabilities, it will begin telling the
+server what objects it wants and what objects it has, so the server
+can make a packfile that only contains the objects that the client needs.
+The client will also send a list of the capabilities it wants to be in
+effect, out of what the server said it could do with the first 'want' line.
+
+----
+  upload-request    =  want-list
+                      have-list
+                      compute-end
+
+  want-list         =  first-want
+                      *additional-want
+                      flush-pkt
+
+  first-want        =  PKT-LINE("want" SP obj-id SP capability-list LF)
+  additional-want   =  PKT-LINE("want" SP obj-id LF)
+
+  have-list         =  *have-line
+  have-line         =  PKT-LINE("have" SP obj-id LF)
+  compute-end       =  flush-pkt / PKT-LINE("done")
+----
+
+Clients MUST send all the obj-ids it wants from the reference
+discovery phase as 'want' lines. Clients MUST send at least one
+'want' command in the request body. Clients MUST NOT mention an
+obj-id in a 'want' command which did not appear in the response
+obtained through ref discovery.
+
+If client is requesting a shallow clone, it will now send a 'deepen'
+line with the depth it is requesting.
+
+Once all the "want"s (and optional 'deepen') are transferred,
+clients MUST send a flush-pkt. If the client has all the references
+on the server, client flushes and disconnects.
+
+TODO: shallow/unshallow response and document the deepen command in the ABNF.
+
+Now the client will send a list of the obj-ids it has using 'have'
+lines.  In multi_ack mode, the canonical implementation will send up
+to 32 of these at a time, then will send a flush-pkt.  The canonical
+implementation will skip ahead and send the next 32 immediately,
+so that there is always a block of 32 "in-flight on the wire" at a
+time.
+
+If the server reads 'have' lines, it then will respond by ACKing any
+of the obj-ids the client said it had that the server also has. The
+server will ACK obj-ids differently depending on which ack mode is
+chosen by the client.
+
+In multi_ack mode:
+
+  * the server will respond with 'ACK obj-id continue' for any common
+    commits.
+
+  * once the server has found an acceptable common base commit and is
+    ready to make a packfile, it will blindly ACK all 'have' obj-ids
+    back to the client.
+
+  * the server will then send a 'NACK' and then wait for another response
+    from the client - either a 'done' or another list of 'have' lines.
+
+In multi_ack_detailed mode:
+
+  * the server will differentiate the ACKs where it is signaling
+    that it is ready to send data with 'ACK obj-id ready' lines, and
+    signals the identified common commits with 'ACK obj-id common' lines.
+
+Without either multi_ack or multi_ack_detailed:
+
+ * upload-pack sends "ACK obj-id" on the first common object it finds.
+   After that it says nothing until the client gives it a "done".
+
+ * upload-pack sends "NAK" on a flush-pkt if no common object
+   has been found yet.  If one has been found, and thus an ACK
+   was already sent, its silent on the flush-pkt.
+
+After the client has gotten enough ACK responses that it can determine
+that the server has enough information to send an efficient packfile
+(in the canonical implementation, this is determined when it has received
+enough ACKs that it can color everything left in the --date-order queue
+as common with the server, or the --date-order queue is empty), or the
+client determines that it wants to give up (in the canonical implementation,
+this is determined when the client sends 256 'have' lines without getting
+any of them ACKed by the server - meaning there is nothing in common and
+the server should just send all it's objects), then the client will send
+a 'done' command.  The 'done' command signals to the server that the client
+is ready to receive it's packfile data.
+
+However, the 256 limit *only* turns on in the canonical client
+implementation if we have received at least one "ACK %s continue"
+during a prior round.  This helps to ensure that at least one common
+ancestor is found before we give up entirely.
+
+Once the 'done' line is read from the client, the server will either
+send a final 'ACK obj-id' or it will send a 'NAK'. The server only sends
+ACK after 'done' if there is at least one common base and multi_ack or
+multi_ack_detailed is enabled. The server always sends NAK after 'done'
+if there is no common base found.
+
+Then the server will start sending it's packfile data.
+
+----
+  server-response = *ack_multi ack / nak
+  ack_multi       = PKT-LINE("ACK" SP obj-id ack_status LF)
+  ack_status      = "continue" / "common" / "ready"
+  ack             = PKT-LINE("ACK SP obj-id LF)
+  nak             = PKT-LINE("NAK" LF)
+----
+
+A simple clone may look like this (with no 'have' lines):
+
+----
+   C: 0054want 74730d410fcb6603ace96f1dc55ea6196122532d\0multi_ack \
+     side-band-64k ofs-delta\n
+   C: 0032want 7d1665144a3a975c05f1f43902ddaf084e784dbe\n
+   C: 0032want 5a3f6be755bbb7deae50065988cbfa1ffa9ab68a\n
+   C: 0032want 7e47fe2bd8d01d481f44d7af0531bd93d3b21c01\n
+   C: 0032want 74730d410fcb6603ace96f1dc55ea6196122532d\n
+   C: 0000
+   C: 0009done\n
+
+   S: 0008NAK\n
+   S: [PACKFILE]
+----
+
+An incremental update (fetch) response might look like this:
+
+----
+   C: 0054want 74730d410fcb6603ace96f1dc55ea6196122532d\0multi_ack \
+     side-band-64k ofs-delta\n
+   C: 0032want 7d1665144a3a975c05f1f43902ddaf084e784dbe\n
+   C: 0032want 5a3f6be755bbb7deae50065988cbfa1ffa9ab68a\n
+   C: 0000
+   C: 0032have 7e47fe2bd8d01d481f44d7af0531bd93d3b21c01\n
+   C: [30 more have lines]
+   C: 0032have 74730d410fcb6603ace96f1dc55ea6196122532d\n
+   C: 0000
+
+   S: 003aACK 7e47fe2bd8d01d481f44d7af0531bd93d3b21c01 continue\n
+   S: 003aACK 74730d410fcb6603ace96f1dc55ea6196122532d continue\n
+   S: 0008NAK\n
+
+   C: 0009done\n
+
+   S: 003aACK 74730d410fcb6603ace96f1dc55ea6196122532d\n
+   S: [PACKFILE]
+----
+
+
+Packfile Data
+-------------
+
+Now that the client and server have finished negotiation about what
+the minimal amount of data that needs to be sent to the client is, the server
+will construct and send the required data in packfile format.
+
+See pack-format.txt for what the packfile itself actually looks like.
+
+If 'side-band' or 'side-band-64k' capabilities have been specified by
+the client, the server will send the packfile data multiplexed.
+
+Each packet starting with the packet-line length of the amount of data
+that follows, followed by a single byte specifying the sideband the
+following data is coming in on.
+
+In 'side-band' mode, it will send up to 999 data bytes plus 1 control
+code, for a total of up to 1000 bytes in a pkt-line.  In 'side-band-64k'
+mode it will send up to 65519 data bytes plus 1 control code, for a
+total of up to 65520 bytes in a pkt-line.
+
+The sideband byte will be a '1', '2' or a '3'. Sideband '1' will contain
+packfile data, sideband '2' will be used for progress information that the
+client will generally print to stderr and sideband '3' is used for error
+information.
+
+If no 'side-band' capability was specified, the server will stream the
+entire packfile without multiplexing.
+
+
+Pushing Data To a Server
+========================
+
+Pushing data to a server will invoke the 'receive-pack' process on the
+server, which will allow the client to tell it which references it should
+update and then send all the data the server will need for those new
+references to be complete.  Once all the data is received and validated,
+the server will then update its references to what the client specified.
+
+Authentication
+--------------
+
+The protocol itself contains no authentication mechanisms.  That is to be
+handled by the transport, such as SSH, before the 'receive-pack' process is
+invoked.  If 'receive-pack' is configured over the Git transport, those
+repositories will be writable by anyone who can access that port (9418) as
+that transport is unauthenticated.
+
+Reference Discovery
+-------------------
+
+The reference discovery phase is done nearly the same way as it is in the
+fetching protocol. Each reference obj-id and name on the server is sent
+in packet-line format to the client, followed by a flush-pkt.  The only
+real difference is that the capability listing is different - the only
+possible values are 'report-status', 'delete-refs' and 'ofs-delta'.
+
+Reference Update Request and Packfile Transfer
+----------------------------------------------
+
+Once the client knows what references the server is at, it can send a
+list of reference update requests.  For each reference on the server
+that it wants to update, it sends a line listing the obj-id currently on
+the server, the obj-id the client would like to update it to and the name
+of the reference.
+
+This list is followed by a flush-pkt and then the packfile that should
+contain all the objects that the server will need to complete the new
+references.
+
+----
+  update-request    =  command-list [pack-file]
+
+  command-list      =  PKT-LINE(command NUL capability-list LF)
+                      *PKT-LINE(command LF)
+                      flush-pkt
+
+  command           =  create / delete / update
+  create            =  zero-id SP new-id  SP name
+  delete            =  old-id  SP zero-id SP name
+  update            =  old-id  SP new-id  SP name
+
+  old-id            =  obj-id
+  new-id            =  obj-id
+
+  pack-file         = "PACK" 28*(OCTET)
+----
+
+If the receiving end does not support delete-refs, the sending end MUST
+NOT ask for delete command.
+
+The pack-file MUST NOT be sent if the only command used is 'delete'.
+
+A pack-file MUST be sent if either create or update command is used,
+even if the server already has all the necessary objects.  In this
+case the client MUST send an empty pack-file.   The only time this
+is likely to happen is if the client is creating
+a new branch or a tag that points to an existing obj-id.
+
+The server will receive the packfile, unpack it, then validate each
+reference that is being updated that it hasn't changed while the request
+was being processed (the obj-id is still the same as the old-id), and
+it will run any update hooks to make sure that the update is acceptable.
+If all of that is fine, the server will then update the references.
+
+Report Status
+-------------
+
+After receiving the pack data from the sender, the receiver sends a
+report if 'report-status' capability is in effect.
+It is a short listing of what happened in that update.  It will first
+list the status of the packfile unpacking as either 'unpack ok' or
+'unpack [error]'.  Then it will list the status for each of the references
+that it tried to update.  Each line is either 'ok [refname]' if the
+update was successful, or 'ng [refname] [error]' if the update was not.
+
+----
+  report-status     = unpack-status
+                     1*(command-status)
+                     flush-pkt
+
+  unpack-status     = PKT-LINE("unpack" SP unpack-result LF)
+  unpack-result     = "ok" / error-msg
+
+  command-status    = command-ok / command-fail
+  command-ok        = PKT-LINE("ok" SP refname LF)
+  command-fail      = PKT-LINE("ng" SP refname SP error-msg LF)
+
+  error-msg         = 1*(OCTECT) ; where not "ok"
+----
+
+Updates can be unsuccessful for a number of reasons.  The reference can have
+changed since the reference discovery phase was originally sent, meaning
+someone pushed in the meantime.  The reference being pushed could be a
+non-fast-forward reference and the update hooks or configuration could be
+set to not allow that, etc.  Also, some references can be updated while others
+can be rejected.
+
+An example client/server communication might look like this:
+
+----
+   S: 007c74730d410fcb6603ace96f1dc55ea6196122532d refs/heads/local\0report-status delete-refs ofs-delta\n
+   S: 003e7d1665144a3a975c05f1f43902ddaf084e784dbe refs/heads/debug\n
+   S: 003f74730d410fcb6603ace96f1dc55ea6196122532d refs/heads/master\n
+   S: 003f74730d410fcb6603ace96f1dc55ea6196122532d refs/heads/team\n
+   S: 0000
+
+   C: 003e7d1665144a3a975c05f1f43902ddaf084e784dbe 74730d410fcb6603ace96f1dc55ea6196122532d refs/heads/debug\n
+   C: 003e74730d410fcb6603ace96f1dc55ea6196122532d 5a3f6be755bbb7deae50065988cbfa1ffa9ab68a refs/heads/master\n
+   C: 0000
+   C: [PACKDATA]
+
+   S: 000aunpack ok\n
+   S: 0014ok refs/heads/debug\n
+   S: 0026ng refs/heads/master non-fast-forward\n
+----
diff --git a/Documentation/technical/protocol-capabilities.txt b/Documentation/technical/protocol-capabilities.txt
new file mode 100644 (file)
index 0000000..1892d3e
--- /dev/null
@@ -0,0 +1,187 @@
+Git Protocol Capabilities
+=========================
+
+Servers SHOULD support all capabilities defined in this document.
+
+On the very first line of the initial server response of either
+receive-pack and upload-pack the first reference is followed by
+a NUL byte and then a list of space delimited server capabilities.
+These allow the server to declare what it can and cannot support
+to the client.
+
+Client will then send a space separated list of capabilities it wants
+to be in effect. The client MUST NOT ask for capabilities the server
+did not say it supports.
+
+Server MUST diagnose and abort if capabilities it does not understand
+was sent.  Server MUST NOT ignore capabilities that client requested
+and server advertised.  As a consequence of these rules, server MUST
+NOT advertise capabilities it does not understand.
+
+The 'report-status' and 'delete-refs' capabilities are sent and
+recognized by the receive-pack (push to server) process.
+
+The 'ofs-delta' capability is sent and recognized by both upload-pack
+and receive-pack protocols.
+
+All other capabilities are only recognized by the upload-pack (fetch
+from server) process.
+
+multi_ack
+---------
+
+The 'multi_ack' capability allows the server to return "ACK obj-id
+continue" as soon as it finds a commit that it can use as a common
+base, between the client's wants and the client's have set.
+
+By sending this early, the server can potentially head off the client
+from walking any further down that particular branch of the client's
+repository history.  The client may still need to walk down other
+branches, sending have lines for those, until the server has a
+complete cut across the DAG, or the client has said "done".
+
+Without multi_ack, a client sends have lines in --date-order until
+the server has found a common base.  That means the client will send
+have lines that are already known by the server to be common, because
+they overlap in time with another branch that the server hasn't found
+a common base on yet.
+
+For example suppose the client has commits in caps that the server
+doesn't and the server has commits in lower case that the client
+doesn't, as in the following diagram:
+
+       +---- u ---------------------- x
+      /              +----- y
+     /              /
+    a -- b -- c -- d -- E -- F
+       \
+       +--- Q -- R -- S
+
+If the client wants x,y and starts out by saying have F,S, the server
+doesn't know what F,S is.  Eventually the client says "have d" and
+the server sends "ACK d continue" to let the client know to stop
+walking down that line (so don't send c-b-a), but its not done yet,
+it needs a base for x. The client keeps going with S-R-Q, until a
+gets reached, at which point the server has a clear base and it all
+ends.
+
+Without multi_ack the client would have sent that c-b-a chain anyway,
+interleaved with S-R-Q.
+
+thin-pack
+---------
+
+This capability means that the server can send a 'thin' pack, a pack
+which does not contain base objects; if those base objects are available
+on client side. Client requests 'thin-pack' capability when it
+understands how to "thicken" it by adding required delta bases making
+it self-contained.
+
+Client MUST NOT request 'thin-pack' capability if it cannot turn a thin
+pack into a self-contained pack.
+
+
+side-band, side-band-64k
+------------------------
+
+This capability means that server can send, and client understand multiplexed
+progress reports and error info interleaved with the packfile itself.
+
+These two options are mutually exclusive. A modern client always
+favors 'side-band-64k'.
+
+Either mode indicates that the packfile data will be streamed broken
+up into packets of up to either 1000 bytes in the case of 'side_band',
+or 65520 bytes in the case of 'side_band_64k'. Each packet is made up
+of a leading 4-byte pkt-line length of how much data is in the packet,
+followed by a 1-byte stream code, followed by the actual data.
+
+The stream code can be one of:
+
+ 1 - pack data
+ 2 - progress messages
+ 3 - fatal error message just before stream aborts
+
+The "side-band-64k" capability came about as a way for newer clients
+that can handle much larger packets to request packets that are
+actually crammed nearly full, while maintaining backward compatibility
+for the older clients.
+
+Further, with side-band and its up to 1000-byte messages, it's actually
+999 bytes of payload and 1 byte for the stream code. With side-band-64k,
+same deal, you have up to 65519 bytes of data and 1 byte for the stream
+code.
+
+The client MUST send only maximum of one of "side-band" and "side-
+band-64k".  Server MUST diagnose it as an error if client requests
+both.
+
+ofs-delta
+---------
+
+Server can send, and client understand PACKv2 with delta refering to
+its base by position in pack rather than by an obj-id.  That is, they can
+send/read OBJ_OFS_DELTA (aka type 6) in a packfile.
+
+shallow
+-------
+
+This capability adds "deepen", "shallow" and "unshallow" commands to
+the  fetch-pack/upload-pack protocol so clients can request shallow
+clones.
+
+no-progress
+-----------
+
+The client was started with "git clone -q" or something, and doesn't
+want that side band 2.  Basically the client just says "I do not
+wish to receive stream 2 on sideband, so do not send it to me, and if
+you did, I will drop it on the floor anyway".  However, the sideband
+channel 3 is still used for error responses.
+
+include-tag
+-----------
+
+The 'include-tag' capability is about sending annotated tags if we are
+sending objects they point to.  If we pack an object to the client, and
+a tag object points exactly at that object, we pack the tag object too.
+In general this allows a client to get all new annotated tags when it
+fetches a branch, in a single network connection.
+
+Clients MAY always send include-tag, hardcoding it into a request when
+the server advertises this capability. The decision for a client to
+request include-tag only has to do with the client's desires for tag
+data, whether or not a server had advertised objects in the
+refs/tags/* namespace.
+
+Servers MUST pack the tags if their referrant is packed and the client
+has requested include-tags.
+
+Clients MUST be prepared for the case where a server has ignored
+include-tag and has not actually sent tags in the pack.  In such
+cases the client SHOULD issue a subsequent fetch to acquire the tags
+that include-tag would have otherwise given the client.
+
+The server SHOULD send include-tag, if it supports it, regardless
+of whether or not there are tags available.
+
+report-status
+-------------
+
+The upload-pack process can receive a 'report-status' capability,
+which tells it that the client wants a report of what happened after
+a packfile upload and reference update.  If the pushing client requests
+this capability, after unpacking and updating references the server
+will respond with whether the packfile unpacked successfully and if
+each reference was updated successfully.  If any of those were not
+successful, it will send back an error message.  See pack-protocol.txt
+for example messages.
+
+delete-refs
+-----------
+
+If the server sends back the 'delete-refs' capability, it means that
+it is capable of accepting an zero-id value as the target
+value of a reference update.  It is not sent back by the client, it
+simply informs the client that it can be sent zero-id values
+to delete references.
diff --git a/Documentation/technical/protocol-common.txt b/Documentation/technical/protocol-common.txt
new file mode 100644 (file)
index 0000000..d30a1b9
--- /dev/null
@@ -0,0 +1,96 @@
+Documentation Common to Pack and Http Protocols
+===============================================
+
+ABNF Notation
+-------------
+
+ABNF notation as described by RFC 5234 is used within the protocol documents,
+except the following replacement core rules are used:
+----
+  HEXDIG    =  DIGIT / "a" / "b" / "c" / "d" / "e" / "f"
+----
+
+We also define the following common rules:
+----
+  NUL       =  %x00
+  zero-id   =  40*"0"
+  obj-id    =  40*(HEXDIGIT)
+
+  refname  =  "HEAD"
+  refname /=  "refs/" <see discussion below>
+----
+
+A refname is a hierarchical octet string beginning with "refs/" and
+not violating the 'git-check-ref-format' command's validation rules.
+More specifically, they:
+
+. They can include slash `/` for hierarchical (directory)
+  grouping, but no slash-separated component can begin with a
+  dot `.`.
+
+. They must contain at least one `/`. This enforces the presence of a
+  category like `heads/`, `tags/` etc. but the actual names are not
+  restricted.
+
+. They cannot have two consecutive dots `..` anywhere.
+
+. They cannot have ASCII control characters (i.e. bytes whose
+  values are lower than \040, or \177 `DEL`), space, tilde `~`,
+  caret `{caret}`, colon `:`, question-mark `?`, asterisk `*`,
+  or open bracket `[` anywhere.
+
+. They cannot end with a slash `/` nor a dot `.`.
+
+. They cannot end with the sequence `.lock`.
+
+. They cannot contain a sequence `@{`.
+
+. They cannot contain a `\\`.
+
+
+pkt-line Format
+---------------
+
+Much (but not all) of the payload is described around pkt-lines.
+
+A pkt-line is a variable length binary string.  The first four bytes
+of the line, the pkt-len, indicates the total length of the line,
+in hexadecimal.  The pkt-len includes the 4 bytes used to contain
+the length's hexadecimal representation.
+
+A pkt-line MAY contain binary data, so implementors MUST ensure
+pkt-line parsing/formatting routines are 8-bit clean.
+
+A non-binary line SHOULD BE terminated by an LF, which if present
+MUST be included in the total length.
+
+The maximum length of a pkt-line's data component is 65520 bytes.
+Implementations MUST NOT send pkt-line whose length exceeds 65524
+(65520 bytes of payload + 4 bytes of length data).
+
+Implementations SHOULD NOT send an empty pkt-line ("0004").
+
+A pkt-line with a length field of 0 ("0000"), called a flush-pkt,
+is a special case and MUST be handled differently than an empty
+pkt-line ("0004").
+
+----
+  pkt-line     =  data-pkt / flush-pkt
+
+  data-pkt     =  pkt-len pkt-payload
+  pkt-len      =  4*(HEXDIG)
+  pkt-payload  =  (pkt-len - 4)*(OCTET)
+
+  flush-pkt    = "0000"
+----
+
+Examples (as C-style strings):
+
+----
+  pkt-line          actual value
+  ---------------------------------
+  "0006a\n"         "a\n"
+  "0005a"           "a"
+  "000bfoobar\n"    "foobar\n"
+  "0004"            ""
+----
index 67ebffa568fd684afd08496281a530c658a217d9..269ec475e6a822c671af994d13693cfc89e5983f 100644 (file)
@@ -1384,7 +1384,7 @@ were merged.
 
 However, if the current branch is a descendant of the other--so every
 commit present in the one is already contained in the other--then git
-just performs a "fast forward"; the head of the current branch is moved
+just performs a "fast-forward"; the head of the current branch is moved
 forward to point at the head of the merged-in branch, without any new
 commits being created.
 
@@ -1719,7 +1719,7 @@ producing a default commit message documenting the branch and
 repository that you pulled from.
 
 (But note that no such commit will be created in the case of a
-<<fast-forwards,fast forward>>; instead, your branch will just be
+<<fast-forwards,fast-forward>>; instead, your branch will just be
 updated to point to the latest commit from the upstream branch.)
 
 The `git pull` command can also be given "." as the "remote" repository,
@@ -1943,7 +1943,7 @@ $ git push ssh://yourserver.com/~you/proj.git master
 -------------------------------------------------
 
 As with `git fetch`, `git push` will complain if this does not result in a
-<<fast-forwards,fast forward>>; see the following section for details on
+<<fast-forwards,fast-forward>>; see the following section for details on
 handling this case.
 
 Note that the target of a "push" is normally a
@@ -1976,7 +1976,7 @@ details.
 What to do when a push fails
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-If a push would not result in a <<fast-forwards,fast forward>> of the
+If a push would not result in a <<fast-forwards,fast-forward>> of the
 remote branch, then it will fail with an error like:
 
 -------------------------------------------------
@@ -2115,7 +2115,7 @@ $ git checkout release && git pull
 
 Important note!  If you have any local changes in these branches, then
 this merge will create a commit object in the history (with no local
-changes git will simply do a "Fast forward" merge).  Many people dislike
+changes git will simply do a "fast-forward" merge).  Many people dislike
 the "noise" that this creates in the Linux history, so you should avoid
 doing this capriciously in the "release" branch, as these noisy commits
 will become part of the permanent history when you ask Linus to pull
@@ -2729,9 +2729,9 @@ In the previous example, when updating an existing branch, "git fetch"
 checks to make sure that the most recent commit on the remote
 branch is a descendant of the most recent commit on your copy of the
 branch before updating your copy of the branch to point at the new
-commit.  Git calls this process a <<fast-forwards,fast forward>>.
+commit.  Git calls this process a <<fast-forwards,fast-forward>>.
 
-A fast forward looks something like this:
+A fast-forward looks something like this:
 
 ................................................
  o--o--o--o <-- old head of the branch
index 08e6073f33f321f218fc2b4478d939c2469bbcf5..710d361233e26a8cc2da94f87f8b436b5af3419b 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v1.6.5
+DEF_VER=v1.6.5.GIT
 
 LF='
 '
index 8e1cfc556fc164ac48c4788aa2d86997a97c4c78..7b8d11d118c7b17213014caee4b50a3d0ce19995 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -159,6 +159,10 @@ all::
 # Define ASCIIDOC_NO_ROFF if your DocBook XSL escapes raw roff directives
 # (versions 1.72 and later and 1.68.1 and earlier).
 #
+# Define GNU_ROFF if your target system uses GNU groff.  This forces
+# apostrophes to be ASCII so that cut&pasting examples to the shell
+# will work.
+#
 # Define NO_PERL_MAKEMAKER if you cannot use Makefiles generated by perl's
 # MakeMaker (e.g. using ActiveState under Cygwin).
 #
@@ -354,6 +358,7 @@ EXTRA_PROGRAMS =
 PROGRAMS += $(EXTRA_PROGRAMS)
 PROGRAMS += git-fast-import$X
 PROGRAMS += git-hash-object$X
+PROGRAMS += git-imap-send$X
 PROGRAMS += git-index-pack$X
 PROGRAMS += git-merge-index$X
 PROGRAMS += git-merge-tree$X
@@ -412,6 +417,7 @@ LIB_H += builtin.h
 LIB_H += cache.h
 LIB_H += cache-tree.h
 LIB_H += commit.h
+LIB_H += compat/bswap.h
 LIB_H += compat/cygwin.h
 LIB_H += compat/mingw.h
 LIB_H += csum-file.h
@@ -452,6 +458,7 @@ LIB_H += sideband.h
 LIB_H += sigchain.h
 LIB_H += strbuf.h
 LIB_H += string-list.h
+LIB_H += submodule.h
 LIB_H += tag.h
 LIB_H += transport.h
 LIB_H += tree.h
@@ -550,6 +557,7 @@ LIB_OBJS += sideband.o
 LIB_OBJS += sigchain.o
 LIB_OBJS += strbuf.o
 LIB_OBJS += string-list.o
+LIB_OBJS += submodule.o
 LIB_OBJS += symlinks.o
 LIB_OBJS += tag.o
 LIB_OBJS += trace.o
@@ -594,7 +602,6 @@ BUILTIN_OBJS += builtin-diff-index.o
 BUILTIN_OBJS += builtin-diff-tree.o
 BUILTIN_OBJS += builtin-diff.o
 BUILTIN_OBJS += builtin-fast-export.o
-BUILTIN_OBJS += builtin-fetch--tool.o
 BUILTIN_OBJS += builtin-fetch-pack.o
 BUILTIN_OBJS += builtin-fetch.o
 BUILTIN_OBJS += builtin-fmt-merge-msg.o
@@ -897,7 +904,7 @@ ifdef MSVC
        GIT_VERSION := $(GIT_VERSION).MSVC
        pathsep = ;
        NO_PREAD = YesPlease
-       NO_OPENSSL = YesPlease
+       NEEDS_CRYPTO_WITH_SSL = YesPlease
        NO_LIBGEN_H = YesPlease
        NO_SYMLINK_HEAD = YesPlease
        NO_IPV6 = YesPlease
@@ -927,6 +934,7 @@ ifdef MSVC
        NO_REGEX = YesPlease
        NO_CURL = YesPlease
        NO_PTHREADS = YesPlease
+       BLK_SHA1 = YesPlease
 
        CC = compat/vcbuild/scripts/clink.pl
        AR = compat/vcbuild/scripts/lib.pl
@@ -949,7 +957,7 @@ else
 ifneq (,$(findstring MINGW,$(uname_S)))
        pathsep = ;
        NO_PREAD = YesPlease
-       NO_OPENSSL = YesPlease
+       NEEDS_CRYPTO_WITH_SSL = YesPlease
        NO_LIBGEN_H = YesPlease
        NO_SYMLINK_HEAD = YesPlease
        NO_IPV6 = YesPlease
@@ -976,6 +984,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
        UNRELIABLE_FSTAT = UnfortunatelyYes
        OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo
        NO_REGEX = YesPlease
+       BLK_SHA1 = YesPlease
        COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/fnmatch
        COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
        COMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o
@@ -1073,7 +1082,6 @@ EXTLIBS += -lz
 
 ifndef NO_POSIX_ONLY_PROGRAMS
        PROGRAMS += git-daemon$X
-       PROGRAMS += git-imap-send$X
 endif
 ifndef NO_OPENSSL
        OPENSSL_LIBSSL = -lssl
@@ -1373,7 +1381,7 @@ SHELL = $(SHELL_PATH)
 
 all:: shell_compatibility_test $(ALL_PROGRAMS) $(BUILT_INS) $(OTHER_PROGRAMS) GIT-BUILD-OPTIONS
 ifneq (,$X)
-       $(QUIET_BUILT_IN)$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) git$X)), test '$p' -ef '$p$X' || $(RM) '$p';)
+       $(QUIET_BUILT_IN)$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) git$X)), test -d '$p' -o '$p' -ef '$p$X' || $(RM) '$p';)
 endif
 
 all::
@@ -1797,7 +1805,10 @@ dist: git.spec git-archive$(X) configure
        gzip -f -9 $(GIT_TARNAME).tar
 
 rpm: dist
-       $(RPMBUILD) -ta $(GIT_TARNAME).tar.gz
+       $(RPMBUILD) \
+               --define "_source_filedigest_algorithm md5" \
+               --define "_binary_filedigest_algorithm md5" \
+               -ta $(GIT_TARNAME).tar.gz
 
 htmldocs = git-htmldocs-$(GIT_VERSION)
 manpages = git-manpages-$(GIT_VERSION)
@@ -1825,7 +1836,7 @@ distclean: clean
        $(RM) configure
 
 clean:
-       $(RM) *.o mozilla-sha1/*.o arm/*.o ppc/*.o compat/*.o compat/*/*.o xdiff/*.o \
+       $(RM) *.o block-sha1/*.o arm/*.o ppc/*.o compat/*.o compat/*/*.o xdiff/*.o \
                $(LIB_FILE) $(XDIFF_LIB)
        $(RM) $(ALL_PROGRAMS) $(BUILT_INS) git$X
        $(RM) $(TEST_PROGRAMS)
index b62449d2e22829f8bcbe404a48ff8f62c47eebd9..5274ceed4e7ecd0210ad8338a0b3570e3648b05e 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes-1.6.5.txt
\ No newline at end of file
+Documentation/RelNotes-1.6.6.txt
\ No newline at end of file
index 0cc79d2a240ac260fec66e6c30e28b438bcb5948..55b273246e006ad55c51d3e5cb6bed3153ae8cf4 100644 (file)
--- a/archive.c
+++ b/archive.c
@@ -31,6 +31,8 @@ static void format_subst(const struct commit *commit,
 {
        char *to_free = NULL;
        struct strbuf fmt = STRBUF_INIT;
+       struct pretty_print_context ctx = {0};
+       ctx.date_mode = DATE_NORMAL;
 
        if (src == buf->buf)
                to_free = strbuf_detach(buf, NULL);
@@ -48,7 +50,7 @@ static void format_subst(const struct commit *commit,
                strbuf_add(&fmt, b + 8, c - b - 8);
 
                strbuf_add(buf, src, b - src);
-               format_commit_message(commit, fmt.buf, buf, DATE_NORMAL);
+               format_commit_message(commit, fmt.buf, buf, &ctx);
                len -= c + 1 - src;
                src  = c + 1;
        }
index c8372a0a8051c331e671aee588b8ea0632ad6430..f667368d161609ea3c93fc6ebe2452b9cd0e557d 100644 (file)
@@ -153,6 +153,7 @@ struct fragment {
        const char *patch;
        int size;
        int rejected;
+       int linenr;
        struct fragment *next;
 };
 
@@ -1227,23 +1228,29 @@ static int find_header(char *line, unsigned long size, int *hdrsize, struct patc
        return -1;
 }
 
-static void check_whitespace(const char *line, int len, unsigned ws_rule)
+static void record_ws_error(unsigned result, const char *line, int len, int linenr)
 {
        char *err;
-       unsigned result = ws_check(line + 1, len - 1, ws_rule);
+
        if (!result)
                return;
 
        whitespace_error++;
        if (squelch_whitespace_errors &&
            squelch_whitespace_errors < whitespace_error)
-               ;
-       else {
-               err = whitespace_error_string(result);
-               fprintf(stderr, "%s:%d: %s.\n%.*s\n",
-                       patch_input_file, linenr, err, len - 2, line + 1);
-               free(err);
-       }
+               return;
+
+       err = whitespace_error_string(result);
+       fprintf(stderr, "%s:%d: %s.\n%.*s\n",
+               patch_input_file, linenr, err, len, line);
+       free(err);
+}
+
+static void check_whitespace(const char *line, int len, unsigned ws_rule)
+{
+       unsigned result = ws_check(line + 1, len - 1, ws_rule);
+
+       record_ws_error(result, line + 1, len - 2, linenr);
 }
 
 /*
@@ -1359,6 +1366,7 @@ static int parse_single_patch(char *line, unsigned long size, struct patch *patc
                int len;
 
                fragment = xcalloc(1, sizeof(*fragment));
+               fragment->linenr = linenr;
                len = parse_fragment(line, size, patch, fragment);
                if (len <= 0)
                        die("corrupt patch at line %d", linenr);
@@ -2142,6 +2150,7 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
                int len = linelen(patch, size);
                int plen, added;
                int added_blank_line = 0;
+               int is_blank_context = 0;
 
                if (!len)
                        break;
@@ -2174,8 +2183,12 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
                        *new++ = '\n';
                        add_line_info(&preimage, "\n", 1, LINE_COMMON);
                        add_line_info(&postimage, "\n", 1, LINE_COMMON);
+                       is_blank_context = 1;
                        break;
                case ' ':
+                       if (plen && (ws_rule & WS_BLANK_AT_EOF) &&
+                           ws_blank_line(patch + 1, plen, ws_rule))
+                               is_blank_context = 1;
                case '-':
                        memcpy(old, patch + 1, plen);
                        add_line_info(&preimage, old, plen,
@@ -2202,7 +2215,8 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
                                      (first == '+' ? 0 : LINE_COMMON));
                        new += added;
                        if (first == '+' &&
-                           added == 1 && new[-1] == '\n')
+                           (ws_rule & WS_BLANK_AT_EOF) &&
+                           ws_blank_line(patch + 1, plen, ws_rule))
                                added_blank_line = 1;
                        break;
                case '@': case '\\':
@@ -2215,6 +2229,8 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
                }
                if (added_blank_line)
                        new_blank_lines_at_end++;
+               else if (is_blank_context)
+                       ;
                else
                        new_blank_lines_at_end = 0;
                patch += len;
@@ -2296,17 +2312,24 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
        }
 
        if (applied_pos >= 0) {
-               if (ws_error_action == correct_ws_error &&
-                   new_blank_lines_at_end &&
-                   postimage.nr + applied_pos == img->nr) {
+               if (new_blank_lines_at_end &&
+                   preimage.nr + applied_pos == img->nr &&
+                   (ws_rule & WS_BLANK_AT_EOF) &&
+                   ws_error_action != nowarn_ws_error) {
+                       record_ws_error(WS_BLANK_AT_EOF, "+", 1, frag->linenr);
+                       if (ws_error_action == correct_ws_error) {
+                               while (new_blank_lines_at_end--)
+                                       remove_last_line(&postimage);
+                       }
                        /*
-                        * If the patch application adds blank lines
-                        * at the end, and if the patch applies at the
-                        * end of the image, remove those added blank
-                        * lines.
+                        * We would want to prevent write_out_results()
+                        * from taking place in apply_patch() that follows
+                        * the callchain led us here, which is:
+                        * apply_patch->check_patch_list->check_patch->
+                        * apply_data->apply_fragments->apply_one_fragment
                         */
-                       while (new_blank_lines_at_end--)
-                               remove_last_line(&postimage);
+                       if (ws_error_action == die_on_ws_error)
+                               apply = 0;
                }
 
                /*
index 7512773b401255e76aadd5be6e561432d7d60772..dd16b2229763addfba8f02f3d9b3c42dcb995935 100644 (file)
@@ -1604,6 +1604,9 @@ static void emit_porcelain(struct scoreboard *sb, struct blame_entry *ent)
                } while (ch != '\n' &&
                         cp < sb->final_buf + sb->final_buf_size);
        }
+
+       if (sb->final_buf_size && cp[-1] != '\n')
+               putchar('\n');
 }
 
 static void emit_other(struct scoreboard *sb, struct blame_entry *ent, int opt)
@@ -1667,6 +1670,9 @@ static void emit_other(struct scoreboard *sb, struct blame_entry *ent, int opt)
                } while (ch != '\n' &&
                         cp < sb->final_buf + sb->final_buf_size);
        }
+
+       if (sb->final_buf_size && cp[-1] != '\n')
+               putchar('\n');
 }
 
 static void output(struct scoreboard *sb, int option)
index 9f57992062314a3d8d168b5cfb6b3c6737605033..05e876e28554fec546ee4256bf3576dcb8017047 100644 (file)
@@ -387,8 +387,9 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
 
                commit = item->commit;
                if (commit && !parse_commit(commit)) {
+                       struct pretty_print_context ctx = {0};
                        pretty_print_commit(CMIT_FMT_ONELINE, commit,
-                                           &subject, 0, NULL, NULL, 0, 0);
+                                           &subject, &ctx);
                        sub = subject.buf;
                }
 
index f9381e07eaeda673e91ef6250eca4027c5ba0278..b106c65d80dfc8fe794d46e34ea1ff78b04f3056 100644 (file)
@@ -7,8 +7,37 @@
 #include "builtin.h"
 #include "strbuf.h"
 
+static const char builtin_check_ref_format_usage[] =
+"git check-ref-format [--print] <refname>\n"
+"   or: git check-ref-format --branch <branchname-shorthand>";
+
+/*
+ * Replace each run of adjacent slashes in src with a single slash,
+ * and write the result to dst.
+ *
+ * This function is similar to normalize_path_copy(), but stripped down
+ * to meet check_ref_format's simpler needs.
+ */
+static void collapse_slashes(char *dst, const char *src)
+{
+       char ch;
+       char prev = '\0';
+
+       while ((ch = *src++) != '\0') {
+               if (prev == '/' && ch == prev)
+                       continue;
+
+               *dst++ = ch;
+               prev = ch;
+       }
+       *dst = '\0';
+}
+
 int cmd_check_ref_format(int argc, const char **argv, const char *prefix)
 {
+       if (argc == 2 && !strcmp(argv[1], "-h"))
+               usage(builtin_check_ref_format_usage);
+
        if (argc == 3 && !strcmp(argv[1], "--branch")) {
                struct strbuf sb = STRBUF_INIT;
 
@@ -17,7 +46,16 @@ int cmd_check_ref_format(int argc, const char **argv, const char *prefix)
                printf("%s\n", sb.buf + 11);
                exit(0);
        }
+       if (argc == 3 && !strcmp(argv[1], "--print")) {
+               char *refname = xmalloc(strlen(argv[2]) + 1);
+
+               if (check_ref_format(argv[2]))
+                       exit(1);
+               collapse_slashes(refname, argv[2]);
+               printf("%s\n", refname);
+               exit(0);
+       }
        if (argc != 2)
-               usage("git check-ref-format refname");
+               usage(builtin_check_ref_format_usage);
        return !!check_ref_format(argv[1]);
 }
index d050c3789fcdaf1b50c12a20c28cbeaf774048eb..64f3a11ae1d415c466def8eccefe9dbc5b6b3926 100644 (file)
@@ -302,8 +302,9 @@ static void show_local_changes(struct object *head)
 static void describe_detached_head(char *msg, struct commit *commit)
 {
        struct strbuf sb = STRBUF_INIT;
+       struct pretty_print_context ctx = {0};
        parse_commit(commit);
-       pretty_print_commit(CMIT_FMT_ONELINE, commit, &sb, 0, NULL, NULL, 0, 0);
+       pretty_print_commit(CMIT_FMT_ONELINE, commit, &sb, &ctx);
        fprintf(stderr, "%s %s... %s\n", msg,
                find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV), sb.buf);
        strbuf_release(&sb);
@@ -572,6 +573,40 @@ static int interactive_checkout(const char *revision, const char **pathspec,
        return run_add_interactive(revision, "--patch=checkout", pathspec);
 }
 
+struct tracking_name_data {
+       const char *name;
+       char *remote;
+       int unique;
+};
+
+static int check_tracking_name(const char *refname, const unsigned char *sha1,
+                              int flags, void *cb_data)
+{
+       struct tracking_name_data *cb = cb_data;
+       const char *slash;
+
+       if (prefixcmp(refname, "refs/remotes/"))
+               return 0;
+       slash = strchr(refname + 13, '/');
+       if (!slash || strcmp(slash + 1, cb->name))
+               return 0;
+       if (cb->remote) {
+               cb->unique = 0;
+               return 0;
+       }
+       cb->remote = xstrdup(refname);
+       return 0;
+}
+
+static const char *unique_tracking_name(const char *name)
+{
+       struct tracking_name_data cb_data = { name, NULL, 1 };
+       for_each_ref(check_tracking_name, &cb_data);
+       if (cb_data.unique)
+               return cb_data.remote;
+       free(cb_data.remote);
+       return NULL;
+}
 
 int cmd_checkout(int argc, const char **argv, const char *prefix)
 {
@@ -582,6 +617,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
        struct tree *source_tree = NULL;
        char *conflict_style = NULL;
        int patch_mode = 0;
+       int dwim_new_local_branch = 1;
        struct option options[] = {
                OPT__QUIET(&opts.quiet),
                OPT_STRING('b', NULL, &opts.new_branch, "new branch", "branch"),
@@ -597,6 +633,9 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
                OPT_STRING(0, "conflict", &conflict_style, "style",
                           "conflict style (merge or diff3)"),
                OPT_BOOLEAN('p', "patch", &patch_mode, "select hunks interactively"),
+               { OPTION_BOOLEAN, 0, "guess", &dwim_new_local_branch, NULL,
+                 "second guess 'git checkout no-such-branch'",
+                 PARSE_OPT_NOARG | PARSE_OPT_HIDDEN },
                OPT_END(),
        };
        int has_dash_dash;
@@ -630,8 +669,6 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
                opts.new_branch = argv0 + 1;
        }
 
-       if (opts.track == BRANCH_TRACK_UNSPECIFIED)
-               opts.track = git_branch_track;
        if (conflict_style) {
                opts.merge = 1; /* implied */
                git_xmerge_config("merge.conflictstyle", conflict_style, NULL);
@@ -655,6 +692,11 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
         *   With no paths, if <something> is a commit, that is to
         *   switch to the branch or detach HEAD at it.
         *
+        *   With no paths, if <something> is _not_ a commit, no -t nor -b
+        *   was given, and there is a tracking branch whose name is
+        *   <something> in one and only one remote, then this is a short-hand
+        *   to fork local <something> from that remote tracking branch.
+        *
         *   Otherwise <something> shall not be ambiguous.
         *   - If it's *only* a reference, treat it like case (1).
         *   - If it's only a path, treat it like case (2).
@@ -677,7 +719,21 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
                if (get_sha1(arg, rev)) {
                        if (has_dash_dash)          /* case (1) */
                                die("invalid reference: %s", arg);
-                       goto no_reference;          /* case (3 -> 2) */
+                       if (!patch_mode &&
+                           dwim_new_local_branch &&
+                           opts.track == BRANCH_TRACK_UNSPECIFIED &&
+                           !opts.new_branch &&
+                           !check_filename(NULL, arg) &&
+                           argc == 1) {
+                               const char *remote = unique_tracking_name(arg);
+                               if (!remote || get_sha1(remote, rev))
+                                       goto no_reference;
+                               opts.new_branch = arg;
+                               arg = remote;
+                               /* DWIMmed to create local branch */
+                       }
+                       else
+                               goto no_reference;
                }
 
                /* we can't end up being in (2) anymore, eat the argument */
@@ -715,6 +771,10 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
        }
 
 no_reference:
+
+       if (opts.track == BRANCH_TRACK_UNSPECIFIED)
+               opts.track = git_branch_track;
+
        if (argc) {
                const char **pathspec = get_pathspec(prefix, argv);
 
index 4992c2597c903d86ce1d0c209828aeb962fef23a..caf3025031d83dc860b22c7798dd5f40b6b89ed2 100644 (file)
@@ -51,7 +51,9 @@ static struct option builtin_clone_options[] = {
        OPT_BOOLEAN('n', "no-checkout", &option_no_checkout,
                    "don't create a checkout"),
        OPT_BOOLEAN(0, "bare", &option_bare, "create a bare repository"),
-       OPT_BOOLEAN(0, "naked", &option_bare, "create a bare repository"),
+       { OPTION_BOOLEAN, 0, "naked", &option_bare, NULL,
+               "create a bare repository",
+               PARSE_OPT_NOARG | PARSE_OPT_HIDDEN },
        OPT_BOOLEAN(0, "mirror", &option_mirror,
                    "create a mirror repository (implies bare)"),
        OPT_BOOLEAN('l', "local", &option_local,
@@ -61,7 +63,7 @@ static struct option builtin_clone_options[] = {
        OPT_BOOLEAN('s', "shared", &option_shared,
                    "setup as shared repository"),
        OPT_BOOLEAN(0, "recursive", &option_recursive,
-                   "setup as shared repository"),
+                   "initialize submodules in the clone"),
        OPT_STRING(0, "template", &option_template, "path",
                   "path the template repository"),
        OPT_STRING(0, "reference", &option_reference, "repo",
@@ -377,8 +379,13 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
        argc = parse_options(argc, argv, prefix, builtin_clone_options,
                             builtin_clone_usage, 0);
 
+       if (argc > 2)
+               usage_msg_opt("Too many arguments.",
+                       builtin_clone_usage, builtin_clone_options);
+
        if (argc == 0)
-               die("You must specify a repository to clone.");
+               usage_msg_opt("You must specify a repository to clone.",
+                       builtin_clone_usage, builtin_clone_options);
 
        if (option_mirror)
                option_bare = 1;
@@ -641,7 +648,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
                        die("unable to write new index file");
 
                err |= run_hook(NULL, "post-checkout", sha1_to_hex(null_sha1),
-                               sha1_to_hex(remote_head->old_sha1), "1", NULL);
+                               sha1_to_hex(our_head_points_at->old_sha1), "1",
+                               NULL);
 
                if (!err && option_recursive)
                        err = run_command_v_opt(argv_submodule, RUN_GIT_CMD);
index 64670777312c71d45b10f72a1efe9fceae3e3b89..ddcb7a4bbbcd45dfd7437209f3187fff882e6e62 100644 (file)
@@ -105,7 +105,7 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
 
        git_config(git_default_config, NULL);
 
-       if (argc < 2)
+       if (argc < 2 || !strcmp(argv[1], "-h"))
                usage(commit_tree_usage);
        if (get_sha1(argv[1], tree_sha1))
                die("Not a valid object name %s", argv[1]);
index 200ffdaad4226ae2021c86ae4b7a2f8ccefb3600..d525b894ec1211476707acb06bdebe25d5828dbb 100644 (file)
@@ -414,6 +414,47 @@ static void determine_author_info(void)
        author_date = date;
 }
 
+static int ends_rfc2822_footer(struct strbuf *sb)
+{
+       int ch;
+       int hit = 0;
+       int i, j, k;
+       int len = sb->len;
+       int first = 1;
+       const char *buf = sb->buf;
+
+       for (i = len - 1; i > 0; i--) {
+               if (hit && buf[i] == '\n')
+                       break;
+               hit = (buf[i] == '\n');
+       }
+
+       while (i < len - 1 && buf[i] == '\n')
+               i++;
+
+       for (; i < len; i = k) {
+               for (k = i; k < len && buf[k] != '\n'; k++)
+                       ; /* do nothing */
+               k++;
+
+               if ((buf[k] == ' ' || buf[k] == '\t') && !first)
+                       continue;
+
+               first = 0;
+
+               for (j = 0; i + j < len; j++) {
+                       ch = buf[i + j];
+                       if (ch == ':')
+                               break;
+                       if (isalnum(ch) ||
+                           (ch == '-'))
+                               continue;
+                       return 0;
+               }
+       }
+       return 1;
+}
+
 static int prepare_to_commit(const char *index_file, const char *prefix,
                             struct wt_status *s)
 {
@@ -489,7 +530,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
                for (i = sb.len - 1; i > 0 && sb.buf[i - 1] != '\n'; i--)
                        ; /* do nothing */
                if (prefixcmp(sb.buf + i, sob.buf)) {
-                       if (prefixcmp(sb.buf + i, sign_off_header))
+                       if (!i || !ends_rfc2822_footer(&sb))
                                strbuf_addch(&sb, '\n');
                        strbuf_addbuf(&sb, &sob);
                }
@@ -684,8 +725,10 @@ static const char *find_author_by_nickname(const char *name)
        prepare_revision_walk(&revs);
        commit = get_revision(&revs);
        if (commit) {
+               struct pretty_print_context ctx = {0};
+               ctx.date_mode = DATE_NORMAL;
                strbuf_release(&buf);
-               format_commit_message(commit, "%an <%ae>", &buf, DATE_NORMAL);
+               format_commit_message(commit, "%an <%ae>", &buf, &ctx);
                return strbuf_detach(&buf, NULL);
        }
        die("No existing author found with '%s'", name);
@@ -942,8 +985,10 @@ static void print_summary(const char *prefix, const unsigned char *sha1)
                initial_commit ? " (root-commit)" : "");
 
        if (!log_tree_commit(&rev, commit)) {
+               struct pretty_print_context ctx = {0};
                struct strbuf buf = STRBUF_INIT;
-               format_commit_message(commit, format + 7, &buf, DATE_NORMAL);
+               ctx.date_mode = DATE_NORMAL;
+               format_commit_message(commit, format + 7, &buf, &ctx);
                printf("%s\n", buf.buf);
                strbuf_release(&buf);
        }
index df67a733ae5c91b0b4278c31c12a7432c0ec601e..71be2a9364748668996696f6c74057dba43315b5 100644 (file)
@@ -5,12 +5,14 @@
 #include "builtin.h"
 #include "exec_cmd.h"
 #include "parse-options.h"
+#include "diff.h"
 
 #define SEEN           (1u<<0)
 #define MAX_TAGS       (FLAG_BITS - 1)
 
 static const char * const describe_usage[] = {
        "git describe [options] <committish>*",
+       "git describe [options] --dirty",
        NULL
 };
 
@@ -23,6 +25,13 @@ static int max_candidates = 10;
 static int found_names;
 static const char *pattern;
 static int always;
+static const char *dirty;
+
+/* diff-index command arguments to check if working tree is dirty. */
+static const char *diff_index_args[] = {
+       "diff-index", "--quiet", "HEAD", "--", NULL
+};
+
 
 struct commit_name {
        struct tag *tag;
@@ -96,8 +105,6 @@ static int get_name(const char *path, const unsigned char *sha1, int flag, void
        if (!all) {
                if (!prio)
                        return 0;
-               if (!tags && prio < 2)
-                       return 0;
        }
        add_to_known_names(all ? path + 5 : path + 10, commit, prio, sha1);
        return 0;
@@ -180,11 +187,11 @@ static void describe(const char *arg, int last_one)
        unsigned char sha1[20];
        struct commit *cmit, *gave_up_on = NULL;
        struct commit_list *list;
-       static int initialized = 0;
        struct commit_name *n;
        struct possible_tag all_matches[MAX_TAGS];
        unsigned int match_cnt = 0, annotated_cnt = 0, cur_match;
        unsigned long seen_commits = 0;
+       unsigned int unannotated_cnt = 0;
 
        if (get_sha1(arg, sha1))
                die("Not a valid object name %s", arg);
@@ -192,22 +199,16 @@ static void describe(const char *arg, int last_one)
        if (!cmit)
                die("%s is not a valid '%s' object", arg, commit_type);
 
-       if (!initialized) {
-               initialized = 1;
-               for_each_ref(get_name, NULL);
-       }
-
-       if (!found_names)
-               die("cannot describe '%s'", sha1_to_hex(sha1));
-
        n = cmit->util;
-       if (n) {
+       if (n && (tags || all || n->prio == 2)) {
                /*
                 * Exact match to an existing ref.
                 */
                display_name(n);
                if (longformat)
                        show_suffix(0, n->tag ? n->tag->tagged->sha1 : sha1);
+               if (dirty)
+                       printf("%s", dirty);
                printf("\n");
                return;
        }
@@ -226,7 +227,9 @@ static void describe(const char *arg, int last_one)
                seen_commits++;
                n = c->util;
                if (n) {
-                       if (match_cnt < max_candidates) {
+                       if (!tags && !all && n->prio < 2) {
+                               unannotated_cnt++;
+                       } else if (match_cnt < max_candidates) {
                                struct possible_tag *t = &all_matches[match_cnt++];
                                t->name = n;
                                t->depth = seen_commits - 1;
@@ -265,10 +268,20 @@ static void describe(const char *arg, int last_one)
        if (!match_cnt) {
                const unsigned char *sha1 = cmit->object.sha1;
                if (always) {
-                       printf("%s\n", find_unique_abbrev(sha1, abbrev));
+                       printf("%s", find_unique_abbrev(sha1, abbrev));
+                       if (dirty)
+                               printf("%s", dirty);
+                       printf("\n");
                        return;
                }
-               die("cannot describe '%s'", sha1_to_hex(sha1));
+               if (unannotated_cnt)
+                       die("No annotated tags can describe '%s'.\n"
+                           "However, there were unannotated tags: try --tags.",
+                           sha1_to_hex(sha1));
+               else
+                       die("No tags can describe '%s'.\n"
+                           "Try --always, or create some tags.",
+                           sha1_to_hex(sha1));
        }
 
        qsort(all_matches, match_cnt, sizeof(all_matches[0]), compare_pt);
@@ -300,6 +313,8 @@ static void describe(const char *arg, int last_one)
        display_name(all_matches[0].name);
        if (abbrev)
                show_suffix(all_matches[0].depth, cmit->object.sha1);
+       if (dirty)
+               printf("%s", dirty);
        printf("\n");
 
        if (!last_one)
@@ -324,6 +339,9 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
                           "only consider tags matching <pattern>"),
                OPT_BOOLEAN(0, "always",     &always,
                           "show abbreviated commit object as fallback"),
+               {OPTION_STRING, 0, "dirty",  &dirty, "mark",
+                          "append <mark> on dirty working tree (default: \"-dirty\")",
+                PARSE_OPT_OPTARG, NULL, (intptr_t) "-dirty"},
                OPT_END(),
        };
 
@@ -359,8 +377,16 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
                return cmd_name_rev(i + argc, args, prefix);
        }
 
+       for_each_ref(get_name, NULL);
+       if (!found_names && !always)
+               die("No names found, cannot describe anything.");
+
        if (argc == 0) {
+               if (dirty && !cmd_diff_index(ARRAY_SIZE(diff_index_args) - 1, diff_index_args, prefix))
+                       dirty = NULL;
                describe("HEAD", 1);
+       } else if (dirty) {
+               die("--dirty is incompatible with committishes");
        } else {
                while (argc-- > 0) {
                        describe(*argv++, argc == 0);
index cb48c57ca3e66b7ec39a98128b2cfb058c2dad15..2728860399460243cdd57ebca995f418b4c19848 100644 (file)
@@ -269,7 +269,7 @@ static int update_local_ref(struct ref *ref,
                strcpy(quickref, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV));
                strcat(quickref, "..");
                strcat(quickref, find_unique_abbrev(ref->new_sha1, DEFAULT_ABBREV));
-               r = s_update_ref("fast forward", ref, 1);
+               r = s_update_ref("fast-forward", ref, 1);
                sprintf(display, "%c %-*s %-*s -> %s%s", r ? '!' : ' ',
                        SUMMARY_WIDTH, quickref, REFCOL_WIDTH, remote,
                        pretty_ref, r ? "  (unable to update local ref)" : "");
@@ -287,7 +287,7 @@ static int update_local_ref(struct ref *ref,
                        r ? "unable to update local ref" : "forced update");
                return r;
        } else {
-               sprintf(display, "! %-*s %-*s -> %s  (non fast forward)",
+               sprintf(display, "! %-*s %-*s -> %s  (non-fast-forward)",
                        SUMMARY_WIDTH, "[rejected]", REFCOL_WIDTH, remote,
                        pretty_ref);
                return 1;
@@ -489,7 +489,8 @@ static int add_existing(const char *refname, const unsigned char *sha1,
                        int flag, void *cbdata)
 {
        struct string_list *list = (struct string_list *)cbdata;
-       string_list_insert(refname, list);
+       struct string_list_item *item = string_list_insert(refname, list);
+       item->util = (void *)sha1;
        return 0;
 }
 
@@ -504,57 +505,98 @@ static int will_fetch(struct ref **head, const unsigned char *sha1)
        return 0;
 }
 
+struct tag_data {
+       struct ref **head;
+       struct ref ***tail;
+};
+
+static int add_to_tail(struct string_list_item *item, void *cb_data)
+{
+       struct tag_data *data = (struct tag_data *)cb_data;
+       struct ref *rm = NULL;
+
+       /* We have already decided to ignore this item */
+       if (!item->util)
+               return 0;
+
+       rm = alloc_ref(item->string);
+       rm->peer_ref = alloc_ref(item->string);
+       hashcpy(rm->old_sha1, item->util);
+
+       **data->tail = rm;
+       *data->tail = &rm->next;
+
+       return 0;
+}
+
 static void find_non_local_tags(struct transport *transport,
                        struct ref **head,
                        struct ref ***tail)
 {
        struct string_list existing_refs = { NULL, 0, 0, 0 };
-       struct string_list new_refs = { NULL, 0, 0, 1 };
-       char *ref_name;
-       int ref_name_len;
-       const unsigned char *ref_sha1;
-       const struct ref *tag_ref;
-       struct ref *rm = NULL;
+       struct string_list remote_refs = { NULL, 0, 0, 0 };
+       struct tag_data data = {head, tail};
        const struct ref *ref;
+       struct string_list_item *item = NULL;
 
        for_each_ref(add_existing, &existing_refs);
        for (ref = transport_get_remote_refs(transport); ref; ref = ref->next) {
                if (prefixcmp(ref->name, "refs/tags"))
                        continue;
 
-               ref_name = xstrdup(ref->name);
-               ref_name_len = strlen(ref_name);
-               ref_sha1 = ref->old_sha1;
-
-               if (!strcmp(ref_name + ref_name_len - 3, "^{}")) {
-                       ref_name[ref_name_len - 3] = 0;
-                       tag_ref = transport_get_remote_refs(transport);
-                       while (tag_ref) {
-                               if (!strcmp(tag_ref->name, ref_name)) {
-                                       ref_sha1 = tag_ref->old_sha1;
-                                       break;
-                               }
-                               tag_ref = tag_ref->next;
-                       }
+               /*
+                * The peeled ref always follows the matching base
+                * ref, so if we see a peeled ref that we don't want
+                * to fetch then we can mark the ref entry in the list
+                * as one to ignore by setting util to NULL.
+                */
+               if (!strcmp(ref->name + strlen(ref->name) - 3, "^{}")) {
+                       if (item && !has_sha1_file(ref->old_sha1) &&
+                           !will_fetch(head, ref->old_sha1) &&
+                           !has_sha1_file(item->util) &&
+                           !will_fetch(head, item->util))
+                               item->util = NULL;
+                       item = NULL;
+                       continue;
                }
 
-               if (!string_list_has_string(&existing_refs, ref_name) &&
-                   !string_list_has_string(&new_refs, ref_name) &&
-                   (has_sha1_file(ref->old_sha1) ||
-                    will_fetch(head, ref->old_sha1))) {
-                       string_list_insert(ref_name, &new_refs);
+               /*
+                * If item is non-NULL here, then we previously saw a
+                * ref not followed by a peeled reference, so we need
+                * to check if it is a lightweight tag that we want to
+                * fetch.
+                */
+               if (item && !has_sha1_file(item->util) &&
+                   !will_fetch(head, item->util))
+                       item->util = NULL;
 
-                       rm = alloc_ref(ref_name);
-                       rm->peer_ref = alloc_ref(ref_name);
-                       hashcpy(rm->old_sha1, ref_sha1);
+               item = NULL;
 
-                       **tail = rm;
-                       *tail = &rm->next;
-               }
-               free(ref_name);
+               /* skip duplicates and refs that we already have */
+               if (string_list_has_string(&remote_refs, ref->name) ||
+                   string_list_has_string(&existing_refs, ref->name))
+                       continue;
+
+               item = string_list_insert(ref->name, &remote_refs);
+               item->util = (void *)ref->old_sha1;
        }
        string_list_clear(&existing_refs, 0);
-       string_list_clear(&new_refs, 0);
+
+       /*
+        * We may have a final lightweight tag that needs to be
+        * checked to see if it needs fetching.
+        */
+       if (item && !has_sha1_file(item->util) &&
+           !will_fetch(head, item->util))
+               item->util = NULL;
+
+       /*
+        * For all the tags in the remote_refs string list, call
+        * add_to_tail to add them to the list of refs to be fetched
+        */
+       for_each_string_list(add_to_tail, &remote_refs, &data);
+
+       string_list_clear(&remote_refs, 0);
 }
 
 static void check_not_current_branch(struct ref *ref_map)
@@ -574,9 +616,14 @@ static void check_not_current_branch(struct ref *ref_map)
 static int do_fetch(struct transport *transport,
                    struct refspec *refs, int ref_count)
 {
+       struct string_list existing_refs = { NULL, 0, 0, 0 };
+       struct string_list_item *peer_item = NULL;
        struct ref *ref_map;
        struct ref *rm;
        int autotags = (transport->remote->fetch_tags == 1);
+
+       for_each_ref(add_existing, &existing_refs);
+
        if (transport->remote->fetch_tags == 2 && tags != TAGS_UNSET)
                tags = TAGS_SET;
        if (transport->remote->fetch_tags == -1)
@@ -599,8 +646,13 @@ static int do_fetch(struct transport *transport,
                check_not_current_branch(ref_map);
 
        for (rm = ref_map; rm; rm = rm->next) {
-               if (rm->peer_ref)
-                       read_ref(rm->peer_ref->name, rm->peer_ref->old_sha1);
+               if (rm->peer_ref) {
+                       peer_item = string_list_lookup(rm->peer_ref->name,
+                                                      &existing_refs);
+                       if (peer_item)
+                               hashcpy(rm->peer_ref->old_sha1,
+                                       peer_item->util);
+               }
        }
 
        if (tags == TAGS_DEFAULT && autotags)
index c58b0e337ed434ffb90cfb5c80540531d94a4a6a..2d88e4570f8217beaf7f5400dc3c3a328222ebe8 100644 (file)
@@ -19,7 +19,7 @@ static int show_root;
 static int show_tags;
 static int show_unreachable;
 static int include_reflogs = 1;
-static int check_full;
+static int check_full = 1;
 static int check_strict;
 static int keep_cache_objects;
 static unsigned char head_sha1[20];
index 7d3e9cc7a04e0aa3eb378cb54b7b71fe17981c95..093517e390044055039b9f4e58132c73d17b741d 100644 (file)
@@ -216,10 +216,13 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
                 */
                if (!need_to_gc())
                        return 0;
-               fprintf(stderr, "Auto packing your repository for optimum "
-                       "performance. You may also\n"
-                       "run \"git gc\" manually. See "
-                       "\"git help gc\" for more information.\n");
+               fprintf(stderr,
+                       "Auto packing the repository for optimum performance.%s\n",
+                       quiet
+                       ? ""
+                       : (" You may also\n"
+                          "run \"git gc\" manually. See "
+                          "\"git help gc\" for more information."));
        } else
                append_option(argv_repack,
                              prune_expire && !strcmp(prune_expire, "now")
index 761799d7d0afd62ecba99d703a8595664faa4723..01be9bf7ff74731969384cc91dad2e20d08d81bc 100644 (file)
@@ -631,7 +631,7 @@ static int file_callback(const struct option *opt, const char *arg, int unset)
        struct grep_opt *grep_opt = opt->value;
        FILE *patterns;
        int lno = 0;
-       struct strbuf sb;
+       struct strbuf sb = STRBUF_INIT;
 
        patterns = fopen(arg, "r");
        if (!patterns)
@@ -788,6 +788,13 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                OPT_END()
        };
 
+       /*
+        * 'git grep -h', unlike 'git grep -h <pattern>', is a request
+        * to show usage information and exit.
+        */
+       if (argc == 2 && !strcmp(argv[1], "-h"))
+               usage_with_options(grep_usage, options);
+
        memset(&opt, 0, sizeof(opt));
        opt.prefix = prefix;
        opt.prefix_length = (prefix && *prefix) ? strlen(prefix) : 0;
index e1eba778a526f500b0a65a6b112e468f04a3f869..ca08519d9d6290f3cda4ee92e29e4acbf8325d0c 100644 (file)
@@ -372,6 +372,7 @@ static void show_info_page(const char *git_cmd)
        const char *page = cmd_to_page(git_cmd);
        setenv("INFOPATH", system_path(GIT_INFO_PATH), 1);
        execlp("info", "info", "gitman", page, NULL);
+       die("no info viewer handled the request");
 }
 
 static void get_html_page_path(struct strbuf *page_path, const char *page)
@@ -416,9 +417,6 @@ int cmd_help(int argc, const char **argv, const char *prefix)
        const char *alias;
        load_command_list("git-", &main_cmds, &other_cmds);
 
-       setup_git_directory_gently(&nongit);
-       git_config(git_help_config, NULL);
-
        argc = parse_options(argc, argv, prefix, builtin_help_options,
                        builtin_help_usage, 0);
 
@@ -429,6 +427,9 @@ int cmd_help(int argc, const char **argv, const char *prefix)
                return 0;
        }
 
+       setup_git_directory_gently(&nongit);
+       git_config(git_help_config, NULL);
+
        if (!argv[0]) {
                printf("usage: %s\n\n", git_usage_string);
                list_common_cmds_help();
index 25e21ed41534c8c3067c2e0d5afe4284faa2881a..33fa6ea6c855df904cfcf30f0b413cb8bca61fa9 100644 (file)
@@ -50,6 +50,12 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,
        if (default_date_mode)
                rev->date_mode = parse_date_format(default_date_mode);
 
+       /*
+        * Check for -h before setup_revisions(), or "git log -h" will
+        * fail when run without a git directory.
+        */
+       if (argc == 2 && !strcmp(argv[1], "-h"))
+               usage(builtin_log_usage);
        argc = setup_revisions(argc, argv, rev, "HEAD");
 
        if (rev->diffopt.pickaxe || rev->diffopt.filter)
@@ -891,6 +897,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
        struct patch_ids ids;
        char *add_signoff = NULL;
        struct strbuf buf = STRBUF_INIT;
+       int use_patch_format = 0;
        const struct option builtin_format_patch_options[] = {
                { OPTION_CALLBACK, 'n', "numbered", &numbered, NULL,
                            "use [PATCH n/m] even with a single patch",
@@ -922,6 +929,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                            "don't output binary diffs"),
                OPT_BOOLEAN(0, "ignore-if-in-upstream", &ignore_if_in_upstream,
                            "don't include a patch matching a commit upstream"),
+               { OPTION_BOOLEAN, 'p', "no-stat", &use_patch_format, NULL,
+                 "show patch format instead of default (patch + stat)",
+                 PARSE_OPT_NONEG | PARSE_OPT_NOARG },
                OPT_GROUP("Messaging"),
                { OPTION_CALLBACK, 0, "add-header", NULL, "header",
                            "add email header", PARSE_OPT_NONEG,
@@ -1027,9 +1037,20 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
        if (argc > 1)
                die ("unrecognized argument: %s", argv[1]);
 
-       if (!rev.diffopt.output_format
-               || rev.diffopt.output_format == DIFF_FORMAT_PATCH)
-               rev.diffopt.output_format = DIFF_FORMAT_DIFFSTAT | DIFF_FORMAT_SUMMARY | DIFF_FORMAT_PATCH;
+       if (rev.diffopt.output_format & DIFF_FORMAT_NAME)
+               die("--name-only does not make sense");
+       if (rev.diffopt.output_format & DIFF_FORMAT_NAME_STATUS)
+               die("--name-status does not make sense");
+       if (rev.diffopt.output_format & DIFF_FORMAT_CHECKDIFF)
+               die("--check does not make sense");
+
+       if (!use_patch_format &&
+               (!rev.diffopt.output_format ||
+                rev.diffopt.output_format == DIFF_FORMAT_PATCH))
+               rev.diffopt.output_format = DIFF_FORMAT_DIFFSTAT | DIFF_FORMAT_SUMMARY;
+
+       /* Always generate a patch */
+       rev.diffopt.output_format |= DIFF_FORMAT_PATCH;
 
        if (!DIFF_OPT_TST(&rev.diffopt, TEXT) && !no_binary_diff)
                DIFF_OPT_SET(&rev.diffopt, BINARY);
@@ -1237,6 +1258,9 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
                argv++;
        }
 
+       if (argc > 1 && !strcmp(argv[1], "-h"))
+               usage(cherry_usage);
+
        switch (argc) {
        case 4:
                limit = argv[3];
@@ -1304,8 +1328,9 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
 
                if (verbose) {
                        struct strbuf buf = STRBUF_INIT;
+                       struct pretty_print_context ctx = {0};
                        pretty_print_commit(CMIT_FMT_ONELINE, commit,
-                                           &buf, 0, NULL, NULL, 0, 0);
+                                           &buf, &ctx);
                        printf("%c %s %s\n", sign,
                               sha1_to_hex(commit->object.sha1), buf.buf);
                        strbuf_release(&buf);
index 2c95ca61056f0c0b6ac0240605e2e4de895a6804..c9a03e5427bbf1390aeefb9d48b4e362ca6a8e1b 100644 (file)
@@ -171,8 +171,8 @@ static void show_files(struct dir_struct *dir, const char *prefix)
                for (i = 0; i < active_nr; i++) {
                        struct cache_entry *ce = active_cache[i];
                        int dtype = ce_to_dtype(ce);
-                       if (excluded(dir, ce->name, &dtype) !=
-                                       !!(dir->flags & DIR_SHOW_IGNORED))
+                       if (dir->flags & DIR_SHOW_IGNORED &&
+                           !excluded(dir, ce->name, &dtype))
                                continue;
                        if (show_unmerged && !ce_stage(ce))
                                continue;
@@ -187,8 +187,8 @@ static void show_files(struct dir_struct *dir, const char *prefix)
                        struct stat st;
                        int err;
                        int dtype = ce_to_dtype(ce);
-                       if (excluded(dir, ce->name, &dtype) !=
-                                       !!(dir->flags & DIR_SHOW_IGNORED))
+                       if (dir->flags & DIR_SHOW_IGNORED &&
+                           !excluded(dir, ce->name, &dtype))
                                continue;
                        if (ce->ce_flags & CE_UPDATE)
                                continue;
index 78a88f74769645f0be86aa77d3dee3f5e99c916f..b5bad0c184fc1ebc49759f211781ecd4031fd027 100644 (file)
@@ -86,10 +86,10 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
                        pattern[j - i] = p;
                }
        }
-       remote = nongit ? NULL : remote_get(dest);
-       if (remote && !remote->url_nr)
+       remote = remote_get(dest);
+       if (!remote->url_nr)
                die("remote %s has no configured URL", dest);
-       transport = transport_get(remote, remote ? remote->url[0] : dest);
+       transport = transport_get(remote, remote->url[0]);
        if (uploadpack != NULL)
                transport_set_option(transport, TRANS_OPT_UPLOADPACK, uploadpack);
 
index 22008dfa8fb94d971b6fb1bd7342ede02a8d3fd0..4484185afc4c144bc0d88d9c3832cbeb1515841b 100644 (file)
@@ -9,6 +9,7 @@
 #include "commit.h"
 #include "quote.h"
 #include "builtin.h"
+#include "parse-options.h"
 
 static int line_termination = '\n';
 #define LS_RECURSIVE 1
@@ -22,8 +23,10 @@ static const char **pathspec;
 static int chomp_prefix;
 static const char *ls_tree_prefix;
 
-static const char ls_tree_usage[] =
-       "git ls-tree [-d] [-r] [-t] [-l] [-z] [--name-only] [--name-status] [--full-name] [--full-tree] [--abbrev[=<n>]] <tree-ish> [path...]";
+static const  char * const ls_tree_usage[] = {
+       "git ls-tree [<options>] <tree-ish> [path...]",
+       NULL
+};
 
 static int show_recursive(const char *base, int baselen, const char *pathname)
 {
@@ -117,76 +120,53 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
 {
        unsigned char sha1[20];
        struct tree *tree;
+       int full_tree = 0;
+       const struct option ls_tree_options[] = {
+               OPT_BIT('d', NULL, &ls_options, "only show trees",
+                       LS_TREE_ONLY),
+               OPT_BIT('r', NULL, &ls_options, "recurse into subtrees",
+                       LS_RECURSIVE),
+               OPT_BIT('t', NULL, &ls_options, "show trees when recursing",
+                       LS_SHOW_TREES),
+               OPT_SET_INT('z', NULL, &line_termination,
+                           "terminate entries with NUL byte", 0),
+               OPT_BIT('l', "long", &ls_options, "include object size",
+                       LS_SHOW_SIZE),
+               OPT_BIT(0, "name-only", &ls_options, "list only filenames",
+                       LS_NAME_ONLY),
+               OPT_BIT(0, "name-status", &ls_options, "list only filenames",
+                       LS_NAME_ONLY),
+               OPT_SET_INT(0, "full-name", &chomp_prefix,
+                           "use full path names", 0),
+               OPT_BOOLEAN(0, "full-tree", &full_tree,
+                           "list entire tree; not just current directory "
+                           "(implies --full-name)"),
+               OPT__ABBREV(&abbrev),
+               OPT_END()
+       };
 
        git_config(git_default_config, NULL);
        ls_tree_prefix = prefix;
        if (prefix && *prefix)
                chomp_prefix = strlen(prefix);
-       while (1 < argc && argv[1][0] == '-') {
-               switch (argv[1][1]) {
-               case 'z':
-                       line_termination = 0;
-                       break;
-               case 'r':
-                       ls_options |= LS_RECURSIVE;
-                       break;
-               case 'd':
-                       ls_options |= LS_TREE_ONLY;
-                       break;
-               case 't':
-                       ls_options |= LS_SHOW_TREES;
-                       break;
-               case 'l':
-                       ls_options |= LS_SHOW_SIZE;
-                       break;
-               case '-':
-                       if (!strcmp(argv[1]+2, "name-only") ||
-                           !strcmp(argv[1]+2, "name-status")) {
-                               ls_options |= LS_NAME_ONLY;
-                               break;
-                       }
-                       if (!strcmp(argv[1]+2, "long")) {
-                               ls_options |= LS_SHOW_SIZE;
-                               break;
-                       }
-                       if (!strcmp(argv[1]+2, "full-name")) {
-                               chomp_prefix = 0;
-                               break;
-                       }
-                       if (!strcmp(argv[1]+2, "full-tree")) {
-                               ls_tree_prefix = prefix = NULL;
-                               chomp_prefix = 0;
-                               break;
-                       }
-                       if (!prefixcmp(argv[1]+2, "abbrev=")) {
-                               abbrev = strtoul(argv[1]+9, NULL, 10);
-                               if (abbrev && abbrev < MINIMUM_ABBREV)
-                                       abbrev = MINIMUM_ABBREV;
-                               else if (abbrev > 40)
-                                       abbrev = 40;
-                               break;
-                       }
-                       if (!strcmp(argv[1]+2, "abbrev")) {
-                               abbrev = DEFAULT_ABBREV;
-                               break;
-                       }
-                       /* otherwise fallthru */
-               default:
-                       usage(ls_tree_usage);
-               }
-               argc--; argv++;
+
+       argc = parse_options(argc, argv, prefix, ls_tree_options,
+                            ls_tree_usage, 0);
+       if (full_tree) {
+               ls_tree_prefix = prefix = NULL;
+               chomp_prefix = 0;
        }
        /* -d -r should imply -t, but -d by itself should not have to. */
        if ( (LS_TREE_ONLY|LS_RECURSIVE) ==
            ((LS_TREE_ONLY|LS_RECURSIVE) & ls_options))
                ls_options |= LS_SHOW_TREES;
 
-       if (argc < 2)
-               usage(ls_tree_usage);
-       if (get_sha1(argv[1], sha1))
-               die("Not a valid object name %s", argv[1]);
+       if (argc < 1)
+               usage_with_options(ls_tree_usage, ls_tree_options);
+       if (get_sha1(argv[0], sha1))
+               die("Not a valid object name %s", argv[0]);
 
-       pathspec = get_pathspec(prefix, argv + 2);
+       pathspec = get_pathspec(prefix, argv + 1);
        tree = parse_tree_indirect(sha1);
        if (!tree)
                die("not a tree object");
index dfe5b151e6e0030abf6248808d414b2fecc5fdb7..207e358ed19cecb8cf7b57d59a9149619909459d 100644 (file)
@@ -231,6 +231,8 @@ int cmd_mailsplit(int argc, const char **argv, const char *prefix)
                        continue;
                } else if ( arg[1] == 'f' ) {
                        nr = strtol(arg+2, NULL, 10);
+               } else if ( arg[1] == 'h' ) {
+                       usage(git_mailsplit_usage);
                } else if ( arg[1] == 'b' && !arg[2] ) {
                        allow_bare = 1;
                } else if (!strcmp(arg, "--keep-cr")) {
index 8f5bbaf402e020e308e7af9cedb7df1b2ec5a2b7..684411694f64ca216fb03430df2d2a0ec9ea93ff 100644 (file)
@@ -10,6 +10,9 @@
 #include "git-compat-util.h"
 #include "builtin.h"
 
+static const char builtin_merge_ours_usage[] =
+       "git merge-ours <base>... -- HEAD <remote>...";
+
 static const char *diff_index_args[] = {
        "diff-index", "--quiet", "--cached", "HEAD", "--", NULL
 };
@@ -17,6 +20,9 @@ static const char *diff_index_args[] = {
 
 int cmd_merge_ours(int argc, const char **argv, const char *prefix)
 {
+       if (argc == 2 && !strcmp(argv[1], "-h"))
+               usage(builtin_merge_ours_usage);
+
        /*
         * We need to exit with 2 if the index does not match our HEAD tree,
         * because the current index is what we will be committing as the
index d26a96e486f2a84fdfc54527d15b9acdf7ea34bb..710674c6b2cccec4f1e0baa477a11d78cda72833 100644 (file)
@@ -33,7 +33,7 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix)
        }
 
        if (argc < 4)
-               die("Usage: %s <base>... -- <head> <remote> ...", argv[0]);
+               usagef("%s <base>... -- <head> <remote> ...", argv[0]);
 
        for (i = 1; i < argc; ++i) {
                if (!strcmp(argv[i], "--"))
index b6b84286b26a4317dfd5185ae83fd861c6f9fa7d..57eedd447d0f899a258998bb3039905a5a49babb 100644 (file)
@@ -43,6 +43,7 @@ static const char * const builtin_merge_usage[] = {
 
 static int show_diffstat = 1, option_log, squash;
 static int option_commit = 1, allow_fast_forward = 1;
+static int fast_forward_only;
 static int allow_trivial = 1, have_message;
 static struct strbuf merge_msg;
 static struct commit_list *remoteheads;
@@ -166,7 +167,9 @@ static struct option builtin_merge_options[] = {
        OPT_BOOLEAN(0, "commit", &option_commit,
                "perform a commit if the merge succeeds (default)"),
        OPT_BOOLEAN(0, "ff", &allow_fast_forward,
-               "allow fast forward (default)"),
+               "allow fast-forward (default)"),
+       OPT_BOOLEAN(0, "ff-only", &fast_forward_only,
+               "abort if fast-forward is not possible"),
        OPT_CALLBACK('s', "strategy", &use_strategies, "strategy",
                "merge strategy to use", option_parse_strategy),
        OPT_CALLBACK('m', "message", &merge_msg, "message",
@@ -264,6 +267,7 @@ static void squash_message(void)
        struct strbuf out = STRBUF_INIT;
        struct commit_list *j;
        int fd;
+       struct pretty_print_context ctx = {0};
 
        printf("Squash commit -- not updating HEAD\n");
        fd = open(git_path("SQUASH_MSG"), O_WRONLY | O_CREAT, 0666);
@@ -285,13 +289,15 @@ static void squash_message(void)
        if (prepare_revision_walk(&rev))
                die("revision walk setup failed");
 
+       ctx.abbrev = rev.abbrev;
+       ctx.date_mode = rev.date_mode;
+
        strbuf_addstr(&out, "Squashed commit of the following:\n");
        while ((commit = get_revision(&rev)) != NULL) {
                strbuf_addch(&out, '\n');
                strbuf_addf(&out, "commit %s\n",
                        sha1_to_hex(commit->object.sha1));
-               pretty_print_commit(rev.commit_format, commit, &out, rev.abbrev,
-                       NULL, NULL, rev.date_mode, 0);
+               pretty_print_commit(rev.commit_format, commit, &out, &ctx);
        }
        if (write(fd, out.buf, out.len) < 0)
                die_errno("Writing SQUASH_MSG");
@@ -840,7 +846,6 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
        const char *best_strategy = NULL, *wt_strategy = NULL;
        struct commit_list **remotes = &remoteheads;
 
-       setup_work_tree();
        if (file_exists(git_path("MERGE_HEAD")))
                die("You have not concluded your merge. (MERGE_HEAD exists)");
        if (read_cache_unmerged())
@@ -874,6 +879,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                option_commit = 0;
        }
 
+       if (!allow_fast_forward && fast_forward_only)
+               die("You cannot combine --no-ff with --ff-only.");
+
        if (!argc)
                usage_with_options(builtin_merge_usage,
                        builtin_merge_options);
@@ -1013,7 +1021,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                                hex,
                                find_unique_abbrev(remoteheads->item->object.sha1,
                                DEFAULT_ABBREV));
-               strbuf_addstr(&msg, "Fast forward");
+               strbuf_addstr(&msg, "Fast-forward");
                if (have_message)
                        strbuf_addstr(&msg,
                                " (no commit created; -m option ignored)");
@@ -1031,16 +1039,16 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
        } else if (!remoteheads->next && common->next)
                ;
                /*
-                * We are not doing octopus and not fast forward.  Need
+                * We are not doing octopus and not fast-forward.  Need
                 * a real merge.
                 */
        else if (!remoteheads->next && !common->next && option_commit) {
                /*
-                * We are not doing octopus, not fast forward, and have
+                * We are not doing octopus, not fast-forward, and have
                 * only one common.
                 */
                refresh_cache(REFRESH_QUIET);
-               if (allow_trivial) {
+               if (allow_trivial && !fast_forward_only) {
                        /* See if it is really trivial. */
                        git_committer_info(IDENT_ERROR_ON_NO_NAME);
                        printf("Trying really trivial in-index merge...\n");
@@ -1079,6 +1087,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                }
        }
 
+       if (fast_forward_only)
+               die("Not possible to fast-forward, aborting.");
+
        /* We are going to make a new commit. */
        git_committer_info(IDENT_ERROR_ON_NO_NAME);
 
index 1b20028c67dec2f9954cb107620bd863b4b3a264..f633d81424f5e41cb85ac660dbdc9f4913852673 100644 (file)
@@ -64,15 +64,15 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
 
        git_config(git_default_config, NULL);
 
-       newfd = hold_locked_index(&lock_file, 1);
-       if (read_cache() < 0)
-               die("index file corrupt");
-
        argc = parse_options(argc, argv, prefix, builtin_mv_options,
                             builtin_mv_usage, 0);
        if (--argc < 1)
                usage_with_options(builtin_mv_usage, builtin_mv_options);
 
+       newfd = hold_locked_index(&lock_file, 1);
+       if (read_cache() < 0)
+               die("index file corrupt");
+
        source = copy_pathspec(prefix, argv, argc, 0);
        modes = xcalloc(argc, sizeof(enum update_mode));
        dest_path = copy_pathspec(prefix, argv + argc, 1, 0);
index 02f9246cdb29903e9d7aafe47604f6882a3e7f86..4c91e944c21df3d5e02535115cdd6098ee49d86d 100644 (file)
@@ -1629,6 +1629,8 @@ static void ll_find_deltas(struct object_entry **list, unsigned list_size,
        struct thread_params *p;
        int i, ret, active_threads = 0;
 
+       if (!delta_search_threads)      /* --threads=0 means autodetect */
+               delta_search_threads = online_cpus();
        if (delta_search_threads <= 1) {
                find_deltas(list, &list_size, window, depth, processed);
                return;
@@ -2324,11 +2326,6 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
        if (keep_unreachable && unpack_unreachable)
                die("--keep-unreachable and --unpack-unreachable are incompatible.");
 
-#ifdef THREADED_DELTA_SEARCH
-       if (!delta_search_threads)      /* --threads=0 means autodetect */
-               delta_search_threads = online_cpus();
-#endif
-
        prepare_packed_git();
 
        if (progress)
index 3cb1ee46d1da898c2be5666a93002ca43df80093..356d7c1fd3a6fae9558e93eb4f240242a60da368 100644 (file)
@@ -10,7 +10,7 @@
 #include "parse-options.h"
 
 static const char * const push_usage[] = {
-       "git push [--all | --mirror] [-n | --dry-run] [--porcelain] [--tags] [--receive-pack=<git-receive-pack>] [--repo=<repository>] [-f | --force] [-v] [<repository> <refspec>...]",
+       "git push [<options>] [<repository> <refspec>...]",
        NULL,
 };
 
@@ -66,7 +66,6 @@ static void setup_push_tracking(void)
 
 static void setup_default_push_refspecs(void)
 {
-       git_config(git_default_config, NULL);
        switch (push_default) {
        default:
        case PUSH_DEFAULT_MATCHING:
@@ -159,7 +158,7 @@ static int do_push(const char *repo, int flags)
                error("failed to push some refs to '%s'", url[i]);
                if (nonfastforward && advice_push_nonfastforward) {
                        printf("To prevent you from losing history, non-fast-forward updates were rejected\n"
-                              "Merge the remote changes before pushing again.  See the 'non-fast forward'\n"
+                              "Merge the remote changes before pushing again.  See the 'non-fast-forward'\n"
                               "section of 'git push --help' for details.\n");
                }
                errs++;
@@ -173,7 +172,6 @@ int cmd_push(int argc, const char **argv, const char *prefix)
        int tags = 0;
        int rc;
        const char *repo = NULL;        /* default repository */
-
        struct option options[] = {
                OPT_BIT('q', "quiet", &flags, "be quiet", TRANSPORT_PUSH_QUIET),
                OPT_BIT('v', "verbose", &flags, "be verbose", TRANSPORT_PUSH_VERBOSE),
@@ -181,7 +179,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
                OPT_BIT( 0 , "all", &flags, "push all refs", TRANSPORT_PUSH_ALL),
                OPT_BIT( 0 , "mirror", &flags, "mirror all refs",
                            (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
-               OPT_BOOLEAN( 0 , "tags", &tags, "push tags"),
+               OPT_BOOLEAN( 0 , "tags", &tags, "push tags (can't be used with --all or --mirror)"),
                OPT_BIT('n' , "dry-run", &flags, "dry run", TRANSPORT_PUSH_DRY_RUN),
                OPT_BIT( 0,  "porcelain", &flags, "machine-readable output", TRANSPORT_PUSH_PORCELAIN),
                OPT_BIT('f', "force", &flags, "force updates", TRANSPORT_PUSH_FORCE),
@@ -191,6 +189,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
                OPT_END()
        };
 
+       git_config(git_default_config, NULL);
        argc = parse_options(argc, argv, prefix, options, push_usage, 0);
 
        if (tags)
index 14c836b1693317d5d834606e5613d7ceacb3189c..2a3a32cbfe83a0e0366d04a99bb49606f647f594 100644 (file)
@@ -108,11 +108,11 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
 
        git_config(git_default_config, NULL);
 
-       newfd = hold_locked_index(&lock_file, 1);
-
        argc = parse_options(argc, argv, unused_prefix, read_tree_options,
                             read_tree_usage, 0);
 
+       newfd = hold_locked_index(&lock_file, 1);
+
        prefix_set = opts.prefix ? 1 : 0;
        if (1 < opts.merge + opts.reset + prefix_set)
                die("Which one? -m, --reset, or --prefix?");
index b771fe9b20f4c4d6e19289f428442d489aba6896..b6895d3f992f17e215d98f185a024a3e4041e507 100644 (file)
@@ -28,6 +28,8 @@ static int transfer_unpack_limit = -1;
 static int unpack_limit = 100;
 static int report_status;
 static int prefer_ofs_delta = 1;
+static int auto_update_server_info;
+static int auto_gc = 1;
 static const char *head_name;
 static char *capabilities_to_send;
 
@@ -88,6 +90,16 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
                return 0;
        }
 
+       if (strcmp(var, "receive.updateserverinfo") == 0) {
+               auto_update_server_info = git_config_bool(var, value);
+               return 0;
+       }
+
+       if (strcmp(var, "receive.autogc") == 0) {
+               auto_gc = git_config_bool(var, value);
+               return 0;
+       }
+
        return git_default_config(var, value, cb);
 }
 
@@ -329,9 +341,9 @@ static const char *update(struct command *cmd)
                                break;
                free_commit_list(bases);
                if (!ent) {
-                       error("denying non-fast forward %s"
+                       error("denying non-fast-forward %s"
                              " (you should pull first)", name);
-                       return "non-fast forward";
+                       return "non-fast-forward";
                }
        }
        if (run_update_hook(cmd)) {
@@ -672,6 +684,14 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
                        report(unpack_status);
                run_receive_hook(post_receive_hook);
                run_update_post_hook(commands);
+               if (auto_gc) {
+                       const char *argv_gc_auto[] = {
+                               "gc", "--auto", "--quiet", NULL,
+                       };
+                       run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
+               }
+               if (auto_update_server_info)
+                       update_server_info(0);
        }
        return 0;
 }
index e23b5ef979d98e5e44693345856a13485695246f..749821078df129cf13de34ebbd40a8cb7a38e00e 100644 (file)
@@ -698,6 +698,9 @@ static const char reflog_usage[] =
 
 int cmd_reflog(int argc, const char **argv, const char *prefix)
 {
+       if (argc > 1 && !strcmp(argv[1], "-h"))
+               usage(reflog_usage);
+
        /* With no command, we default to showing it. */
        if (argc < 2 || *argv[1] == '-')
                return cmd_log_reflog(argc, argv, prefix);
index 0777dd719b41ec4c545b336bc5144a73d34001d7..9aafc19c4d20dd223002feb480980d5610b0b5f7 100644 (file)
@@ -953,7 +953,7 @@ static int show_push_info_item(struct string_list_item *item, void *cb_data)
                status = "up to date";
                break;
        case PUSH_STATUS_FASTFORWARD:
-               status = "fast forwardable";
+               status = "fast-forwardable";
                break;
        case PUSH_STATUS_OUTOFDATE:
                status = "local out of date";
index adfb7b5f48597c19c23235b74cf1a0c779985dc6..343d6cde48266d63c0aa6826b973e55b48820745 100644 (file)
@@ -106,6 +106,9 @@ int cmd_rerere(int argc, const char **argv, const char *prefix)
        if (argc < 2)
                return rerere();
 
+       if (!strcmp(argv[1], "-h"))
+               usage(git_rerere_usage);
+
        fd = setup_rerere(&merge_rr);
        if (fd < 0)
                return 0;
index 4ba1c12e0b6fedb056aebed6ffc8f8bb8d6cfd18..ac1136a3f5a6d61e8b5ae18ae32451674effb0d8 100644 (file)
@@ -96,9 +96,10 @@ static void show_commit(struct commit *commit, void *data)
 
        if (revs->verbose_header && commit->buffer) {
                struct strbuf buf = STRBUF_INIT;
-               pretty_print_commit(revs->commit_format, commit,
-                                   &buf, revs->abbrev, NULL, NULL,
-                                   revs->date_mode, 0);
+               struct pretty_print_context ctx = {0};
+               ctx.abbrev = revs->abbrev;
+               ctx.date_mode = revs->date_mode;
+               pretty_print_commit(revs->commit_format, commit, &buf, &ctx);
                if (revs->graph) {
                        if (buf.len) {
                                if (revs->commit_format != CMIT_FMT_ONELINE)
@@ -319,6 +320,8 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
 
        memset(&info, 0, sizeof(info));
        info.revs = &revs;
+       if (revs.bisect)
+               bisect_list = 1;
 
        quiet = DIFF_OPT_TST(&revs.diffopt, QUIET);
        for (i = 1 ; i < argc; i++) {
index 45bead65451e87a4b564e59fed3518a4de9198e9..37d02335212dea9672e2472970f66dc4ac95dfd1 100644 (file)
@@ -180,6 +180,12 @@ static int show_reference(const char *refname, const unsigned char *sha1, int fl
        return 0;
 }
 
+static int anti_reference(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
+{
+       show_rev(REVERSED, sha1, refname);
+       return 0;
+}
+
 static void show_datestring(const char *flag, const char *datestr)
 {
        static char buffer[100];
@@ -426,6 +432,13 @@ static void die_no_single_rev(int quiet)
                die("Needed a single revision");
 }
 
+static const char builtin_rev_parse_usage[] =
+"git rev-parse --parseopt [options] -- [<args>...]\n"
+"   or: git rev-parse --sq-quote [<arg>...]\n"
+"   or: git rev-parse [options] [<arg>...]\n"
+"\n"
+"Run \"git rev-parse --parseopt -h\" for more information on the first usage.";
+
 int cmd_rev_parse(int argc, const char **argv, const char *prefix)
 {
        int i, as_is = 0, verify = 0, quiet = 0, revs_count = 0, type = 0;
@@ -438,6 +451,9 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
        if (argc > 1 && !strcmp("--sq-quote", argv[1]))
                return cmd_sq_quote(argc - 2, argv + 2);
 
+       if (argc > 1 && !strcmp("-h", argv[1]))
+               usage(builtin_rev_parse_usage);
+
        prefix = setup_git_directory();
        git_config(git_default_config, NULL);
        for (i = 1; i < argc; i++) {
@@ -548,6 +564,11 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
                                for_each_ref(show_reference, NULL);
                                continue;
                        }
+                       if (!strcmp(arg, "--bisect")) {
+                               for_each_ref_in("refs/bisect/bad", show_reference, NULL);
+                               for_each_ref_in("refs/bisect/good", anti_reference, NULL);
+                               continue;
+                       }
                        if (!strcmp(arg, "--branches")) {
                                for_each_branch_ref(show_reference, NULL);
                                continue;
index 37e528e28364fbde5a5ba31316aa7bf66d43586b..37acad5ac190b7e203c61de475c15a0b86b8548a 100644 (file)
@@ -246,7 +246,7 @@ static int print_one_push_status(struct ref *ref, const char *dest, int count)
                break;
        case REF_STATUS_REJECT_NONFASTFORWARD:
                print_ref_status('!', "[rejected]", ref, ref->peer_ref,
-                               "non-fast forward");
+                               "non-fast-forward");
                break;
        case REF_STATUS_REMOTE_REJECT:
                print_ref_status('!', "[remote rejected]", ref,
index 4d4a3c82d6209ce3ec897dad0c69d58a329b4303..8aa63c7857fb3a704826bf223ddefb3e40f0eaf7 100644 (file)
@@ -158,9 +158,12 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit)
                    sha1_to_hex(commit->object.sha1));
        if (log->user_format) {
                struct strbuf buf = STRBUF_INIT;
-
-               pretty_print_commit(CMIT_FMT_USERFORMAT, commit, &buf,
-                       DEFAULT_ABBREV, "", "", DATE_NORMAL, 0);
+               struct pretty_print_context ctx = {0};
+               ctx.abbrev = DEFAULT_ABBREV;
+               ctx.subject = "";
+               ctx.after_subject = "";
+               ctx.date_mode = DATE_NORMAL;
+               pretty_print_commit(CMIT_FMT_USERFORMAT, commit, &buf, &ctx);
                insert_one_record(log, author, buf.buf);
                strbuf_release(&buf);
                return;
index be95930b783f47ade274e281227844e795729f5a..9f13caa76d3b147993b2cf39397d2f5761cfca22 100644 (file)
@@ -293,8 +293,8 @@ static void show_one_commit(struct commit *commit, int no_name)
        struct commit_name *name = commit->util;
 
        if (commit->object.parsed) {
-               pretty_print_commit(CMIT_FMT_ONELINE, commit,
-                                   &pretty, 0, NULL, NULL, 0, 0);
+               struct pretty_print_context ctx = {0};
+               pretty_print_commit(CMIT_FMT_ONELINE, commit, &pretty, &ctx);
                pretty_str = pretty.buf;
        }
        if (!prefixcmp(pretty_str, "[PATCH] "))
index c46550c9c01da8fe74145e16656a5163a7e4f07b..17ada88dfb9543ba782b84507b451fabfec28e10 100644 (file)
@@ -7,7 +7,7 @@
 #include "parse-options.h"
 
 static const char * const show_ref_usage[] = {
-       "git show-ref [-q|--quiet] [--verify] [-h|--head] [-d|--dereference] [-s|--hash[=<n>]] [--abbrev[=<n>]] [--tags] [--heads] [--] [pattern*] ",
+       "git show-ref [-q|--quiet] [--verify] [--head] [-d|--dereference] [-s|--hash[=<n>]] [--abbrev[=<n>]] [--tags] [--heads] [--] [pattern*] ",
        "git show-ref --exclude-existing[=pattern] < ref-list",
        NULL
 };
@@ -183,7 +183,10 @@ static const struct option show_ref_options[] = {
        OPT_BOOLEAN(0, "heads", &heads_only, "only show heads (can be combined with tags)"),
        OPT_BOOLEAN(0, "verify", &verify, "stricter reference checking, "
                    "requires exact ref path"),
-       OPT_BOOLEAN('h', "head", &show_head, "show the HEAD reference"),
+       { OPTION_BOOLEAN, 'h', NULL, &show_head, NULL,
+         "show the HEAD reference",
+         PARSE_OPT_NOARG | PARSE_OPT_HIDDEN },
+       OPT_BOOLEAN(0, "head", &show_head, "show the HEAD reference"),
        OPT_BOOLEAN('d', "dereference", &deref_tags,
                    "dereference tags into object IDs"),
        { OPTION_CALLBACK, 's', "hash", &abbrev, "n",
@@ -201,6 +204,9 @@ static const struct option show_ref_options[] = {
 
 int cmd_show_ref(int argc, const char **argv, const char *prefix)
 {
+       if (argc == 2 && !strcmp(argv[1], "-h"))
+               usage_with_options(show_ref_usage, show_ref_options);
+
        argc = parse_options(argc, argv, prefix, show_ref_options,
                             show_ref_usage, PARSE_OPT_NO_INTERNAL_HELP);
 
index 1fd2205d530ad510a18ff5a441ca7b5cb1cc34a6..4d3b93fedb5f2eca68edca15ca1e10cb60176d36 100644 (file)
@@ -73,9 +73,11 @@ int cmd_stripspace(int argc, const char **argv, const char *prefix)
        struct strbuf buf = STRBUF_INIT;
        int strip_comments = 0;
 
-       if (argc > 1 && (!strcmp(argv[1], "-s") ||
+       if (argc == 2 && (!strcmp(argv[1], "-s") ||
                                !strcmp(argv[1], "--strip-comments")))
                strip_comments = 1;
+       else if (argc > 1)
+               usage("git stripspace [-s | --strip-comments] < <stream>");
 
        if (strbuf_read(&buf, 0, 1024) < 0)
                die_errno("could not read the input");
index 8b3a35e12da2cca8b632d4139bc2c5ba2409d322..3f1e7012db1af7d3695e6517956721a313229d65 100644 (file)
@@ -11,6 +11,9 @@ static const char tar_tree_usage[] =
 "git tar-tree [--remote=<repo>] <tree-ish> [basedir]\n"
 "*** Note that this command is now deprecated; use \"git archive\" instead.";
 
+static const char builtin_get_tar_commit_id_usage[] =
+"git get-tar-commit-id < <tarfile>";
+
 int cmd_tar_tree(int argc, const char **argv, const char *prefix)
 {
        /*
@@ -81,6 +84,9 @@ int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix)
        char *content = buffer + RECORDSIZE;
        ssize_t n;
 
+       if (argc != 1)
+               usage(builtin_get_tar_commit_id_usage);
+
        n = read_in_full(0, buffer, HEADERSIZE);
        if (n < HEADERSIZE)
                die("git get-tar-commit-id: read error");
index c4cd1e1327f18ae27b74fac6dfd41938cd9dfe5d..29446e84ccf9322e722830f5af11da0c56709fb8 100644 (file)
@@ -132,7 +132,6 @@ int cmd_upload_archive(int argc, const char **argv, const char *prefix)
 
        while (1) {
                struct pollfd pfd[2];
-               ssize_t processed[2] = { 0, 0 };
                int status;
 
                pfd[0].fd = fd1[0];
@@ -147,15 +146,14 @@ int cmd_upload_archive(int argc, const char **argv, const char *prefix)
                        }
                        continue;
                }
-               if (pfd[0].revents & POLLIN)
-                       /* Data stream ready */
-                       processed[0] = process_input(pfd[0].fd, 1);
                if (pfd[1].revents & POLLIN)
                        /* Status stream ready */
-                       processed[1] = process_input(pfd[1].fd, 2);
-               /* Always finish to read data when available */
-               if (processed[0] || processed[1])
-                       continue;
+                       if (process_input(pfd[1].fd, 2))
+                               continue;
+               if (pfd[0].revents & POLLIN)
+                       /* Data stream ready */
+                       if (process_input(pfd[0].fd, 1))
+                               continue;
 
                if (waitpid(writer, &status, 0) < 0)
                        error_clnt("%s", lostchild);
index a2174dc855ad89e486c57ae1c3a458cb1572edbb..c3f83c093f6d18dc21ff4112513abbc84fb7858c 100644 (file)
--- a/builtin.h
+++ b/builtin.h
@@ -48,7 +48,6 @@ extern int cmd_diff_tree(int argc, const char **argv, const char *prefix);
 extern int cmd_fast_export(int argc, const char **argv, const char *prefix);
 extern int cmd_fetch(int argc, const char **argv, const char *prefix);
 extern int cmd_fetch_pack(int argc, const char **argv, const char *prefix);
-extern int cmd_fetch__tool(int argc, const char **argv, const char *prefix);
 extern int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix);
 extern int cmd_for_each_ref(int argc, const char **argv, const char *prefix);
 extern int cmd_format_patch(int argc, const char **argv, const char *prefix);
diff --git a/cache.h b/cache.h
index a5eeead1e275523fbc7bc192a836193720370991..71a731dbc988a8a22d0a2e1f8f3a5223f4c5d67a 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -396,6 +396,7 @@ extern const char *setup_git_directory_gently(int *);
 extern const char *setup_git_directory(void);
 extern const char *prefix_path(const char *prefix, int len, const char *path);
 extern const char *prefix_filename(const char *prefix, int len, const char *path);
+extern int check_filename(const char *prefix, const char *name);
 extern void verify_filename(const char *prefix, const char *name);
 extern void verify_non_filename(const char *prefix, const char *name);
 
@@ -986,10 +987,12 @@ void shift_tree(const unsigned char *, const unsigned char *, unsigned char *, i
  * whitespace rules.
  * used by both diff and apply
  */
-#define WS_TRAILING_SPACE      01
+#define WS_BLANK_AT_EOL         01
 #define WS_SPACE_BEFORE_TAB    02
 #define WS_INDENT_WITH_NON_TAB 04
 #define WS_CR_AT_EOL           010
+#define WS_BLANK_AT_EOF        020
+#define WS_TRAILING_SPACE      (WS_BLANK_AT_EOL|WS_BLANK_AT_EOF)
 #define WS_DEFAULT_RULE (WS_TRAILING_SPACE|WS_SPACE_BEFORE_TAB)
 extern unsigned whitespace_rule_cfg;
 extern unsigned whitespace_rule(const char *);
index fb03a2ebb5d51f46d00fad3b3f6b1794d4fdad2b..59b0adc39b7c2d30103fe5d30b416b6d4ca64c31 100644 (file)
@@ -92,6 +92,7 @@ git-reflog                              ancillarymanipulators
 git-relink                              ancillarymanipulators
 git-remote                              ancillarymanipulators
 git-repack                              ancillarymanipulators
+git-replace                             ancillarymanipulators
 git-repo-config                         ancillarymanipulators  deprecated
 git-request-pull                        foreignscminterface
 git-rerere                              ancillaryinterrogators
index fedbd5e5267ec4beaf1f245a879918a2685c10b9..6393e1b36218e5f8970b0c43092b07f5d94b0bce 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -132,8 +132,8 @@ struct commit_graft *read_graft_line(char *buf, int len)
        int i;
        struct commit_graft *graft = NULL;
 
-       if (buf[len-1] == '\n')
-               buf[--len] = 0;
+       while (len && isspace(buf[len-1]))
+               buf[--len] = '\0';
        if (buf[0] == '#' || buf[0] == '\0')
                return NULL;
        if ((len + 1) % 41) {
index f4fc5c5589a3ae6f2b99e533c3dd0f3a7a7f418a..422f778f3f5b997ea1a3d8569cf6fa573481fff1 100644 (file)
--- a/commit.h
+++ b/commit.h
@@ -63,6 +63,16 @@ enum cmit_fmt {
        CMIT_FMT_UNSPECIFIED,
 };
 
+struct pretty_print_context
+{
+       int abbrev;
+       const char *subject;
+       const char *after_subject;
+       enum date_mode date_mode;
+       int need_8bit_cte;
+       struct reflog_walk_info *reflog_info;
+};
+
 extern int non_ascii(int);
 extern int has_non_ascii(const char *text);
 struct rev_info; /* in revision.h, it circularly uses enum cmit_fmt */
@@ -70,13 +80,11 @@ extern char *reencode_commit_message(const struct commit *commit,
                                     const char **encoding_p);
 extern void get_commit_format(const char *arg, struct rev_info *);
 extern void format_commit_message(const struct commit *commit,
-                                 const void *format, struct strbuf *sb,
-                                 enum date_mode dmode);
-extern void pretty_print_commit(enum cmit_fmt fmt, const struct commit*,
-                                struct strbuf *,
-                                int abbrev, const char *subject,
-                                const char *after_subject, enum date_mode,
-                               int need_8bit_cte);
+                                 const char *format, struct strbuf *sb,
+                                 const struct pretty_print_context *context);
+extern void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,
+                               struct strbuf *sb,
+                               const struct pretty_print_context *context);
 void pp_user_info(const char *what, enum cmit_fmt fmt, struct strbuf *sb,
                   const char *line, enum date_mode dmode,
                   const char *encoding);
index 5cc4acbfccef771769974b9f7cd8f6bca9321354..279e0b48b15e091fc0ca975c3efbd461ab02c149 100644 (file)
@@ -28,6 +28,16 @@ static inline uint32_t default_swab32(uint32_t val)
        } \
        __res; })
 
+#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
+
+#include <stdlib.h>
+
+#define bswap32(x) _byteswap_ulong(x)
+
+#endif
+
+#ifdef bswap32
+
 #undef ntohl
 #undef htonl
 #define ntohl(x) bswap32(x)
index 5b5258bcebbbead7e4ed15a4dea7bf755739b98e..6907345f90128eb20c1ca0a81c452af775877b4b 100644 (file)
@@ -124,6 +124,27 @@ static inline int waitpid(pid_t pid, int *status, unsigned options)
        return -1;
 }
 
+#ifndef NO_OPENSSL
+#include <openssl/ssl.h>
+static inline int mingw_SSL_set_fd(SSL *ssl, int fd)
+{
+       return SSL_set_fd(ssl, _get_osfhandle(fd));
+}
+#define SSL_set_fd mingw_SSL_set_fd
+
+static inline int mingw_SSL_set_rfd(SSL *ssl, int fd)
+{
+       return SSL_set_rfd(ssl, _get_osfhandle(fd));
+}
+#define SSL_set_rfd mingw_SSL_set_rfd
+
+static inline int mingw_SSL_set_wfd(SSL *ssl, int fd)
+{
+       return SSL_set_wfd(ssl, _get_osfhandle(fd));
+}
+#define SSL_set_wfd mingw_SSL_set_wfd
+#endif
+
 /*
  * implementations of missing functions
  */
index f9528c0ea10db41f948e6d24b84125d2d54f6dda..8a2112f22f46b3066d75bd5472dfe05bf88836c8 100644 (file)
@@ -29,6 +29,9 @@ while (@ARGV) {
                push(@args, "zlib.lib");
        } elsif ("$arg" eq "-liconv") {
                push(@args, "iconv.lib");
+       } elsif ("$arg" eq "-lcrypto") {
+               push(@args, "libeay32.lib");
+               push(@args, "ssleay32.lib");
        } elsif ("$arg" =~ /^-L/ && "$arg" ne "-LTCG") {
                $arg =~ s/^-L/-LIBPATH:/;
                push(@args, $arg);
index be94ba18d2b42a5b67f6853cac4611fd06c9c71e..cfa74adcc23881f229c84c29a78d7bfd4aa2f2a4 100644 (file)
@@ -178,6 +178,7 @@ sub createLibProject {
                                MinimalRebuild="true"
                                RuntimeLibrary="1"
                                UsePrecompiledHeader="0"
+                               ProgramDataBaseFileName="\$(IntDir)\\\$(TargetName).pdb"
                                WarningLevel="3"
                                DebugInformationFormat="3"
                        />
@@ -244,6 +245,7 @@ sub createLibProject {
                                RuntimeLibrary="0"
                                EnableFunctionLevelLinking="true"
                                UsePrecompiledHeader="0"
+                               ProgramDataBaseFileName="\$(IntDir)\\\$(TargetName).pdb"
                                WarningLevel="3"
                                DebugInformationFormat="3"
                        />
@@ -401,6 +403,7 @@ sub createAppProject {
                                MinimalRebuild="true"
                                RuntimeLibrary="1"
                                UsePrecompiledHeader="0"
+                               ProgramDataBaseFileName="\$(IntDir)\\\$(TargetName).pdb"
                                WarningLevel="3"
                                DebugInformationFormat="3"
                        />
@@ -472,6 +475,7 @@ sub createAppProject {
                                RuntimeLibrary="0"
                                EnableFunctionLevelLinking="true"
                                UsePrecompiledHeader="0"
+                               ProgramDataBaseFileName="\$(IntDir)\\\$(TargetName).pdb"
                                WarningLevel="3"
                                DebugInformationFormat="3"
                        />
index 20bd061b3e5a909fcd8dec732915c499cdac1a7b..d506717bfd304a1aaf4a02ad262ee96a0e468771 100644 (file)
@@ -315,6 +315,9 @@ sub handleLinkLine
             $appout = shift @parts;
         } elsif ("$part" eq "-lz") {
             push(@libs, "zlib.lib");
+       } elsif ("$part" eq "-lcrypto") {
+            push(@libs, "libeay32.lib");
+            push(@libs, "ssleay32.lib");
         } elsif ($part =~ /^-/) {
             push(@lflags, $part);
         } elsif ($part =~ /\.(a|lib)$/) {
index 7cf855746832b7400f9923297c4a0170cfacce36..bd66639d481db97511ef6fe3abf1b0a5d3da6ea3 100755 (executable)
@@ -953,11 +953,13 @@ _git_diff ()
 }
 
 __git_mergetools_common="diffuse ecmerge emerge kdiff3 meld opendiff
-                       tkdiff vimdiff gvimdiff xxdiff araxis
+                       tkdiff vimdiff gvimdiff xxdiff araxis p4merge
 "
 
 _git_difftool ()
 {
+       __git_has_doubledash && return
+
        local cur="${COMP_WORDS[COMP_CWORD]}"
        case "$cur" in
        --tool=*)
@@ -965,11 +967,15 @@ _git_difftool ()
                return
                ;;
        --*)
-               __gitcomp "--tool="
+               __gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
+                       --base --ours --theirs
+                       --no-renames --diff-filter= --find-copies-harder
+                       --relative --ignore-submodules
+                       --tool="
                return
                ;;
        esac
-       COMPREPLY=()
+       __git_complete_file
 }
 
 __git_fetch_options="
@@ -1069,7 +1075,8 @@ _git_grep ()
                return
                ;;
        esac
-       COMPREPLY=()
+
+       __gitcomp "$(__git_refs)"
 }
 
 _git_help ()
@@ -1217,7 +1224,7 @@ _git_log ()
 
 __git_merge_options="
        --no-commit --no-stat --log --no-log --squash --strategy
-       --commit --stat --no-squash --ff --no-ff
+       --commit --stat --no-squash --ff --no-ff --ff-only
 "
 
 _git_merge ()
@@ -1322,8 +1329,18 @@ _git_rebase ()
        fi
        __git_complete_strategy && return
        case "$cur" in
+       --whitespace=*)
+               __gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}"
+               return
+               ;;
        --*)
-               __gitcomp "--onto --merge --strategy --interactive"
+               __gitcomp "
+                       --onto --merge --strategy --interactive
+                       --preserve-merges --stat --no-stat
+                       --committer-date-is-author-date --ignore-date
+                       --ignore-whitespace --whitespace=
+                       "
+
                return
        esac
        __gitcomp "$(__git_refs)"
index 4fa70c5ad47fcd717d9cbdb23a8142f89227f630..7f4c7929784f8e2d8b24b0eaf9f05a2f10c1c6eb 100644 (file)
 
 (eval-when-compile (require 'cl))                            ; to use `push', `pop'
 
+(defface git-blame-prefix-face
+  '((((background dark)) (:foreground "gray"
+                          :background "black"))
+    (((background light)) (:foreground "gray"
+                           :background "white"))
+    (t (:weight bold)))
+  "The face used for the hash prefix."
+  :group 'git-blame)
+
+(defgroup git-blame nil
+  "A minor mode showing Git blame information."
+  :group 'git
+  :link '(function-link git-blame-mode))
+
+
+(defcustom git-blame-use-colors t
+  "Use colors to indicate commits in `git-blame-mode'."
+  :type 'boolean
+  :group 'git-blame)
+
+(defcustom git-blame-prefix-format
+  "%h %20A:"
+  "The format of the prefix added to each line in `git-blame'
+mode. The format is passed to `format-spec' with the following format keys:
+
+  %h - the abbreviated hash
+  %H - the full hash
+  %a - the author name
+  %A - the author email
+  %c - the committer name
+  %C - the committer email
+  %s - the commit summary
+"
+  :group 'git-blame)
+
+(defcustom git-blame-mouseover-format
+  "%h %a %A: %s"
+  "The format of the description shown when pointing at a line in
+`git-blame' mode. The format string is passed to `format-spec'
+with the following format keys:
+
+  %h - the abbreviated hash
+  %H - the full hash
+  %a - the author name
+  %A - the author email
+  %c - the committer name
+  %C - the committer email
+  %s - the commit summary
+"
+  :group 'git-blame)
+
 
 (defun git-blame-color-scale (&rest elements)
   "Given a list, returns a list of triples formed with each
@@ -302,72 +353,69 @@ See also function `git-blame-mode'."
                (src-line (string-to-number (match-string 2)))
                (res-line (string-to-number (match-string 3)))
                (num-lines (string-to-number (match-string 4))))
-           (setq git-blame-current
-                 (if (string= hash "0000000000000000000000000000000000000000")
-                     nil
-                   (git-blame-new-commit
-                    hash src-line res-line num-lines))))
-         (delete-region (point) (match-end 0))
-         t)
-        ((looking-at "filename \\(.+\\)\n")
-         (let ((filename (match-string 1)))
-           (git-blame-add-info "filename" filename))
-         (delete-region (point) (match-end 0))
+           (delete-region (point) (match-end 0))
+           (setq git-blame-current (list (git-blame-new-commit hash)
+                                         src-line res-line num-lines)))
          t)
         ((looking-at "\\([a-z-]+\\) \\(.+\\)\n")
          (let ((key (match-string 1))
                (value (match-string 2)))
-           (git-blame-add-info key value))
-         (delete-region (point) (match-end 0))
-         t)
-        ((looking-at "boundary\n")
-         (setq git-blame-current nil)
-         (delete-region (point) (match-end 0))
+           (delete-region (point) (match-end 0))
+           (git-blame-add-info (car git-blame-current) key value)
+           (when (string= key "filename")
+             (git-blame-create-overlay (car git-blame-current)
+                                       (caddr git-blame-current)
+                                       (cadddr git-blame-current))
+             (setq git-blame-current nil)))
          t)
         (t
          nil)))
 
-(defun git-blame-new-commit (hash src-line res-line num-lines)
+(defun git-blame-new-commit (hash)
+  (with-current-buffer git-blame-file
+    (or (gethash hash git-blame-cache)
+        ;; 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))
+               (info `(,hash (color . ,color))))
+          (puthash hash info git-blame-cache)
+          info))))
+
+(defun git-blame-create-overlay (info start-line num-lines)
   (save-excursion
     (set-buffer git-blame-file)
-    (let ((info (gethash hash git-blame-cache))
-          (inhibit-point-motion-hooks t)
+    (let ((inhibit-point-motion-hooks t)
           (inhibit-modification-hooks t))
-      (when (not info)
-       ;; 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))))
-        (puthash hash info git-blame-cache))
-      (goto-line res-line)
-      (while (> num-lines 0)
-        (if (get-text-property (point) 'git-blame)
-            (forward-line)
-          (let* ((start (point))
-                 (end (progn (forward-line 1) (point)))
-                 (ovl (make-overlay start end)))
-            (push ovl git-blame-overlays)
-            (overlay-put ovl 'git-blame info)
-            (overlay-put ovl 'help-echo hash)
+      (goto-line start-line)
+      (let* ((start (point))
+             (end (progn (forward-line num-lines) (point)))
+             (ovl (make-overlay start end))
+             (hash (car info))
+             (spec `((?h . ,(substring hash 0 6))
+                     (?H . ,hash)
+                     (?a . ,(git-blame-get-info info 'author))
+                     (?A . ,(git-blame-get-info info 'author-mail))
+                     (?c . ,(git-blame-get-info info 'committer))
+                     (?C . ,(git-blame-get-info info 'committer-mail))
+                     (?s . ,(git-blame-get-info info 'summary)))))
+        (push ovl git-blame-overlays)
+        (overlay-put ovl 'git-blame info)
+        (overlay-put ovl 'help-echo
+                     (format-spec git-blame-mouseover-format spec))
+        (if git-blame-use-colors
             (overlay-put ovl 'face (list :background
-                                         (cdr (assq 'color (nthcdr 5 info)))))
-            ;; the point-entered property doesn't seem to work in overlays
-            ;;(overlay-put ovl 'point-entered
-            ;;             `(lambda (x y) (git-blame-identify ,hash)))
-            (let ((modified (buffer-modified-p)))
-              (put-text-property (if (= start 1) start (1- start)) (1- end)
-                                 'point-entered
-                                 `(lambda (x y) (git-blame-identify ,hash)))
-              (set-buffer-modified-p modified))))
-        (setq num-lines (1- num-lines))))))
-
-(defun git-blame-add-info (key value)
-  (if git-blame-current
-      (nconc git-blame-current (list (cons (intern key) value)))))
+                                         (cdr (assq 'color (cdr info))))))
+        (overlay-put ovl 'line-prefix
+                     (propertize (format-spec git-blame-prefix-format spec)
+                                 'face 'git-blame-prefix-face))))))
+
+(defun git-blame-add-info (info key value)
+  (nconc info (list (cons (intern key) value))))
+
+(defun git-blame-get-info (info key)
+  (cdr (assq key (cdr info))))
 
 (defun git-blame-current-commit ()
   (let ((info (get-char-property (point) 'git-blame)))
similarity index 98%
rename from builtin-fetch--tool.c
rename to contrib/examples/builtin-fetch--tool.c
index 3dbdf7a2887002f0d7a67a1db35bd3c72d7a9d30..cd10dbcbc90ee155e05cffb49e88defcf35c5a59 100644 (file)
@@ -97,21 +97,21 @@ static int update_local_ref(const char *name,
        strcpy(newh, find_unique_abbrev(sha1_new, DEFAULT_ABBREV));
 
        if (in_merge_bases(current, &updated, 1)) {
-               fprintf(stderr, "* %s: fast forward to %s\n",
+               fprintf(stderr, "* %s: fast-forward to %s\n",
                        name, note);
                fprintf(stderr, "  old..new: %s..%s\n", oldh, newh);
-               return update_ref_env("fast forward", name, sha1_new, sha1_old);
+               return update_ref_env("fast-forward", name, sha1_new, sha1_old);
        }
        if (!force) {
                fprintf(stderr,
-                       "* %s: not updating to non-fast forward %s\n",
+                       "* %s: not updating to non-fast-forward %s\n",
                        name, note);
                fprintf(stderr,
                        "  old...new: %s...%s\n", oldh, newh);
                return 1;
        }
        fprintf(stderr,
-               "* %s: forcing update to non-fast forward %s\n",
+               "* %s: forcing update to non-fast-forward %s\n",
                name, note);
        fprintf(stderr, "  old...new: %s...%s\n", oldh, newh);
        return update_ref_env("forced-update", name, sha1_new, sha1_old);
index e9588eec33ba5b64d186ff048bb040c18c57e6bc..500635fe4bb5a8f60bc76502ef15cd97bd273f74 100755 (executable)
@@ -14,7 +14,7 @@ summary              (synonym to --stat)
 log                  add list of one-line log to merge commit message
 squash               create a single commit instead of doing a merge
 commit               perform a commit if the merge succeeds (default)
-ff                   allow fast forward (default)
+ff                   allow fast-forward (default)
 s,strategy=          merge strategy to use
 m,message=           message to be used for the merge commit (if any)
 "
@@ -353,7 +353,7 @@ t,1,"$head",*)
        # Again the most common case of merging one remote.
        echo "Updating $(git rev-parse --short $head)..$(git rev-parse --short $1)"
        git update-index --refresh 2>/dev/null
-       msg="Fast forward"
+       msg="Fast-forward"
        if test -n "$have_message"
        then
                msg="$msg (no commit created; -m option ignored)"
@@ -365,11 +365,11 @@ t,1,"$head",*)
        exit 0
        ;;
 ?,1,?*"$LF"?*,*)
-       # We are not doing octopus and not fast forward.  Need a
+       # We are not doing octopus and not fast-forward.  Need a
        # real merge.
        ;;
 ?,1,*,)
-       # We are not doing octopus, not fast forward, and have only
+       # We are not doing octopus, not fast-forward, and have only
        # one common.
        git update-index --refresh 2>/dev/null
        case "$allow_trivial_merge" in
index 0ee1bd898ecbb725d13385408b4ed4bcb413f503..8f98142f77b5d6eda44b301082da20604a893db0 100755 (executable)
@@ -48,7 +48,7 @@ case "$common" in
 "$head")
        echo "Updating $(git rev-parse --short $head)..$(git rev-parse --short $merge)"
        git read-tree -u -m $head $merge || exit 1
-       git update-ref -m "resolve $merge_name: Fast forward" \
+       git update-ref -m "resolve $merge_name: Fast-forward" \
                HEAD "$merge" "$head"
        git diff-tree -p $head $merge | git apply --stat
        dropheads
index 7001862bfdf8de1c7d446c7ca17d87d5f953ca91..95438e1ed42f7289131a1b08654a2b23098c8e26 100755 (executable)
@@ -20,7 +20,7 @@ use Getopt::Long;
 
 my $metaext = '';
 
-die "usage: import-tars [--metainfo=extension] *.tar.{gz,bz2,Z}\n"
+die "usage: import-tars [--metainfo=extension] *.tar.{gz,bz2,lzma,xz,Z}\n"
        unless GetOptions('metainfo=s' => \$metaext) && @ARGV;
 
 my $branch_name = 'import-tars';
@@ -49,6 +49,9 @@ foreach my $tar_file (@ARGV)
        } elsif ($tar_name =~ s/\.tar\.Z$//) {
                open(I, '-|', 'uncompress', '-c', $tar_file)
                        or die "Unable to uncompress -c $tar_file: $!\n";
+       } elsif ($tar_name =~ s/\.(tar\.(lzma|xz)|(tlz|txz))$//) {
+               open(I, '-|', 'xz', '-dc', $tar_file)
+                       or die "Unable to xz -dc $tar_file: $!\n";
        } elsif ($tar_name =~ s/\.tar$//) {
                open(I, $tar_file) or die "Unable to open $tar_file: $!\n";
        } else {
index 2a66063e44e2ca8e1742b59e046b3702721086cb..58a35c82870c54f844fd1154a82237891655f38f 100755 (executable)
@@ -315,8 +315,8 @@ generate_update_branch_email()
        # "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
+       # 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
        fast_forward=""
        rev=""
@@ -411,7 +411,7 @@ generate_update_branch_email()
        # 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.
+       # non-fast-forward updates.
        echo ""
        echo "Summary of changes:"
        git diff-tree --stat --summary --find-copies-harder $oldrev..$newrev
index 4ebc1dbd87d9b90ad2aaa5c7d4601761e2d1d724..aae8e7accc1ff955bd76c62b379b37f343f61cc4 100644 (file)
@@ -201,8 +201,8 @@ void diff_no_index(struct rev_info *revs,
                        return;
        }
        if (argc != i + 2)
-               die("git diff %s takes two paths",
-                   no_index ? "--no-index" : "[--no-index]");
+               usagef("git diff %s <path> <path>",
+                      no_index ? "--no-index" : "[--no-index]");
 
        diff_setup(&revs->diffopt);
        for (i = 1; i < argc - 2; ) {
diff --git a/diff.c b/diff.c
index e1be189742f3239de028393ceabf7c6539bb0440..0d7f5ea4a87d2152638f36b30d6366406d33bfa9 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -13,6 +13,7 @@
 #include "utf8.h"
 #include "userdiff.h"
 #include "sigchain.h"
+#include "submodule.h"
 
 #ifdef NO_FAST_WORKING_DIRECTORY
 #define FAST_WORKING_DIRECTORY 0
@@ -174,6 +175,175 @@ static struct diff_tempfile {
        char tmp_path[PATH_MAX];
 } diff_temp[2];
 
+typedef unsigned long (*sane_truncate_fn)(char *line, unsigned long len);
+
+struct emit_callback {
+       int color_diff;
+       unsigned ws_rule;
+       int blank_at_eof_in_preimage;
+       int blank_at_eof_in_postimage;
+       int lno_in_preimage;
+       int lno_in_postimage;
+       sane_truncate_fn truncate;
+       const char **label_path;
+       struct diff_words_data *diff_words;
+       int *found_changesp;
+       FILE *file;
+};
+
+static int count_lines(const char *data, int size)
+{
+       int count, ch, completely_empty = 1, nl_just_seen = 0;
+       count = 0;
+       while (0 < size--) {
+               ch = *data++;
+               if (ch == '\n') {
+                       count++;
+                       nl_just_seen = 1;
+                       completely_empty = 0;
+               }
+               else {
+                       nl_just_seen = 0;
+                       completely_empty = 0;
+               }
+       }
+       if (completely_empty)
+               return 0;
+       if (!nl_just_seen)
+               count++; /* no trailing newline */
+       return count;
+}
+
+static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one)
+{
+       if (!DIFF_FILE_VALID(one)) {
+               mf->ptr = (char *)""; /* does not matter */
+               mf->size = 0;
+               return 0;
+       }
+       else if (diff_populate_filespec(one, 0))
+               return -1;
+
+       mf->ptr = one->data;
+       mf->size = one->size;
+       return 0;
+}
+
+static int count_trailing_blank(mmfile_t *mf, unsigned ws_rule)
+{
+       char *ptr = mf->ptr;
+       long size = mf->size;
+       int cnt = 0;
+
+       if (!size)
+               return cnt;
+       ptr += size - 1; /* pointing at the very end */
+       if (*ptr != '\n')
+               ; /* incomplete line */
+       else
+               ptr--; /* skip the last LF */
+       while (mf->ptr < ptr) {
+               char *prev_eol;
+               for (prev_eol = ptr; mf->ptr <= prev_eol; prev_eol--)
+                       if (*prev_eol == '\n')
+                               break;
+               if (!ws_blank_line(prev_eol + 1, ptr - prev_eol, ws_rule))
+                       break;
+               cnt++;
+               ptr = prev_eol - 1;
+       }
+       return cnt;
+}
+
+static void check_blank_at_eof(mmfile_t *mf1, mmfile_t *mf2,
+                              struct emit_callback *ecbdata)
+{
+       int l1, l2, at;
+       unsigned ws_rule = ecbdata->ws_rule;
+       l1 = count_trailing_blank(mf1, ws_rule);
+       l2 = count_trailing_blank(mf2, ws_rule);
+       if (l2 <= l1) {
+               ecbdata->blank_at_eof_in_preimage = 0;
+               ecbdata->blank_at_eof_in_postimage = 0;
+               return;
+       }
+       at = count_lines(mf1->ptr, mf1->size);
+       ecbdata->blank_at_eof_in_preimage = (at - l1) + 1;
+
+       at = count_lines(mf2->ptr, mf2->size);
+       ecbdata->blank_at_eof_in_postimage = (at - l2) + 1;
+}
+
+static void emit_line_0(FILE *file, const char *set, const char *reset,
+                       int first, const char *line, int len)
+{
+       int has_trailing_newline, has_trailing_carriage_return;
+       int nofirst;
+
+       if (len == 0) {
+               has_trailing_newline = (first == '\n');
+               has_trailing_carriage_return = (!has_trailing_newline &&
+                                               (first == '\r'));
+               nofirst = has_trailing_newline || has_trailing_carriage_return;
+       } else {
+               has_trailing_newline = (len > 0 && line[len-1] == '\n');
+               if (has_trailing_newline)
+                       len--;
+               has_trailing_carriage_return = (len > 0 && line[len-1] == '\r');
+               if (has_trailing_carriage_return)
+                       len--;
+               nofirst = 0;
+       }
+
+       fputs(set, file);
+
+       if (!nofirst)
+               fputc(first, file);
+       fwrite(line, len, 1, file);
+       fputs(reset, file);
+       if (has_trailing_carriage_return)
+               fputc('\r', file);
+       if (has_trailing_newline)
+               fputc('\n', file);
+}
+
+static void emit_line(FILE *file, const char *set, const char *reset,
+                     const char *line, int len)
+{
+       emit_line_0(file, set, reset, line[0], line+1, len-1);
+}
+
+static int new_blank_line_at_eof(struct emit_callback *ecbdata, const char *line, int len)
+{
+       if (!((ecbdata->ws_rule & WS_BLANK_AT_EOF) &&
+             ecbdata->blank_at_eof_in_preimage &&
+             ecbdata->blank_at_eof_in_postimage &&
+             ecbdata->blank_at_eof_in_preimage <= ecbdata->lno_in_preimage &&
+             ecbdata->blank_at_eof_in_postimage <= ecbdata->lno_in_postimage))
+               return 0;
+       return ws_blank_line(line, len, ecbdata->ws_rule);
+}
+
+static void emit_add_line(const char *reset,
+                         struct emit_callback *ecbdata,
+                         const char *line, int len)
+{
+       const char *ws = diff_get_color(ecbdata->color_diff, DIFF_WHITESPACE);
+       const char *set = diff_get_color(ecbdata->color_diff, DIFF_FILE_NEW);
+
+       if (!*ws)
+               emit_line_0(ecbdata->file, set, reset, '+', line, len);
+       else if (new_blank_line_at_eof(ecbdata, line, len))
+               /* Blank line at EOF - paint '+' as well */
+               emit_line_0(ecbdata->file, ws, reset, '+', line, len);
+       else {
+               /* Emit just the prefix, then the rest. */
+               emit_line_0(ecbdata->file, set, reset, '+', "", 0);
+               ws_check_emit(line, len, ecbdata->ws_rule,
+                             ecbdata->file, set, reset, ws);
+       }
+}
+
 static struct diff_tempfile *claim_diff_tempfile(void) {
        int i;
        for (i = 0; i < ARRAY_SIZE(diff_temp); i++)
@@ -201,29 +371,6 @@ static void remove_tempfile_on_signal(int signo)
        raise(signo);
 }
 
-static int count_lines(const char *data, int size)
-{
-       int count, ch, completely_empty = 1, nl_just_seen = 0;
-       count = 0;
-       while (0 < size--) {
-               ch = *data++;
-               if (ch == '\n') {
-                       count++;
-                       nl_just_seen = 1;
-                       completely_empty = 0;
-               }
-               else {
-                       nl_just_seen = 0;
-                       completely_empty = 0;
-               }
-       }
-       if (completely_empty)
-               return 0;
-       if (!nl_just_seen)
-               count++; /* no trailing newline */
-       return count;
-}
-
 static void print_line_count(FILE *file, int count)
 {
        switch (count) {
@@ -239,26 +386,36 @@ static void print_line_count(FILE *file, int count)
        }
 }
 
-static void copy_file_with_prefix(FILE *file,
-                                 int prefix, const char *data, int size,
-                                 const char *set, const char *reset)
+static void emit_rewrite_lines(struct emit_callback *ecb,
+                              int prefix, const char *data, int size)
 {
-       int ch, nl_just_seen = 1;
-       while (0 < size--) {
-               ch = *data++;
-               if (nl_just_seen) {
-                       fputs(set, file);
-                       putc(prefix, file);
+       const char *endp = NULL;
+       static const char *nneof = " No newline at end of file\n";
+       const char *old = diff_get_color(ecb->color_diff, DIFF_FILE_OLD);
+       const char *reset = diff_get_color(ecb->color_diff, DIFF_RESET);
+
+       while (0 < size) {
+               int len;
+
+               endp = memchr(data, '\n', size);
+               len = endp ? (endp - data + 1) : size;
+               if (prefix != '+') {
+                       ecb->lno_in_preimage++;
+                       emit_line_0(ecb->file, old, reset, '-',
+                                   data, len);
+               } else {
+                       ecb->lno_in_postimage++;
+                       emit_add_line(reset, ecb, data, len);
                }
-               if (ch == '\n') {
-                       nl_just_seen = 1;
-                       fputs(reset, file);
-               } else
-                       nl_just_seen = 0;
-               putc(ch, file);
+               size -= len;
+               data += len;
+       }
+       if (!endp) {
+               const char *plain = diff_get_color(ecb->color_diff,
+                                                  DIFF_PLAIN);
+               emit_line_0(ecb->file, plain, reset, '\\',
+                           nneof, strlen(nneof));
        }
-       if (!nl_just_seen)
-               fprintf(file, "%s\n\\ No newline at end of file\n", reset);
 }
 
 static void emit_rewrite_diff(const char *name_a,
@@ -274,13 +431,12 @@ static void emit_rewrite_diff(const char *name_a,
        const char *name_a_tab, *name_b_tab;
        const char *metainfo = diff_get_color(color_diff, DIFF_METAINFO);
        const char *fraginfo = diff_get_color(color_diff, DIFF_FRAGINFO);
-       const char *old = diff_get_color(color_diff, DIFF_FILE_OLD);
-       const char *new = diff_get_color(color_diff, DIFF_FILE_NEW);
        const char *reset = diff_get_color(color_diff, DIFF_RESET);
        static struct strbuf a_name = STRBUF_INIT, b_name = STRBUF_INIT;
        const char *a_prefix, *b_prefix;
        const char *data_one, *data_two;
        size_t size_one, size_two;
+       struct emit_callback ecbdata;
 
        if (diff_mnemonic_prefix && DIFF_OPT_TST(o, REVERSE_DIFF)) {
                a_prefix = o->b_prefix;
@@ -321,6 +477,22 @@ static void emit_rewrite_diff(const char *name_a,
                size_two = two->size;
        }
 
+       memset(&ecbdata, 0, sizeof(ecbdata));
+       ecbdata.color_diff = color_diff;
+       ecbdata.found_changesp = &o->found_changes;
+       ecbdata.ws_rule = whitespace_rule(name_b ? name_b : name_a);
+       ecbdata.file = o->file;
+       if (ecbdata.ws_rule & WS_BLANK_AT_EOF) {
+               mmfile_t mf1, mf2;
+               mf1.ptr = (char *)data_one;
+               mf2.ptr = (char *)data_two;
+               mf1.size = size_one;
+               mf2.size = size_two;
+               check_blank_at_eof(&mf1, &mf2, &ecbdata);
+       }
+       ecbdata.lno_in_preimage = 1;
+       ecbdata.lno_in_postimage = 1;
+
        lc_a = count_lines(data_one, size_one);
        lc_b = count_lines(data_two, size_two);
        fprintf(o->file,
@@ -332,24 +504,9 @@ static void emit_rewrite_diff(const char *name_a,
        print_line_count(o->file, lc_b);
        fprintf(o->file, " @@%s\n", reset);
        if (lc_a)
-               copy_file_with_prefix(o->file, '-', data_one, size_one, old, reset);
+               emit_rewrite_lines(&ecbdata, '-', data_one, size_one);
        if (lc_b)
-               copy_file_with_prefix(o->file, '+', data_two, size_two, new, reset);
-}
-
-static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one)
-{
-       if (!DIFF_FILE_VALID(one)) {
-               mf->ptr = (char *)""; /* does not matter */
-               mf->size = 0;
-               return 0;
-       }
-       else if (diff_populate_filespec(one, 0))
-               return -1;
-
-       mf->ptr = one->data;
-       mf->size = one->size;
-       return 0;
+               emit_rewrite_lines(&ecbdata, '+', data_two, size_two);
 }
 
 struct diff_words_buffer {
@@ -529,26 +686,18 @@ static void diff_words_show(struct diff_words_data *diff_words)
        diff_words->minus.text.size = diff_words->plus.text.size = 0;
 }
 
-typedef unsigned long (*sane_truncate_fn)(char *line, unsigned long len);
-
-struct emit_callback {
-       int nparents, color_diff;
-       unsigned ws_rule;
-       sane_truncate_fn truncate;
-       const char **label_path;
-       struct diff_words_data *diff_words;
-       int *found_changesp;
-       FILE *file;
-};
+/* In "color-words" mode, show word-diff of words accumulated in the buffer */
+static void diff_words_flush(struct emit_callback *ecbdata)
+{
+       if (ecbdata->diff_words->minus.text.size ||
+           ecbdata->diff_words->plus.text.size)
+               diff_words_show(ecbdata->diff_words);
+}
 
 static void free_diff_words_data(struct emit_callback *ecbdata)
 {
        if (ecbdata->diff_words) {
-               /* flush buffers */
-               if (ecbdata->diff_words->minus.text.size ||
-                               ecbdata->diff_words->plus.text.size)
-                       diff_words_show(ecbdata->diff_words);
-
+               diff_words_flush(ecbdata);
                free (ecbdata->diff_words->minus.text.ptr);
                free (ecbdata->diff_words->minus.orig);
                free (ecbdata->diff_words->plus.text.ptr);
@@ -566,42 +715,6 @@ const char *diff_get_color(int diff_use_color, enum color_diff ix)
        return "";
 }
 
-static void emit_line(FILE *file, const char *set, const char *reset, const char *line, int len)
-{
-       int has_trailing_newline, has_trailing_carriage_return;
-
-       has_trailing_newline = (len > 0 && line[len-1] == '\n');
-       if (has_trailing_newline)
-               len--;
-       has_trailing_carriage_return = (len > 0 && line[len-1] == '\r');
-       if (has_trailing_carriage_return)
-               len--;
-
-       fputs(set, file);
-       fwrite(line, len, 1, file);
-       fputs(reset, file);
-       if (has_trailing_carriage_return)
-               fputc('\r', file);
-       if (has_trailing_newline)
-               fputc('\n', file);
-}
-
-static void emit_add_line(const char *reset, struct emit_callback *ecbdata, const char *line, int len)
-{
-       const char *ws = diff_get_color(ecbdata->color_diff, DIFF_WHITESPACE);
-       const char *set = diff_get_color(ecbdata->color_diff, DIFF_FILE_NEW);
-
-       if (!*ws)
-               emit_line(ecbdata->file, set, reset, line, len);
-       else {
-               /* Emit just the prefix, then the rest. */
-               emit_line(ecbdata->file, set, reset, line, ecbdata->nparents);
-               ws_check_emit(line + ecbdata->nparents,
-                             len - ecbdata->nparents, ecbdata->ws_rule,
-                             ecbdata->file, set, reset, ws);
-       }
-}
-
 static unsigned long sane_truncate_line(struct emit_callback *ecb, char *line, unsigned long len)
 {
        const char *cp;
@@ -620,10 +733,23 @@ static unsigned long sane_truncate_line(struct emit_callback *ecb, char *line, u
        return allot - l;
 }
 
+static void find_lno(const char *line, struct emit_callback *ecbdata)
+{
+       const char *p;
+       ecbdata->lno_in_preimage = 0;
+       ecbdata->lno_in_postimage = 0;
+       p = strchr(line, '-');
+       if (!p)
+               return; /* cannot happen */
+       ecbdata->lno_in_preimage = strtol(p + 1, NULL, 10);
+       p = strchr(p, '+');
+       if (!p)
+               return; /* cannot happen */
+       ecbdata->lno_in_postimage = strtol(p + 1, NULL, 10);
+}
+
 static void fn_out_consume(void *priv, char *line, unsigned long len)
 {
-       int i;
-       int color;
        struct emit_callback *ecbdata = priv;
        const char *meta = diff_get_color(ecbdata->color_diff, DIFF_METAINFO);
        const char *plain = diff_get_color(ecbdata->color_diff, DIFF_PLAIN);
@@ -650,14 +776,11 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
                len = 1;
        }
 
-       /* This is not really necessary for now because
-        * this codepath only deals with two-way diffs.
-        */
-       for (i = 0; i < len && line[i] == '@'; i++)
-               ;
-       if (2 <= i && i < len && line[i] == ' ') {
-               ecbdata->nparents = i - 1;
+       if (line[0] == '@') {
+               if (ecbdata->diff_words)
+                       diff_words_flush(ecbdata);
                len = sane_truncate_line(ecbdata, line, len);
+               find_lno(line, ecbdata);
                emit_line(ecbdata->file,
                          diff_get_color(ecbdata->color_diff, DIFF_FRAGINFO),
                          reset, line, len);
@@ -666,15 +789,11 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
                return;
        }
 
-       if (len < ecbdata->nparents) {
+       if (len < 1) {
                emit_line(ecbdata->file, reset, reset, line, len);
                return;
        }
 
-       color = DIFF_PLAIN;
-       if (ecbdata->diff_words && ecbdata->nparents != 1)
-               /* fall back to normal diff */
-               free_diff_words_data(ecbdata);
        if (ecbdata->diff_words) {
                if (line[0] == '-') {
                        diff_words_append(line, len,
@@ -685,28 +804,25 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
                                          &ecbdata->diff_words->plus);
                        return;
                }
-               if (ecbdata->diff_words->minus.text.size ||
-                   ecbdata->diff_words->plus.text.size)
-                       diff_words_show(ecbdata->diff_words);
+               diff_words_flush(ecbdata);
                line++;
                len--;
                emit_line(ecbdata->file, plain, reset, line, len);
                return;
        }
-       for (i = 0; i < ecbdata->nparents && len; i++) {
-               if (line[i] == '-')
-                       color = DIFF_FILE_OLD;
-               else if (line[i] == '+')
-                       color = DIFF_FILE_NEW;
-       }
 
-       if (color != DIFF_FILE_NEW) {
-               emit_line(ecbdata->file,
-                         diff_get_color(ecbdata->color_diff, color),
-                         reset, line, len);
-               return;
+       if (line[0] != '+') {
+               const char *color =
+                       diff_get_color(ecbdata->color_diff,
+                                      line[0] == '-' ? DIFF_FILE_OLD : DIFF_PLAIN);
+               ecbdata->lno_in_preimage++;
+               if (line[0] == ' ')
+                       ecbdata->lno_in_postimage++;
+               emit_line(ecbdata->file, color, reset, line, len);
+       } else {
+               ecbdata->lno_in_postimage++;
+               emit_add_line(reset, ecbdata, line + 1, len - 1);
        }
-       emit_add_line(reset, ecbdata, line, len);
 }
 
 static char *pprint_rename(const char *a, const char *b)
@@ -999,7 +1115,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
               total_files, adds, dels);
 }
 
-static void show_shortstats(struct diffstat_tdata, struct diff_options *options)
+static void show_shortstats(struct diffstat_t *data, struct diff_options *options)
 {
        int i, adds = 0, dels = 0, total_files = data->nr;
 
@@ -1211,7 +1327,6 @@ struct checkdiff_t {
        struct diff_options *o;
        unsigned ws_rule;
        unsigned status;
-       int trailing_blanks_start;
 };
 
 static int is_conflict_marker(const char *line, unsigned long len)
@@ -1255,10 +1370,6 @@ static void checkdiff_consume(void *priv, char *line, unsigned long len)
        if (line[0] == '+') {
                unsigned bad;
                data->lineno++;
-               if (!ws_blank_line(line + 1, len - 1, data->ws_rule))
-                       data->trailing_blanks_start = 0;
-               else if (!data->trailing_blanks_start)
-                       data->trailing_blanks_start = data->lineno;
                if (is_conflict_marker(line + 1, len - 1)) {
                        data->status |= 1;
                        fprintf(data->o->file,
@@ -1278,14 +1389,12 @@ static void checkdiff_consume(void *priv, char *line, unsigned long len)
                              data->o->file, set, reset, ws);
        } else if (line[0] == ' ') {
                data->lineno++;
-               data->trailing_blanks_start = 0;
        } else if (line[0] == '@') {
                char *plus = strchr(line, '+');
                if (plus)
                        data->lineno = strtol(plus, NULL, 10) - 1;
                else
                        die("invalid diff");
-               data->trailing_blanks_start = 0;
        }
 }
 
@@ -1453,6 +1562,17 @@ static void builtin_diff(const char *name_a,
        const char *a_prefix, *b_prefix;
        const char *textconv_one = NULL, *textconv_two = NULL;
 
+       if (DIFF_OPT_TST(o, SUBMODULE_LOG) &&
+                       (!one->mode || S_ISGITLINK(one->mode)) &&
+                       (!two->mode || S_ISGITLINK(two->mode))) {
+               const char *del = diff_get_color_opt(o, DIFF_FILE_OLD);
+               const char *add = diff_get_color_opt(o, DIFF_FILE_NEW);
+               show_submodule_summary(o->file, one ? one->path : two->path,
+                               one->sha1, two->sha1,
+                               del, add, reset);
+               return;
+       }
+
        if (DIFF_OPT_TST(o, ALLOW_TEXTCONV)) {
                textconv_one = get_textconv(one);
                textconv_two = get_textconv(two);
@@ -1562,6 +1682,8 @@ static void builtin_diff(const char *name_a,
                ecbdata.color_diff = DIFF_OPT_TST(o, COLOR_DIFF);
                ecbdata.found_changesp = &o->found_changes;
                ecbdata.ws_rule = whitespace_rule(name_b ? name_b : name_a);
+               if (ecbdata.ws_rule & WS_BLANK_AT_EOF)
+                       check_blank_at_eof(&mf1, &mf2, &ecbdata);
                ecbdata.file = o->file;
                xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
                xecfg.ctxlen = o->context;
@@ -1704,11 +1826,22 @@ static void builtin_checkdiff(const char *name_a, const char *name_b,
                xdi_diff_outf(&mf1, &mf2, checkdiff_consume, &data,
                              &xpp, &xecfg, &ecb);
 
-               if ((data.ws_rule & WS_TRAILING_SPACE) &&
-                   data.trailing_blanks_start) {
-                       fprintf(o->file, "%s:%d: ends with blank lines.\n",
-                               data.filename, data.trailing_blanks_start);
-                       data.status = 1; /* report errors */
+               if (data.ws_rule & WS_BLANK_AT_EOF) {
+                       struct emit_callback ecbdata;
+                       int blank_at_eof;
+
+                       ecbdata.ws_rule = data.ws_rule;
+                       check_blank_at_eof(&mf1, &mf2, &ecbdata);
+                       blank_at_eof = ecbdata.blank_at_eof_in_preimage;
+
+                       if (blank_at_eof) {
+                               static char *err;
+                               if (!err)
+                                       err = whitespace_error_string(WS_BLANK_AT_EOF);
+                               fprintf(o->file, "%s:%d: %s.\n",
+                                       data.filename, blank_at_eof, err);
+                               data.status = 1; /* report errors */
+                       }
                }
        }
  free_and_return:
@@ -2640,6 +2773,12 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
                DIFF_OPT_CLR(options, ALLOW_TEXTCONV);
        else if (!strcmp(arg, "--ignore-submodules"))
                DIFF_OPT_SET(options, IGNORE_SUBMODULES);
+       else if (!strcmp(arg, "--submodule"))
+               DIFF_OPT_SET(options, SUBMODULE_LOG);
+       else if (!prefixcmp(arg, "--submodule=")) {
+               if (!strcmp(arg + 12, "log"))
+                       DIFF_OPT_SET(options, SUBMODULE_LOG);
+       }
 
        /* misc options */
        else if (!strcmp(arg, "-z"))
diff --git a/diff.h b/diff.h
index 6616877ee5d15a8101cbdea0271cc18f8837d2f1..2740421cfe9985a57f61855dc6372e8402231e0e 100644 (file)
--- a/diff.h
+++ b/diff.h
@@ -66,6 +66,9 @@ typedef void (*diff_format_fn_t)(struct diff_queue_struct *q,
 #define DIFF_OPT_DIRSTAT_CUMULATIVE  (1 << 19)
 #define DIFF_OPT_DIRSTAT_BY_FILE     (1 << 20)
 #define DIFF_OPT_ALLOW_TEXTCONV      (1 << 21)
+
+#define DIFF_OPT_SUBMODULE_LOG       (1 << 23)
+
 #define DIFF_OPT_TST(opts, flag)    ((opts)->flags & DIFF_OPT_##flag)
 #define DIFF_OPT_SET(opts, flag)    ((opts)->flags |= DIFF_OPT_##flag)
 #define DIFF_OPT_CLR(opts, flag)    ((opts)->flags &= ~DIFF_OPT_##flag)
index 6faaaacb68999db294d20ecbb30772223bfc1b57..f4f1de6dd7f313ffe123bcf86bd92b70f54d3f5d 100644 (file)
@@ -2405,6 +2405,9 @@ int main(int argc, const char **argv)
 
        git_extract_argv0_path(argv[0]);
 
+       if (argc == 2 && !strcmp(argv[1], "-h"))
+               usage(fast_import_usage);
+
        setup_git_directory();
        git_config(git_pack_config, NULL);
        if (!pack_compression_seen && core_compression_seen)
index 392efb913f7c2ff13bbbb46e4414325b71e07676..8ce1ec92c2b04e1271b3ee1a41a2ac60d2f8aad4 100755 (executable)
@@ -259,7 +259,7 @@ sub list_modified {
                @tracked = map {
                        chomp $_;
                        unquote_path($_);
-               } run_cmd_pipe(qw(git ls-files --exclude-standard --), @ARGV);
+               } run_cmd_pipe(qw(git ls-files --), @ARGV);
                return if (!@tracked);
        }
 
@@ -731,14 +731,17 @@ sub parse_diff_header {
 
        my $head = { TEXT => [], DISPLAY => [], TYPE => 'header' };
        my $mode = { TEXT => [], DISPLAY => [], TYPE => 'mode' };
+       my $deletion = { TEXT => [], DISPLAY => [], TYPE => 'deletion' };
 
        for (my $i = 0; $i < @{$src->{TEXT}}; $i++) {
-               my $dest = $src->{TEXT}->[$i] =~ /^(old|new) mode (\d+)$/ ?
-                       $mode : $head;
+               my $dest =
+                  $src->{TEXT}->[$i] =~ /^(old|new) mode (\d+)$/ ? $mode :
+                  $src->{TEXT}->[$i] =~ /^deleted file/ ? $deletion :
+                  $head;
                push @{$dest->{TEXT}}, $src->{TEXT}->[$i];
                push @{$dest->{DISPLAY}}, $src->{DISPLAY}->[$i];
        }
-       return ($head, $mode);
+       return ($head, $mode, $deletion);
 }
 
 sub hunk_splittable {
@@ -1206,7 +1209,7 @@ sub patch_update_file {
        my ($ix, $num);
        my $path = shift;
        my ($head, @hunk) = parse_diff($path);
-       ($head, my $mode) = parse_diff_header($head);
+       ($head, my $mode, my $deletion) = parse_diff_header($head);
        for (@{$head->{DISPLAY}}) {
                print;
        }
@@ -1214,6 +1217,9 @@ sub patch_update_file {
        if (@{$mode->{TEXT}}) {
                unshift @hunk, $mode;
        }
+       if (@{$deletion->{TEXT}} && !@hunk) {
+               @hunk = ($deletion);
+       }
 
        $num = scalar @hunk;
        $ix = 0;
@@ -1267,7 +1273,9 @@ sub patch_update_file {
                        print;
                }
                print colored $prompt_color, $patch_mode_flavour{VERB},
-                 ($hunk[$ix]{TYPE} eq 'mode' ? ' mode change' : ' this hunk'),
+                 ($hunk[$ix]{TYPE} eq 'mode' ? ' mode change' :
+                  $hunk[$ix]{TYPE} eq 'deletion' ? ' deletion' :
+                  ' this hunk'),
                  $patch_mode_flavour{TARGET},
                  " [y,n,q,a,d,/$other,?]? ";
                my $line = prompt_single_character;
index 6f6f03966f5905c799a1a67df58e11b0a5f7564c..8b3c5858a901619eecd162229f92eb431b3e63f9 100755 (executable)
@@ -13,8 +13,8 @@ git bisect skip [(<rev>|<range>)...]
         mark <rev>... untestable revisions.
 git bisect next
         find next bisection to test and check it out.
-git bisect reset [<branch>]
-        finish bisection search and go back to branch.
+git bisect reset [<commit>]
+        finish bisection search and go back to commit.
 git bisect visualize
         show bisect status in gitk.
 git bisect replay <logfile>
@@ -311,8 +311,8 @@ bisect_reset() {
        }
        case "$#" in
        0) branch=$(cat "$GIT_DIR/BISECT_START") ;;
-       1) git show-ref --verify --quiet -- "refs/heads/$1" ||
-              die "$1 does not seem to be a valid branch"
+       1) git rev-parse --quiet --verify "$1^{commit}" > /dev/null ||
+              die "'$1' is not a valid commit"
           branch="$1" ;;
        *)
            usage ;;
index ef6080338480f509e720a484998c286ae1814b0a..5c596875c2e78a92031915948444971126d91a78 100644 (file)
@@ -189,6 +189,7 @@ extern char *gitbasename(char *);
 
 /* General helper functions */
 extern NORETURN void usage(const char *err);
+extern NORETURN void usagef(const char *err, ...) __attribute__((format (printf, 1, 2)));
 extern NORETURN void die(const char *err, ...) __attribute__((format (printf, 1, 2)));
 extern NORETURN void die_errno(const char *err, ...) __attribute__((format (printf, 1, 2)));
 extern int error(const char *err, ...) __attribute__((format (printf, 1, 2)));
index 1ad20ac96450d100fbce7e992ec65972a8c0a7ba..a7d215c8aa479bc6b456ec5c3792e931598ac365 100755 (executable)
@@ -579,10 +579,21 @@ sub get_headref ($) {
        return $r;
 }
 
+my $user_filename_prepend = '';
+sub munge_user_filename {
+       my $name = shift;
+       return File::Spec->file_name_is_absolute($name) ?
+               $name :
+               $user_filename_prepend . $name;
+}
+
 -d $git_tree
        or mkdir($git_tree,0777)
        or die "Could not create $git_tree: $!";
-chdir($git_tree);
+if ($git_tree ne '.') {
+       $user_filename_prepend = getwd() . '/';
+       chdir($git_tree);
+}
 
 my $last_branch = "";
 my $orig_branch = "";
@@ -644,7 +655,7 @@ unless (-d $git_dir) {
 -f "$git_dir/cvs-authors" and
   read_author_info("$git_dir/cvs-authors");
 if ($opt_A) {
-       read_author_info($opt_A);
+       read_author_info(munge_user_filename($opt_A));
        write_author_info("$git_dir/cvs-authors");
 }
 
@@ -679,7 +690,7 @@ unless ($opt_P) {
        $? == 0 or die "git-cvsimport: fatal: cvsps reported error\n";
        close $cvspsfh;
 } else {
-       $cvspsfile = $opt_P;
+       $cvspsfile = munge_user_filename($opt_P);
 }
 
 open(CVS, "<$cvspsfile") or die $!;
index a480d6fc70a4ca738c8ead14052afc3c1f5e8b02..6b8b6a4f26a60c325a2c76e1d5b0e747b9d1d99b 100755 (executable)
@@ -125,6 +125,7 @@ filter_subdir=
 orig_namespace=refs/original/
 force=
 prune_empty=
+remap_to_ancestor=
 while :
 do
        case "$1" in
@@ -137,6 +138,11 @@ do
                force=t
                continue
                ;;
+       --remap-to-ancestor)
+               shift
+               remap_to_ancestor=t
+               continue
+               ;;
        --prune-empty)
                shift
                prune_empty=t
@@ -182,6 +188,7 @@ do
                ;;
        --subdirectory-filter)
                filter_subdir="$OPTARG"
+               remap_to_ancestor=t
                ;;
        --original)
                orig_namespace=$(expr "$OPTARG/" : '\(.*[^/]\)/*$')/
@@ -257,15 +264,24 @@ git read-tree || die "Could not seed the index"
 # map old->new commit ids for rewriting parents
 mkdir ../map || die "Could not create map/ directory"
 
+# we need "--" only if there are no path arguments in $@
+nonrevs=$(git rev-parse --no-revs "$@") || exit
+test -z "$nonrevs" && dashdash=-- || dashdash=
+rev_args=$(git rev-parse --revs-only "$@")
+
 case "$filter_subdir" in
 "")
-       git rev-list --reverse --topo-order --default HEAD \
-               --parents --simplify-merges "$@"
+       eval set -- "$(git rev-parse --sq --no-revs "$@")"
        ;;
 *)
-       git rev-list --reverse --topo-order --default HEAD \
-               --parents --simplify-merges "$@" -- "$filter_subdir"
-esac > ../revs || die "Could not get the commits"
+       eval set -- "$(git rev-parse --sq --no-revs "$@" $dashdash \
+               "$filter_subdir")"
+       ;;
+esac
+
+git rev-list --reverse --topo-order --default HEAD \
+       --parents --simplify-merges $rev_args "$@" > ../revs ||
+       die "Could not get the commits"
 commits=$(wc -l <../revs | tr -d " ")
 
 test $commits -eq 0 && die "Found nothing to rewrite"
@@ -345,19 +361,19 @@ while read commit parents; do
                        die "could not write rewritten commit"
 done <../revs
 
-# In case of a subdirectory filter, it is possible that a specified head
-# is not in the set of rewritten commits, because it was pruned by the
-# revision walker.  Fix it by mapping these heads to the unique nearest
-# ancestor that survived the pruning.
+# If we are filtering for paths, as in the case of a subdirectory
+# filter, it is possible that a specified head is not in the set of
+# rewritten commits, because it was pruned by the revision walker.
+# Ancestor remapping fixes this by mapping these heads to the unique
+# nearest ancestor that survived the pruning.
 
-if test "$filter_subdir"
+if test "$remap_to_ancestor" = t
 then
        while read ref
        do
                sha1=$(git rev-parse "$ref"^0)
                test -f "$workdir"/../map/$sha1 && continue
-               ancestor=$(git rev-list --simplify-merges -1 \
-                               $ref -- "$filter_subdir")
+               ancestor=$(git rev-list --simplify-merges -1 "$ref" "$@")
                test "$ancestor" && echo $(map $ancestor) >> "$workdir"/../map/$sha1
        done < "$tempdir"/heads
 fi
index 14b92ba786554f4e714c89191e5584a825964ab2..037a1f2c21958252052f4c1cf0d8a8507574ca95 100755 (executable)
@@ -745,6 +745,8 @@ set default_config(gui.newbranchtemplate) {}
 set default_config(gui.spellingdictionary) {}
 set default_config(gui.fontui) [font configure font_ui]
 set default_config(gui.fontdiff) [font configure font_diff]
+# TODO: this option should be added to the git-config documentation
+set default_config(gui.maxfilesdisplayed) 5000
 set font_descs {
        {fontui   font_ui   {mc "Main Font"}}
        {fontdiff font_diff {mc "Diff/Console Font"}}
@@ -1132,6 +1134,7 @@ set current_branch {}
 set is_detached 0
 set current_diff_path {}
 set is_3way_diff 0
+set is_submodule_diff 0
 set is_conflict_diff 0
 set selected_commit_type new
 set diff_empty_count 0
@@ -1698,10 +1701,12 @@ proc display_all_files_helper {w path icon_name m} {
        $w insert end "[escape_path $path]\n"
 }
 
+set files_warning 0
 proc display_all_files {} {
        global ui_index ui_workdir
        global file_states file_lists
        global last_clicked
+       global files_warning
 
        $ui_index conf -state normal
        $ui_workdir conf -state normal
@@ -1713,7 +1718,18 @@ proc display_all_files {} {
        set file_lists($ui_index) [list]
        set file_lists($ui_workdir) [list]
 
-       foreach path [lsort [array names file_states]] {
+       set to_display [lsort [array names file_states]]
+       set display_limit [get_config gui.maxfilesdisplayed]
+       if {[llength $to_display] > $display_limit} {
+               if {!$files_warning} {
+                       # do not repeatedly warn:
+                       set files_warning 1
+                       info_popup [mc "Displaying only %s of %s files." \
+                               $display_limit [llength $to_display]]
+               }
+               set to_display [lrange $to_display 0 [expr {$display_limit-1}]]
+       }
+       foreach path $to_display {
                set s $file_states($path)
                set m [lindex $s 0]
                set icon_name [lindex $s 1]
@@ -2010,6 +2026,19 @@ proc do_quit {{rc {1}}} {
 
                # -- Stash our current window geometry into this repository.
                #
+               set cfg_wmstate [wm state .]
+               if {[catch {set rc_wmstate $repo_config(gui.wmstate)}]} {
+                       set rc_wmstate {}
+               }
+               if {$cfg_wmstate ne $rc_wmstate} {
+                       catch {git config gui.wmstate $cfg_wmstate}
+               }
+               if {$cfg_wmstate eq {zoomed}} {
+                       # on Windows wm geometry will lie about window
+                       # position (but not size) when window is zoomed
+                       # restore the window before querying wm geometry
+                       wm state . normal
+               }
                set cfg_geometry [list]
                lappend cfg_geometry [wm geometry .]
                lappend cfg_geometry [lindex [.vpane sash coord 0] 0]
@@ -3054,7 +3083,7 @@ frame .vpane.lower.diff.body
 set ui_diff .vpane.lower.diff.body.t
 text $ui_diff -background white -foreground black \
        -borderwidth 0 \
-       -width 80 -height 15 -wrap none \
+       -width 80 -height 5 -wrap none \
        -font font_diff \
        -xscrollcommand {.vpane.lower.diff.body.sbx set} \
        -yscrollcommand {.vpane.lower.diff.body.sby set} \
@@ -3212,7 +3241,7 @@ proc popup_diff_menu {ctxm ctxmmg x y X Y} {
                        set l [mc "Stage Hunk For Commit"]
                        set t [mc "Stage Line For Commit"]
                }
-               if {$::is_3way_diff
+               if {$::is_3way_diff || $::is_submodule_diff
                        || $current_diff_path eq {}
                        || {__} eq $state
                        || {_O} eq $state
@@ -3249,6 +3278,14 @@ wm geometry . [lindex $gm 0]
 unset gm
 }
 
+# -- Load window state
+#
+catch {
+set gws $repo_config(gui.wmstate)
+wm state . $gws
+unset gws
+}
+
 # -- Key Bindings
 #
 bind $ui_comm <$M1B-Key-Return> {do_commit;break}
index 925b3f56c1c23cc5e0c2b270b9f7e160013c9009..bd5d189ed1ec1a6520b7e9fefc4d5d6f36b9a007 100644 (file)
@@ -255,7 +255,7 @@ proc show_other_diff {path w m cont_info} {
 
 proc start_show_diff {cont_info {add_opts {}}} {
        global file_states file_lists
-       global is_3way_diff diff_active repo_config
+       global is_3way_diff is_submodule_diff diff_active repo_config
        global ui_diff ui_index ui_workdir
        global current_diff_path current_diff_side current_diff_header
 
@@ -265,6 +265,7 @@ proc start_show_diff {cont_info {add_opts {}}} {
        set s $file_states($path)
        set m [lindex $s 0]
        set is_3way_diff 0
+       set is_submodule_diff 0
        set diff_active 1
        set current_diff_header {}
 
@@ -295,6 +296,16 @@ proc start_show_diff {cont_info {add_opts {}}} {
                lappend cmd $path
        }
 
+       if {[string match {160000 *} [lindex $s 2]]
+        || [string match {160000 *} [lindex $s 3]]} {
+               set is_submodule_diff 1
+               if {$w eq $ui_index} {
+                       set cmd [list submodule summary --cached -- $path]
+               } else {
+                       set cmd [list submodule summary --files -- $path]
+               }
+       }
+
        if {[catch {set fd [eval git_read --nice $cmd]} err]} {
                set diff_active 0
                unlock_index
@@ -312,7 +323,7 @@ proc start_show_diff {cont_info {add_opts {}}} {
 }
 
 proc read_diff {fd cont_info} {
-       global ui_diff diff_active
+       global ui_diff diff_active is_submodule_diff
        global is_3way_diff is_conflict_diff current_diff_header
        global current_diff_queue
        global diff_empty_count
@@ -374,6 +385,23 @@ proc read_diff {fd cont_info} {
                                set tags {}
                        }
                        }
+               } elseif {$is_submodule_diff} {
+                       if {$line == ""} continue
+                       if {[regexp {^\* } $line]} {
+                               set line [string replace $line 0 1 {Submodule }]
+                               set tags d_@
+                       } else {
+                               set op [string range $line 0 2]
+                               switch -- $op {
+                               {  <} {set tags d_-}
+                               {  >} {set tags d_+}
+                               {  W} {set tags {}}
+                               default {
+                                       puts "error: Unhandled submodule diff marker: {$op}"
+                                       set tags {}
+                               }
+                               }
+                       }
                } else {
                        set op [string index $line 0]
                        switch -- $op {
index 4e02fc0d393ff9fe8d2983fec99a03db7f36273a..31e09474880c8d22122334f649cfcc126bf2c82e 100644 (file)
@@ -208,13 +208,15 @@ method _delete {} {
                return
        }
 
-       if {[tk_messageBox \
-               -icon warning \
-               -type yesno \
-               -title [wm title $w] \
-               -parent $w \
-               -message [mc "Recovering deleted branches is difficult.\n\nDelete the selected branches?"]] ne yes} {
-               return
+       if {$checktype ne {head}} {
+               if {[tk_messageBox \
+                       -icon warning \
+                       -type yesno \
+                       -title [wm title $w] \
+                       -parent $w \
+                       -message [mc "Recovering deleted branches is difficult.\n\nDelete the selected branches?"]] ne yes} {
+                       return
+               }
        }
 
        destroy $w
diff --git a/git-gui/po/el.po b/git-gui/po/el.po
new file mode 100644 (file)
index 0000000..3634ba4
--- /dev/null
@@ -0,0 +1,2005 @@
+# Translation of git-gui to Greek
+# Copyright (C) 2009 Jimmy Angelakos
+# This file is distributed under the same license as the git-gui package.
+# Jimmy Angelakos <vyruss@hellug.gr>, 2009.
+msgid ""
+msgstr ""
+"Project-Id-Version: el\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2008-03-14 07:18+0100\n"
+"PO-Revision-Date: 2009-06-23 21:33+0300\n"
+"Last-Translator: Jimmy Angelakos <vyruss@hellug.gr>\n"
+"Language-Team: Greek <i18n@lists.hellug.gr>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Lokalize 0.3\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: git-gui.sh:41 git-gui.sh:634 git-gui.sh:648 git-gui.sh:661 git-gui.sh:744
+#: git-gui.sh:763
+msgid "git-gui: fatal error"
+msgstr "git-gui: κρίσιμο σφάλμα"
+
+#: git-gui.sh:593
+#, tcl-format
+msgid "Invalid font specified in %s:"
+msgstr "Μη έγκυρη γραμματοσειρά στο %s:"
+
+#: git-gui.sh:620
+msgid "Main Font"
+msgstr "Κύρια Γραμματοσειρά"
+
+#: git-gui.sh:621
+msgid "Diff/Console Font"
+msgstr "Γραμματοσειρά Διαφοράς/Κονσόλας"
+
+#: git-gui.sh:635
+msgid "Cannot find git in PATH."
+msgstr "Δε βρέθηκε το git στο PATH."
+
+#: git-gui.sh:662
+msgid "Cannot parse Git version string:"
+msgstr "Αδύνατη η ανάγνωση στοιχειοσειράς έκδοσης Git:"
+
+#: git-gui.sh:680
+#, tcl-format
+msgid ""
+"Git version cannot be determined.\n"
+"\n"
+"%s claims it is version '%s'.\n"
+"\n"
+"%s requires at least Git 1.5.0 or later.\n"
+"\n"
+"Assume '%s' is version 1.5.0?\n"
+msgstr ""
+"Δε μπορεί να ανιχνευτεί η έκδοση του Git. \n"
+"\n"
+"Το %s υποστηρίζει πως είναι η έκδοση '%s'.\n"
+"\n"
+"Το %s  απαιτεί τουλάχιστον Git 1.5.0 ή πιό πρόσφατη.\n"
+"\n"
+"Να υποτεθεί πως το '%s' είναι η έκδοση 1.5.0;\n"
+
+#: git-gui.sh:918
+msgid "Git directory not found:"
+msgstr "Δε βρέθηκε φάκελος Git:"
+
+#: git-gui.sh:925
+msgid "Cannot move to top of working directory:"
+msgstr "Δεν είναι δυνατή η μετακίνηση στην κορυφή του φακέλου εργασίας:"
+
+#: git-gui.sh:932
+msgid "Cannot use funny .git directory:"
+msgstr "Δεν είναι δυνατή η χρήση περίεργου φακέλου .git:"
+
+#: git-gui.sh:937
+msgid "No working directory"
+msgstr "Δεν υπάρχει φάκελος εργασίας"
+
+#: git-gui.sh:1084 lib/checkout_op.tcl:283
+msgid "Refreshing file status..."
+msgstr "Ανανέωση κατάστασης αρχείου..."
+
+#: git-gui.sh:1149
+msgid "Scanning for modified files ..."
+msgstr "Ανίχνευση για τροποποιημένα αρχεία..."
+
+#: git-gui.sh:1324 lib/browser.tcl:246
+msgid "Ready."
+msgstr "Έτοιμο."
+
+#: git-gui.sh:1590
+msgid "Unmodified"
+msgstr "Μη τροποποιημένο"
+
+#: git-gui.sh:1592
+msgid "Modified, not staged"
+msgstr "Τροποποιημένο, μη σταδιοποιημένο"
+
+#: git-gui.sh:1593 git-gui.sh:1598
+msgid "Staged for commit"
+msgstr "Σταδιοποιημένο προς υποβολή"
+
+#: git-gui.sh:1594 git-gui.sh:1599
+msgid "Portions staged for commit"
+msgstr "Μέρη σταδιοποιημένα προς υποβολή"
+
+#: git-gui.sh:1595 git-gui.sh:1600
+msgid "Staged for commit, missing"
+msgstr "Σταδιοποιημένο προς υποβολή, λείπει"
+
+#: git-gui.sh:1597
+msgid "Untracked, not staged"
+msgstr "Μη παρακολουθούμενο, μη σταδιοποιημένο"
+
+#: git-gui.sh:1602
+msgid "Missing"
+msgstr "Λείπει"
+
+#: git-gui.sh:1603
+msgid "Staged for removal"
+msgstr "Σταδιοποιημένο προς αφαίρεση"
+
+#: git-gui.sh:1604
+msgid "Staged for removal, still present"
+msgstr "Σταδιοποιημένο προς αφαίρεση, ακόμα παρόν"
+
+#: git-gui.sh:1606 git-gui.sh:1607 git-gui.sh:1608 git-gui.sh:1609
+msgid "Requires merge resolution"
+msgstr "Απαιτεί επίλυση συγχώνευσης"
+
+#: git-gui.sh:1644
+msgid "Starting gitk... please wait..."
+msgstr "Γίνεται εκκίνηση του gitk... παρακαλώ περιμένετε..."
+
+#: git-gui.sh:1653
+#, tcl-format
+msgid ""
+"Unable to start gitk:\n"
+"\n"
+"%s does not exist"
+msgstr ""
+"Αδυναμία εκκίνησης του gitk:\n"
+"\n"
+"Το %s δεν υπάρχει"
+
+#: git-gui.sh:1860 lib/choose_repository.tcl:36
+msgid "Repository"
+msgstr "Αποθετήριο"
+
+#: git-gui.sh:1861
+msgid "Edit"
+msgstr "Επεξεργασία"
+
+#: git-gui.sh:1863 lib/choose_rev.tcl:561
+msgid "Branch"
+msgstr "Κλάδος"
+
+#: git-gui.sh:1866 lib/choose_rev.tcl:548
+msgid "Commit@@noun"
+msgstr "Υποβολή@@noun"
+
+#: git-gui.sh:1869 lib/merge.tcl:120 lib/merge.tcl:149 lib/merge.tcl:167
+msgid "Merge"
+msgstr "Συγχώνευση"
+
+#: git-gui.sh:1870 lib/choose_rev.tcl:557
+msgid "Remote"
+msgstr "Απομακρυσμένο"
+
+#: git-gui.sh:1879
+msgid "Browse Current Branch's Files"
+msgstr "Περιήγηση Αρχείων Τρέχοντα Κλάδου"
+
+#: git-gui.sh:1883
+msgid "Browse Branch Files..."
+msgstr "Περιήγηση Αρχείων Κλάδου..."
+
+#: git-gui.sh:1888
+msgid "Visualize Current Branch's History"
+msgstr "Απεικόνιση Ιστορικού Τρέχοντα Κλάδου"
+
+#: git-gui.sh:1892
+msgid "Visualize All Branch History"
+msgstr "Απεικόνιση Ιστορικού Όλων των Κλάδων"
+
+#: git-gui.sh:1899
+#, tcl-format
+msgid "Browse %s's Files"
+msgstr "Περιήγηση Αρχείων του %s"
+
+#: git-gui.sh:1901
+#, tcl-format
+msgid "Visualize %s's History"
+msgstr "Απεικόνιση Ιστορικού του %s"
+
+#: git-gui.sh:1906 lib/database.tcl:27 lib/database.tcl:67
+msgid "Database Statistics"
+msgstr "Στατιστικά Βάσης Δεδομένων"
+
+#: git-gui.sh:1909 lib/database.tcl:34
+msgid "Compress Database"
+msgstr "Συμπίεση Βάσης Δεδομένων"
+
+#: git-gui.sh:1912
+msgid "Verify Database"
+msgstr "Επαλήθευση Βάσης Δεδομένων"
+
+#: git-gui.sh:1919 git-gui.sh:1923 git-gui.sh:1927 lib/shortcut.tcl:7
+#: lib/shortcut.tcl:39 lib/shortcut.tcl:71
+msgid "Create Desktop Icon"
+msgstr "Δημιουργία Εικονιδίου Επιφάνειας Εργασίας"
+
+#: git-gui.sh:1932 lib/choose_repository.tcl:177 lib/choose_repository.tcl:185
+msgid "Quit"
+msgstr "Έξοδος"
+
+#: git-gui.sh:1939
+msgid "Undo"
+msgstr "Αναίρεση"
+
+#: git-gui.sh:1942
+msgid "Redo"
+msgstr "Ξανά"
+
+#: git-gui.sh:1946 git-gui.sh:2443
+msgid "Cut"
+msgstr "Αποκοπή"
+
+#: git-gui.sh:1949 git-gui.sh:2446 git-gui.sh:2520 git-gui.sh:2614
+#: lib/console.tcl:69
+msgid "Copy"
+msgstr "Αντιγραφή"
+
+#: git-gui.sh:1952 git-gui.sh:2449
+msgid "Paste"
+msgstr "Επικόλληση"
+
+#: git-gui.sh:1955 git-gui.sh:2452 lib/branch_delete.tcl:26
+#: lib/remote_branch_delete.tcl:38
+msgid "Delete"
+msgstr "Διαγραφή"
+
+#: git-gui.sh:1959 git-gui.sh:2456 git-gui.sh:2618 lib/console.tcl:71
+msgid "Select All"
+msgstr "Επιλογή Όλων"
+
+#: git-gui.sh:1968
+msgid "Create..."
+msgstr "Δημιουργία..."
+
+#: git-gui.sh:1974
+msgid "Checkout..."
+msgstr "Εξαγωγή..."
+
+#: git-gui.sh:1980
+msgid "Rename..."
+msgstr "Μετονομασία..."
+
+#: git-gui.sh:1985 git-gui.sh:2085
+msgid "Delete..."
+msgstr "Διαγραφή..."
+
+#: git-gui.sh:1990
+msgid "Reset..."
+msgstr "Επαναφορά..."
+
+#: git-gui.sh:2002 git-gui.sh:2389
+msgid "New Commit"
+msgstr "Νέα Υποβολή"
+
+#: git-gui.sh:2010 git-gui.sh:2396
+msgid "Amend Last Commit"
+msgstr "Διόρθωση Τελευταίας Υποβολής"
+
+#: git-gui.sh:2019 git-gui.sh:2356 lib/remote_branch_delete.tcl:99
+msgid "Rescan"
+msgstr "Επανανίχνευση"
+
+#: git-gui.sh:2025
+msgid "Stage To Commit"
+msgstr "Σταδιοποίηση Προς Υποβολή"
+
+#: git-gui.sh:2031
+msgid "Stage Changed Files To Commit"
+msgstr "Σταδιοποίηση Αλλαγμένων Αρχείων Προς Υποβολή"
+
+#: git-gui.sh:2037
+msgid "Unstage From Commit"
+msgstr "Αποσταδιοποίηση Από Υποβολή"
+
+#: git-gui.sh:2042 lib/index.tcl:395
+msgid "Revert Changes"
+msgstr "Αναίρεση Αλλαγών"
+
+#: git-gui.sh:2049 git-gui.sh:2368 git-gui.sh:2467
+msgid "Sign Off"
+msgstr "Αποσύνδεση"
+
+#: git-gui.sh:2053 git-gui.sh:2372
+msgid "Commit@@verb"
+msgstr "Υποβολή@@verb"
+
+#: git-gui.sh:2064
+msgid "Local Merge..."
+msgstr "Τοπική Συγχώνευση..."
+
+#: git-gui.sh:2069
+msgid "Abort Merge..."
+msgstr "Ακύρωση Συγχώνευσης..."
+
+#: git-gui.sh:2081
+msgid "Push..."
+msgstr "Ώθηση..."
+
+#: git-gui.sh:2092 lib/choose_repository.tcl:41
+#, fuzzy
+msgid "Apple"
+msgstr ""
+
+#: git-gui.sh:2095 git-gui.sh:2117 lib/about.tcl:14
+#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:50
+#, tcl-format
+msgid "About %s"
+msgstr "Περί %s"
+
+#: git-gui.sh:2099
+msgid "Preferences..."
+msgstr "Προτιμήσεις..."
+
+#: git-gui.sh:2107 git-gui.sh:2639
+msgid "Options..."
+msgstr "Επιλογές..."
+
+#: git-gui.sh:2113 lib/choose_repository.tcl:47
+msgid "Help"
+msgstr "Βοήθεια"
+
+#: git-gui.sh:2154
+msgid "Online Documentation"
+msgstr "Διαδικτυακή Τεκμηρίωση"
+
+#: git-gui.sh:2238
+#, tcl-format
+msgid "fatal: cannot stat path %s: No such file or directory"
+msgstr "κρίσιμο: δε βρέθηκε η διαδρομή: %s: Δεν υπάρχει το αρχείο ή ο φάκελος"
+
+#: git-gui.sh:2271
+msgid "Current Branch:"
+msgstr "Τρέχων Κλάδος:"
+
+#: git-gui.sh:2292
+msgid "Staged Changes (Will Commit)"
+msgstr "Σταδιοποιημένες Αλλαγές (Θα Υποβληθούν)"
+
+#: git-gui.sh:2312
+msgid "Unstaged Changes"
+msgstr "Μη Σταδιοποιημένες Αλλαγές"
+
+#: git-gui.sh:2362
+msgid "Stage Changed"
+msgstr "Σταδιοποίηση Αλλαγών"
+
+#: git-gui.sh:2378 lib/transport.tcl:93 lib/transport.tcl:182
+msgid "Push"
+msgstr "Ώθηση"
+
+#: git-gui.sh:2408
+msgid "Initial Commit Message:"
+msgstr "Αρχικό Μήνυμα Υποβολής:"
+
+#: git-gui.sh:2409
+msgid "Amended Commit Message:"
+msgstr "Διορθωμένο Μήνυμα Υποβολής:"
+
+#: git-gui.sh:2410
+msgid "Amended Initial Commit Message:"
+msgstr "Διορθωμένο Αρχικό Μήνυμα Υποβολής:"
+
+#: git-gui.sh:2411
+msgid "Amended Merge Commit Message:"
+msgstr "Διορθωμένο Μήνυμα Υποβολής Συγχώνευσης:"
+
+#: git-gui.sh:2412
+msgid "Merge Commit Message:"
+msgstr "Μήνυμα Υποβολής Συγχώνευσης:"
+
+#: git-gui.sh:2413
+msgid "Commit Message:"
+msgstr "Μήνυμα Υποβολής:"
+
+#: git-gui.sh:2459 git-gui.sh:2622 lib/console.tcl:73
+msgid "Copy All"
+msgstr "Αντιγραφή Όλων"
+
+#: git-gui.sh:2483 lib/blame.tcl:107
+msgid "File:"
+msgstr "Αρχείο:"
+
+#: git-gui.sh:2589
+msgid "Apply/Reverse Hunk"
+msgstr "Εφαρμογή/Αντιστροφή Κομματιού"
+
+#: git-gui.sh:2595
+msgid "Show Less Context"
+msgstr "Προβολή Στενότερου Πλαισίου"
+
+#: git-gui.sh:2602
+msgid "Show More Context"
+msgstr "Προβολή Ευρύτερου Πλαισίου"
+
+#: git-gui.sh:2610
+msgid "Refresh"
+msgstr "Ανανέωση"
+
+#: git-gui.sh:2631
+msgid "Decrease Font Size"
+msgstr "Μείωση Μεγέθους Γραμματοσειράς"
+
+#: git-gui.sh:2635
+msgid "Increase Font Size"
+msgstr "Αύξηση Μεγέθους Γραμματοσειράς"
+
+#: git-gui.sh:2646
+msgid "Unstage Hunk From Commit"
+msgstr "Αποσταδιοποίηση Κομματιού Από Υποβολή"
+
+#: git-gui.sh:2648
+msgid "Stage Hunk For Commit"
+msgstr "Σταδιοποίηση Κομματιού Προς Υποβολή"
+
+#: git-gui.sh:2667
+msgid "Initializing..."
+msgstr "Γίνεται αρχικοποίηση..."
+
+#: git-gui.sh:2762
+#, tcl-format
+msgid ""
+"Possible environment issues exist.\n"
+"\n"
+"The following environment variables are probably\n"
+"going to be ignored by any Git subprocess run\n"
+"by %s:\n"
+"\n"
+msgstr ""
+"Υπάρχουν πιθανά θέματα με το περιβάλλον.\n"
+"\n"
+"Οι εξής μεταβλητές περιβάλλοντος μάλλον θα\n"
+"αγνοηθούν από πιθανή εκτέλεση υποδιεργασίας Git\n"
+"από το %s:\n"
+"\n"
+
+#: git-gui.sh:2792
+msgid ""
+"\n"
+"This is due to a known issue with the\n"
+"Tcl binary distributed by Cygwin."
+msgstr ""
+"\n"
+"Αυτό οφείλεται σε ένα γνωστό θέμα με το\n"
+"εκτελέσιμο Tcl που διανέμεται με το Cygwin."
+
+#: git-gui.sh:2797
+#, tcl-format
+msgid ""
+"\n"
+"\n"
+"A good replacement for %s\n"
+"is placing values for the user.name and\n"
+"user.email settings into your personal\n"
+"~/.gitconfig file.\n"
+msgstr ""
+"\n"
+"\n"
+"Ένα καλό υποκατάστατο για το %s\n"
+"είναι η τοποθέτηση τιμών για τις ρυθμίσεις\n"
+"user.name και user.email στο προσωπικό σας\n"
+"αρχείο ~/.gitconfig .\n"
+
+#: lib/about.tcl:26
+msgid "git-gui - a graphical user interface for Git."
+msgstr "git-gui - ένα γραφικό περιβάλλον για το Git."
+
+#: lib/blame.tcl:77
+msgid "File Viewer"
+msgstr "Εφαρμογή Προβολής Αρχείου"
+
+#: lib/blame.tcl:81
+msgid "Commit:"
+msgstr "Υποβολή:"
+
+#: lib/blame.tcl:264
+msgid "Copy Commit"
+msgstr "Αντιγραφή Υποβολής"
+
+#: lib/blame.tcl:384
+#, tcl-format
+msgid "Reading %s..."
+msgstr "Ανάγνωση %s..."
+
+#: lib/blame.tcl:488
+msgid "Loading copy/move tracking annotations..."
+msgstr "Γίνεται φόρτωση σχολίων παρακολούθησης αντιγραφής/μετακίνησης..."
+
+#: lib/blame.tcl:508
+msgid "lines annotated"
+msgstr "γραμμές σχολιασμένες"
+
+#: lib/blame.tcl:689
+msgid "Loading original location annotations..."
+msgstr "Γίνεται φόρτωση σχολίων αρχικής τοποθεσίας..."
+
+#: lib/blame.tcl:692
+msgid "Annotation complete."
+msgstr "Έγινε ολοκλήρωση του σχολιασμού."
+
+#: lib/blame.tcl:746
+msgid "Loading annotation..."
+msgstr "Φόρτωση σχολίου..."
+
+#: lib/blame.tcl:802
+msgid "Author:"
+msgstr "Δημιουργός:"
+
+#: lib/blame.tcl:806
+msgid "Committer:"
+msgstr "Υποβολέας:"
+
+#: lib/blame.tcl:811
+msgid "Original File:"
+msgstr "Αρχικό Αρχείο:"
+
+#: lib/blame.tcl:925
+msgid "Originally By:"
+msgstr "Αρχικά Από:"
+
+#: lib/blame.tcl:931
+msgid "In File:"
+msgstr "Στο Αρχείο:"
+
+#: lib/blame.tcl:936
+msgid "Copied Or Moved Here By:"
+msgstr "Αντιγράφηκε ή Μετακινήθηκε Εδώ Από:"
+
+#: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19
+msgid "Checkout Branch"
+msgstr "Εξαγωγή Κλάδου"
+
+#: lib/branch_checkout.tcl:23
+msgid "Checkout"
+msgstr "Εξαγωγή"
+
+#: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35
+#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:282
+#: lib/checkout_op.tcl:522 lib/choose_font.tcl:43 lib/merge.tcl:171
+#: lib/option.tcl:103 lib/remote_branch_delete.tcl:42 lib/transport.tcl:97
+msgid "Cancel"
+msgstr "Ακύρωση"
+
+#: lib/branch_checkout.tcl:32 lib/browser.tcl:287
+msgid "Revision"
+msgstr "Αναθεώρηση"
+
+#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:242
+msgid "Options"
+msgstr "Επιλογές"
+
+#: lib/branch_checkout.tcl:39 lib/branch_create.tcl:92
+msgid "Fetch Tracking Branch"
+msgstr "Ανάκτηση Κλάδου Παρακολούθησης"
+
+#: lib/branch_checkout.tcl:44
+msgid "Detach From Local Branch"
+msgstr "Αποκόλληση Από Τοπικό Κλάδο"
+
+#: lib/branch_create.tcl:22
+msgid "Create Branch"
+msgstr "Δημιουργία Κλάδου"
+
+#: lib/branch_create.tcl:27
+msgid "Create New Branch"
+msgstr "Δημιουργία Νέου Κλάδου"
+
+#: lib/branch_create.tcl:31 lib/choose_repository.tcl:371
+msgid "Create"
+msgstr "Δημιουργία"
+
+#: lib/branch_create.tcl:40
+msgid "Branch Name"
+msgstr "Όνομα Κλάδου"
+
+#: lib/branch_create.tcl:43
+msgid "Name:"
+msgstr "Όνομα:"
+
+#: lib/branch_create.tcl:58
+msgid "Match Tracking Branch Name"
+msgstr "Συμφωνία Ονόματος Κλάδου Παρακολούθησης"
+
+#: lib/branch_create.tcl:66
+msgid "Starting Revision"
+msgstr "Αρχική Αναθεώρηση"
+
+#: lib/branch_create.tcl:72
+msgid "Update Existing Branch:"
+msgstr "Ενημέρωση Υπάρχοντα Κλάδου:"
+
+#: lib/branch_create.tcl:75
+#, fuzzy
+msgid "No"
+msgstr "Όχι"
+
+#: lib/branch_create.tcl:80
+msgid "Fast Forward Only"
+msgstr "Συγχώνευση Επιτάχυνσης Μόνο"
+
+#: lib/branch_create.tcl:85 lib/checkout_op.tcl:514
+msgid "Reset"
+msgstr "Επαναφορά"
+
+#: lib/branch_create.tcl:97
+msgid "Checkout After Creation"
+msgstr "Εξαγωγή Μετά τη Δημιουργία"
+
+#: lib/branch_create.tcl:131
+msgid "Please select a tracking branch."
+msgstr "Παρακαλώ επιλέξτε έναν κλάδο παρακολούθησης."
+
+#: lib/branch_create.tcl:140
+#, tcl-format
+msgid "Tracking branch %s is not a branch in the remote repository."
+msgstr ""
+"Ο κλάδος παρακολούθησης %s δεν είναι κλάδος που βρίσκεται στο απομακρυσμένο "
+"αποθετήριο."
+
+#: lib/branch_create.tcl:153 lib/branch_rename.tcl:86
+msgid "Please supply a branch name."
+msgstr "Παρακαλώ δώστε ένα όνομα κλάδου."
+
+#: lib/branch_create.tcl:164 lib/branch_rename.tcl:106
+#, tcl-format
+msgid "'%s' is not an acceptable branch name."
+msgstr "'%s' δεν είναι αποδεκτό όνομα κλάδου."
+
+#: lib/branch_delete.tcl:15
+msgid "Delete Branch"
+msgstr "Διαγραφή Κλάδου"
+
+#: lib/branch_delete.tcl:20
+msgid "Delete Local Branch"
+msgstr "Διαγραφή Τοπικού Κλάδου"
+
+#: lib/branch_delete.tcl:37
+msgid "Local Branches"
+msgstr "Τοπικοί Κλάδοι"
+
+#: lib/branch_delete.tcl:52
+msgid "Delete Only If Merged Into"
+msgstr "Διαγραφή Μόνο Εάν Είναι Συγχωνευμένο Με"
+
+#: lib/branch_delete.tcl:54
+msgid "Always (Do not perform merge test.)"
+msgstr "Πάντα (Μη διενεργηθεί δοκιμή συγχώνευσης.)"
+
+#: lib/branch_delete.tcl:103
+#, tcl-format
+msgid "The following branches are not completely merged into %s:"
+msgstr "Οι εξής κλάδοι δεν είναι πλήρως συγχωνευμένοι με το %s:"
+
+#: lib/branch_delete.tcl:115
+msgid ""
+"Recovering deleted branches is difficult. \n"
+"\n"
+" Delete the selected branches?"
+msgstr ""
+"Η ανάκτηση διεγραμμένων κλάδων είναι δύσκολη.\n"
+"\n"
+"Διαγραφή των επιλεγμένων κλάδων;"
+
+#: lib/branch_delete.tcl:141
+#, tcl-format
+msgid ""
+"Failed to delete branches:\n"
+"%s"
+msgstr ""
+"Αποτυχία διαγραφής κλάδων:\n"
+"%s"
+
+#: lib/branch_rename.tcl:14 lib/branch_rename.tcl:22
+msgid "Rename Branch"
+msgstr "Μετονομασία Κλάδου"
+
+#: lib/branch_rename.tcl:26
+msgid "Rename"
+msgstr "Μετονομασία"
+
+#: lib/branch_rename.tcl:36
+msgid "Branch:"
+msgstr "Κλάδος:"
+
+#: lib/branch_rename.tcl:39
+msgid "New Name:"
+msgstr "Νέο Όνομα:"
+
+#: lib/branch_rename.tcl:75
+msgid "Please select a branch to rename."
+msgstr "Παρακαλώ επιλέξτε κλάδο προς μετονομασία:"
+
+#: lib/branch_rename.tcl:96 lib/checkout_op.tcl:179
+#, tcl-format
+msgid "Branch '%s' already exists."
+msgstr "Ο Κλάδος '%s' υπάρχει ήδη."
+
+#: lib/branch_rename.tcl:117
+#, tcl-format
+msgid "Failed to rename '%s'."
+msgstr "Αποτυχία μετονομασίας '%s'."
+
+#: lib/browser.tcl:17
+msgid "Starting..."
+msgstr "Γίνεται Εκκίνηση..."
+
+#: lib/browser.tcl:26
+msgid "File Browser"
+msgstr "Περιηγητής Αρχείων"
+
+#: lib/browser.tcl:126 lib/browser.tcl:143
+#, tcl-format
+msgid "Loading %s..."
+msgstr "Γίνεται φόρτωση %s..."
+
+#: lib/browser.tcl:187
+#, fuzzy
+msgid "[Up To Parent]"
+msgstr "[Πάνω Προς Γονέα]"
+
+#: lib/browser.tcl:267 lib/browser.tcl:273
+msgid "Browse Branch Files"
+msgstr "Περιήγηση Αρχείων Κλάδου"
+
+#: lib/browser.tcl:278 lib/choose_repository.tcl:387
+#: lib/choose_repository.tcl:474 lib/choose_repository.tcl:484
+#: lib/choose_repository.tcl:987
+msgid "Browse"
+msgstr "Περιήγηση"
+
+#: lib/checkout_op.tcl:79
+#, tcl-format
+msgid "Fetching %s from %s"
+msgstr "Ανάκτηση %s από το %s"
+
+#: lib/checkout_op.tcl:127
+#, tcl-format
+msgid "fatal: Cannot resolve %s"
+msgstr "κρίσιμο: Δε μπόρεσε να επιλυθεί το %s"
+
+#: lib/checkout_op.tcl:140 lib/console.tcl:81 lib/database.tcl:31
+msgid "Close"
+msgstr "Κλείσιμο"
+
+#: lib/checkout_op.tcl:169
+#, tcl-format
+msgid "Branch '%s' does not exist."
+msgstr "Ο Κλάδος '%s' δεν υπάρχει."
+
+#: lib/checkout_op.tcl:206
+#, tcl-format
+msgid ""
+"Branch '%s' already exists.\n"
+"\n"
+"It cannot fast-forward to %s.\n"
+"A merge is required."
+msgstr ""
+"Ο Κλάδος '%s' υπάρχει ήδη.\n"
+"\n"
+"Δε γίνεται συγχώνευση επιτάχυνσής του στο %s.\n"
+"Απαιτείται συγχώνευση."
+
+#: lib/checkout_op.tcl:220
+#, tcl-format
+msgid "Merge strategy '%s' not supported."
+msgstr "Η στρατηγική Συγχώνευσης %s δεν υποστηρίζεται."
+
+#: lib/checkout_op.tcl:239
+#, tcl-format
+msgid "Failed to update '%s'."
+msgstr "Αποτυχία ενημέρωσης '%s'."
+
+#: lib/checkout_op.tcl:251
+msgid "Staging area (index) is already locked."
+msgstr "Η περιοχή σταδιοποίησης (το ευρετήριο) είναι ήδη κλειδωμένη."
+
+#: lib/checkout_op.tcl:266
+msgid ""
+"Last scanned state does not match repository state.\n"
+"\n"
+"Another Git program has modified this repository since the last scan.  A "
+"rescan must be performed before the current branch can be changed.\n"
+"\n"
+"The rescan will be automatically started now.\n"
+msgstr ""
+"Η τελευταία κατάσταση που ανιχνεύθηκε δε συμφωνεί με την κατάσταση του "
+"αποθετηρίου.\n"
+"\n"
+"Κάποιο άλλο πρόγραμμα Git τροποποίησε το αποθετήριο από την τελευταία "
+"ανίχνευση. Πρέπει να γίνει επανανίχνευση πριν να αλλαχθεί ο τρέχων κλάδος.\n"
+"\n"
+"Η επανανίχνευση θα ξεκινήσει αυτόματα τώρα.\n"
+
+#: lib/checkout_op.tcl:322
+#, tcl-format
+msgid "Updating working directory to '%s'..."
+msgstr "Ενημέρωση φακέλου εργασίας σε '%s'..."
+
+#: lib/checkout_op.tcl:323
+msgid "files checked out"
+msgstr "αρχεία έχουν εξαχθεί"
+
+#: lib/checkout_op.tcl:353
+#, tcl-format
+msgid "Aborted checkout of '%s' (file level merging is required)."
+msgstr ""
+"Έγινε ακύρωση εξαγωγής του '%s' (απαιτείται συγχώνευση επιπέδου αρχείου)."
+
+#: lib/checkout_op.tcl:354
+msgid "File level merge required."
+msgstr "Απαιτείται συγχώνευση επιπέδου αρχείου."
+
+#: lib/checkout_op.tcl:358
+#, tcl-format
+msgid "Staying on branch '%s'."
+msgstr "Παραμονή στον κλάδο '%s'."
+
+#: lib/checkout_op.tcl:429
+msgid ""
+"You are no longer on a local branch.\n"
+"\n"
+"If you wanted to be on a branch, create one now starting from 'This Detached "
+"Checkout'."
+msgstr ""
+"Δε βρίσκεστε πια σε τοπικό κλάδο.\n"
+"\n"
+"Αν θέλατε να βρίσκεστε σε κλάδο, δημιουργήστε έναν τώρα αρχίζοντας από 'This "
+"Detached Checkout'."
+
+#: lib/checkout_op.tcl:446 lib/checkout_op.tcl:450
+#, tcl-format
+msgid "Checked out '%s'."
+msgstr "Έγινε εξαγωγή του '%s'."
+
+#: lib/checkout_op.tcl:478
+#, tcl-format
+msgid "Resetting '%s' to '%s' will lose the following commits:"
+msgstr "Η επαναφορά '%s' στο '%s' θα χάσει τις εξής υποβολές:"
+
+#: lib/checkout_op.tcl:500
+msgid "Recovering lost commits may not be easy."
+msgstr "Η ανάκτηση χαμένων υποβολών μπορεί να είναι δύσκολη."
+
+#: lib/checkout_op.tcl:505
+#, tcl-format
+msgid "Reset '%s'?"
+msgstr "Επαναφορά '%s';"
+
+#: lib/checkout_op.tcl:510 lib/merge.tcl:163
+msgid "Visualize"
+msgstr "Απεικόνιση"
+
+#: lib/checkout_op.tcl:578
+#, tcl-format
+msgid ""
+"Failed to set current branch.\n"
+"\n"
+"This working directory is only partially switched.  We successfully updated "
+"your files, but failed to update an internal Git file.\n"
+"\n"
+"This should not have occurred.  %s will now close and give up."
+msgstr ""
+"Αποτυχία ορισμού τρέχοντος κλάδου.\n"
+"\n"
+"Αυτός ο φάκελος εργασίας είναι μόνο εν μέρει επιλεγμένος. 'Εγινε επιτυχής "
+"ενημέρωση των αρχείων σας, αλλά απέτυχε η ενημέρωση ενός εσωτερικού αρχείου "
+"του Git.\n"
+"\n"
+"Αυτό δε θα έπρεπε να συμβεί. Το %s θα κλείσει και θα εγκαταλείψει τώρα."
+
+#: lib/choose_font.tcl:39
+msgid "Select"
+msgstr "Επιλογή"
+
+#: lib/choose_font.tcl:53
+msgid "Font Family"
+msgstr "Οικογένεια Γραμματοσειράς"
+
+#: lib/choose_font.tcl:74
+msgid "Font Size"
+msgstr "Μέγεθος Γραμματοσειράς"
+
+#: lib/choose_font.tcl:91
+msgid "Font Example"
+msgstr "Παράδειγμα Γραμματοσειράς"
+
+#: lib/choose_font.tcl:103
+msgid ""
+"This is example text.\n"
+"If you like this text, it can be your font."
+msgstr ""
+"Αυτό είναι ένα παράδειγμα κειμένου.\n"
+"Αν σας αρέσει αυτό το κείμενο, μπορεί να γίνει δικό σας."
+
+#: lib/choose_repository.tcl:28
+msgid "Git Gui"
+msgstr "Γραφικό Περιβάλλον Git"
+
+#: lib/choose_repository.tcl:81 lib/choose_repository.tcl:376
+msgid "Create New Repository"
+msgstr "Δημιουργία Νέου Αποθετηρίου"
+
+#: lib/choose_repository.tcl:87
+msgid "New..."
+msgstr "Νέο..."
+
+#: lib/choose_repository.tcl:94 lib/choose_repository.tcl:460
+msgid "Clone Existing Repository"
+msgstr "Κλωνοποίηση Υπάρχοντος Αποθετηρίου"
+
+#: lib/choose_repository.tcl:100
+msgid "Clone..."
+msgstr "Κλωνοποίηση..."
+
+#: lib/choose_repository.tcl:107 lib/choose_repository.tcl:976
+msgid "Open Existing Repository"
+msgstr "Άνοιγμα Υπάρχοντος Αποθετηρίου"
+
+#: lib/choose_repository.tcl:113
+msgid "Open..."
+msgstr "Άνοιγμα..."
+
+#: lib/choose_repository.tcl:126
+msgid "Recent Repositories"
+msgstr "Πρόσφατα Αποθετήρια"
+
+#: lib/choose_repository.tcl:132
+msgid "Open Recent Repository:"
+msgstr "Άνοιγμα Πρόσφατου Αποθετηρίου:"
+
+#: lib/choose_repository.tcl:296 lib/choose_repository.tcl:303
+#: lib/choose_repository.tcl:310
+#, tcl-format
+msgid "Failed to create repository %s:"
+msgstr "Αποτυχία δημιουργίας αποθετηρίου %s:"
+
+#: lib/choose_repository.tcl:381 lib/choose_repository.tcl:478
+msgid "Directory:"
+msgstr "Φάκελος:"
+
+#: lib/choose_repository.tcl:412 lib/choose_repository.tcl:537
+#: lib/choose_repository.tcl:1011
+msgid "Git Repository"
+msgstr "Αποθετήριο Git"
+
+#: lib/choose_repository.tcl:437
+#, tcl-format
+msgid "Directory %s already exists."
+msgstr "Ο Φάκελος '%s' υπάρχει ήδη."
+
+#: lib/choose_repository.tcl:441
+#, tcl-format
+msgid "File %s already exists."
+msgstr "Το αρχείο %s υπάρχει ήδη."
+
+#: lib/choose_repository.tcl:455
+msgid "Clone"
+msgstr "Κλώνος"
+
+#: lib/choose_repository.tcl:468
+#, fuzzy
+msgid "URL:"
+msgstr ""
+
+#: lib/choose_repository.tcl:489
+msgid "Clone Type:"
+msgstr "Τύπος Κλώνου:"
+
+#: lib/choose_repository.tcl:495
+msgid "Standard (Fast, Semi-Redundant, Hardlinks)"
+msgstr "Τυπικό (Ταχύ, Ημι-Πλεονάζον, Hardlinks)"
+
+#: lib/choose_repository.tcl:501
+msgid "Full Copy (Slower, Redundant Backup)"
+msgstr "Πλήρες Αντίγραφο (Πιο αργό, Πλεονάζον Αντίγραφο Ασφαλείας)"
+
+#: lib/choose_repository.tcl:507
+msgid "Shared (Fastest, Not Recommended, No Backup)"
+msgstr "Κοινή Χρήση (Ταχύτατο, Δε Συνιστάται, Κανένα Αντίγραφο Ασφαλείας)"
+
+#: lib/choose_repository.tcl:543 lib/choose_repository.tcl:590
+#: lib/choose_repository.tcl:736 lib/choose_repository.tcl:806
+#: lib/choose_repository.tcl:1017 lib/choose_repository.tcl:1025
+#, tcl-format
+msgid "Not a Git repository: %s"
+msgstr "Δεν είναι αποθετήριο Git: %s"
+
+#: lib/choose_repository.tcl:579
+msgid "Standard only available for local repository."
+msgstr "\"Τυπικό\" διαθέσιμο μόνο για τοπικό αποθετήριο."
+
+#: lib/choose_repository.tcl:583
+msgid "Shared only available for local repository."
+msgstr "\"Κοινή Χρήση\" διαθέσιμη μόνο για τοπικό αποθετήριο."
+
+#: lib/choose_repository.tcl:604
+#, tcl-format
+msgid "Location %s already exists."
+msgstr "Η Τοποθεσία %s υπάρχει ήδη."
+
+#: lib/choose_repository.tcl:615
+msgid "Failed to configure origin"
+msgstr "Αποτυχία ρύθμισης πηγής"
+
+#: lib/choose_repository.tcl:627
+msgid "Counting objects"
+msgstr "Γίνεται καταμέτρηση αντικειμένων"
+
+#: lib/choose_repository.tcl:628
+#, fuzzy
+msgid "buckets"
+msgstr ""
+
+#: lib/choose_repository.tcl:652
+#, tcl-format
+msgid "Unable to copy objects/info/alternates: %s"
+msgstr "Αδυναμία αντιγραφής αντικειμένων/πληροφοριών/ενναλακτικών: %s"
+
+#: lib/choose_repository.tcl:688
+#, tcl-format
+msgid "Nothing to clone from %s."
+msgstr "Τίποτα προς κλωνοποίηση από το %s."
+
+#: lib/choose_repository.tcl:690 lib/choose_repository.tcl:904
+#: lib/choose_repository.tcl:916
+msgid "The 'master' branch has not been initialized."
+msgstr "Ο κλάδος 'master' δεν έχει αρχικοποιηθεί."
+
+#: lib/choose_repository.tcl:703
+msgid "Hardlinks are unavailable.  Falling back to copying."
+msgstr "Hardlinks μη διαθέσιμα. Μετάπτωση σε αντιγραφή."
+
+#: lib/choose_repository.tcl:715
+#, tcl-format
+msgid "Cloning from %s"
+msgstr "Γίνεται κλωνοποίηση από το %s"
+
+#: lib/choose_repository.tcl:746
+msgid "Copying objects"
+msgstr "Γίνεται αντιγραφή αντικειμένων"
+
+#: lib/choose_repository.tcl:747
+#, fuzzy
+msgid "KiB"
+msgstr ""
+
+#: lib/choose_repository.tcl:771
+#, tcl-format
+msgid "Unable to copy object: %s"
+msgstr "Αδυναμία αντιγραφής αντικειμένου: %s"
+
+#: lib/choose_repository.tcl:781
+msgid "Linking objects"
+msgstr "Γίνεται σύνδεση αντικειμένων"
+
+#: lib/choose_repository.tcl:782
+msgid "objects"
+msgstr "αντικείμενα"
+
+#: lib/choose_repository.tcl:790
+#, tcl-format
+msgid "Unable to hardlink object: %s"
+msgstr "Αδυναμία hardlink αντικειμένου: %s"
+
+#: lib/choose_repository.tcl:845
+msgid "Cannot fetch branches and objects.  See console output for details."
+msgstr ""
+"Δε μπόρεσε να γίνει ανάκτηση κλάδων και αντικειμένων. Δείτε την έξοδο "
+"κονσόλας για λεπτομέρειες."
+
+#: lib/choose_repository.tcl:856
+msgid "Cannot fetch tags.  See console output for details."
+msgstr ""
+"Δε μπόρεσε να γίνει ανάκτηση ετικετών. Δείτε την έξοδο κονσόλας για "
+"λεπτομέρειες."
+
+#: lib/choose_repository.tcl:880
+msgid "Cannot determine HEAD.  See console output for details."
+msgstr ""
+"Δε μπόρεσε να γίνει καθορισμός του HEAD (παρακλαδιού). Δείτε την έξοδο "
+"κονσόλας για "
+"λεπτομέρειες."
+
+#: lib/choose_repository.tcl:889
+#, tcl-format
+msgid "Unable to cleanup %s"
+msgstr "Αδυναμία εκκαθάρισης %s"
+
+#: lib/choose_repository.tcl:895
+msgid "Clone failed."
+msgstr "Αποτυχία κλωνοποίησης."
+
+#: lib/choose_repository.tcl:902
+msgid "No default branch obtained."
+msgstr "Δεν έγινε ανάκτηση προεπιλεγμένου κλάδου."
+
+#: lib/choose_repository.tcl:913
+#, tcl-format
+msgid "Cannot resolve %s as a commit."
+msgstr "Δε μπόρεσε να επιλυθεί το %s ως υποβολή."
+
+#: lib/choose_repository.tcl:925
+msgid "Creating working directory"
+msgstr "Δημιουργία φακέλου εργασίας"
+
+#: lib/choose_repository.tcl:926 lib/index.tcl:65 lib/index.tcl:127
+#: lib/index.tcl:193
+msgid "files"
+msgstr "αρχεία"
+
+#: lib/choose_repository.tcl:955
+msgid "Initial file checkout failed."
+msgstr "Η αρχική εξαγωγή αρχείου απέτυχε."
+
+#: lib/choose_repository.tcl:971
+msgid "Open"
+msgstr "Άνοιγμα"
+
+#: lib/choose_repository.tcl:981
+msgid "Repository:"
+msgstr "Αποθετήριο:"
+
+#: lib/choose_repository.tcl:1031
+#, tcl-format
+msgid "Failed to open repository %s:"
+msgstr "Αποτυχία ανοίγματος αποθετηρίου %s:"
+
+#: lib/choose_rev.tcl:53
+#, fuzzy
+msgid "This Detached Checkout"
+msgstr "Αποσυνδεδεμένη Εξαγωγή"
+
+#: lib/choose_rev.tcl:60
+msgid "Revision Expression:"
+msgstr "Έκφραση Αναθεώρησης:"
+
+#: lib/choose_rev.tcl:74
+msgid "Local Branch"
+msgstr "Τοπικός Κλάδος"
+
+#: lib/choose_rev.tcl:79
+msgid "Tracking Branch"
+msgstr "Κλάδος Παρακολούθησης"
+
+#: lib/choose_rev.tcl:84 lib/choose_rev.tcl:538
+msgid "Tag"
+msgstr "Ετικέτα"
+
+#: lib/choose_rev.tcl:317
+#, tcl-format
+msgid "Invalid revision: %s"
+msgstr "Μη έγκυρη αναθεώρηση: %s"
+
+#: lib/choose_rev.tcl:338
+msgid "No revision selected."
+msgstr "Δεν έχει επιλεγεί αναθεώρηση."
+
+#: lib/choose_rev.tcl:346
+msgid "Revision expression is empty."
+msgstr "Η έκφραση αναθεώρησης είναι κενή."
+
+#: lib/choose_rev.tcl:531
+msgid "Updated"
+msgstr "Ενημερωμένο"
+
+#: lib/choose_rev.tcl:559
+#, fuzzy
+msgid "URL"
+msgstr ""
+
+#: lib/commit.tcl:9
+msgid ""
+"There is nothing to amend.\n"
+"\n"
+"You are about to create the initial commit.  There is no commit before this "
+"to amend.\n"
+msgstr ""
+"Δεν υπάρχει κάτι προς διόρθωση.\n"
+"\n"
+"Πρόκειται να δημιουργήσετε την αρχική υποβολή. Δεν υπάρχει υποβολή πριν από "
+"αυτή για να διορθώσετε.\n"
+
+#: lib/commit.tcl:18
+msgid ""
+"Cannot amend while merging.\n"
+"\n"
+"You are currently in the middle of a merge that has not been fully "
+"completed.  You cannot amend the prior commit unless you first abort the "
+"current merge activity.\n"
+msgstr ""
+"Δε γίνεται διόρθωση καθώς συγχωνεύετε.\n"
+"\n"
+"Βρίσκεστε στο μέσο μιας συγχώνευσης που δεν έχει ολοκληρωθεί. Δε μπορείτε να "
+"διορθώσετε την προηγούμενη υποβολή εκτός εάν ακυρώσετε την τρέχουσα ενέργεια "
+"συγχώνευσης.\n"
+
+#: lib/commit.tcl:49
+msgid "Error loading commit data for amend:"
+msgstr "Σφάλμα φόρτωσης δεδομένων υποβολής προς διόρθωση:"
+
+#: lib/commit.tcl:76
+msgid "Unable to obtain your identity:"
+msgstr "Αδυναμία ανάκτησης της ταυτότητάς σας:"
+
+#: lib/commit.tcl:81
+msgid "Invalid GIT_COMMITTER_IDENT:"
+msgstr "Μη έγκυρο GIT_COMMITTER_IDENT:"
+
+#: lib/commit.tcl:133
+msgid ""
+"Last scanned state does not match repository state.\n"
+"\n"
+"Another Git program has modified this repository since the last scan.  A "
+"rescan must be performed before another commit can be created.\n"
+"\n"
+"The rescan will be automatically started now.\n"
+msgstr ""
+"Η τελευταία κατάσταση που ανιχνεύθηκε δε συμφωνεί με την κατάσταση του "
+"αποθετηρίου.\n"
+"\n"
+"Κάποιο άλλο πρόγραμμα Git τροποποίησε το αποθετήριο από την τελευταία "
+"ανίχνευση. Πρέπει να γίνει επανανίχνευση πριν τη δημιουργία νέας υποβολής.\n"
+"\n"
+"Η επανανίχνευση θα ξεκινήσει αυτόματα τώρα.\n"
+
+#: lib/commit.tcl:154
+#, tcl-format
+msgid ""
+"Unmerged files cannot be committed.\n"
+"\n"
+"File %s has merge conflicts.  You must resolve them and stage the file "
+"before committing.\n"
+msgstr ""
+"Τα μη συγχωνευμένα αρχεία δε μπορούν να υποβληθούν.\n"
+"\n"
+"Το αρχείο %s έχει συγκρούσεις συγχώνευσης. Πρέπει να τις επιλύσετε και να "
+"σταδιοποιήσετε το αρχείο πριν την υποβολή.\n"
+
+#: lib/commit.tcl:162
+#, tcl-format
+msgid ""
+"Unknown file state %s detected.\n"
+"\n"
+"File %s cannot be committed by this program.\n"
+msgstr ""
+"Άγνωστη κατάσταση αρχείου %s ανιχνεύθηκε.\n"
+"\n"
+"Το αρχείο %s δε μπορεί να υποβληθεί από αυτό το πρόγραμμα.\n"
+
+#: lib/commit.tcl:170
+msgid ""
+"No changes to commit.\n"
+"\n"
+"You must stage at least 1 file before you can commit.\n"
+msgstr ""
+"Δεν υπάρχουν αλλαγές προς υποβολή.\n"
+"\n "
+"Πρέπει να σταδιοποιήσετε τουλάχιστον 1 αρχείο πριν να κάνετε υποβολή.\n"
+
+#: lib/commit.tcl:183
+msgid ""
+"Please supply a commit message.\n"
+"\n"
+"A good commit message has the following format:\n"
+"\n"
+"- First line: Describe in one sentence what you did.\n"
+"- Second line: Blank\n"
+"- Remaining lines: Describe why this change is good.\n"
+msgstr ""
+"Παρακαλώ δώστε ένα μήνυμα υποβολής.\n"
+"\n"
+"Ένα σωστό μήνυμα υποβολής έχει την εξής μορφή:\n"
+"\n"
+"- Πρώτη γραμμή: Περιγραφή σε μία πρόταση του τι κάνατε.\n"
+"- Δεύτερη γραμμή: Κενή\n"
+"- Υπόλοιπες γραμμές: Περιγραφή του γιατί αυτή η αλλαγή είναι σωστή.\n"
+
+#: lib/commit.tcl:207
+#, tcl-format
+msgid "warning: Tcl does not support encoding '%s'."
+msgstr "προειδοποίηση: H Tcl δεν υποστηρίζει την κωδικοποίηση '%s'."
+
+#: lib/commit.tcl:221
+msgid "Calling pre-commit hook..."
+msgstr "Γίνεται κλήση του pre-commit hook..."
+
+#: lib/commit.tcl:236
+msgid "Commit declined by pre-commit hook."
+msgstr "Η υποβολή απορρίφθηκε από το pre-commit hook."
+
+#: lib/commit.tcl:259
+msgid "Calling commit-msg hook..."
+msgstr "Γίνεται κλήση του commit-msg hook..."
+
+#: lib/commit.tcl:274
+msgid "Commit declined by commit-msg hook."
+msgstr "Η υποβολή απορρίφθηκε από το commit-msg hook."
+
+#: lib/commit.tcl:287
+msgid "Committing changes..."
+msgstr "Γίνεται υποβολή των αλλαγών..."
+
+#: lib/commit.tcl:303
+msgid "write-tree failed:"
+msgstr "το write-tree απέτυχε:"
+
+#: lib/commit.tcl:304 lib/commit.tcl:348 lib/commit.tcl:368
+msgid "Commit failed."
+msgstr "Η υποβολή απέτυχε."
+
+#: lib/commit.tcl:321
+#, tcl-format
+msgid "Commit %s appears to be corrupt"
+msgstr "Η υποβολή %s δείχνει κατεστραμμένη"
+
+#: lib/commit.tcl:326
+msgid ""
+"No changes to commit.\n"
+"\n"
+"No files were modified by this commit and it was not a merge commit.\n"
+"\n"
+"A rescan will be automatically started now.\n"
+msgstr ""
+"Δεν υπάρχουν αλλαγές προς υποβολή.\n"
+"\n"
+"Δεν τροποποιήθηκαν αρχεία από αυτή την υποβολή και δεν ήταν υποβολή "
+"συγχώνευσης.\n"
+"\n"
+"Θα ξεκινήσει αυτόματα επανανίχνευση τώρα.\n"
+
+#: lib/commit.tcl:333
+msgid "No changes to commit."
+msgstr "Δεν υπάρχουν αλλαγές προς υποβολή."
+
+#: lib/commit.tcl:347
+msgid "commit-tree failed:"
+msgstr "το commit-tree απέτυχε:"
+
+#: lib/commit.tcl:367
+msgid "update-ref failed:"
+msgstr "το update-ref απέτυχε:"
+
+#: lib/commit.tcl:454
+#, tcl-format
+msgid "Created commit %s: %s"
+msgstr "Δημιουργήθηκε υποβολή %s: %s"
+
+#: lib/console.tcl:59
+msgid "Working... please wait..."
+msgstr "Γίνεται εργασία... Παρακαλώ περιμένετε..."
+
+#: lib/console.tcl:186
+msgid "Success"
+msgstr "Επιτυχία"
+
+#: lib/console.tcl:200
+msgid "Error: Command Failed"
+msgstr "Σφάλμα: Η Εντολή Απέτυχε"
+
+#: lib/database.tcl:43
+msgid "Number of loose objects"
+msgstr "Αριθμός ελεύθερων αντικειμένων"
+
+#: lib/database.tcl:44
+msgid "Disk space used by loose objects"
+msgstr "Χώρος κατειλλημένος από ελεύθερα αντικείμενα"
+
+#: lib/database.tcl:45
+msgid "Number of packed objects"
+msgstr "Αριθμός πακεταρισμένων αντικειμένων"
+
+#: lib/database.tcl:46
+msgid "Number of packs"
+msgstr "Αριθμός πακέτων"
+
+#: lib/database.tcl:47
+msgid "Disk space used by packed objects"
+msgstr "Χώρος κατειλλημένος από πακεταρισμένα αντικείμενα"
+
+#: lib/database.tcl:48
+msgid "Packed objects waiting for pruning"
+msgstr "Πακεταρισμένα αντικείμενα έτοιμα για κλάδεμα"
+
+#: lib/database.tcl:49
+msgid "Garbage files"
+msgstr "Άχρηστα αρχεία"
+
+#: lib/database.tcl:72
+msgid "Compressing the object database"
+msgstr "Γίνεται συμπίεση της βάσης δεδομένων αντικειμένων"
+
+#: lib/database.tcl:83
+msgid "Verifying the object database with fsck-objects"
+msgstr ""
+"Γίνεται επαλήθευση της βάσης δεδομένων αντικειμένων με αντικείμενα fsck"
+
+#: lib/database.tcl:108
+#, tcl-format
+msgid ""
+"This repository currently has approximately %i loose objects.\n"
+"\n"
+"To maintain optimal performance it is strongly recommended that you compress "
+"the database when more than %i loose objects exist.\n"
+"\n"
+"Compress the database now?"
+msgstr ""
+"Αυτό το αποθετήριο έχει αυτή τη στιγμή περίπου %i ελεύθερα αντικείμενα.\n"
+"\n"
+"Για τη διατήρηση βέλτιστων επιδόσεων συνιστάται να συμπιέσετε τη βάση "
+"δεδομένων όταν υπάρχουν περισσότερα από %i ελεύθερα αντικείμενα.\n"
+"\n"
+"Συμπίεση της βάσης δεδομένων τώρα;"
+
+#: lib/date.tcl:25
+#, tcl-format
+msgid "Invalid date from Git: %s"
+msgstr "Μη έγκυρη ημερομηνία από το Git: %s"
+
+#: lib/diff.tcl:42
+#, tcl-format
+msgid ""
+"No differences detected.\n"
+"\n"
+"%s has no changes.\n"
+"\n"
+"The modification date of this file was updated by another application, but "
+"the content within the file was not changed.\n"
+"\n"
+"A rescan will be automatically started to find other files which may have "
+"the same state."
+msgstr ""
+"Δεν ανιχνεύθηκαν διαφορές.\n"
+"\n"
+"Το %s δεν έχει αλλαγές."
+"\n"
+"Η ημερομηνία τροποποίησης αυτού του αρχείου ενημερώθηκε από άλλη εφαρμογή, "
+"αλλά το περιεχόμενο του αρχείου δεν άλλαξε.\n"
+"\n"
+"Θα ξεκινήσει αυτόματα επανανίχνευση για να βρεθούν άλλα αρχεία που μπορεί να "
+"βρίσκονται σε ίδια κατάσταση."
+
+#: lib/diff.tcl:81
+#, tcl-format
+msgid "Loading diff of %s..."
+msgstr "Γίνεται φόρτωση διαφοράς του %s..."
+
+#: lib/diff.tcl:114 lib/diff.tcl:184
+#, tcl-format
+msgid "Unable to display %s"
+msgstr "Δεν είναι δυνατή η προβολή του %s"
+
+#: lib/diff.tcl:115
+msgid "Error loading file:"
+msgstr "Σφάλμα φόρτωσης αρχείου:"
+
+#: lib/diff.tcl:122
+msgid "Git Repository (subproject)"
+msgstr "Αποθετήριο Git (θυγατρικό έργο)"
+
+#: lib/diff.tcl:134
+msgid "* Binary file (not showing content)."
+msgstr "* Δυαδικό αρχείο (μη εμφάνιση περιεχομένου)."
+
+#: lib/diff.tcl:185
+msgid "Error loading diff:"
+msgstr "Σφάλμα φόρτωσης διαφοράς:"
+
+#: lib/diff.tcl:303
+msgid "Failed to unstage selected hunk."
+msgstr "Αποτυχία αποσταδιοποίησης επιλεγμένου κομματιού."
+
+#: lib/diff.tcl:310
+msgid "Failed to stage selected hunk."
+msgstr "Αποτυχία σταδιοποίησης επιλεγμένου κομματιού."
+
+#: lib/error.tcl:20 lib/error.tcl:114
+msgid "error"
+msgstr "σφάλμα"
+
+#: lib/error.tcl:36
+msgid "warning"
+msgstr "προειδοποίηση"
+
+#: lib/error.tcl:94
+msgid "You must correct the above errors before committing."
+msgstr "Πρέπει να διορθώσετε τα παραπάνω λάθη πριν την υποβολή."
+
+#: lib/index.tcl:6
+msgid "Unable to unlock the index."
+msgstr "Αδυναμία ξεκλειδώματος του ευρετηρίου."
+
+#: lib/index.tcl:15
+msgid "Index Error"
+msgstr "Σφάλμα Ευρετηρίου"
+
+#: lib/index.tcl:21
+msgid ""
+"Updating the Git index failed.  A rescan will be automatically started to "
+"resynchronize git-gui."
+msgstr ""
+"Η ενημέρωση του ευρετηρίου Git απέτυχε. Θα ξεκινήσει αυτόματα επανανίχνευση "
+"για επανασυγχρονισμό του git-gui."
+
+#: lib/index.tcl:27
+msgid "Continue"
+msgstr "Συνέχεια"
+
+#: lib/index.tcl:31
+msgid "Unlock Index"
+msgstr "Ξεκλείδωμα Ευρετηρίου"
+
+#: lib/index.tcl:282
+#, tcl-format
+msgid "Unstaging %s from commit"
+msgstr "Αποσταδιοποίηση %s από υποβολή"
+
+#: lib/index.tcl:313
+msgid "Ready to commit."
+msgstr "Έτοιμο προς υποβολή."
+
+#: lib/index.tcl:326
+#, tcl-format
+msgid "Adding %s"
+msgstr "Προσθήκη %s"
+
+#: lib/index.tcl:381
+#, tcl-format
+msgid "Revert changes in file %s?"
+msgstr "Αναίρεση αλλαγών στο αρχείο %s;"
+
+#: lib/index.tcl:383
+#, tcl-format
+msgid "Revert changes in these %i files?"
+msgstr "Αναίρεση αλλαγών σε αυτά τα %i αρχεία;"
+
+#: lib/index.tcl:391
+msgid "Any unstaged changes will be permanently lost by the revert."
+msgstr ""
+"Όλες οι μη σταδιοποιημένες αλλαγές θα χαθούν οριστικά από την αναίρεση."
+
+#: lib/index.tcl:394
+msgid "Do Nothing"
+msgstr "Καμία Ενέργεια"
+
+#: lib/merge.tcl:13
+msgid ""
+"Cannot merge while amending.\n"
+"\n"
+"You must finish amending this commit before starting any type of merge.\n"
+msgstr ""
+"Δε γίνεται συγχώνευση καθώς διορθώνετε.\n"
+"\n"
+"Πρέπει να τελειώσετε τη διόρθωση αυτής της υποβολής πριν να ξεκινήσετε "
+"οποιασδήποτε μορφής συγχώνευση.\n"
+
+#: lib/merge.tcl:27
+msgid ""
+"Last scanned state does not match repository state.\n"
+"\n"
+"Another Git program has modified this repository since the last scan.  A "
+"rescan must be performed before a merge can be performed.\n"
+"\n"
+"The rescan will be automatically started now.\n"
+msgstr ""
+"Η τελευταία κατάσταση που ανιχνεύθηκε δε συμφωνεί με την κατάσταση του "
+"αποθετηρίου.\n"
+"\n"
+"Κάποιο άλλο πρόγραμμα Git τροποποίησε το αποθετήριο από την τελευταία "
+"ανίχνευση. Πρέπει να γίνει επανανίχνευση πριν τη διενέργεια συγχώνευσης.\n"
+"\n"
+"Η επανανίχνευση θα ξεκινήσει αυτόματα τώρα.\n"
+
+#: lib/merge.tcl:44
+#, tcl-format
+msgid ""
+"You are in the middle of a conflicted merge.\n"
+"\n"
+"File %s has merge conflicts.\n"
+"\n"
+"You must resolve them, stage the file, and commit to complete the current "
+"merge.  Only then can you begin another merge.\n"
+msgstr ""
+"Βρίσκεστε στο μέσο μιας συγκρουόμενης συγχώνευσης.\n"
+"\n"
+"Το αρχείο %s έχει συγκρούσεις συγχώνευσης.\n"
+"\n"
+"Πρέπει να τις επιλύσετε, να σταδιοποιήσετε το αρχείο, και να κάνετε υποβολή "
+"για να ολοκληρώσετε την τρέχουσα συγχώνευση. Μόνο τότε μπορείτε να "
+"ξεκινήσετε άλλη συγχώνευση.\n"
+
+#: lib/merge.tcl:54
+#, tcl-format
+msgid ""
+"You are in the middle of a change.\n"
+"\n"
+"File %s is modified.\n"
+"\n"
+"You should complete the current commit before starting a merge.  Doing so "
+"will help you abort a failed merge, should the need arise.\n"
+msgstr ""
+"Βρίσκεστε στο μέσο μιας αλλαγής.\n"
+"\n"
+"Το αρχείο %s έχει τροποποιηθεί.\n"
+"\n"
+"Πρέπει να ολοκληρώσετε την τρέχουσα συγχώνευση πριν να ξεκινήσετε συγχώνευση."
+" Αυτό βοηθά στην ακύρωση αποτυχημένης συγχώνευσης, εάν χρειαστεί.\n"
+
+#: lib/merge.tcl:106
+#, tcl-format
+msgid "%s of %s"
+msgstr "%s από %s"
+
+#: lib/merge.tcl:119
+#, tcl-format
+msgid "Merging %s and %s..."
+msgstr "Γίνεται συγχώνευση του %s με το %s..."
+
+#: lib/merge.tcl:130
+msgid "Merge completed successfully."
+msgstr "Η συγχώνευση ολοκληρώθηκε επιτυχώς."
+
+#: lib/merge.tcl:132
+msgid "Merge failed.  Conflict resolution is required."
+msgstr "Η συγχώνευση απέτυχε. Απαιτείται επίλυση συγκρούσεων."
+
+#: lib/merge.tcl:157
+#, tcl-format
+msgid "Merge Into %s"
+msgstr "Συγχώνευση με %s"
+
+#: lib/merge.tcl:176
+msgid "Revision To Merge"
+msgstr "Αναθεώρηση Προς Συγχώνευση"
+
+#: lib/merge.tcl:211
+msgid ""
+"Cannot abort while amending.\n"
+"\n"
+"You must finish amending this commit.\n"
+msgstr ""
+"Δε γίνεται ακύρωση καθώς διορθώνετε.\n"
+"\n"
+"Πρέπει να τελειώσετε τη διόρθωση αυτής της υποβολής.\n"
+
+#: lib/merge.tcl:221
+msgid ""
+"Abort merge?\n"
+"\n"
+"Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n"
+"\n"
+"Continue with aborting the current merge?"
+msgstr ""
+"Ακύρωση συγχώνευσης;\n"
+"\n"
+"Η ακύρωση της τρέχουσας συγχώνευσης θα προκαλέσει απώλεια *ΟΛΩΝ* των μη "
+"υποβεβλημένων αλλαγών.\n"
+"\n"
+"Να προχωρήσει η ακύρωση της τρέχουσας συγχώνευσης;"
+
+#: lib/merge.tcl:227
+msgid ""
+"Reset changes?\n"
+"\n"
+"Resetting the changes will cause *ALL* uncommitted changes to be lost.\n"
+"\n"
+"Continue with resetting the current changes?"
+msgstr ""
+"Επαναφορά αλλαγών;\n"
+"\n"
+"Η επαναφορά των αλλαγών θα προκαλέσει απώλεια *ΟΛΩΝ* των μη υποβεβλημένων "
+"αλλαγών.\n"
+"\n"
+"Να συνεχίσει η επαναφορά των τρέχουσων αλλαγών;"
+
+#: lib/merge.tcl:238
+msgid "Aborting"
+msgstr "Γίνεται ακύρωση"
+
+#: lib/merge.tcl:238
+msgid "files reset"
+msgstr "αρχεία που επαναφέρθηκαν"
+
+#: lib/merge.tcl:265
+msgid "Abort failed."
+msgstr "Η ακύρωση απέτυχε."
+
+#: lib/merge.tcl:267
+msgid "Abort completed.  Ready."
+msgstr "Η ακύρωση απέτυχε. Έτοιμο."
+
+#: lib/option.tcl:95
+msgid "Restore Defaults"
+msgstr "Επαναφορά Προεπιλογών"
+
+#: lib/option.tcl:99
+msgid "Save"
+msgstr "Αποθήκευση"
+
+#: lib/option.tcl:109
+#, tcl-format
+msgid "%s Repository"
+msgstr "%s Αποθετήριο"
+
+#: lib/option.tcl:110
+msgid "Global (All Repositories)"
+msgstr "Ολικό (Όλα τα Αποθετήρια)"
+
+#: lib/option.tcl:116
+msgid "User Name"
+msgstr "Όνομα Χρήστη"
+
+#: lib/option.tcl:117
+msgid "Email Address"
+msgstr "Διεύθυνση Email"
+
+#: lib/option.tcl:119
+msgid "Summarize Merge Commits"
+msgstr "Περίληψη Υποβολών Συγχώνευσης"
+
+#: lib/option.tcl:120
+msgid "Merge Verbosity"
+msgstr "Λεπτομέρεια Συγχώνευσης"
+
+#: lib/option.tcl:121
+msgid "Show Diffstat After Merge"
+msgstr "Προβολή Στατιστικών Διαφοράς Μετά από Συγχώνευση"
+
+#: lib/option.tcl:123
+msgid "Trust File Modification Timestamps"
+msgstr "Εμπιστοσύνη Ημερομηνιών Μετατροπής Αρχείων"
+
+#: lib/option.tcl:124
+msgid "Prune Tracking Branches During Fetch"
+msgstr "Κλάδεμα Κλάδων Παρακολούθησης Κατά Την Ανάκτηση"
+
+#: lib/option.tcl:125
+msgid "Match Tracking Branches"
+msgstr "Συμφωνία Κλάδων Παρακολούθησης"
+
+#: lib/option.tcl:126
+msgid "Number of Diff Context Lines"
+msgstr "Αριθμός Γραμμών Εννοιολογικού Πλαισίου Διαφοράς"
+
+#: lib/option.tcl:127
+msgid "Commit Message Text Width"
+msgstr "Πλάτος Κειμένου Μηνύματος Υποβολής"
+
+#: lib/option.tcl:128
+msgid "New Branch Name Template"
+msgstr "Νέο Πρότυπο Ονόματος Κλάδου"
+
+#: lib/option.tcl:192
+msgid "Spelling Dictionary:"
+msgstr "Λεξικό Ορθογραφίας:"
+
+#: lib/option.tcl:216
+msgid "Change Font"
+msgstr "Αλλαγή Γραμματοσειράς"
+
+#: lib/option.tcl:220
+#, tcl-format
+msgid "Choose %s"
+msgstr "Επιλογή %s"
+
+#: lib/option.tcl:226
+#, fuzzy
+msgid "pt."
+msgstr ""
+
+#: lib/option.tcl:240
+msgid "Preferences"
+msgstr "Προτιμήσεις"
+
+#: lib/option.tcl:275
+msgid "Failed to completely save options:"
+msgstr "Αποτυχία πλήρους αποθήκευσης επιλογών:"
+
+#: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34
+msgid "Delete Remote Branch"
+msgstr "Διαγραφή Απομακρυσμένου Κλάδου"
+
+#: lib/remote_branch_delete.tcl:47
+msgid "From Repository"
+msgstr "Από Αποθετήριο"
+
+#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:123
+msgid "Remote:"
+msgstr "Απομακρυσμένο:"
+
+#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:138
+#, fuzzy
+msgid "Arbitrary URL:"
+msgstr "Αυθαίρετο URL:"
+
+#: lib/remote_branch_delete.tcl:84
+msgid "Branches"
+msgstr "Κλάδοι"
+
+#: lib/remote_branch_delete.tcl:109
+msgid "Delete Only If"
+msgstr "Διαγραφή Μόνο Εάν"
+
+#: lib/remote_branch_delete.tcl:111
+msgid "Merged Into:"
+msgstr "Συγχωνευμένο Με:"
+
+#: lib/remote_branch_delete.tcl:119
+msgid "Always (Do not perform merge checks)"
+msgstr "Πάντα (Μη διενεργηθούν έλεγχοι συγχώνευσης)"
+
+#: lib/remote_branch_delete.tcl:152
+msgid "A branch is required for 'Merged Into'."
+msgstr "Απαιτείται ένας κλάδος για 'Συγχωνευμένο Με'."
+
+#: lib/remote_branch_delete.tcl:184
+#, tcl-format
+msgid ""
+"The following branches are not completely merged into %s:\n"
+"\n"
+" - %s"
+msgstr ""
+"Οι εξής κλάδοι δεν είναι πλήρως συγχωνευμένοι με το %s:\n"
+"\n"
+" - %s"
+
+#: lib/remote_branch_delete.tcl:189
+#, tcl-format
+msgid ""
+"One or more of the merge tests failed because you have not fetched the "
+"necessary commits.  Try fetching from %s first."
+msgstr ""
+"Μία ή περισσότερες από τις δοκιμές συγχώνευσης απέτυχαν επειδή δεν έχετε "
+"φέρει τις αναγκαίες υποβολές. Δοκιμάστε ανάκτηση από το %s πρώτα."
+
+#: lib/remote_branch_delete.tcl:207
+msgid "Please select one or more branches to delete."
+msgstr "Παρακαλώ επιλέξτε έναν ή περισσότερους κλάδους προς διαγραφή."
+
+#: lib/remote_branch_delete.tcl:216
+msgid ""
+"Recovering deleted branches is difficult.\n"
+"\n"
+"Delete the selected branches?"
+msgstr ""
+"Η ανάκτηση διεγραμμένων κλάδων είναι δύσκολη.\n"
+"\n"
+"Διαγραφή των επιλεγμένων κλάδων;"
+
+#: lib/remote_branch_delete.tcl:226
+#, tcl-format
+msgid "Deleting branches from %s"
+msgstr "Γίνεται διαγραφή κλάδων από %s"
+
+#: lib/remote_branch_delete.tcl:286
+msgid "No repository selected."
+msgstr "Δεν έχει επιλεγεί αποθετήριο."
+
+#: lib/remote_branch_delete.tcl:291
+#, tcl-format
+msgid "Scanning %s..."
+msgstr "Ανίχνευση %s..."
+
+#: lib/remote.tcl:165
+msgid "Prune from"
+msgstr "Κλάδεμα από"
+
+#: lib/remote.tcl:170
+msgid "Fetch from"
+msgstr "Ανάκτηση από"
+
+#: lib/remote.tcl:213
+msgid "Push to"
+msgstr "Ώθηση σε"
+
+#: lib/shortcut.tcl:20 lib/shortcut.tcl:61
+msgid "Cannot write shortcut:"
+msgstr "Δε μπόρεσε να αποθηκευτεί η συντόμευση:"
+
+#: lib/shortcut.tcl:136
+msgid "Cannot write icon:"
+msgstr "Δε μπόρεσε να αποθηκευτεί το εικονίδιο:"
+
+#: lib/spellcheck.tcl:57
+msgid "Unsupported spell checker"
+msgstr "Mη υποστηριζόμενος ελεγκτής ορθογραφίας"
+
+#: lib/spellcheck.tcl:65
+msgid "Spell checking is unavailable"
+msgstr "Έλεγχος ορθογραφίας μη διαθέσιμος"
+
+#: lib/spellcheck.tcl:68
+msgid "Invalid spell checking configuration"
+msgstr "Μη έγκυρη ρύθμιση ελέγχου ορθογραφίας"
+
+#: lib/spellcheck.tcl:70
+#, tcl-format
+msgid "Reverting dictionary to %s."
+msgstr "Γίνεται επαναφορά του λεξικού σε %s."
+
+#: lib/spellcheck.tcl:73
+msgid "Spell checker silently failed on startup"
+msgstr "Ο ελεγκτής ορθογραφίας απέτυχε σιωπηλά κατά την εκκίνηση"
+
+#: lib/spellcheck.tcl:80
+msgid "Unrecognized spell checker"
+msgstr "Μη αναγνωρίσιμος ελεγκτής ορθογραφίας"
+
+#: lib/spellcheck.tcl:180
+msgid "No Suggestions"
+msgstr "Καμία Πρόταση"
+
+#: lib/spellcheck.tcl:381
+msgid "Unexpected EOF from spell checker"
+msgstr "Μη αναμενόμενο τέλος αρχείου από τον ελεγκτή ορθογραφίας"
+
+#: lib/spellcheck.tcl:385
+msgid "Spell Checker Failed"
+msgstr "Αποτυχία Ελεγκτή Ορθογραφίας"
+
+#: lib/status_bar.tcl:83
+#, tcl-format
+msgid "%s ... %*i of %*i %s (%3i%%)"
+msgstr "%s ... %*i από %*i %s (%3i%%)"
+
+#: lib/transport.tcl:6
+#, tcl-format
+msgid "fetch %s"
+msgstr "ανάκτηση %s"
+
+#: lib/transport.tcl:7
+#, tcl-format
+msgid "Fetching new changes from %s"
+msgstr "Ανάκτηση νέων αλλαγών από το %s"
+
+#: lib/transport.tcl:18
+#, tcl-format
+msgid "remote prune %s"
+msgstr "απομακρυσμένο κλάδεμα %s"
+
+#: lib/transport.tcl:19
+#, tcl-format
+msgid "Pruning tracking branches deleted from %s"
+msgstr "Γίνεται κλάδεμα κλάδων παρακολούθησης που διεγράφησαν από το %s"
+
+#: lib/transport.tcl:25 lib/transport.tcl:71
+#, tcl-format
+msgid "push %s"
+msgstr "ώθηση %s"
+
+#: lib/transport.tcl:26
+#, tcl-format
+msgid "Pushing changes to %s"
+msgstr "Γίνεται ώθηση αλλαγών στο %s"
+
+#: lib/transport.tcl:72
+#, tcl-format
+msgid "Pushing %s %s to %s"
+msgstr "Γίνεται ώθηση %s %s στο %s"
+
+#: lib/transport.tcl:89
+msgid "Push Branches"
+msgstr "Ώθηση Κλάδων"
+
+#: lib/transport.tcl:103
+msgid "Source Branches"
+msgstr "Πηγαίοι Κλάδοι"
+
+#: lib/transport.tcl:120
+msgid "Destination Repository"
+msgstr "Αποθετήριο Προορισμού"
+
+#: lib/transport.tcl:158
+msgid "Transfer Options"
+msgstr "Επιλογές Μεταφοράς"
+
+#: lib/transport.tcl:160
+msgid "Force overwrite existing branch (may discard changes)"
+msgstr ""
+"Εξαναγκασμός επεγγραφής υπάρχοντος κλάδου (μπορεί να απορρίψει αλλαγές)"
+
+#: lib/transport.tcl:164
+msgid "Use thin pack (for slow network connections)"
+msgstr "Χρήση ισχνού πακέτου (για αργές συνδέσεις δικτύου)"
+
+#: lib/transport.tcl:168
+msgid "Include tags"
+msgstr "Συμπερίληψη ετικετών"
+
+
index 53b7d3634d842a43f8043e3f825d4232e17588aa..074582d979e87704969ebdd2380566537c6a9548 100644 (file)
@@ -90,6 +90,11 @@ msgstr ""
 msgid "Ready."
 msgstr ""
 
+#: git-gui.sh:1726
+#, tcl-format
+msgid "Displaying only %s of %s files."
+msgstr ""
+
 #: git-gui.sh:1819
 msgid "Unmodified"
 msgstr ""
diff --git a/git-gui/po/glossary/el.po b/git-gui/po/glossary/el.po
new file mode 100644 (file)
index 0000000..1d3cc81
--- /dev/null
@@ -0,0 +1,171 @@
+# Translation of git-gui glossary to Greek
+# Copyright (C) 2009 Jimmy Angelakos
+# This file is distributed under the same license as the git-gui package.
+# Jimmy Angelakos <vyruss@hellug.gr>, 2009.
+msgid ""
+msgstr ""
+"Project-Id-Version: git-gui-glossary\n"
+"POT-Creation-Date: 2008-01-07 21:20+0100\n"
+"PO-Revision-Date: 2009-06-23 20:41+0300\n"
+"Last-Translator: Jimmy Angelakos <vyruss@hellug.gr>\n"
+"Language-Team: Greek <i18n@lists.hellug.gr>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Lokalize 0.3\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. "English Definition (Dear translator: This file will never be visible to the user! It should only serve as a tool for you, the translator. Nothing more.)"
+msgid "English Term (Dear translator: This file will never be visible to the user!)"
+msgstr ""
+
+#. ""
+msgid "amend"
+msgstr "διόρθωση"
+
+#. ""
+msgid "annotate"
+msgstr "σχολιασμός"
+
+#. "A 'branch' is an active line of development."
+msgid "branch [noun]"
+msgstr "κλάδος [αντικείμενο]"
+
+#. ""
+msgid "branch [verb]"
+msgstr "διακλάδωση [ενέργεια]"
+
+#. ""
+msgid "checkout [noun]"
+msgstr "εξαγωγή [αντικείμενο]"
+
+#. "The action of updating the working tree to a revision which was stored in the object database."
+msgid "checkout [verb]"
+msgstr "εξαγωγή [ενέργεια]"
+
+#. ""
+msgid "clone [verb]"
+msgstr "κλωνοποίηση [ενέργεια]"
+
+#. "A single point in the git history."
+msgid "commit [noun]"
+msgstr "υποβολή [αντικείμενο] "
+
+#. "The action of storing a new snapshot of the project's state in the git history."
+msgid "commit [verb]"
+msgstr "υποβολή [ενέργεια]"
+
+#. ""
+msgid "diff [noun]"
+msgstr "διαφορά [αντικείμενο] "
+
+#. ""
+msgid "diff [verb]"
+msgstr "διαφορά [ενέργεια]"
+
+#. "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."
+msgid "fast forward merge"
+msgstr "συγχώνευση επιτάχυνσης"
+
+#. "Fetching a branch means to get the branch's head from a remote repository, to find out which objects are missing from the local object database, and to get them, too."
+msgid "fetch"
+msgstr "ανάκτηση"
+
+#. "One context of consecutive lines in a whole patch, which consists of many such hunks"
+msgid "hunk"
+msgstr "κομμάτι"
+
+#. "A collection of files. The index is a stored version of your working tree."
+msgid "index (in git-gui: staging area)"
+msgstr "ευρετήριο (στο git-gui: περιοχή σταδιοποίησης)"
+
+#. "A successful merge results in the creation of a new commit representing the result of the merge."
+msgid "merge [noun]"
+msgstr "συγχώνευση [αντικείμενο]"
+
+#. "To bring the contents of another branch into the current branch."
+msgid "merge [verb]"
+msgstr "συγχώνευση [ενέργεια]"
+
+#. ""
+msgid "message"
+msgstr "μήνυμα"
+
+#. "Deletes all stale tracking branches under <name>. These stale branches have already been removed from the remote repository referenced by <name>, but are still locally available in 'remotes/<name>'."
+msgid "prune"
+msgstr "κλάδεμα"
+
+#. "Pulling a branch means to fetch it and merge it."
+msgid "pull"
+msgstr "λήψη"
+
+#. "Pushing a branch means to get the branch's head ref from a remote repository, and ... (well, can someone please explain it for mere mortals?)"
+msgid "push"
+msgstr "ώθηση"
+
+#. ""
+msgid "redo"
+msgstr "ξανά"
+
+#. "An other repository ('remote'). One might have a set of remotes whose branches one tracks."
+msgid "remote"
+msgstr "απομακρυσμένο"
+
+#. "A collection of refs (?) together with an object database containing all objects which are reachable from the refs... (oops, you've lost me here. Again, please an explanation for mere mortals?)"
+msgid "repository"
+msgstr "αποθετήριο"
+
+#. ""
+msgid "reset"
+msgstr "επαναφορά"
+
+#. ""
+msgid "revert"
+msgstr "αναίρεση"
+
+#. "A particular state of files and directories which was stored in the object database."
+msgid "revision"
+msgstr "αναθεώρηση"
+
+#. ""
+#, fuzzy
+msgid "sign off"
+msgstr "αποσύνδεση"
+
+#. ""
+msgid "staging area"
+msgstr "περιοχή σταδιοποίησης"
+
+#. ""
+msgid "status"
+msgstr "κατάσταση"
+
+#. "A ref pointing to a tag or commit object"
+msgid "tag [noun]"
+msgstr "ετικέτα [αντικείμενο]"
+
+#. ""
+msgid "tag [verb]"
+msgstr "ετικέτα [ενέργεια]"
+
+#. "A regular git branch that is used to follow changes from another repository."
+msgid "tracking branch"
+msgstr "κλάδος παρακολούθησης"
+
+#. ""
+msgid "undo"
+msgstr "αναίρεση"
+
+#. ""
+msgid "update"
+msgstr "ενημέρωση"
+
+#. ""
+msgid "verify"
+msgstr "επαλήθευση"
+
+#. "The tree of actual checked out files."
+msgid "working copy, working tree"
+msgstr "αντίγραφο εργασίας"
+
+
index 0ffc4a418fccb4453c1601ca87668e2d185e14db..364c074c504ce2150effdbf01927aa052107c1af 100644 (file)
@@ -90,12 +90,18 @@ msgstr "Вызов программы поддержки репозитория
 
 #: git-gui.sh:1384
 msgid "Commit declined by prepare-commit-msg hook."
-msgstr "Сохранение прервано программой поддержки репозитория prepare-commit-msg"
+msgstr ""
+"Сохранение прервано программой поддержки репозитория prepare-commit-msg"
 
 #: git-gui.sh:1542 lib/browser.tcl:246
 msgid "Ready."
 msgstr "Готово."
 
+#: git-gui.sh:1726
+#, tcl-format
+msgid "Displaying only %s of %s files."
+msgstr "Показано %s из %s файлов."
+
 #: git-gui.sh:1819
 msgid "Unmodified"
 msgstr "Не изменено"
@@ -1297,8 +1303,8 @@ msgid ""
 msgstr ""
 "Невозможно исправить состояние во время операции слияния.\n"
 "\n"
-"Текущее слияние не завершено. Невозможно исправить предыдущее "
-"Ñ\81оÑ\85Ñ\80аненное Ñ\81оÑ\81Ñ\82оÑ\8fние, Ð½Ðµ Ð¿Ñ\80еÑ\80Ñ\8bваÑ\8f Ñ\8dÑ\82Ñ\83 Ð¾Ð¿ÐµÑ\80аÑ\86иÑ\8e.\n"
+"Текущее слияние не завершено. Невозможно исправить предыдущее сохраненное "
+"состояние, не прерывая эту операцию.\n"
 
 #: lib/commit.tcl:48
 msgid "Error loading commit data for amend:"
@@ -1723,8 +1729,7 @@ msgid ""
 msgstr ""
 "Невозможно выполнить слияние во время исправления.\n"
 "\n"
-"Завершите исправление данного состояния перед выполнением операции "
-"слияния.\n"
+"Завершите исправление данного состояния перед выполнением операции слияния.\n"
 
 #: lib/merge.tcl:27
 msgid ""
@@ -1888,8 +1893,8 @@ msgstr ""
 #, tcl-format
 msgid "File %s seems to have unresolved conflicts, still stage?"
 msgstr ""
-"Файл %s кажется содержит необработаные конфликты. "
-"Продолжить подготовку к сохранению?"
+"Файл %s кажется содержит необработаные конфликты. Продолжить подготовку к "
+"сохранению?"
 
 #: lib/mergetool.tcl:60
 #, tcl-format
@@ -2213,8 +2218,8 @@ msgid ""
 "One or more of the merge tests failed because you have not fetched the "
 "necessary commits.  Try fetching from %s first."
 msgstr ""
-"Некоторые тесты на слияние не прошли, потому что Вы не "
-"получили необходимые состояния. Попытайтесь получить их из %s."
+"Некоторые тесты на слияние не прошли, потому что Вы не получили необходимые "
+"состояния. Попытайтесь получить их из %s."
 
 #: lib/remote_branch_delete.tcl:207
 msgid "Please select one or more branches to delete."
@@ -2381,8 +2386,8 @@ msgstr "Выполнение: %s"
 
 #: lib/tools.tcl:149
 #, tcl-format
-msgid "Tool completed succesfully: %s"
-msgstr "Программа %s успешно завершилась."
+msgid "Tool completed successfully: %s"
+msgstr "Программа %s завершилась успешно."
 
 #: lib/tools.tcl:151
 #, tcl-format
@@ -2538,4 +2543,3 @@ msgstr "Использовать thin pack (для медленных сетев
 #: lib/transport.tcl:179
 msgid "Include tags"
 msgstr "Передать метки"
-
index d96eddbe56783d61304941a134361797c82480e7..622a5f0eb25e3420c085d51fd85944ab1286147e 100755 (executable)
@@ -317,7 +317,21 @@ EOF
                resolve_full_httpd
                list_mods=$(echo "$full_httpd" | sed "s/-f$/-l/")
                $list_mods | grep 'mod_cgi\.c' >/dev/null 2>&1 || \
-               echo "LoadModule cgi_module $module_path/mod_cgi.so" >> "$conf"
+               if test -f "$module_path/mod_cgi.so"
+               then
+                       echo "LoadModule cgi_module $module_path/mod_cgi.so" >> "$conf"
+               else
+                       $list_mods | grep 'mod_cgid\.c' >/dev/null 2>&1 || \
+                       if test -f "$module_path/mod_cgid.so"
+                       then
+                               echo "LoadModule cgid_module $module_path/mod_cgid.so" \
+                                       >> "$conf"
+                       else
+                               echo "You have no CGI support!"
+                               exit 2
+                       fi
+                       echo "ScriptSock logs/gitweb.sock" >> "$conf"
+               fi
                cat >> "$conf" <<EOF
 AddHandler cgi-script .cgi
 <Location /gitweb.cgi>
index 1dadbb49666c6d796df76babbfd291a2de4357e4..825c52c2436d15edb12a2ce7850437e0e531e0e3 100755 (executable)
@@ -81,7 +81,7 @@ do
                # tree as the intermediate result of the merge.
                # We still need to count this as part of the parent set.
 
-               echo "Fast forwarding to: $SHA1"
+               echo "Fast-forwarding to: $SHA1"
                git read-tree -u -m $head $SHA1 || exit
                MRC=$SHA1 MRT=$(git write-tree)
                continue
index 9c2c1b7202462370509a7bdb391982ae32564bd6..d067894bf45fd0a50513e196ea2a5e671d901681 100755 (executable)
 # been handled already by git read-tree, but that one doesn't
 # do any merges that might change the tree layout.
 
+USAGE='<orig blob> <our blob> <their blob> <path>'
+USAGE="$USAGE <orig mode> <our mode> <their mode>"
+LONG_USAGE="Usage: git merge-one-file $USAGE
+
+Blob ids and modes should be empty for missing files."
+
+if ! test "$#" -eq 7
+then
+       echo "$LONG_USAGE"
+       exit 1
+fi
+
 case "${1:-.}${2:-.}${3:-.}" in
 #
 # Deleted in both or deleted in one and unchanged in the other
index bfb01f7842e6192e0b3fbc0e3f2ab96269578289..f7c571e73cdf471148b606242066536361ac7c3d 100644 (file)
@@ -46,7 +46,7 @@ check_unchanged () {
 valid_tool () {
        case "$1" in
        kdiff3 | tkdiff | xxdiff | meld | opendiff | \
-       emerge | vimdiff | gvimdiff | ecmerge | diffuse | araxis)
+       emerge | vimdiff | gvimdiff | ecmerge | diffuse | araxis | p4merge)
                ;; # happy
        tortoisemerge)
                if ! merge_mode; then
@@ -130,6 +130,19 @@ run_merge_tool () {
                        "$merge_tool_path" "$LOCAL" "$REMOTE"
                fi
                ;;
+       p4merge)
+               if merge_mode; then
+                   touch "$BACKUP"
+                       if $base_present; then
+                               "$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" "$MERGED"
+                       else
+                               "$merge_tool_path" "$LOCAL" "$LOCAL" "$REMOTE" "$MERGED"
+                       fi
+                       check_unchanged
+               else
+                       "$merge_tool_path" "$LOCAL" "$REMOTE"
+               fi
+               ;;
        meld)
                if merge_mode; then
                        touch "$BACKUP"
@@ -323,7 +336,7 @@ guess_merge_tool () {
                else
                        tools="opendiff kdiff3 tkdiff xxdiff meld $tools"
                fi
-               tools="$tools gvimdiff diffuse ecmerge araxis"
+               tools="$tools gvimdiff diffuse ecmerge p4merge araxis"
        fi
        if echo "${VISUAL:-$EDITOR}" | grep emacs > /dev/null 2>&1; then
                # $EDITOR is emacs so add emerge as a candidate
index fc78592ae04283db2af633ec080f99c6404ceda7..bfeb4a0ff65fabaa49b212411ee2451cbf656f3d 100755 (executable)
@@ -16,7 +16,8 @@ cd_to_toplevel
 test -z "$(git ls-files -u)" ||
        die "You are in the middle of a conflicted merge."
 
-strategy_args= diffstat= no_commit= squash= no_ff= log_arg= verbosity=
+strategy_args= diffstat= no_commit= squash= no_ff= ff_only=
+log_arg= verbosity=
 curr_branch=$(git symbolic-ref -q HEAD)
 curr_branch_short=$(echo "$curr_branch" | sed "s|refs/heads/||")
 rebase=$(git config --bool branch.$curr_branch_short.rebase)
@@ -45,6 +46,8 @@ do
                no_ff=--ff ;;
        --no-ff)
                no_ff=--no-ff ;;
+       --ff-only)
+               ff_only=--ff-only ;;
        -s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\
                --strateg=*|--strategy=*|\
        -s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy)
@@ -171,7 +174,7 @@ then
        # First update the working tree to match $curr_head.
 
        echo >&2 "Warning: fetch updated the current branch head."
-       echo >&2 "Warning: fast forwarding your working tree from"
+       echo >&2 "Warning: fast-forwarding your working tree from"
        echo >&2 "Warning: commit $orig_head."
        git update-index -q --refresh
        git read-tree -u -m "$orig_head" "$curr_head" ||
@@ -215,5 +218,5 @@ merge_name=$(git fmt-merge-msg $log_arg <"$GIT_DIR/FETCH_HEAD") || exit
 test true = "$rebase" &&
        exec git-rebase $diffstat $strategy_args --onto $merge_head \
        ${oldremoteref:-$merge_head}
-exec git-merge $diffstat $no_commit $squash $no_ff $log_arg $strategy_args \
+exec git-merge $diffstat $no_commit $squash $no_ff $ff_only $log_arg $strategy_args \
        "$merge_name" HEAD $merge_head $verbosity
index 23ded48322bf795b06aa40e4684bc710c8232549..27daaa9ded9745b6747dc2995ea344ad038443a5 100755 (executable)
@@ -168,7 +168,7 @@ pick_one () {
                output git reset --hard $sha1
                test "a$1" = a-n && output git reset --soft $current_sha1
                sha1=$(git rev-parse --short $sha1)
-               output warn Fast forward to $sha1
+               output warn Fast-forward to $sha1
        else
                output git cherry-pick "$@"
        fi
@@ -248,9 +248,9 @@ pick_one_preserving_merges () {
        done
        case $fast_forward in
        t)
-               output warn "Fast forward to $sha1"
+               output warn "Fast-forward to $sha1"
                output git reset --hard $sha1 ||
-                       die "Cannot fast forward to $sha1"
+                       die "Cannot fast-forward to $sha1"
                ;;
        f)
                first_parent=$(expr "$new_parents" : ' \([^ ]*\)')
@@ -340,6 +340,14 @@ do_next () {
                pick_one $sha1 ||
                        die_with_patch $sha1 "Could not apply $sha1... $rest"
                ;;
+       reword|r)
+               comment_for_reflog reword
+
+               mark_action_done
+               pick_one $sha1 ||
+                       die_with_patch $sha1 "Could not apply $sha1... $rest"
+               git commit --amend
+               ;;
        edit|e)
                comment_for_reflog edit
 
@@ -408,7 +416,12 @@ do_next () {
                ;;
        *)
                warn "Unknown command: $command $sha1 $rest"
-               die_with_patch $sha1 "Please fix this in the file $TODO."
+               if git rev-parse --verify -q "$sha1" >/dev/null
+               then
+                       die_with_patch $sha1 "Please fix this in the file $TODO."
+               else
+                       die "Please fix this in the file $TODO."
+               fi
                ;;
        esac
        test -s "$TODO" && return
@@ -752,6 +765,7 @@ first and then run 'git rebase --continue' again."
 #
 # Commands:
 #  p, pick = use commit
+#  r, reword = use commit, but edit the commit message
 #  e, edit = use commit, but stop for amending
 #  s, squash = use commit, but meld into previous commit
 #
index 6ec155cf03c98f2e075f298039037d0e099311b1..6830e1627d67c59407885a3cfa44e83a802613bc 100755 (executable)
@@ -496,7 +496,7 @@ then
 fi
 
 # If the $onto is a proper descendant of the tip of the branch, then
-# we just fast forwarded.
+# we just fast-forwarded.
 if test "$mb" = "$branch"
 then
        say "Fast-forwarded $branch_name to $onto_name."
index f5ba4e7699936499021a8a955b198668b98a1696..a0279de687064c762a4ee24dfe2ed1922afab53a 100755 (executable)
@@ -835,7 +835,7 @@ sub send_message
            $gitversion = Git::version();
        }
 
-       my $cc = join(", ", unique_email_list(@cc));
+       my $cc = join(",\n\t", unique_email_list(@cc));
        my $ccline = "";
        if ($cc ne '') {
                $ccline = "\nCc: $cc";
@@ -976,7 +976,9 @@ X-Mailer: git-send-email $gitversion
                if ($smtp_server !~ m#^/#) {
                        print "Server: $smtp_server\n";
                        print "MAIL FROM:<$raw_from>\n";
-                       print "RCPT TO:".join(',',(map { "<$_>" } @recipients))."\n";
+                       foreach my $entry (@recipients) {
+                           print "RCPT TO:<$entry>\n";
+                       }
                } else {
                        print "Sendmail: $smtp_server ".join(' ',@sendmail_parameters)."\n";
                }
index 4febbbfa5d13b241e9bfcc479c6767a90bd12919..f796c2fe24f0eaec3de45bc5bf14f7dd2e29f4bd 100755 (executable)
@@ -205,8 +205,7 @@ have_stash () {
 
 list_stash () {
        have_stash || return 0
-       git log --no-color --pretty=oneline -g "$@" $ref_stash -- |
-       sed -n -e 's/^[.0-9a-f]* refs\///p'
+       git log --format="%gd: %gs" -g "$@" $ref_stash --
 }
 
 show_stash () {
@@ -383,11 +382,6 @@ test -n "$seen_non_option" || set "save" "$@"
 case "$1" in
 list)
        shift
-       if test $# = 0
-       then
-               set x -n 10
-               shift
-       fi
        list_stash "$@"
        ;;
 show)
index 0462e529d934750fb63a5a897f135d60ac674b5e..850d4235a003a9934681b319199e82da07a865dd 100755 (executable)
@@ -5,7 +5,7 @@
 # Copyright (c) 2007 Lars Hjemli
 
 dashless=$(basename "$0" | sed -e 's/-/ /')
-USAGE="[--quiet] add [-b branch] [--reference <repository>] [--] <repository> <path>
+USAGE="[--quiet] add [-b branch] [--reference <repository>] [--] <repository> [<path>]
    or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
    or: $dashless [--quiet] init [--] [<path>...]
    or: $dashless [--quiet] update [--init] [-N|--no-fetch] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
@@ -160,6 +160,11 @@ cmd_add()
        repo=$1
        path=$2
 
+       if test -z "$path"; then
+               path=$(echo "$repo" |
+                       sed -e 's|/$||' -e 's|:*/*\.git$||' -e 's|.*[/:]||g')
+       fi
+
        if test -z "$repo" -o -z "$path"; then
                usage
        fi
index eb4b75aff347670b1817fb1c2584cff11a08fad5..ab0a8dd0990ac030db046efdcdae74978a2d8c46 100755 (executable)
@@ -168,6 +168,9 @@ my %cmd = (
                             'Create a .gitignore per svn:ignore',
                             { 'revision|r=i' => \$_revision
                             } ],
+       'mkdirs' => [ \&cmd_mkdirs ,
+                     "recreate empty directories after a checkout",
+                     { 'revision|r=i' => \$_revision } ],
         'propget' => [ \&cmd_propget,
                       'Print the value of a property on a file or directory',
                       { 'revision|r=i' => \$_revision } ],
@@ -274,7 +277,7 @@ unless ($cmd && $cmd =~ /(?:clone|init|multi-init)$/) {
 
 my %opts = %{$cmd{$cmd}->[2]} if (defined $cmd);
 
-read_repo_config(\%opts);
+read_git_config(\%opts);
 if ($cmd && ($cmd eq 'log' || $cmd eq 'blame')) {
        Getopt::Long::Configure('pass_through');
 }
@@ -769,6 +772,7 @@ sub cmd_rebase {
                $_fetch_all ? $gs->fetch_all : $gs->fetch;
        }
        command_noisy(rebase_cmd(), $gs->refname);
+       $gs->mkemptydirs;
 }
 
 sub cmd_show_ignore {
@@ -830,6 +834,12 @@ sub cmd_create_ignore {
        });
 }
 
+sub cmd_mkdirs {
+       my ($url, $rev, $uuid, $gs) = working_head_info('HEAD');
+       $gs ||= Git::SVN->new;
+       $gs->mkemptydirs($_revision);
+}
+
 sub canonicalize_path {
        my ($path) = @_;
        my $dot_slash_added = 0;
@@ -1196,6 +1206,7 @@ sub post_fetch_checkout {
        command_noisy(qw/read-tree -m -u -v HEAD HEAD/);
        print STDERR "Checked out HEAD:\n  ",
                     $gs->full_url, " r", $gs->last_rev, "\n";
+       $gs->mkemptydirs($gs->last_rev);
 }
 
 sub complete_svn_url {
@@ -1390,8 +1401,7 @@ sub load_authors {
 }
 
 # convert GetOpt::Long specs for use by git-config
-sub read_repo_config {
-       return unless -d $ENV{GIT_DIR};
+sub read_git_config {
        my $opts = shift;
        my @config_only;
        foreach my $o (keys %$opts) {
@@ -1765,7 +1775,7 @@ sub read_all_remotes {
        my $use_svm_props = eval { command_oneline(qw/config --bool
            svn.useSvmProps/) };
        $use_svm_props = $use_svm_props eq 'true' if $use_svm_props;
-       my $svn_refspec = qr{\s*/?(.*?)\s*:\s*(.+?)\s*};
+       my $svn_refspec = qr{\s*(.*?)\s*:\s*(.+?)\s*};
        foreach (grep { s/^svn-remote\.// } command(qw/config -l/)) {
                if (m!^(.+)\.fetch=$svn_refspec$!) {
                        my ($remote, $local_ref, $remote_ref) = ($1, $2, $3);
@@ -1979,7 +1989,7 @@ sub find_ref {
        my ($ref_id) = @_;
        foreach (command(qw/config -l/)) {
                next unless m!^svn-remote\.(.+)\.fetch=
-                             \s*/?(.*?)\s*:\s*(.+?)\s*$!x;
+                             \s*(.*?)\s*:\s*(.+?)\s*$!x;
                my ($repo_id, $path, $ref) = ($1, $2, $3);
                if ($ref eq $ref_id) {
                        $path = '' if ($path =~ m#^\./?#);
@@ -2725,6 +2735,34 @@ sub do_fetch {
        $self->make_log_entry($rev, \@parents, $ed);
 }
 
+sub mkemptydirs {
+       my ($self, $r) = @_;
+       my %empty_dirs = ();
+
+       open my $fh, '<', "$self->{dir}/unhandled.log" or return;
+       binmode $fh or croak "binmode: $!";
+       while (<$fh>) {
+               if (defined $r && /^r(\d+)$/) {
+                       last if $1 > $r;
+               } elsif (/^  \+empty_dir: (.+)$/) {
+                       $empty_dirs{$1} = 1;
+               } elsif (/^  \-empty_dir: (.+)$/) {
+                       delete $empty_dirs{$1};
+               }
+       }
+       close $fh;
+       foreach my $d (sort keys %empty_dirs) {
+               $d = uri_decode($d);
+               next if -d $d;
+               if (-e _) {
+                       warn "$d exists but is not a directory\n";
+               } else {
+                       print "creating empty directory: $d\n";
+                       mkpath([$d]);
+               }
+       }
+}
+
 sub get_untracked {
        my ($self, $ed) = @_;
        my @out;
@@ -2878,14 +2916,160 @@ sub check_author {
        $author;
 }
 
+sub find_extra_svk_parents {
+       my ($self, $ed, $tickets, $parents) = @_;
+       # aha!  svk:merge property changed...
+       my @tickets = split "\n", $tickets;
+       my @known_parents;
+       for my $ticket ( @tickets ) {
+               my ($uuid, $path, $rev) = split /:/, $ticket;
+               if ( $uuid eq $self->ra_uuid ) {
+                       my $url = $self->rewrite_root || $self->{url};
+                       my $repos_root = $url;
+                       my $branch_from = $path;
+                       $branch_from =~ s{^/}{};
+                       my $gs = $self->other_gs($repos_root."/".$branch_from,
+                                                $url,
+                                                $branch_from,
+                                                $rev,
+                                                $self->{ref_id});
+                       if ( my $commit = $gs->rev_map_get($rev, $uuid) ) {
+                               # wahey!  we found it, but it might be
+                               # an old one (!)
+                               push @known_parents, $commit;
+                       }
+               }
+       }
+       for my $parent ( @known_parents ) {
+               my @cmd = ('rev-list', $parent, map { "^$_" } @$parents );
+               my ($msg_fh, $ctx) = command_output_pipe(@cmd);
+               my $new;
+               while ( <$msg_fh> ) {
+                       $new=1;last;
+               }
+               command_close_pipe($msg_fh, $ctx);
+               if ( $new ) {
+                       print STDERR
+                           "Found merge parent (svk:merge ticket): $parent\n";
+                       push @$parents, $parent;
+               }
+       }
+}
+
+# note: this function should only be called if the various dirprops
+# have actually changed
+sub find_extra_svn_parents {
+       my ($self, $ed, $mergeinfo, $parents) = @_;
+       # aha!  svk:merge property changed...
+
+       # We first search for merged tips which are not in our
+       # history.  Then, we figure out which git revisions are in
+       # that tip, but not this revision.  If all of those revisions
+       # are now marked as merge, we can add the tip as a parent.
+       my @merges = split "\n", $mergeinfo;
+       my @merge_tips;
+       my @merged_commit_ranges;
+       my $url = $self->rewrite_root || $self->{url};
+       for my $merge ( @merges ) {
+               my ($source, $revs) = split ":", $merge;
+               my $path = $source;
+               $path =~ s{^/}{};
+               my $gs = Git::SVN->find_by_url($url.$source, $url, $path);
+               if ( !$gs ) {
+                       warn "Couldn't find revmap for $url$source\n";
+                       next;
+               }
+               my @ranges = split ",", $revs;
+               my ($tip, $tip_commit);
+               # find the tip
+               for my $range ( @ranges ) {
+                       my ($bottom, $top) = split "-", $range;
+                       $top ||= $bottom;
+                       my $bottom_commit =
+                               $gs->rev_map_get($bottom, $self->ra_uuid) ||
+                               $gs->rev_map_get($bottom+1, $self->ra_uuid);
+                       my $top_commit;
+                       for (; !$top_commit && $top >= $bottom; --$top) {
+                               $top_commit =
+                                       $gs->rev_map_get($top, $self->ra_uuid);
+                       }
+
+                       unless ($top_commit and $bottom_commit) {
+                               warn "W:unknown path/rev in svn:mergeinfo "
+                                       ."dirprop: $source:$range\n";
+                               next;
+                       }
+
+                       push @merged_commit_ranges,
+                               "$bottom_commit..$top_commit";
+
+                       if ( !defined $tip or $top > $tip ) {
+                               $tip = $top;
+                               $tip_commit = $top_commit;
+                       }
+               }
+               unless (!$tip_commit or
+                               grep { $_ eq $tip_commit } @$parents ) {
+                       push @merge_tips, $tip_commit;
+               } else {
+                       push @merge_tips, undef;
+               }
+       }
+       for my $merge_tip ( @merge_tips ) {
+               my $spec = shift @merges;
+               next unless $merge_tip;
+               my @cmd = ('rev-list', "-1", $merge_tip,
+                          "--not", @$parents );
+               my ($msg_fh, $ctx) = command_output_pipe(@cmd);
+               my $new;
+               while ( <$msg_fh> ) {
+                       $new=1;last;
+               }
+               command_close_pipe($msg_fh, $ctx);
+               if ( $new ) {
+                       push @cmd, @merged_commit_ranges;
+                       my ($msg_fh, $ctx) = command_output_pipe(@cmd);
+                       my $unmerged;
+                       while ( <$msg_fh> ) {
+                               $unmerged=1;last;
+                       }
+                       command_close_pipe($msg_fh, $ctx);
+                       if ( $unmerged ) {
+                               warn "W:svn cherry-pick ignored ($spec)\n";
+                       } else {
+                               warn
+                                 "Found merge parent (svn:mergeinfo prop): ",
+                                 $merge_tip, "\n";
+                               push @$parents, $merge_tip;
+                       }
+               }
+       }
+}
+
 sub make_log_entry {
        my ($self, $rev, $parents, $ed) = @_;
        my $untracked = $self->get_untracked($ed);
 
+       my @parents = @$parents;
+       my $ps = $ed->{path_strip} || "";
+       for my $path ( grep { m/$ps/ } %{$ed->{dir_prop}} ) {
+               my $props = $ed->{dir_prop}{$path};
+               if ( $props->{"svk:merge"} ) {
+                       $self->find_extra_svk_parents
+                               ($ed, $props->{"svk:merge"}, \@parents);
+               }
+               if ( $props->{"svn:mergeinfo"} ) {
+                       $self->find_extra_svn_parents
+                               ($ed,
+                                $props->{"svn:mergeinfo"},
+                                \@parents);
+               }
+       }
+
        open my $un, '>>', "$self->{dir}/unhandled.log" or croak $!;
        print $un "r$rev\n" or croak $!;
        print $un $_, "\n" foreach @$untracked;
-       my %log_entry = ( parents => $parents || [], revision => $rev,
+       my %log_entry = ( parents => \@parents, revision => $rev,
                          log => '');
 
        my $headrev;
@@ -3411,6 +3595,12 @@ sub uri_encode {
        $f
 }
 
+sub uri_decode {
+       my ($f) = @_;
+       $f =~ s#%([0-9a-fA-F]{2})#chr(hex($1))#eg;
+       $f
+}
+
 sub remove_username {
        $_[0] =~ s{^([^:]*://)[^@]+@}{$1};
 }
diff --git a/git.c b/git.c
index 9883009b5d9f29d4f53187947a6d8664da4d80f4..743ee57100ac49aca8d90892b1abec5f18eb18c1 100644 (file)
--- a/git.c
+++ b/git.c
@@ -6,7 +6,7 @@
 
 const char git_usage_string[] =
        "git [--version] [--exec-path[=GIT_EXEC_PATH]] [--html-path]\n"
-       "           [-p|--paginate|--no-pager]\n"
+       "           [-p|--paginate|--no-pager] [--no-replace-objects]\n"
        "           [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE]\n"
        "           [--help] COMMAND [ARGS]";
 
@@ -87,6 +87,8 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
                        use_pager = 0;
                        if (envchanged)
                                *envchanged = 1;
+               } else if (!strcmp(cmd, "--no-replace-objects")) {
+                       read_replace_refs = 0;
                } else if (!strcmp(cmd, "--git-dir")) {
                        if (*argc < 2) {
                                fprintf(stderr, "No directory given for --git-dir.\n" );
@@ -227,21 +229,24 @@ struct cmd_struct {
 
 static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
 {
-       int status;
+       int status, help;
        struct stat st;
        const char *prefix;
 
        prefix = NULL;
-       if (p->option & RUN_SETUP)
-               prefix = setup_git_directory();
-
-       if (use_pager == -1 && p->option & RUN_SETUP)
-               use_pager = check_pager_config(p->cmd);
-       if (use_pager == -1 && p->option & USE_PAGER)
-               use_pager = 1;
+       help = argc == 2 && !strcmp(argv[1], "-h");
+       if (!help) {
+               if (p->option & RUN_SETUP)
+                       prefix = setup_git_directory();
+
+               if (use_pager == -1 && p->option & RUN_SETUP)
+                       use_pager = check_pager_config(p->cmd);
+               if (use_pager == -1 && p->option & USE_PAGER)
+                       use_pager = 1;
+       }
        commit_pager_choice();
 
-       if (p->option & NEED_WORK_TREE)
+       if (!help && p->option & NEED_WORK_TREE)
                setup_work_tree();
 
        trace_argv_printf(argv, "trace: built-in: git");
@@ -302,7 +307,6 @@ static void handle_internal_command(int argc, const char **argv)
                { "fast-export", cmd_fast_export, RUN_SETUP },
                { "fetch", cmd_fetch, RUN_SETUP },
                { "fetch-pack", cmd_fetch_pack, RUN_SETUP },
-               { "fetch--tool", cmd_fetch__tool, RUN_SETUP },
                { "fmt-merge-msg", cmd_fmt_merge_msg, RUN_SETUP },
                { "for-each-ref", cmd_for_each_ref, RUN_SETUP },
                { "format-patch", cmd_format_patch, RUN_SETUP },
index 8f68fe30914b2cf4f5337a303202b39eec3cdbd7..cb3f0baf05e8a48484132bb8936b4f46f22493ed 100644 (file)
@@ -32,6 +32,10 @@ img.avatar {
        vertical-align: middle;
 }
 
+a.list img.avatar {
+       border-style: none;
+}
+
 div.page_header {
        height: 25px;
        padding: 8px;
@@ -341,6 +345,12 @@ td.mode {
        font-family: monospace;
 }
 
+/* format of (optional) objects size in 'tree' view */
+td.size {
+       font-family: monospace;
+       text-align: right;
+}
+
 /* styling of diffs (patchsets): commitdiff and blobdiff views */
 div.diff.header,
 div.diff.extended_header {
index 24b219310a73f6ff8412b9236e7e5a95a7860e2f..681e635090f81e2cf8df7cd10494451c22f993e4 100755 (executable)
@@ -297,6 +297,19 @@ our %feature = (
                'override' => 0,
                'default' => [1]},
 
+       # Enable showing size of blobs in a 'tree' view, in a separate
+       # column, similar to what 'ls -l' does.  This cost a bit of IO.
+
+       # To disable system wide have in $GITWEB_CONFIG
+       # $feature{'show-sizes'}{'default'} = [0];
+       # To have project specific config enable override in $GITWEB_CONFIG
+       # $feature{'show-sizes'}{'override'} = 1;
+       # and in project config gitweb.showsizes = 0|1;
+       'show-sizes' => {
+               'sub' => sub { feature_bool('showsizes', @_) },
+               'override' => 0,
+               'default' => [1]},
+
        # Make gitweb use an alternative format of the URLs which can be
        # more readable and natural-looking: project name is embedded
        # directly in the path and the query string contains other
@@ -1083,8 +1096,7 @@ sub to_utf8 {
 # correct, but quoted slashes look too horrible in bookmarks
 sub esc_param {
        my $str = shift;
-       $str =~ s/([^A-Za-z0-9\-_.~()\/:@])/sprintf("%%%02X", ord($1))/eg;
-       $str =~ s/\+/%2B/g;
+       $str =~ s/([^A-Za-z0-9\-_.~()\/:@ ]+)/CGI::escape($1)/eg;
        $str =~ s/ /\+/g;
        return $str;
 }
@@ -1595,6 +1607,29 @@ sub git_get_avatar {
        }
 }
 
+sub format_search_author {
+       my ($author, $searchtype, $displaytext) = @_;
+       my $have_search = gitweb_check_feature('search');
+
+       if ($have_search) {
+               my $performed = "";
+               if ($searchtype eq 'author') {
+                       $performed = "authored";
+               } elsif ($searchtype eq 'committer') {
+                       $performed = "committed";
+               }
+
+               return $cgi->a({-href => href(action=>"search", hash=>$hash,
+                               searchtext=>$author,
+                               searchtype=>$searchtype), class=>"list",
+                               title=>"Search for commits $performed by $author"},
+                               $displaytext);
+
+       } else {
+               return $displaytext;
+       }
+}
+
 # format the author name of the given commit with the given tag
 # the author name is chopped and escaped according to the other
 # optional parameters (see chop_str).
@@ -1603,8 +1638,10 @@ sub format_author_html {
        my $co = shift;
        my $author = chop_and_escape_str($co->{'author_name'}, @_);
        return "<$tag class=\"author\">" .
-              git_get_avatar($co->{'author_email'}, -pad_after => 1) .
-              $author . "</$tag>";
+              format_search_author($co->{'author_name'}, "author",
+                      git_get_avatar($co->{'author_email'}, -pad_after => 1) .
+                      $author) .
+              "</$tag>";
 }
 
 # format git diff header line, i.e. "diff --(git|combined|cc) ..."
@@ -2764,16 +2801,31 @@ sub parse_ls_tree_line {
        my %opts = @_;
        my %res;
 
-       #'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa  panic.c'
-       $line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.+)$/s;
+       if ($opts{'-l'}) {
+               #'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa   16717  panic.c'
+               $line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40}) +(-|[0-9]+)\t(.+)$/s;
 
-       $res{'mode'} = $1;
-       $res{'type'} = $2;
-       $res{'hash'} = $3;
-       if ($opts{'-z'}) {
-               $res{'name'} = $4;
+               $res{'mode'} = $1;
+               $res{'type'} = $2;
+               $res{'hash'} = $3;
+               $res{'size'} = $4;
+               if ($opts{'-z'}) {
+                       $res{'name'} = $5;
+               } else {
+                       $res{'name'} = unquote($5);
+               }
        } else {
-               $res{'name'} = unquote($4);
+               #'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa  panic.c'
+               $line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.+)$/s;
+
+               $res{'mode'} = $1;
+               $res{'type'} = $2;
+               $res{'hash'} = $3;
+               if ($opts{'-z'}) {
+                       $res{'name'} = $4;
+               } else {
+                       $res{'name'} = unquote($4);
+               }
        }
 
        return wantarray ? %res : \%res;
@@ -3311,22 +3363,18 @@ sub git_print_page_nav {
 }
 
 sub format_paging_nav {
-       my ($action, $hash, $head, $page, $has_next_link) = @_;
+       my ($action, $page, $has_next_link) = @_;
        my $paging_nav;
 
 
-       if ($hash ne $head || $page) {
-               $paging_nav .= $cgi->a({-href => href(action=>$action)}, "HEAD");
-       } else {
-               $paging_nav .= "HEAD";
-       }
-
        if ($page > 0) {
-               $paging_nav .= " &sdot; " .
+               $paging_nav .=
+                       $cgi->a({-href => href(-replay=>1, page=>undef)}, "first") .
+                       " &sdot; " .
                        $cgi->a({-href => href(-replay=>1, page=>$page-1),
                                 -accesskey => "p", -title => "Alt-p"}, "prev");
        } else {
-               $paging_nav .= " &sdot; prev";
+               $paging_nav .= "first &sdot; prev";
        }
 
        if ($has_next_link) {
@@ -3373,10 +3421,11 @@ sub git_print_authorship {
        my $co = shift;
        my %opts = @_;
        my $tag = $opts{-tag} || 'div';
+       my $author = $co->{'author_name'};
 
        my %ad = parse_date($co->{'author_epoch'}, $co->{'author_tz'});
        print "<$tag class=\"author_date\">" .
-             esc_html($co->{'author_name'}) .
+             format_search_author($author, "author", esc_html($author)) .
              " [$ad{'rfc2822'}";
        print_local_time(%ad) if ($opts{-localtime});
        print "]" . git_get_avatar($co->{'author_email'}, -pad_before => 1)
@@ -3395,8 +3444,12 @@ sub git_print_authorship_rows {
        @people = ('author', 'committer') unless @people;
        foreach my $who (@people) {
                my %wd = parse_date($co->{"${who}_epoch"}, $co->{"${who}_tz"});
-               print "<tr><td>$who</td><td>" . esc_html($co->{$who}) . "</td>" .
-                     "<td rowspan=\"2\">" .
+               print "<tr><td>$who</td><td>" .
+                     format_search_author($co->{"${who}_name"}, $who,
+                              esc_html($co->{"${who}_name"})) . " " .
+                     format_search_author($co->{"${who}_email"}, $who,
+                              esc_html("<" . $co->{"${who}_email"} . ">")) .
+                     "</td><td rowspan=\"2\">" .
                      git_get_avatar($co->{"${who}_email"}, -size => 'double') .
                      "</td></tr>\n" .
                      "<tr>" .
@@ -3564,6 +3617,9 @@ sub git_print_tree_entry {
        # and link is the action links of the entry.
 
        print "<td class=\"mode\">" . mode_str($t->{'mode'}) . "</td>\n";
+       if (exists $t->{'size'}) {
+               print "<td class=\"size\">$t->{'size'}</td>\n";
+       }
        if ($t->{'type'} eq "blob") {
                print "<td class=\"list\">" .
                        $cgi->a({-href => href(action=>"blob", hash=>$t->{'hash'},
@@ -3609,12 +3665,14 @@ sub git_print_tree_entry {
        } elsif ($t->{'type'} eq "tree") {
                print "<td class=\"list\">";
                print $cgi->a({-href => href(action=>"tree", hash=>$t->{'hash'},
-                                            file_name=>"$basedir$t->{'name'}", %base_key)},
+                                            file_name=>"$basedir$t->{'name'}",
+                                            %base_key)},
                              esc_path($t->{'name'}));
                print "</td>\n";
                print "<td class=\"link\">";
                print $cgi->a({-href => href(action=>"tree", hash=>$t->{'hash'},
-                                            file_name=>"$basedir$t->{'name'}", %base_key)},
+                                            file_name=>"$basedir$t->{'name'}",
+                                            %base_key)},
                              "tree");
                if (defined $hash_base) {
                        print " | " .
@@ -4299,6 +4357,46 @@ sub git_project_list_body {
        print "</table>\n";
 }
 
+sub git_log_body {
+       # uses global variable $project
+       my ($commitlist, $from, $to, $refs, $extra) = @_;
+
+       $from = 0 unless defined $from;
+       $to = $#{$commitlist} if (!defined $to || $#{$commitlist} < $to);
+
+       for (my $i = 0; $i <= $to; $i++) {
+               my %co = %{$commitlist->[$i]};
+               next if !%co;
+               my $commit = $co{'id'};
+               my $ref = format_ref_marker($refs, $commit);
+               my %ad = parse_date($co{'author_epoch'});
+               git_print_header_div('commit',
+                              "<span class=\"age\">$co{'age_string'}</span>" .
+                              esc_html($co{'title'}) . $ref,
+                              $commit);
+               print "<div class=\"title_text\">\n" .
+                     "<div class=\"log_link\">\n" .
+                     $cgi->a({-href => href(action=>"commit", hash=>$commit)}, "commit") .
+                     " | " .
+                     $cgi->a({-href => href(action=>"commitdiff", hash=>$commit)}, "commitdiff") .
+                     " | " .
+                     $cgi->a({-href => href(action=>"tree", hash=>$commit, hash_base=>$commit)}, "tree") .
+                     "<br/>\n" .
+                     "</div>\n";
+                     git_print_authorship(\%co, -tag => 'span');
+                     print "<br/>\n</div>\n";
+
+               print "<div class=\"log_body\">\n";
+               git_print_log($co{'comment'}, -final_empty_line=> 1);
+               print "</div>\n";
+       }
+       if ($extra) {
+               print "<div class=\"page_nav\">\n";
+               print "$extra\n";
+               print "</div>\n";
+       }
+}
+
 sub git_shortlog_body {
        # uses global variable $project
        my ($commitlist, $from, $to, $refs, $extra) = @_;
@@ -4345,7 +4443,8 @@ sub git_shortlog_body {
 
 sub git_history_body {
        # Warning: assumes constant type (blob or tree) during history
-       my ($commitlist, $from, $to, $refs, $hash_base, $ftype, $extra) = @_;
+       my ($commitlist, $from, $to, $refs, $extra,
+           $file_name, $file_hash, $ftype) = @_;
 
        $from = 0 unless defined $from;
        $to = $#{$commitlist} unless (defined $to && $to <= $#{$commitlist});
@@ -4379,7 +4478,7 @@ sub git_history_body {
                      $cgi->a({-href => href(action=>"commitdiff", hash=>$commit)}, "commitdiff");
 
                if ($ftype eq 'blob') {
-                       my $blob_current = git_get_hash_by_path($hash_base, $file_name);
+                       my $blob_current = $file_hash;
                        my $blob_parent  = git_get_hash_by_path($commit, $file_name);
                        if (defined $blob_current && defined $blob_parent &&
                                        $blob_current ne $blob_parent) {
@@ -5065,7 +5164,8 @@ sub git_blob {
                        chomp $line;
                        $nr++;
                        $line = untabify($line);
-                       printf "<div class=\"pre\"><a id=\"l%i\" href=\"#l%i\" class=\"linenr\">%4i</a> %s</div>\n",
+                       printf "<div class=\"pre\"><a id=\"l%i\" href=\"" . href(-replay => 1)
+                               . "#l%i\" class=\"linenr\">%4i</a> %s</div>\n",
                               $nr, $nr, $nr, esc_html($line, -nbsp=>1);
                }
        }
@@ -5088,10 +5188,14 @@ sub git_tree {
        }
        die_error(404, "No such tree") unless defined($hash);
 
+       my $show_sizes = gitweb_check_feature('show-sizes');
+       my $have_blame = gitweb_check_feature('blame');
+
        my @entries = ();
        {
                local $/ = "\0";
-               open my $fd, "-|", git_cmd(), "ls-tree", '-z', $hash
+               open my $fd, "-|", git_cmd(), "ls-tree", '-z',
+                       ($show_sizes ? '-l' : ()), @extra_options, $hash
                        or die_error(500, "Open git-ls-tree failed");
                @entries = map { chomp; $_ } <$fd>;
                close $fd
@@ -5102,7 +5206,6 @@ sub git_tree {
        my $ref = format_ref_marker($refs, $hash_base);
        git_header_html();
        my $basedir = '';
-       my $have_blame = gitweb_check_feature('blame');
        if (defined $hash_base && (my %co = parse_commit($hash_base))) {
                my @views_nav = ();
                if (defined $file_name) {
@@ -5118,7 +5221,8 @@ sub git_tree {
                        # FIXME: Should be available when we have no hash base as well.
                        push @views_nav, $snapshot_links;
                }
-               git_print_page_nav('tree','', $hash_base, undef, undef, join(' | ', @views_nav));
+               git_print_page_nav('tree','', $hash_base, undef, undef,
+                                  join(' | ', @views_nav));
                git_print_header_div('commit', esc_html($co{'title'}) . $ref, $hash_base);
        } else {
                undef $hash_base;
@@ -5151,8 +5255,10 @@ sub git_tree {
                undef $up unless $up;
                # based on git_print_tree_entry
                print '<td class="mode">' . mode_str('040000') . "</td>\n";
+               print '<td class="size">&nbsp;</td>'."\n" if $show_sizes;
                print '<td class="list">';
-               print $cgi->a({-href => href(action=>"tree", hash_base=>$hash_base,
+               print $cgi->a({-href => href(action=>"tree",
+                                            hash_base=>$hash_base,
                                             file_name=>$up)},
                              "..");
                print "</td>\n";
@@ -5161,7 +5267,7 @@ sub git_tree {
                print "</tr>\n";
        }
        foreach my $line (@entries) {
-               my %t = parse_ls_tree_line($line, -z => 1);
+               my %t = parse_ls_tree_line($line, -z => 1, -l => $show_sizes);
 
                if ($alternate) {
                        print "<tr class=\"dark\">\n";
@@ -5228,22 +5334,57 @@ sub git_snapshot {
        close $fd;
 }
 
-sub git_log {
+sub git_log_generic {
+       my ($fmt_name, $body_subr, $base, $parent, $file_name, $file_hash) = @_;
+
        my $head = git_get_head_hash($project);
-       if (!defined $hash) {
-               $hash = $head;
+       if (!defined $base) {
+               $base = $head;
        }
        if (!defined $page) {
                $page = 0;
        }
        my $refs = git_get_references();
 
-       my @commitlist = parse_commits($hash, 101, (100 * $page));
+       my $commit_hash = $base;
+       if (defined $parent) {
+               $commit_hash = "$parent..$base";
+       }
+       my @commitlist =
+               parse_commits($commit_hash, 101, (100 * $page),
+                             defined $file_name ? ($file_name, "--full-history") : ());
 
-       my $paging_nav = format_paging_nav('log', $hash, $head, $page, $#commitlist >= 100);
+       my $ftype;
+       if (!defined $file_hash && defined $file_name) {
+               # some commits could have deleted file in question,
+               # and not have it in tree, but one of them has to have it
+               for (my $i = 0; $i < @commitlist; $i++) {
+                       $file_hash = git_get_hash_by_path($commitlist[$i]{'id'}, $file_name);
+                       last if defined $file_hash;
+               }
+       }
+       if (defined $file_hash) {
+               $ftype = git_get_type($file_hash);
+       }
+       if (defined $file_name && !defined $ftype) {
+               die_error(500, "Unknown type of object");
+       }
+       my %co;
+       if (defined $file_name) {
+               %co = parse_commit($base)
+                       or die_error(404, "Unknown commit object");
+       }
 
-       my ($patch_max) = gitweb_get_feature('patches');
-       if ($patch_max) {
+
+       my $paging_nav = format_paging_nav($fmt_name, $page, $#commitlist >= 100);
+       my $next_link = '';
+       if ($#commitlist >= 100) {
+               $next_link =
+                       $cgi->a({-href => href(-replay=>1, page=>$page+1),
+                                -accesskey => "n", -title => "Alt-n"}, "next");
+       }
+       my $patch_max = gitweb_get_feature('patches');
+       if ($patch_max && !defined $file_name) {
                if ($patch_max < 0 || @commitlist <= $patch_max) {
                        $paging_nav .= " &sdot; " .
                                $cgi->a({-href => href(action=>"patches", -replay=>1)},
@@ -5252,50 +5393,26 @@ sub git_log {
        }
 
        git_header_html();
-       git_print_page_nav('log','', $hash,undef,undef, $paging_nav);
-
-       if (!@commitlist) {
-               my %co = parse_commit($hash);
-
-               git_print_header_div('summary', $project);
-               print "<div class=\"page_body\"> Last change $co{'age_string'}.<br/><br/></div>\n";
+       git_print_page_nav($fmt_name,'', $hash,$hash,$hash, $paging_nav);
+       if (defined $file_name) {
+               git_print_header_div('commit', esc_html($co{'title'}), $base);
+       } else {
+               git_print_header_div('summary', $project)
        }
-       my $to = ($#commitlist >= 99) ? (99) : ($#commitlist);
-       for (my $i = 0; $i <= $to; $i++) {
-               my %co = %{$commitlist[$i]};
-               next if !%co;
-               my $commit = $co{'id'};
-               my $ref = format_ref_marker($refs, $commit);
-               my %ad = parse_date($co{'author_epoch'});
-               git_print_header_div('commit',
-                              "<span class=\"age\">$co{'age_string'}</span>" .
-                              esc_html($co{'title'}) . $ref,
-                              $commit);
-               print "<div class=\"title_text\">\n" .
-                     "<div class=\"log_link\">\n" .
-                     $cgi->a({-href => href(action=>"commit", hash=>$commit)}, "commit") .
-                     " | " .
-                     $cgi->a({-href => href(action=>"commitdiff", hash=>$commit)}, "commitdiff") .
-                     " | " .
-                     $cgi->a({-href => href(action=>"tree", hash=>$commit, hash_base=>$commit)}, "tree") .
-                     "<br/>\n" .
-                     "</div>\n";
-                     git_print_authorship(\%co, -tag => 'span');
-                     print "<br/>\n</div>\n";
+       git_print_page_path($file_name, $ftype, $hash_base)
+               if (defined $file_name);
+
+       $body_subr->(\@commitlist, 0, 99, $refs, $next_link,
+                    $file_name, $file_hash, $ftype);
 
-               print "<div class=\"log_body\">\n";
-               git_print_log($co{'comment'}, -final_empty_line=> 1);
-               print "</div>\n";
-       }
-       if ($#commitlist >= 100) {
-               print "<div class=\"page_nav\">\n";
-               print $cgi->a({-href => href(-replay=>1, page=>$page+1),
-                              -accesskey => "n", -title => "Alt-n"}, "next");
-               print "</div>\n";
-       }
        git_footer_html();
 }
 
+sub git_log {
+       git_log_generic('log', \&git_log_body,
+                       $hash, $hash_parent);
+}
+
 sub git_commit {
        $hash ||= $hash_base || "HEAD";
        my %co = parse_commit($hash)
@@ -5328,7 +5445,7 @@ sub git_commit {
                        } @$parents ) .
                        ')';
        }
-       if (gitweb_check_feature('patches')) {
+       if (gitweb_check_feature('patches') && @$parents <= 1) {
                $formats_nav .= " | " .
                        $cgi->a({-href => href(action=>"patch", -replay=>1)},
                                "patch");
@@ -5616,7 +5733,7 @@ sub git_commitdiff {
                $formats_nav =
                        $cgi->a({-href => href(action=>"commitdiff_plain", -replay=>1)},
                                "raw");
-               if ($patch_max) {
+               if ($patch_max && @{$co{'parents'}} <= 1) {
                        $formats_nav .= " | " .
                                $cgi->a({-href => href(action=>"patch", -replay=>1)},
                                        "patch");
@@ -5824,7 +5941,7 @@ sub git_commitdiff_plain {
 
 # format-patch-style patches
 sub git_patch {
-       git_commitdiff(-format => 'patch', -single=> 1);
+       git_commitdiff(-format => 'patch', -single => 1);
 }
 
 sub git_patches {
@@ -5832,70 +5949,9 @@ sub git_patches {
 }
 
 sub git_history {
-       if (!defined $hash_base) {
-               $hash_base = git_get_head_hash($project);
-       }
-       if (!defined $page) {
-               $page = 0;
-       }
-       my $ftype;
-       my %co = parse_commit($hash_base)
-           or die_error(404, "Unknown commit object");
-
-       my $refs = git_get_references();
-       my $limit = sprintf("--max-count=%i", (100 * ($page+1)));
-
-       my @commitlist = parse_commits($hash_base, 101, (100 * $page),
-                                      $file_name, "--full-history")
-           or die_error(404, "No such file or directory on given branch");
-
-       if (!defined $hash && defined $file_name) {
-               # some commits could have deleted file in question,
-               # and not have it in tree, but one of them has to have it
-               for (my $i = 0; $i <= @commitlist; $i++) {
-                       $hash = git_get_hash_by_path($commitlist[$i]{'id'}, $file_name);
-                       last if defined $hash;
-               }
-       }
-       if (defined $hash) {
-               $ftype = git_get_type($hash);
-       }
-       if (!defined $ftype) {
-               die_error(500, "Unknown type of object");
-       }
-
-       my $paging_nav = '';
-       if ($page > 0) {
-               $paging_nav .=
-                       $cgi->a({-href => href(action=>"history", hash=>$hash, hash_base=>$hash_base,
-                                              file_name=>$file_name)},
-                               "first");
-               $paging_nav .= " &sdot; " .
-                       $cgi->a({-href => href(-replay=>1, page=>$page-1),
-                                -accesskey => "p", -title => "Alt-p"}, "prev");
-       } else {
-               $paging_nav .= "first";
-               $paging_nav .= " &sdot; prev";
-       }
-       my $next_link = '';
-       if ($#commitlist >= 100) {
-               $next_link =
-                       $cgi->a({-href => href(-replay=>1, page=>$page+1),
-                                -accesskey => "n", -title => "Alt-n"}, "next");
-               $paging_nav .= " &sdot; $next_link";
-       } else {
-               $paging_nav .= " &sdot; next";
-       }
-
-       git_header_html();
-       git_print_page_nav('history','', $hash_base,$co{'tree'},$hash_base, $paging_nav);
-       git_print_header_div('commit', esc_html($co{'title'}), $hash_base);
-       git_print_page_path($file_name, $ftype, $hash_base);
-
-       git_history_body(\@commitlist, 0, 99,
-                        $refs, $hash_base, $ftype, $next_link);
-
-       git_footer_html();
+       git_log_generic('history', \&git_history_body,
+                       $hash_base, $hash_parent_base,
+                       $file_name, $hash);
 }
 
 sub git_search {
@@ -6159,44 +6215,8 @@ EOT
 }
 
 sub git_shortlog {
-       my $head = git_get_head_hash($project);
-       if (!defined $hash) {
-               $hash = $head;
-       }
-       if (!defined $page) {
-               $page = 0;
-       }
-       my $refs = git_get_references();
-
-       my $commit_hash = $hash;
-       if (defined $hash_parent) {
-               $commit_hash = "$hash_parent..$hash";
-       }
-       my @commitlist = parse_commits($commit_hash, 101, (100 * $page));
-
-       my $paging_nav = format_paging_nav('shortlog', $hash, $head, $page, $#commitlist >= 100);
-       my $next_link = '';
-       if ($#commitlist >= 100) {
-               $next_link =
-                       $cgi->a({-href => href(-replay=>1, page=>$page+1),
-                                -accesskey => "n", -title => "Alt-n"}, "next");
-       }
-       my $patch_max = gitweb_check_feature('patches');
-       if ($patch_max) {
-               if ($patch_max < 0 || @commitlist <= $patch_max) {
-                       $paging_nav .= " &sdot; " .
-                               $cgi->a({-href => href(action=>"patches", -replay=>1)},
-                                       "patches");
-               }
-       }
-
-       git_header_html();
-       git_print_page_nav('shortlog','', $hash,$hash,$hash, $paging_nav);
-       git_print_header_div('summary', $project);
-
-       git_shortlog_body(\@commitlist, 0, 99, $refs, $next_link);
-
-       git_footer_html();
+       git_log_generic('shortlog', \&git_shortlog_body,
+                       $hash, $hash_parent);
 }
 
 ## ......................................................................
index e8f44babd9d3a1cd86eba659b054aed6ac2c792a..ffd0ad7e295d7341776bb7b6407602cdb2997ef3 100644 (file)
@@ -1,6 +1,10 @@
 #include "cache.h"
+#include "exec_cmd.h"
 #include "walker.h"
 
+static const char http_fetch_usage[] = "git http-fetch "
+"[-c] [-t] [-a] [-v] [--recover] [-w ref] [--stdin] commit-id url";
+
 int main(int argc, const char **argv)
 {
        const char *prefix;
@@ -19,9 +23,7 @@ int main(int argc, const char **argv)
        int get_verbosely = 0;
        int get_recover = 0;
 
-       prefix = setup_git_directory();
-
-       git_config(git_default_config, NULL);
+       git_extract_argv0_path(argv[0]);
 
        while (arg < argc && argv[arg][0] == '-') {
                if (argv[arg][1] == 't') {
@@ -37,6 +39,8 @@ int main(int argc, const char **argv)
                } else if (argv[arg][1] == 'w') {
                        write_ref = &argv[arg + 1];
                        arg++;
+               } else if (argv[arg][1] == 'h') {
+                       usage(http_fetch_usage);
                } else if (!strcmp(argv[arg], "--recover")) {
                        get_recover = 1;
                } else if (!strcmp(argv[arg], "--stdin")) {
@@ -44,10 +48,8 @@ int main(int argc, const char **argv)
                }
                arg++;
        }
-       if (argc < arg + 2 - commits_on_stdin) {
-               usage("git http-fetch [-c] [-t] [-a] [-v] [--recover] [-w ref] [--stdin] commit-id url");
-               return 1;
-       }
+       if (argc != arg + 2 - commits_on_stdin)
+               usage(http_fetch_usage);
        if (commits_on_stdin) {
                commits = walker_targets_stdin(&commit_id, &write_ref);
        } else {
@@ -55,6 +57,11 @@ int main(int argc, const char **argv)
                commits = 1;
        }
        url = argv[arg];
+
+       prefix = setup_git_directory();
+
+       git_config(git_default_config, NULL);
+
        if (url && url[strlen(url)-1] != '/') {
                rewritten_url = xmalloc(strlen(url)+2);
                strcpy(rewritten_url, url);
index 00e83dcec1d973b069d4c75105aed96634b00994..ad1a6c90967b36365563de210ec2d066ae9d979a 100644 (file)
@@ -1792,8 +1792,6 @@ int main(int argc, char **argv)
 
        git_extract_argv0_path(argv[0]);
 
-       setup_git_directory();
-
        repo = xcalloc(sizeof(*repo), 1);
 
        argv++;
@@ -1827,6 +1825,8 @@ int main(int argc, char **argv)
                                force_delete = 1;
                                continue;
                        }
+                       if (!strcmp(arg, "-h"))
+                               usage(http_push_usage);
                }
                if (!repo->url) {
                        char *path = strstr(arg, "//");
@@ -1854,6 +1854,8 @@ int main(int argc, char **argv)
        if (delete_branch && nr_refspec != 1)
                die("You must specify only one branch name when deleting a remote branch");
 
+       setup_git_directory();
+
        memset(remote_dir_exists, -1, 256);
 
        /*
index 3847fd151df6e9f41fdb0b95573882a7d9ac992a..834301cf409c311d47b22a0f7504917a32847647 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "cache.h"
 #include "exec_cmd.h"
+#include "run-command.h"
 #ifdef NO_OPENSSL
 typedef void *SSL;
 #endif
@@ -93,6 +94,9 @@ struct msg_data {
        unsigned int crlf:1;
 };
 
+static const char imap_send_usage[] = "git imap-send < <mbox>";
+
+#undef DRV_OK
 #define DRV_OK          0
 #define DRV_MSG_BAD     -1
 #define DRV_BOX_BAD     -2
@@ -123,9 +127,6 @@ static int nfvasprintf(char **strp, const char *fmt, va_list ap)
        return len;
 }
 
-static void arc4_init(void);
-static unsigned char arc4_getbyte(void);
-
 struct imap_server_conf {
        char *name;
        char *tunnel;
@@ -154,7 +155,7 @@ struct imap_list {
 };
 
 struct imap_socket {
-       int fd;
+       int fd[2];
        SSL *ssl;
 };
 
@@ -272,8 +273,12 @@ static int ssl_socket_connect(struct imap_socket *sock, int use_tls_only, int ve
 #ifdef NO_OPENSSL
        fprintf(stderr, "SSL requested but SSL support not compiled in\n");
        return -1;
+#else
+#if (OPENSSL_VERSION_NUMBER >= 0x10000000L)
+       const SSL_METHOD *meth;
 #else
        SSL_METHOD *meth;
+#endif
        SSL_CTX *ctx;
        int ret;
 
@@ -304,8 +309,12 @@ static int ssl_socket_connect(struct imap_socket *sock, int use_tls_only, int ve
                ssl_socket_perror("SSL_new");
                return -1;
        }
-       if (!SSL_set_fd(sock->ssl, sock->fd)) {
-               ssl_socket_perror("SSL_set_fd");
+       if (!SSL_set_rfd(sock->ssl, sock->fd[0])) {
+               ssl_socket_perror("SSL_set_rfd");
+               return -1;
+       }
+       if (!SSL_set_wfd(sock->ssl, sock->fd[1])) {
+               ssl_socket_perror("SSL_set_wfd");
                return -1;
        }
 
@@ -327,11 +336,12 @@ static int socket_read(struct imap_socket *sock, char *buf, int len)
                n = SSL_read(sock->ssl, buf, len);
        else
 #endif
-               n = xread(sock->fd, buf, len);
+               n = xread(sock->fd[0], buf, len);
        if (n <= 0) {
                socket_perror("read", sock, n);
-               close(sock->fd);
-               sock->fd = -1;
+               close(sock->fd[0]);
+               close(sock->fd[1]);
+               sock->fd[0] = sock->fd[1] = -1;
        }
        return n;
 }
@@ -344,11 +354,12 @@ static int socket_write(struct imap_socket *sock, const char *buf, int len)
                n = SSL_write(sock->ssl, buf, len);
        else
 #endif
-               n = write_in_full(sock->fd, buf, len);
+               n = write_in_full(sock->fd[1], buf, len);
        if (n != len) {
                socket_perror("write", sock, n);
-               close(sock->fd);
-               sock->fd = -1;
+               close(sock->fd[0]);
+               close(sock->fd[1]);
+               sock->fd[0] = sock->fd[1] = -1;
        }
        return n;
 }
@@ -361,7 +372,8 @@ static void socket_shutdown(struct imap_socket *sock)
                SSL_free(sock->ssl);
        }
 #endif
-       close(sock->fd);
+       close(sock->fd[0]);
+       close(sock->fd[1]);
 }
 
 /* simple line buffering */
@@ -489,52 +501,6 @@ static int nfsnprintf(char *buf, int blen, const char *fmt, ...)
        return ret;
 }
 
-static struct {
-       unsigned char i, j, s[256];
-} rs;
-
-static void arc4_init(void)
-{
-       int i, fd;
-       unsigned char j, si, dat[128];
-
-       if ((fd = open("/dev/urandom", O_RDONLY)) < 0 && (fd = open("/dev/random", O_RDONLY)) < 0) {
-               fprintf(stderr, "Fatal: no random number source available.\n");
-               exit(3);
-       }
-       if (read_in_full(fd, dat, 128) != 128) {
-               fprintf(stderr, "Fatal: cannot read random number source.\n");
-               exit(3);
-       }
-       close(fd);
-
-       for (i = 0; i < 256; i++)
-               rs.s[i] = i;
-       for (i = j = 0; i < 256; i++) {
-               si = rs.s[i];
-               j += si + dat[i & 127];
-               rs.s[i] = rs.s[j];
-               rs.s[j] = si;
-       }
-       rs.i = rs.j = 0;
-
-       for (i = 0; i < 256; i++)
-               arc4_getbyte();
-}
-
-static unsigned char arc4_getbyte(void)
-{
-       unsigned char si, sj;
-
-       rs.i++;
-       si = rs.s[rs.i];
-       rs.j += si;
-       sj = rs.s[rs.j];
-       rs.s[rs.i] = sj;
-       rs.s[rs.j] = si;
-       return rs.s[(si + sj) & 0xff];
-}
-
 static struct imap_cmd *v_issue_imap_cmd(struct imap_store *ctx,
                                         struct imap_cmd_cb *cb,
                                         const char *fmt, va_list ap)
@@ -960,7 +926,7 @@ static void imap_close_server(struct imap_store *ictx)
 {
        struct imap *imap = ictx->imap;
 
-       if (imap->buf.sock.fd != -1) {
+       if (imap->buf.sock.fd[0] != -1) {
                imap_exec(ictx, NULL, "LOGOUT");
                socket_shutdown(&imap->buf.sock);
        }
@@ -982,40 +948,35 @@ static struct store *imap_open_store(struct imap_server_conf *srvc)
        struct imap_store *ctx;
        struct imap *imap;
        char *arg, *rsp;
-       int s = -1, a[2], preauth;
-       pid_t pid;
+       int s = -1, preauth;
 
        ctx = xcalloc(sizeof(*ctx), 1);
 
        ctx->imap = imap = xcalloc(sizeof(*imap), 1);
-       imap->buf.sock.fd = -1;
+       imap->buf.sock.fd[0] = imap->buf.sock.fd[1] = -1;
        imap->in_progress_append = &imap->in_progress;
 
        /* open connection to IMAP server */
 
        if (srvc->tunnel) {
-               imap_info("Starting tunnel '%s'... ", srvc->tunnel);
+               const char *argv[4];
+               struct child_process tunnel = {0};
 
-               if (socketpair(PF_UNIX, SOCK_STREAM, 0, a)) {
-                       perror("socketpair");
-                       exit(1);
-               }
+               imap_info("Starting tunnel '%s'... ", srvc->tunnel);
 
-               pid = fork();
-               if (pid < 0)
-                       _exit(127);
-               if (!pid) {
-                       if (dup2(a[0], 0) == -1 || dup2(a[0], 1) == -1)
-                               _exit(127);
-                       close(a[0]);
-                       close(a[1]);
-                       execl("/bin/sh", "sh", "-c", srvc->tunnel, NULL);
-                       _exit(127);
-               }
+               argv[0] = "sh";
+               argv[1] = "-c";
+               argv[2] = srvc->tunnel;
+               argv[3] = NULL;
 
-               close(a[0]);
+               tunnel.argv = argv;
+               tunnel.in = -1;
+               tunnel.out = -1;
+               if (start_command(&tunnel))
+                       die("cannot start proxy %s", argv[0]);
 
-               imap->buf.sock.fd = a[1];
+               imap->buf.sock.fd[0] = tunnel.out;
+               imap->buf.sock.fd[1] = tunnel.in;
 
                imap_info("ok\n");
        } else {
@@ -1092,7 +1053,8 @@ static struct store *imap_open_store(struct imap_server_conf *srvc)
                        goto bail;
                }
 
-               imap->buf.sock.fd = s;
+               imap->buf.sock.fd[0] = s;
+               imap->buf.sock.fd[1] = dup(s);
 
                if (srvc->use_ssl &&
                    ssl_socket_connect(&imap->buf.sock, 0, srvc->ssl_verify)) {
@@ -1198,88 +1160,20 @@ static int imap_make_flags(int flags, char *buf)
        return d;
 }
 
-#define TUIDL 8
-
-static int imap_store_msg(struct store *gctx, struct msg_data *data, int *uid)
+static int imap_store_msg(struct store *gctx, struct msg_data *data)
 {
        struct imap_store *ctx = (struct imap_store *)gctx;
        struct imap *imap = ctx->imap;
        struct imap_cmd_cb cb;
-       char *fmap, *buf;
        const char *prefix, *box;
-       int ret, i, j, d, len, extra, nocr;
-       int start, sbreak = 0, ebreak = 0;
-       char flagstr[128], tuid[TUIDL * 2 + 1];
+       int ret, d;
+       char flagstr[128];
 
        memset(&cb, 0, sizeof(cb));
 
-       fmap = data->data;
-       len = data->len;
-       nocr = !data->crlf;
-       extra = 0, i = 0;
-       if (!CAP(UIDPLUS) && uid) {
-       nloop:
-               start = i;
-               while (i < len)
-                       if (fmap[i++] == '\n') {
-                               extra += nocr;
-                               if (i - 2 + nocr == start) {
-                                       sbreak = ebreak = i - 2 + nocr;
-                                       goto mktid;
-                               }
-                               if (!memcmp(fmap + start, "X-TUID: ", 8)) {
-                                       extra -= (ebreak = i) - (sbreak = start) + nocr;
-                                       goto mktid;
-                               }
-                               goto nloop;
-                       }
-               /* invalid message */
-               free(fmap);
-               return DRV_MSG_BAD;
-       mktid:
-               for (j = 0; j < TUIDL; j++)
-                       sprintf(tuid + j * 2, "%02x", arc4_getbyte());
-               extra += 8 + TUIDL * 2 + 2;
-       }
-       if (nocr)
-               for (; i < len; i++)
-                       if (fmap[i] == '\n')
-                               extra++;
-
-       cb.dlen = len + extra;
-       buf = cb.data = xmalloc(cb.dlen);
-       i = 0;
-       if (!CAP(UIDPLUS) && uid) {
-               if (nocr) {
-                       for (; i < sbreak; i++)
-                               if (fmap[i] == '\n') {
-                                       *buf++ = '\r';
-                                       *buf++ = '\n';
-                               } else
-                                       *buf++ = fmap[i];
-               } else {
-                       memcpy(buf, fmap, sbreak);
-                       buf += sbreak;
-               }
-               memcpy(buf, "X-TUID: ", 8);
-               buf += 8;
-               memcpy(buf, tuid, TUIDL * 2);
-               buf += TUIDL * 2;
-               *buf++ = '\r';
-               *buf++ = '\n';
-               i = ebreak;
-       }
-       if (nocr) {
-               for (; i < len; i++)
-                       if (fmap[i] == '\n') {
-                               *buf++ = '\r';
-                               *buf++ = '\n';
-                       } else
-                               *buf++ = fmap[i];
-       } else
-               memcpy(buf, fmap + i, len - i);
-
-       free(fmap);
+       cb.dlen = data->len;
+       cb.data = xmalloc(cb.dlen);
+       memcpy(cb.data, data->data, data->len);
 
        d = 0;
        if (data->flags) {
@@ -1288,26 +1182,14 @@ static int imap_store_msg(struct store *gctx, struct msg_data *data, int *uid)
        }
        flagstr[d] = 0;
 
-       if (!uid) {
-               box = gctx->conf->trash;
-               prefix = ctx->prefix;
-               cb.create = 1;
-               if (ctx->trashnc)
-                       imap->caps = imap->rcaps & ~(1 << LITERALPLUS);
-       } else {
-               box = gctx->name;
-               prefix = !strcmp(box, "INBOX") ? "" : ctx->prefix;
-               cb.create = 0;
-       }
-       cb.ctx = uid;
+       box = gctx->name;
+       prefix = !strcmp(box, "INBOX") ? "" : ctx->prefix;
+       cb.create = 0;
        ret = imap_exec_m(ctx, &cb, "APPEND \"%s%s\" %s", prefix, box, flagstr);
        imap->caps = imap->rcaps;
        if (ret != DRV_OK)
                return ret;
-       if (!uid)
-               ctx->trashnc = 0;
-       else
-               gctx->count++;
+       gctx->count++;
 
        return DRV_OK;
 }
@@ -1483,7 +1365,6 @@ int main(int argc, char **argv)
 {
        struct msg_data all_msgs, msg;
        struct store *ctx = NULL;
-       int uid = 0;
        int ofs = 0;
        int r;
        int total, n = 0;
@@ -1491,8 +1372,8 @@ int main(int argc, char **argv)
 
        git_extract_argv0_path(argv[0]);
 
-       /* init the random number generator */
-       arc4_init();
+       if (argc != 1)
+               usage(imap_send_usage);
 
        setup_git_directory_gently(&nongit_ok);
        git_config(git_imap_config, NULL);
@@ -1540,7 +1421,7 @@ int main(int argc, char **argv)
                        break;
                if (server.use_html)
                        wrap_in_html(&msg);
-               r = imap_store_msg(ctx, &msg, &uid);
+               r = imap_store_msg(ctx, &msg);
                if (r != DRV_OK)
                        break;
                n++;
index b4f82786592e2e34392191e823d645e17d955fcf..190f372dd81f85d76068b166cc1688487640fdba 100644 (file)
@@ -882,6 +882,9 @@ int main(int argc, char **argv)
 
        git_extract_argv0_path(argv[0]);
 
+       if (argc == 2 && !strcmp(argv[1], "-h"))
+               usage(index_pack_usage);
+
        /*
         * We wish to read the repository's config file if any, and
         * for that it is necessary to call setup_git_directory_gently().
index 1618f3c79a3095ab88553d9ca71ce0c4024c6b97..0fdf159f8098532e3ed77251d36e163b695310ba 100644 (file)
@@ -43,6 +43,7 @@ void load_ref_decorations(int flags)
        if (!loaded) {
                loaded = 1;
                for_each_ref(add_ref_decoration, &flags);
+               head_ref(add_ref_decoration, &flags);
        }
 }
 
@@ -178,8 +179,10 @@ void get_patch_filename(struct commit *commit, int nr, const char *suffix,
        strbuf_addf(buf, commit ? "%04d-" : "%d", nr);
        if (commit) {
                int max_len = start_len + FORMAT_PATCH_NAME_MAX - suffix_len;
+               struct pretty_print_context ctx = {0};
+               ctx.date_mode = DATE_NORMAL;
 
-               format_commit_message(commit, "%f", buf, DATE_NORMAL);
+               format_commit_message(commit, "%f", buf, &ctx);
                if (max_len < buf->len)
                        strbuf_setlen(buf, max_len);
                strbuf_addstr(buf, suffix);
@@ -276,10 +279,9 @@ void show_log(struct rev_info *opt)
        struct strbuf msgbuf = STRBUF_INIT;
        struct log_info *log = opt->loginfo;
        struct commit *commit = log->commit, *parent = log->parent;
-       int abbrev = opt->diffopt.abbrev;
        int abbrev_commit = opt->abbrev_commit ? opt->abbrev : 40;
-       const char *subject = NULL, *extra_headers = opt->extra_headers;
-       int need_8bit_cte = 0;
+       const char *extra_headers = opt->extra_headers;
+       struct pretty_print_context ctx = {0};
 
        opt->loginfo = NULL;
        if (!opt->verbose_header) {
@@ -346,8 +348,8 @@ void show_log(struct rev_info *opt)
         */
 
        if (opt->commit_format == CMIT_FMT_EMAIL) {
-               log_write_email_headers(opt, commit, &subject, &extra_headers,
-                                       &need_8bit_cte);
+               log_write_email_headers(opt, commit, &ctx.subject, &extra_headers,
+                                       &ctx.need_8bit_cte);
        } else if (opt->commit_format != CMIT_FMT_USERFORMAT) {
                fputs(diff_get_color_opt(&opt->diffopt, DIFF_COMMIT), stdout);
                if (opt->commit_format != CMIT_FMT_ONELINE)
@@ -404,11 +406,13 @@ void show_log(struct rev_info *opt)
        /*
         * And then the pretty-printed message itself
         */
-       if (need_8bit_cte >= 0)
-               need_8bit_cte = has_non_ascii(opt->add_signoff);
-       pretty_print_commit(opt->commit_format, commit, &msgbuf,
-                           abbrev, subject, extra_headers, opt->date_mode,
-                           need_8bit_cte);
+       if (ctx.need_8bit_cte >= 0)
+               ctx.need_8bit_cte = has_non_ascii(opt->add_signoff);
+       ctx.date_mode = opt->date_mode;
+       ctx.abbrev = opt->diffopt.abbrev;
+       ctx.after_subject = extra_headers;
+       ctx.reflog_info = opt->reflog_info;
+       pretty_print_commit(opt->commit_format, commit, &msgbuf, &ctx);
 
        if (opt->add_signoff)
                append_signoff(&msgbuf, opt->add_signoff);
index 69a7ab2e27d39ecabca5c0cc25c4e372caafb46c..21c61dbbe9bd5e2f9770109bc4a9daaf2a2f6cc4 100644 (file)
@@ -603,6 +603,9 @@ int main(int argc, char **argv)
 
        git_extract_argv0_path(argv[0]);
 
+       if (argc == 2 && !strcmp(argv[1], "-h"))
+               usage(pack_redundant_usage);
+
        setup_git_directory();
 
        for (i = 1; i < argc; i++) {
index f5983f8baa98b69338707b4220e64012ef4e5d11..2e031e62fd98c02bfa6cc558fc49aef86c03ed09 100644 (file)
--- a/pretty.c
+++ b/pretty.c
@@ -7,6 +7,7 @@
 #include "mailmap.h"
 #include "log-tree.h"
 #include "color.h"
+#include "reflog-walk.h"
 
 static char *user_format;
 
@@ -442,9 +443,10 @@ struct chunk {
 
 struct format_commit_context {
        const struct commit *commit;
-       enum date_mode dmode;
+       const struct pretty_print_context *pretty_ctx;
        unsigned commit_header_parsed:1;
        unsigned commit_message_parsed:1;
+       size_t width, indent1, indent2;
 
        /* These offsets are relative to the start of the commit message. */
        struct chunk author;
@@ -458,6 +460,7 @@ struct format_commit_context {
        struct chunk abbrev_commit_hash;
        struct chunk abbrev_tree_hash;
        struct chunk abbrev_parent_hashes;
+       size_t wrap_start;
 };
 
 static int add_again(struct strbuf *sb, struct chunk *chunk)
@@ -595,6 +598,35 @@ static void format_decoration(struct strbuf *sb, const struct commit *commit)
                strbuf_addch(sb, ')');
 }
 
+static void strbuf_wrap(struct strbuf *sb, size_t pos,
+                       size_t width, size_t indent1, size_t indent2)
+{
+       struct strbuf tmp = STRBUF_INIT;
+
+       if (pos)
+               strbuf_add(&tmp, sb->buf, pos);
+       strbuf_add_wrapped_text(&tmp, sb->buf + pos,
+                               (int) indent1, (int) indent2, (int) width);
+       strbuf_swap(&tmp, sb);
+       strbuf_release(&tmp);
+}
+
+static void rewrap_message_tail(struct strbuf *sb,
+                               struct format_commit_context *c,
+                               size_t new_width, size_t new_indent1,
+                               size_t new_indent2)
+{
+       if (c->width == new_width && c->indent1 == new_indent1 &&
+           c->indent2 == new_indent2)
+               return;
+       if (c->wrap_start < sb->len)
+               strbuf_wrap(sb, c->wrap_start, c->width, c->indent1, c->indent2);
+       c->wrap_start = sb->len;
+       c->width = new_width;
+       c->indent1 = new_indent1;
+       c->indent2 = new_indent2;
+}
+
 static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
                                void *context)
 {
@@ -645,6 +677,30 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
                        return 3;
                } else
                        return 0;
+       case 'w':
+               if (placeholder[1] == '(') {
+                       unsigned long width = 0, indent1 = 0, indent2 = 0;
+                       char *next;
+                       const char *start = placeholder + 2;
+                       const char *end = strchr(start, ')');
+                       if (!end)
+                               return 0;
+                       if (end > start) {
+                               width = strtoul(start, &next, 10);
+                               if (*next == ',') {
+                                       indent1 = strtoul(next + 1, &next, 10);
+                                       if (*next == ',') {
+                                               indent2 = strtoul(next + 1,
+                                                                &next, 10);
+                                       }
+                               }
+                               if (*next != ')')
+                                       return 0;
+                       }
+                       rewrap_message_tail(sb, c, width, indent1, indent2);
+                       return end - placeholder + 1;
+               } else
+                       return 0;
        }
 
        /* these depend on the commit */
@@ -701,6 +757,22 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
        case 'd':
                format_decoration(sb, commit);
                return 1;
+       case 'g':               /* reflog info */
+               switch(placeholder[1]) {
+               case 'd':       /* reflog selector */
+               case 'D':
+                       if (c->pretty_ctx->reflog_info)
+                               get_reflog_selector(sb,
+                                                   c->pretty_ctx->reflog_info,
+                                                   c->pretty_ctx->date_mode,
+                                                   (placeholder[1] == 'd'));
+                       return 2;
+               case 's':       /* reflog message */
+                       if (c->pretty_ctx->reflog_info)
+                               get_reflog_message(sb, c->pretty_ctx->reflog_info);
+                       return 2;
+               }
+               return 0;       /* unknown %g placeholder */
        }
 
        /* For the rest we have to parse the commit header. */
@@ -711,11 +783,11 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
        case 'a':       /* author ... */
                return format_person_part(sb, placeholder[1],
                                   msg + c->author.off, c->author.len,
-                                  c->dmode);
+                                  c->pretty_ctx->date_mode);
        case 'c':       /* committer ... */
                return format_person_part(sb, placeholder[1],
                                   msg + c->committer.off, c->committer.len,
-                                  c->dmode);
+                                  c->pretty_ctx->date_mode);
        case 'e':       /* encoding */
                strbuf_add(sb, msg + c->encoding.off, c->encoding.len);
                return 1;
@@ -740,15 +812,17 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
 }
 
 void format_commit_message(const struct commit *commit,
-                          const void *format, struct strbuf *sb,
-                          enum date_mode dmode)
+                          const char *format, struct strbuf *sb,
+                          const struct pretty_print_context *pretty_ctx)
 {
        struct format_commit_context context;
 
        memset(&context, 0, sizeof(context));
        context.commit = commit;
-       context.dmode = dmode;
+       context.pretty_ctx = pretty_ctx;
+       context.wrap_start = sb->len;
        strbuf_expand(sb, format, format_commit_item, &context);
+       rewrap_message_tail(sb, &context, 0, 0, 0);
 }
 
 static void pp_header(enum cmit_fmt fmt,
@@ -900,18 +974,18 @@ char *reencode_commit_message(const struct commit *commit, const char **encoding
 }
 
 void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,
-                        struct strbuf *sb, int abbrev,
-                        const char *subject, const char *after_subject,
-                        enum date_mode dmode, int need_8bit_cte)
+                        struct strbuf *sb,
+                        const struct pretty_print_context *context)
 {
        unsigned long beginning_of_body;
        int indent = 4;
        const char *msg = commit->buffer;
        char *reencoded;
        const char *encoding;
+       int need_8bit_cte = context->need_8bit_cte;
 
        if (fmt == CMIT_FMT_USERFORMAT) {
-               format_commit_message(commit, user_format, sb, dmode);
+               format_commit_message(commit, user_format, sb, context);
                return;
        }
 
@@ -946,8 +1020,9 @@ void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,
                }
        }
 
-       pp_header(fmt, abbrev, dmode, encoding, commit, &msg, sb);
-       if (fmt != CMIT_FMT_ONELINE && !subject) {
+       pp_header(fmt, context->abbrev, context->date_mode, encoding,
+                 commit, &msg, sb);
+       if (fmt != CMIT_FMT_ONELINE && !context->subject) {
                strbuf_addch(sb, '\n');
        }
 
@@ -956,8 +1031,8 @@ void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,
 
        /* These formats treat the title line specially. */
        if (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL)
-               pp_title_line(fmt, &msg, sb, subject,
-                             after_subject, encoding, need_8bit_cte);
+               pp_title_line(fmt, &msg, sb, context->subject,
+                             context->after_subject, encoding, need_8bit_cte);
 
        beginning_of_body = sb->len;
        if (fmt != CMIT_FMT_ONELINE)
index 132ed95a3d44d33ec0b8c887fbe05c0db11e37b1..3971f49f4ddaa774806bd1717379a1edd22ba17c 100644 (file)
@@ -131,7 +131,13 @@ static void throughput_string(struct throughput *tp, off_t total,
        } else {
                l -= snprintf(tp->display, l, ", %u bytes", (int)total);
        }
-       if (rate)
+
+       if (rate > 1 << 10) {
+               int x = rate + 5;  /* for rounding */
+               snprintf(tp->display + sizeof(tp->display) - l, l,
+                        " | %u.%2.2u MiB/s",
+                        x >> 10, ((x & ((1 << 10) - 1)) * 100) >> 10);
+       } else if (rate)
                snprintf(tp->display + sizeof(tp->display) - l, l,
                         " | %u KiB/s", rate);
 }
index 5623ea6b48a2f355e8866eabb2805b51b4127a4a..caba4f743f2dcc1cf7046cec294f242b2af19052 100644 (file)
@@ -8,6 +8,7 @@
 
 struct complete_reflogs {
        char *ref;
+       const char *short_ref;
        struct reflog_info {
                unsigned char osha1[20], nsha1[20];
                char *email;
@@ -241,36 +242,74 @@ void fake_reflog_parent(struct reflog_walk_info *info, struct commit *commit)
        commit->object.flags &= ~(ADDED | SEEN | SHOWN);
 }
 
-void show_reflog_message(struct reflog_walk_info *info, int oneline,
+void get_reflog_selector(struct strbuf *sb,
+                        struct reflog_walk_info *reflog_info,
+                        enum date_mode dmode,
+                        int shorten)
+{
+       struct commit_reflog *commit_reflog = reflog_info->last_commit_reflog;
+       struct reflog_info *info;
+       const char *printed_ref;
+
+       if (!commit_reflog)
+               return;
+
+       if (shorten) {
+               if (!commit_reflog->reflogs->short_ref)
+                       commit_reflog->reflogs->short_ref
+                               = shorten_unambiguous_ref(commit_reflog->reflogs->ref, 0);
+               printed_ref = commit_reflog->reflogs->short_ref;
+       } else {
+               printed_ref = commit_reflog->reflogs->ref;
+       }
+
+       strbuf_addf(sb, "%s@{", printed_ref);
+       if (commit_reflog->flag || dmode) {
+               info = &commit_reflog->reflogs->items[commit_reflog->recno+1];
+               strbuf_addstr(sb, show_date(info->timestamp, info->tz, dmode));
+       } else {
+               strbuf_addf(sb, "%d", commit_reflog->reflogs->nr
+                           - 2 - commit_reflog->recno);
+       }
+
+       strbuf_addch(sb, '}');
+}
+
+void get_reflog_message(struct strbuf *sb,
+                       struct reflog_walk_info *reflog_info)
+{
+       struct commit_reflog *commit_reflog = reflog_info->last_commit_reflog;
+       struct reflog_info *info;
+       size_t len;
+
+       if (!commit_reflog)
+               return;
+
+       info = &commit_reflog->reflogs->items[commit_reflog->recno+1];
+       len = strlen(info->message);
+       if (len > 0)
+               len--; /* strip away trailing newline */
+       strbuf_add(sb, info->message, len);
+}
+
+void show_reflog_message(struct reflog_walk_info *reflog_info, int oneline,
        enum date_mode dmode)
 {
-       if (info && info->last_commit_reflog) {
-               struct commit_reflog *commit_reflog = info->last_commit_reflog;
+       if (reflog_info && reflog_info->last_commit_reflog) {
+               struct commit_reflog *commit_reflog = reflog_info->last_commit_reflog;
                struct reflog_info *info;
+               struct strbuf selector = STRBUF_INIT;
 
                info = &commit_reflog->reflogs->items[commit_reflog->recno+1];
+               get_reflog_selector(&selector, reflog_info, dmode, 0);
                if (oneline) {
-                       printf("%s@{", commit_reflog->reflogs->ref);
-                       if (commit_reflog->flag || dmode)
-                               printf("%s", show_date(info->timestamp,
-                                                      info->tz,
-                                                      dmode));
-                       else
-                               printf("%d", commit_reflog->reflogs->nr
-                                      - 2 - commit_reflog->recno);
-                       printf("}: %s", info->message);
+                       printf("%s: %s", selector.buf, info->message);
                }
                else {
-                       printf("Reflog: %s@{", commit_reflog->reflogs->ref);
-                       if (commit_reflog->flag || dmode)
-                               printf("%s", show_date(info->timestamp,
-                                                       info->tz,
-                                                       dmode));
-                       else
-                               printf("%d", commit_reflog->reflogs->nr
-                                      - 2 - commit_reflog->recno);
-                       printf("} (%s)\nReflog message: %s",
-                              info->email, info->message);
+                       printf("Reflog: %s (%s)\nReflog message: %s",
+                              selector.buf, info->email, info->message);
                }
+
+               strbuf_release(&selector);
        }
 }
index 74c90964bd95dcd97a5acde83c83b2f3b61c2441..7bd2cd4c4e5cd9d51e645509eeacc49a83a44ba7 100644 (file)
@@ -3,6 +3,8 @@
 
 #include "cache.h"
 
+struct reflog_walk_info;
+
 extern void init_reflog_walk(struct reflog_walk_info** info);
 extern int add_reflog_for_walk(struct reflog_walk_info *info,
                struct commit *commit, const char *name);
@@ -10,5 +12,11 @@ extern void fake_reflog_parent(struct reflog_walk_info *info,
                struct commit *commit);
 extern void show_reflog_message(struct reflog_walk_info *info, int,
                enum date_mode);
+extern void get_reflog_message(struct strbuf *sb,
+               struct reflog_walk_info *reflog_info);
+extern void get_reflog_selector(struct strbuf *sb,
+               struct reflog_walk_info *reflog_info,
+               enum date_mode dmode,
+               int shorten);
 
 #endif
index ad6a1637b52dedeeb461315e9cc0d313b1c6087f..ebdab3603ec767b42ce04e0de2c3deeb516f2525 100644 (file)
@@ -3,6 +3,7 @@
 #include "strbuf.h"
 #include "walker.h"
 #include "http.h"
+#include "exec_cmd.h"
 
 static struct ref *get_refs(struct walker *walker, const char *url)
 {
@@ -81,8 +82,10 @@ int main(int argc, const char **argv)
        struct strbuf buf = STRBUF_INIT;
        const char *url;
        struct walker *walker = NULL;
+       int nongit;
 
-       setup_git_directory();
+       git_extract_argv0_path(argv[0]);
+       setup_git_directory_gently(&nongit);
        if (argc < 2) {
                fprintf(stderr, "Remote needed\n");
                return 1;
@@ -101,6 +104,8 @@ int main(int argc, const char **argv)
                        break;
                if (!prefixcmp(buf.buf, "fetch ")) {
                        char *obj = buf.buf + strlen("fetch ");
+                       if (nongit)
+                               die("Fetch attempted without a local repo");
                        if (!walker)
                                walker = get_http_walker(url, remote);
                        walker->get_all = 1;
index 73d33f2584b061085fcaa0958c26b1c3d4665904..e0d17bb83060561c17114905c253eebdf925a01c 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -6,6 +6,7 @@
 #include "revision.h"
 #include "dir.h"
 #include "tag.h"
+#include "string-list.h"
 
 static struct refspec s_tag_refspec = {
        0,
@@ -734,29 +735,33 @@ int for_each_remote(each_remote_fn fn, void *priv)
 
 void ref_remove_duplicates(struct ref *ref_map)
 {
-       struct ref **posn;
-       struct ref *next;
-       for (; ref_map; ref_map = ref_map->next) {
+       struct string_list refs = { NULL, 0, 0, 0 };
+       struct string_list_item *item = NULL;
+       struct ref *prev = NULL, *next = NULL;
+       for (; ref_map; prev = ref_map, ref_map = next) {
+               next = ref_map->next;
                if (!ref_map->peer_ref)
                        continue;
-               posn = &ref_map->next;
-               while (*posn) {
-                       if ((*posn)->peer_ref &&
-                           !strcmp((*posn)->peer_ref->name,
-                                   ref_map->peer_ref->name)) {
-                               if (strcmp((*posn)->name, ref_map->name))
-                                       die("%s tracks both %s and %s",
-                                           ref_map->peer_ref->name,
-                                           (*posn)->name, ref_map->name);
-                               next = (*posn)->next;
-                               free((*posn)->peer_ref);
-                               free(*posn);
-                               *posn = next;
-                       } else {
-                               posn = &(*posn)->next;
-                       }
+
+               item = string_list_lookup(ref_map->peer_ref->name, &refs);
+               if (item) {
+                       if (strcmp(((struct ref *)item->util)->name,
+                                  ref_map->name))
+                               die("%s tracks both %s and %s",
+                                   ref_map->peer_ref->name,
+                                   ((struct ref *)item->util)->name,
+                                   ref_map->name);
+                       prev->next = ref_map->next;
+                       free(ref_map->peer_ref);
+                       free(ref_map);
+                       ref_map = prev; /* skip this; we freed it */
+                       continue;
                }
+
+               item = string_list_insert(ref_map->peer_ref->name, &refs);
+               item->util = ref_map;
        }
+       string_list_clear(&refs, 0);
 }
 
 int remote_has_url(struct remote *remote, const char *url)
index 9fc4e8d3818f29261b1963f4995bc36f8af31179..a36c0d9bcd962665fc46fb2a1f75342e176f7773 100644 (file)
@@ -994,7 +994,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
        if (!strcmp(arg, "--all") || !strcmp(arg, "--branches") ||
            !strcmp(arg, "--tags") || !strcmp(arg, "--remotes") ||
            !strcmp(arg, "--reflog") || !strcmp(arg, "--not") ||
-           !strcmp(arg, "--no-walk") || !strcmp(arg, "--do-walk"))
+           !strcmp(arg, "--no-walk") || !strcmp(arg, "--do-walk") ||
+           !strcmp(arg, "--bisect"))
        {
                unkv[(*unkc)++] = arg;
                return 1;
@@ -1218,6 +1219,16 @@ void parse_revision_opt(struct rev_info *revs, struct parse_opt_ctx_t *ctx,
        ctx->argc -= n;
 }
 
+static int for_each_bad_bisect_ref(each_ref_fn fn, void *cb_data)
+{
+       return for_each_ref_in("refs/bisect/bad", fn, cb_data);
+}
+
+static int for_each_good_bisect_ref(each_ref_fn fn, void *cb_data)
+{
+       return for_each_ref_in("refs/bisect/good", fn, cb_data);
+}
+
 /*
  * Parse revision information, filling in the "rev_info" structure,
  * and removing the used arguments from the argument list.
@@ -1259,6 +1270,12 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
                                handle_refs(revs, flags, for_each_branch_ref);
                                continue;
                        }
+                       if (!strcmp(arg, "--bisect")) {
+                               handle_refs(revs, flags, for_each_bad_bisect_ref);
+                               handle_refs(revs, flags ^ UNINTERESTING, for_each_good_bisect_ref);
+                               revs->bisect = 1;
+                               continue;
+                       }
                        if (!strcmp(arg, "--tags")) {
                                handle_refs(revs, flags, for_each_tag_ref);
                                continue;
index b6421a64321168237443ecb7e56e6b0765256c8b..921656aaabe74adaf24c8a14426f9533040a4669 100644 (file)
@@ -63,6 +63,7 @@ struct rev_info {
                        reverse:1,
                        reverse_output_stage:1,
                        cherry_pick:1,
+                       bisect:1,
                        first_parent_only:1;
 
        /* Diff flags */
diff --git a/setup.c b/setup.c
index 029371e5844a1069d62456c6bb51028efbb671c4..f67250b7c1f7b5a62c30de0122c404554357f61b 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -61,6 +61,19 @@ const char *prefix_filename(const char *pfx, int pfx_len, const char *arg)
        return path;
 }
 
+int check_filename(const char *prefix, const char *arg)
+{
+       const char *name;
+       struct stat st;
+
+       name = prefix ? prefix_filename(prefix, strlen(prefix), arg) : arg;
+       if (!lstat(name, &st))
+               return 1; /* file exists */
+       if (errno == ENOENT || errno == ENOTDIR)
+               return 0; /* file does not exist */
+       die_errno("failed to stat '%s'", arg);
+}
+
 /*
  * Verify a filename that we got as an argument for a pathspec
  * entry. Note that a filename that begins with "-" never verifies
@@ -70,18 +83,12 @@ const char *prefix_filename(const char *pfx, int pfx_len, const char *arg)
  */
 void verify_filename(const char *prefix, const char *arg)
 {
-       const char *name;
-       struct stat st;
-
        if (*arg == '-')
                die("bad flag '%s' used after filename", arg);
-       name = prefix ? prefix_filename(prefix, strlen(prefix), arg) : arg;
-       if (!lstat(name, &st))
+       if (check_filename(prefix, arg))
                return;
-       if (errno == ENOENT)
-               die("ambiguous argument '%s': unknown revision or path not in the working tree.\n"
-                   "Use '--' to separate paths from revisions", arg);
-       die_errno("failed to stat '%s'", arg);
+       die("ambiguous argument '%s': unknown revision or path not in the working tree.\n"
+           "Use '--' to separate paths from revisions", arg);
 }
 
 /*
@@ -91,19 +98,14 @@ void verify_filename(const char *prefix, const char *arg)
  */
 void verify_non_filename(const char *prefix, const char *arg)
 {
-       const char *name;
-       struct stat st;
-
        if (!is_inside_work_tree() || is_inside_git_dir())
                return;
        if (*arg == '-')
                return; /* flag */
-       name = prefix ? prefix_filename(prefix, strlen(prefix), arg) : arg;
-       if (!lstat(name, &st))
-               die("ambiguous argument '%s': both revision and filename\n"
-                   "Use '--' to separate filenames from revisions", arg);
-       if (errno != ENOENT && errno != ENOTDIR)
-               die_errno("failed to stat '%s'", arg);
+       if (!check_filename(prefix, arg))
+               return;
+       die("ambiguous argument '%s': both revision and filename\n"
+           "Use '--' to separate filenames from revisions", arg);
 }
 
 const char **get_pathspec(const char *prefix, const char **pathspec)
index 4ea0b18d0aaeca48ed75ed21863195c5ce830cbc..63981fb3fd9cfa6cca4126eba5a964b449c62444 100644 (file)
@@ -1587,13 +1587,15 @@ static void *unpack_compressed_entry(struct packed_git *p,
        buffer[size] = 0;
        memset(&stream, 0, sizeof(stream));
        stream.next_out = buffer;
-       stream.avail_out = size;
+       stream.avail_out = size + 1;
 
        git_inflate_init(&stream);
        do {
                in = use_pack(p, w_curs, curpos, &stream.avail_in);
                stream.next_in = in;
                st = git_inflate(&stream, Z_FINISH);
+               if (!stream.avail_out)
+                       break; /* the payload is larger than it should be */
                curpos += stream.next_in - in;
        } while (st == Z_OK || st == Z_BUF_ERROR);
        git_inflate_end(&stream);
index 45bb535773fd9c36f73502df9462f7de800009c8..63f9da53237d4233bede66a28e4bcf27d5b44af1 100644 (file)
@@ -1,6 +1,9 @@
 #include "cache.h"
 #include "pack.h"
 
+static const char show_index_usage[] =
+"git show-index < <packed archive index>";
+
 int main(int argc, char **argv)
 {
        int i;
@@ -8,6 +11,8 @@ int main(int argc, char **argv)
        unsigned int version;
        static unsigned int top_index[256];
 
+       if (argc != 1)
+               usage(show_index_usage);
        if (fread(top_index, 2 * 4, 1, stdin) != 1)
                die("unable to read header");
        if (top_index[0] == htonl(PACK_IDX_SIGNATURE)) {
diff --git a/submodule.c b/submodule.c
new file mode 100644 (file)
index 0000000..86aad65
--- /dev/null
@@ -0,0 +1,114 @@
+#include "cache.h"
+#include "submodule.h"
+#include "dir.h"
+#include "diff.h"
+#include "commit.h"
+#include "revision.h"
+
+int add_submodule_odb(const char *path)
+{
+       struct strbuf objects_directory = STRBUF_INIT;
+       struct alternate_object_database *alt_odb;
+
+       strbuf_addf(&objects_directory, "%s/.git/objects/", path);
+       if (!is_directory(objects_directory.buf))
+               return -1;
+
+       /* avoid adding it twice */
+       for (alt_odb = alt_odb_list; alt_odb; alt_odb = alt_odb->next)
+               if (alt_odb->name - alt_odb->base == objects_directory.len &&
+                               !strncmp(alt_odb->base, objects_directory.buf,
+                                       objects_directory.len))
+                       return 0;
+
+       alt_odb = xmalloc(objects_directory.len + 42 + sizeof(*alt_odb));
+       alt_odb->next = alt_odb_list;
+       strcpy(alt_odb->base, objects_directory.buf);
+       alt_odb->name = alt_odb->base + objects_directory.len;
+       alt_odb->name[2] = '/';
+       alt_odb->name[40] = '\0';
+       alt_odb->name[41] = '\0';
+       alt_odb_list = alt_odb;
+       prepare_alt_odb();
+       return 0;
+}
+
+void show_submodule_summary(FILE *f, const char *path,
+               unsigned char one[20], unsigned char two[20],
+               const char *del, const char *add, const char *reset)
+{
+       struct rev_info rev;
+       struct commit *commit, *left = left, *right = right;
+       struct commit_list *merge_bases, *list;
+       const char *message = NULL;
+       struct strbuf sb = STRBUF_INIT;
+       static const char *format = "  %m %s";
+       int fast_forward = 0, fast_backward = 0;
+
+       if (is_null_sha1(two))
+               message = "(submodule deleted)";
+       else if (add_submodule_odb(path))
+               message = "(not checked out)";
+       else if (is_null_sha1(one))
+               message = "(new submodule)";
+       else if (!(left = lookup_commit_reference(one)) ||
+                !(right = lookup_commit_reference(two)))
+               message = "(commits not present)";
+
+       if (!message) {
+               init_revisions(&rev, NULL);
+               setup_revisions(0, NULL, &rev, NULL);
+               rev.left_right = 1;
+               rev.first_parent_only = 1;
+               left->object.flags |= SYMMETRIC_LEFT;
+               add_pending_object(&rev, &left->object, path);
+               add_pending_object(&rev, &right->object, path);
+               merge_bases = get_merge_bases(left, right, 1);
+               if (merge_bases) {
+                       if (merge_bases->item == left)
+                               fast_forward = 1;
+                       else if (merge_bases->item == right)
+                               fast_backward = 1;
+               }
+               for (list = merge_bases; list; list = list->next) {
+                       list->item->object.flags |= UNINTERESTING;
+                       add_pending_object(&rev, &list->item->object,
+                               sha1_to_hex(list->item->object.sha1));
+               }
+               if (prepare_revision_walk(&rev))
+                       message = "(revision walker failed)";
+       }
+
+       strbuf_addf(&sb, "Submodule %s %s..", path,
+                       find_unique_abbrev(one, DEFAULT_ABBREV));
+       if (!fast_backward && !fast_forward)
+               strbuf_addch(&sb, '.');
+       strbuf_addf(&sb, "%s", find_unique_abbrev(two, DEFAULT_ABBREV));
+       if (message)
+               strbuf_addf(&sb, " %s\n", message);
+       else
+               strbuf_addf(&sb, "%s:\n", fast_backward ? " (rewind)" : "");
+       fwrite(sb.buf, sb.len, 1, f);
+
+       if (!message) {
+               while ((commit = get_revision(&rev))) {
+                       struct pretty_print_context ctx = {0};
+                       ctx.date_mode = rev.date_mode;
+                       strbuf_setlen(&sb, 0);
+                       if (commit->object.flags & SYMMETRIC_LEFT) {
+                               if (del)
+                                       strbuf_addstr(&sb, del);
+                       }
+                       else if (add)
+                               strbuf_addstr(&sb, add);
+                       format_commit_message(commit, format, &sb, &ctx);
+                       if (reset)
+                               strbuf_addstr(&sb, reset);
+                       strbuf_addch(&sb, '\n');
+                       fprintf(f, "%s", sb.buf);
+               }
+               clear_commit_marks(left, ~0);
+               clear_commit_marks(right, ~0);
+       }
+       strbuf_release(&sb);
+}
diff --git a/submodule.h b/submodule.h
new file mode 100644 (file)
index 0000000..4c0269d
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef SUBMODULE_H
+#define SUBMODULE_H
+
+void show_submodule_summary(FILE *f, const char *path,
+               unsigned char one[20], unsigned char two[20],
+               const char *del, const char *add, const char *reset);
+
+#endif
index fd8631f90686bb4dfe6d39290434136fc4741068..0f7f35ccc9e1315d3ac8e5d37df51c106847d920 100644 (file)
@@ -16,6 +16,7 @@ fi
 GIT_DIR=$PWD/.git
 GIT_SVN_DIR=$GIT_DIR/svn/refs/remotes/git-svn
 SVN_TREE=$GIT_SVN_DIR/svn-tree
+PERL=${PERL:-perl}
 
 svn >/dev/null 2>&1
 if test $? -ne 1
@@ -29,7 +30,7 @@ export svnrepo
 svnconf=$PWD/svnconf
 export svnconf
 
-perl -w -e "
+$PERL -w -e "
 use SVN::Core;
 use SVN::Repos;
 \$SVN::Core::VERSION gt '1.1.0' or exit(42);
@@ -130,7 +131,7 @@ stop_httpd () {
 }
 
 convert_to_rev_db () {
-       perl -w -- - "$@" <<\EOF
+       $PERL -w -- - "$@" <<\EOF
 use strict;
 @ARGV == 2 or die "Usage: convert_to_rev_db <input> <output>";
 open my $wr, '+>', $ARGV[1] or die "$!: couldn't open: $ARGV[1]";
index 260a231933a3cc9ce1f96eeb5952f34d7dc18d72..62f452c8ea2c2718fff300d39531fbc4c2e6a44a 100644 (file)
@@ -9,8 +9,8 @@
 #
 #      "[<lineno1>] [<lineno2>]..."
 #
-#   If a line number is prefixed with "squash" or "edit", the respective line's
-#   command will be replaced with the specified one.
+#   If a line number is prefixed with "squash", "edit", or "reword", the
+#   respective line's command will be replaced with the specified one.
 
 set_fake_editor () {
        echo "#!$SHELL_PATH" >fake-editor.sh
@@ -32,7 +32,7 @@ cat "$1".tmp
 action=pick
 for line in $FAKE_LINES; do
        case $line in
-       squash|edit)
+       squash|edit|reword)
                action="$line";;
        *)
                echo sed -n "${line}s/^pick/$action/p"
index 271bc4e17f0c12cda550ffa4f54f1ad7555b3bed..c2d408b46120ef9d962272b652a68a83ba0852a5 100755 (executable)
@@ -5,7 +5,7 @@
 
 test_description='Two way merge with read-tree -m $H $M
 
-This test tries two-way merge (aka fast forward with carry forward).
+This test tries two-way merge (aka fast-forward with carry forward).
 
 There is the head (called H) and another commit (called M), which is
 simply ahead of H.  The index and the work tree contains a state that
@@ -51,7 +51,7 @@ check_cache_at () {
 }
 
 cat >bozbar-old <<\EOF
-This is a sample file used in two-way fast forward merge
+This is a sample file used in two-way fast-forward merge
 tests.  Its second line ends with a magic word bozbar
 which will be modified by the merged head to gnusto.
 It has some extra lines so that external tools can
@@ -300,7 +300,7 @@ test_expect_success \
      echo gnusto gnusto >bozbar &&
      if read_tree_twoway $treeH $treeM; then false; else :; fi'
 
-# This fails with straight two-way fast forward.
+# This fails with straight two-way fast-forward.
 test_expect_success \
     '22 - local change cache updated.' \
     'rm -f .git/index &&
index 67e637b7810190e1b7d12dab70cd41d83db0e442..6bf84755f39378cb3a328a0a1f37b13cdb03a0ca 100755 (executable)
@@ -7,14 +7,18 @@ test_description='A simple turial in the form of a test case'
 
 . ./test-lib.sh
 
-echo "Hello World" > hello
-echo "Silly example" > example
+test_expect_success 'blob'  '
+       echo "Hello World" > hello &&
+       echo "Silly example" > example &&
 
-git update-index --add hello example
+       git update-index --add hello example &&
 
-test_expect_success 'blob' "test blob = \"$(git cat-file -t 557db03)\""
+       test blob = "$(git cat-file -t 557db03)"
+'
 
-test_expect_success 'blob 557db03' "test \"Hello World\" = \"$(git cat-file blob 557db03)\""
+test_expect_success 'blob 557db03' '
+       test "Hello World" = "$(git cat-file blob 557db03)"
+'
 
 echo "It's a new day for git" >>hello
 cat > diff.expect << EOF
@@ -26,25 +30,34 @@ index 557db03..263414f 100644
  Hello World
 +It's a new day for git
 EOF
-git diff-files -p > diff.output
-test_expect_success 'git diff-files -p' 'cmp diff.expect diff.output'
-git diff > diff.output
-test_expect_success 'git diff' 'cmp diff.expect diff.output'
-
-tree=$(git write-tree 2>/dev/null)
 
-test_expect_success 'tree' "test 8988da15d077d4829fc51d8544c097def6644dbb = $tree"
+test_expect_success 'git diff-files -p' '
+       git diff-files -p > diff.output &&
+       test_cmp diff.expect diff.output
+'
 
-output="$(echo "Initial commit" | git commit-tree $(git write-tree) 2>&1 > .git/refs/heads/master)"
+test_expect_success 'git diff' '
+       git diff > diff.output &&
+       test_cmp diff.expect diff.output
+'
 
-git diff-index -p HEAD > diff.output
-test_expect_success 'git diff-index -p HEAD' 'cmp diff.expect diff.output'
+test_expect_success 'tree' '
+       tree=$(git write-tree 2>/dev/null)
+       test 8988da15d077d4829fc51d8544c097def6644dbb = $tree
+'
 
-git diff HEAD > diff.output
-test_expect_success 'git diff HEAD' 'cmp diff.expect diff.output'
+test_expect_success 'git diff-index -p HEAD' '
+       tree=$(git write-tree)
+       commit=$(echo "Initial commit" | git commit-tree $tree) &&
+       git update-ref HEAD $commit &&
+       git diff-index -p HEAD > diff.output &&
+       test_cmp diff.expect diff.output
+'
 
-#rm hello
-#test_expect_success 'git read-tree --reset HEAD' "git read-tree --reset HEAD ; test \"hello: needs update\" = \"$(git update-index --refresh)\""
+test_expect_success 'git diff HEAD' '
+       git diff HEAD > diff.output &&
+       test_cmp diff.expect diff.output
+'
 
 cat > whatchanged.expect << EOF
 commit VARIABLE
@@ -69,39 +82,45 @@ index 0000000..557db03
 +Hello World
 EOF
 
-git whatchanged -p --root | \
-       sed -e "1s/^\(.\{7\}\).\{40\}/\1VARIABLE/" \
+test_expect_success 'git whatchanged -p --root' '
+       git whatchanged -p --root |
+               sed -e "1s/^\(.\{7\}\).\{40\}/\1VARIABLE/" \
                -e "2,3s/^\(.\{8\}\).*$/\1VARIABLE/" \
-> whatchanged.output
-test_expect_success 'git whatchanged -p --root' 'cmp whatchanged.expect whatchanged.output'
-
-git tag my-first-tag
-test_expect_success 'git tag my-first-tag' 'cmp .git/refs/heads/master .git/refs/tags/my-first-tag'
+       > whatchanged.output &&
+       test_cmp whatchanged.expect whatchanged.output
+'
 
-# TODO: test git clone
+test_expect_success 'git tag my-first-tag' '
+       git tag my-first-tag &&
+       test_cmp .git/refs/heads/master .git/refs/tags/my-first-tag
+'
 
-git checkout -b mybranch
-test_expect_success 'git checkout -b mybranch' 'cmp .git/refs/heads/master .git/refs/heads/mybranch'
+test_expect_success 'git checkout -b mybranch' '
+       git checkout -b mybranch &&
+       test_cmp .git/refs/heads/master .git/refs/heads/mybranch
+'
 
 cat > branch.expect <<EOF
   master
 * mybranch
 EOF
 
-git branch > branch.output
-test_expect_success 'git branch' 'cmp branch.expect branch.output'
+test_expect_success 'git branch' '
+       git branch > branch.output &&
+       test_cmp branch.expect branch.output
+'
 
-git checkout mybranch
-echo "Work, work, work" >>hello
-git commit -m 'Some work.' -i hello
+test_expect_success 'git resolve now fails' '
+       git checkout mybranch &&
+       echo "Work, work, work" >>hello &&
+       git commit -m "Some work." -i hello &&
 
-git checkout master
+       git checkout master &&
 
-echo "Play, play, play" >>hello
-echo "Lots of fun" >>example
-git commit -m 'Some fun.' -i hello example
+       echo "Play, play, play" >>hello &&
+       echo "Lots of fun" >>example &&
+       git commit -m "Some fun." -i hello example &&
 
-test_expect_success 'git resolve now fails' '
        test_must_fail git merge -m "Merge work in mybranch" mybranch
 '
 
@@ -112,52 +131,131 @@ Play, play, play
 Work, work, work
 EOF
 
-git commit -m 'Merged "mybranch" changes.' -i hello
-
-test_done
-
 cat > show-branch.expect << EOF
-* [master] Merged "mybranch" changes.
+* [master] Merge work in mybranch
  ! [mybranch] Some work.
 --
--  [master] Merged "mybranch" changes.
+-  [master] Merge work in mybranch
 *+ [mybranch] Some work.
+*  [master^] Some fun.
 EOF
 
-git show-branch --topo-order master mybranch > show-branch.output
-test_expect_success 'git show-branch' 'cmp show-branch.expect show-branch.output'
-
-git checkout mybranch
+test_expect_success 'git show-branch' '
+       git commit -m "Merge work in mybranch" -i hello &&
+       git show-branch --topo-order --more=1 master mybranch \
+               > show-branch.output &&
+       test_cmp show-branch.expect show-branch.output
+'
 
 cat > resolve.expect << EOF
-Updating from VARIABLE to VARIABLE
+Updating VARIABLE..VARIABLE
+FASTFORWARD (no commit created; -m option ignored)
  example |    1 +
  hello   |    1 +
  2 files changed, 2 insertions(+), 0 deletions(-)
 EOF
 
-git merge -s "Merge upstream changes." master | \
-       sed -e "1s/[0-9a-f]\{40\}/VARIABLE/g" >resolve.output
-test_expect_success 'git resolve' 'cmp resolve.expect resolve.output'
+test_expect_success 'git resolve' '
+       git checkout mybranch &&
+       git merge -m "Merge upstream changes." master |
+               sed -e "1s/[0-9a-f]\{7\}/VARIABLE/g" \
+               -e "s/^Fast[- ]forward /FASTFORWARD /" >resolve.output &&
+       test_cmp resolve.expect resolve.output
+'
 
 cat > show-branch2.expect << EOF
-! [master] Merged "mybranch" changes.
- * [mybranch] Merged "mybranch" changes.
+! [master] Merge work in mybranch
+ * [mybranch] Merge work in mybranch
+--
+-- [master] Merge work in mybranch
+EOF
+
+test_expect_success 'git show-branch (part 2)' '
+       git show-branch --topo-order master mybranch > show-branch2.output &&
+       test_cmp show-branch2.expect show-branch2.output
+'
+
+cat > show-branch3.expect << EOF
+! [master] Merge work in mybranch
+ * [mybranch] Merge work in mybranch
+--
+-- [master] Merge work in mybranch
++* [master^2] Some work.
++* [master^] Some fun.
+EOF
+
+test_expect_success 'git show-branch (part 3)' '
+       git show-branch --topo-order --more=2 master mybranch \
+               > show-branch3.output &&
+       test_cmp show-branch3.expect show-branch3.output
+'
+
+test_expect_success 'rewind to "Some fun." and "Some work."' '
+       git checkout mybranch &&
+       git reset --hard master^2 &&
+       git checkout master &&
+       git reset --hard master^
+'
+
+cat > show-branch4.expect << EOF
+* [master] Some fun.
+ ! [mybranch] Some work.
 --
--- [master] Merged "mybranch" changes.
+ + [mybranch] Some work.
+*  [master] Some fun.
+*+ [mybranch^] Initial commit
+EOF
+
+test_expect_success 'git show-branch (part 4)' '
+       git show-branch --topo-order > show-branch4.output &&
+       test_cmp show-branch4.expect show-branch4.output
+'
+
+test_expect_success 'manual merge' '
+       mb=$(git merge-base HEAD mybranch) &&
+       git name-rev --name-only --tags $mb > name-rev.output &&
+       test "my-first-tag" = $(cat name-rev.output) &&
+
+       git read-tree -m -u $mb HEAD mybranch
+'
+
+cat > ls-files.expect << EOF
+100644 7f8b141b65fdcee47321e399a2598a235a032422 0      example
+100644 557db03de997c86a4a028e1ebd3a1ceb225be238 1      hello
+100644 ba42a2a96e3027f3333e13ede4ccf4498c3ae942 2      hello
+100644 cc44c73eb783565da5831b4d820c962954019b69 3      hello
+EOF
+
+test_expect_success 'git ls-files --stage' '
+       git ls-files --stage > ls-files.output &&
+       test_cmp ls-files.expect ls-files.output
+'
+
+cat > ls-files-unmerged.expect << EOF
+100644 557db03de997c86a4a028e1ebd3a1ceb225be238 1      hello
+100644 ba42a2a96e3027f3333e13ede4ccf4498c3ae942 2      hello
+100644 cc44c73eb783565da5831b4d820c962954019b69 3      hello
 EOF
 
-git show-branch --topo-order master mybranch > show-branch2.output
-test_expect_success 'git show-branch' 'cmp show-branch2.expect show-branch2.output'
+test_expect_success 'git ls-files --unmerged' '
+       git ls-files --unmerged > ls-files-unmerged.output &&
+       test_cmp ls-files-unmerged.expect ls-files-unmerged.output
+'
 
-# TODO: test git fetch
+test_expect_success 'git-merge-index' '
+       test_must_fail git merge-index git-merge-one-file hello
+'
 
-# TODO: test git push
+test_expect_success 'git ls-files --stage (part 2)' '
+       git ls-files --stage > ls-files.output2 &&
+       test_cmp ls-files.expect ls-files.output2
+'
 
 test_expect_success 'git repack' 'git repack'
 test_expect_success 'git prune-packed' 'git prune-packed'
 test_expect_success '-> only packed objects' '
-       ! find -type f .git/objects/[0-9a-f][0-9a-f]
+       git prune && # Remove conflict marked blobs
+       ! find .git/objects/[0-9a-f][0-9a-f] -type f
 '
 
 test_done
diff --git a/t/t1402-check-ref-format.sh b/t/t1402-check-ref-format.sh
new file mode 100755 (executable)
index 0000000..eb45afb
--- /dev/null
@@ -0,0 +1,61 @@
+#!/bin/sh
+
+test_description='Test git check-ref-format'
+
+. ./test-lib.sh
+
+valid_ref() {
+       test_expect_success "ref name '$1' is valid" \
+               "git check-ref-format '$1'"
+}
+invalid_ref() {
+       test_expect_success "ref name '$1' is not valid" \
+               "test_must_fail git check-ref-format '$1'"
+}
+
+valid_ref 'heads/foo'
+invalid_ref 'foo'
+valid_ref 'foo/bar/baz'
+valid_ref 'refs///heads/foo'
+invalid_ref 'heads/foo/'
+invalid_ref './foo'
+invalid_ref '.refs/foo'
+invalid_ref 'heads/foo..bar'
+invalid_ref 'heads/foo?bar'
+valid_ref 'foo./bar'
+invalid_ref 'heads/foo.lock'
+valid_ref 'heads/foo@bar'
+invalid_ref 'heads/v@{ation'
+invalid_ref 'heads/foo\bar'
+
+test_expect_success "check-ref-format --branch @{-1}" '
+       T=$(git write-tree) &&
+       sha1=$(echo A | git commit-tree $T) &&
+       git update-ref refs/heads/master $sha1 &&
+       git update-ref refs/remotes/origin/master $sha1
+       git checkout master &&
+       git checkout origin/master &&
+       git checkout master &&
+       refname=$(git check-ref-format --branch @{-1}) &&
+       test "$refname" = "$sha1" &&
+       refname2=$(git check-ref-format --branch @{-2}) &&
+       test "$refname2" = master'
+
+valid_ref_normalized() {
+       test_expect_success "ref name '$1' simplifies to '$2'" "
+               refname=\$(git check-ref-format --print '$1') &&
+               test \"\$refname\" = '$2'"
+}
+invalid_ref_normalized() {
+       test_expect_success "check-ref-format --print rejects '$1'" "
+               test_must_fail git check-ref-format --print '$1'"
+}
+
+valid_ref_normalized 'heads/foo' 'heads/foo'
+valid_ref_normalized 'refs///heads/foo' 'refs/heads/foo'
+invalid_ref_normalized 'foo'
+invalid_ref_normalized 'heads/foo/../bar'
+invalid_ref_normalized 'heads/./foo'
+invalid_ref_normalized 'heads\foo'
+
+test_done
diff --git a/t/t3003-ls-files-exclude.sh b/t/t3003-ls-files-exclude.sh
new file mode 100755 (executable)
index 0000000..d5ec333
--- /dev/null
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+test_description='ls-files --exclude does not affect index files'
+. ./test-lib.sh
+
+test_expect_success 'create repo with file' '
+       echo content >file &&
+       git add file &&
+       git commit -m file &&
+       echo modification >file
+'
+
+check_output() {
+test_expect_success "ls-files output contains file ($1)" "
+       echo '$2' >expect &&
+       git ls-files --exclude-standard --$1 >output &&
+       test_cmp expect output
+"
+}
+
+check_all_output() {
+       check_output 'cached' 'file'
+       check_output 'modified' 'file'
+}
+
+check_all_output
+test_expect_success 'add file to gitignore' '
+       echo file >.gitignore
+'
+check_all_output
+
+test_expect_success 'ls-files -i lists only tracked-but-ignored files' '
+       echo content >other-file &&
+       git add other-file &&
+       echo file >expect &&
+       git ls-files -i --exclude-standard >output &&
+       test_cmp expect output
+'
+
+test_done
index 51cb4a30f571772399697bc073153b7e956853bf..8be9fb411276e3c416374a813d691ff0455a8746 100755 (executable)
@@ -39,8 +39,8 @@ test_expect_success \
      tree=`git write-tree` &&
      echo $tree'
 
-_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
-_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
+_x05='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
+_x40="$_x05$_x05$_x05$_x05$_x05$_x05$_x05$_x05"
 test_output () {
     sed -e "s/ $_x40   / X     /" <current >check
     test_cmp expected check
@@ -141,4 +141,89 @@ test_expect_success 'ls-tree filter is leading path match' '
        test_output
 '
 
+test_expect_success 'ls-tree --full-name' '
+       (
+               cd path0 &&
+               git ls-tree --full-name $tree a
+       ) >current &&
+       cat >expected <<\EOF &&
+040000 tree X  path0/a
+EOF
+       test_output
+'
+
+test_expect_success 'ls-tree --full-tree' '
+       (
+               cd path1/b/c &&
+               git ls-tree --full-tree $tree
+       ) >current &&
+       cat >expected <<\EOF &&
+100644 blob X  1.txt
+100644 blob X  2.txt
+040000 tree X  path0
+040000 tree X  path1
+040000 tree X  path2
+040000 tree X  path3
+EOF
+       test_output
+'
+
+test_expect_success 'ls-tree --full-tree -r' '
+       (
+               cd path3/ &&
+               git ls-tree --full-tree -r $tree
+       ) >current &&
+       cat >expected <<\EOF &&
+100644 blob X  1.txt
+100644 blob X  2.txt
+100644 blob X  path0/a/b/c/1.txt
+100644 blob X  path1/b/c/1.txt
+100644 blob X  path2/1.txt
+100644 blob X  path3/1.txt
+100644 blob X  path3/2.txt
+EOF
+       test_output
+'
+
+test_expect_success 'ls-tree --abbrev=5' '
+       git ls-tree --abbrev=5 $tree >current &&
+       sed -e "s/ $_x05[0-9a-f]*       / X     /" <current >check &&
+       cat >expected <<\EOF &&
+100644 blob X  1.txt
+100644 blob X  2.txt
+040000 tree X  path0
+040000 tree X  path1
+040000 tree X  path2
+040000 tree X  path3
+EOF
+       test_cmp expected check
+'
+
+test_expect_success 'ls-tree --name-only' '
+       git ls-tree --name-only $tree >current
+       cat >expected <<\EOF &&
+1.txt
+2.txt
+path0
+path1
+path2
+path3
+EOF
+       test_output
+'
+
+test_expect_success 'ls-tree --name-only -r' '
+       git ls-tree --name-only -r $tree >current
+       cat >expected <<\EOF &&
+1.txt
+2.txt
+path0/a/b/c/1.txt
+path1/b/c/1.txt
+path2/1.txt
+path3/1.txt
+path3/2.txt
+EOF
+       test_output
+'
+
 test_done
index 4cae019521f988fe6a3eea0902d35dbbdae32dc8..3a37793c0ddbdab8820dba033521d5e113bc33ac 100755 (executable)
@@ -470,4 +470,18 @@ test_expect_success 'avoid unnecessary reset' '
        test 123456789 = $MTIME
 '
 
+test_expect_success 'reword' '
+       git checkout -b reword-branch master &&
+       FAKE_LINES="1 2 3 reword 4" FAKE_COMMIT_MESSAGE="E changed" git rebase -i A &&
+       git show HEAD | grep "E changed" &&
+       test $(git rev-parse master) != $(git rev-parse HEAD) &&
+       test $(git rev-parse master^) = $(git rev-parse HEAD^) &&
+       FAKE_LINES="1 2 reword 3 4" FAKE_COMMIT_MESSAGE="D changed" git rebase -i A &&
+       git show HEAD^ | grep "D changed" &&
+       FAKE_LINES="reword 1 2 3 4" FAKE_COMMIT_MESSAGE="B changed" git rebase -i A &&
+       git show HEAD~3 | grep "B changed" &&
+       FAKE_LINES="1 reword 2 3 4" FAKE_COMMIT_MESSAGE="C changed" git rebase -i A &&
+       git show HEAD~2 | grep "C changed"
+'
+
 test_done
index 62fd65e18d434711176ddb1c22ef057b879e992a..d86bc81abfd954194c245e7e180a23f2b9b7c840 100755 (executable)
@@ -138,6 +138,20 @@ test_expect_success 'real edit works' '
        test_cmp expected output
 '
 
+test_expect_success 'skip files similarly as commit -a' '
+       git reset &&
+       echo file >.gitignore &&
+       echo changed >file &&
+       echo y | git add -p file &&
+       git diff >output &&
+       git reset &&
+       git commit -am commit &&
+       git diff >expected &&
+       test_cmp expected output &&
+       git reset --hard HEAD^
+'
+rm -f .gitignore
+
 if test "$(git config --bool core.filemode)" = false
 then
        say 'skipping filemode tests (filesystem does not properly support modes)'
@@ -214,4 +228,21 @@ test_expect_success 'add first line works' '
        test_cmp expected diff
 '
 
+cat >expected <<EOF
+diff --git a/empty b/empty
+deleted file mode 100644
+index e69de29..0000000
+EOF
+
+test_expect_success 'deleting an empty file' '
+       git reset --hard &&
+       > empty &&
+       git add empty &&
+       git commit -m empty &&
+       rm empty &&
+       echo y | git add -p empty &&
+       git diff --cached >diff &&
+       test_cmp expected diff
+'
+
 test_done
index 903d9d96595243b83d102004869e18f4df1ea3bb..d155e0bab29000a99eb797681450be1174185846 100644 (file)
@@ -1,5 +1,5 @@
 $ git log --decorate=full --all
-commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (refs/heads/master)
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD, refs/heads/master)
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
index 954210ea907cb04f6113d82194c0753019270d8a..fd7c3e64396b4ea57c3b03d2e120580205263462 100644 (file)
@@ -1,5 +1,5 @@
 $ git log --decorate --all
-commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (master)
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD, master)
 Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
index 531f5b795c197d942223db3cdc2d2030208e9beb..5689d590fd80e0c664000f573c64262b54243982 100755 (executable)
@@ -455,6 +455,27 @@ test_expect_success 'format-patch respects -U' '
 
 '
 
+cat > expect << EOF
+
+diff --git a/file b/file
+index 40f36c6..2dc5c23 100644
+--- a/file
++++ b/file
+@@ -14,3 +14,19 @@ C
+ D
+ E
+ F
++5
+EOF
+
+test_expect_success 'format-patch -p suppresses stat' '
+
+       git format-patch -p -2 &&
+       sed -e "1,/^$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
+       test_cmp expect output
+
+'
+
 test_expect_success 'format-patch from a subdirectory (1)' '
        filename=$(
                rm -rf sub &&
@@ -515,4 +536,22 @@ test_expect_success 'format-patch --signoff' '
        grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
 '
 
+echo "fatal: --name-only does not make sense" > expect.name-only
+echo "fatal: --name-status does not make sense" > expect.name-status
+echo "fatal: --check does not make sense" > expect.check
+
+test_expect_success 'options no longer allowed for format-patch' '
+       test_must_fail git format-patch --name-only 2> output &&
+       test_cmp expect.name-only output &&
+       test_must_fail git format-patch --name-status 2> output &&
+       test_cmp expect.name-status output &&
+       test_must_fail git format-patch --check 2> output &&
+       test_cmp expect.check output'
+
+test_expect_success 'format-patch --numstat should produce a patch' '
+       git format-patch --numstat --stdout master..side |
+       grep "^diff --git a/" |
+       wc -l |
+       xargs test 6 = '
+
 test_done
index 6d13da30dad5a78fb17a01e86ef33072ea9e6250..8dd147d78f6ee6a4be4b1af235ed35af19b273df 100755 (executable)
@@ -362,10 +362,17 @@ test_expect_success 'line numbers in --check output are correct' '
 
 '
 
-test_expect_success 'checkdiff detects trailing blank lines' '
+test_expect_success 'checkdiff detects new trailing blank lines (1)' '
        echo "foo();" >x &&
        echo "" >>x &&
-       git diff --check | grep "ends with blank"
+       git diff --check | grep "new blank line"
+'
+
+test_expect_success 'checkdiff detects new trailing blank lines (2)' '
+       { echo a; echo b; echo; echo; } >x &&
+       git add x &&
+       { echo a; echo; echo; echo; echo; } >x &&
+       git diff --check | grep "new blank line"
 '
 
 test_expect_success 'checkdiff allows new blank lines' '
index 84a1fe31151c2af38554eaca8f03e2c1e2e7848f..3a3663fbcb4795a9e3755fe831c89a7e312f659e 100755 (executable)
@@ -165,7 +165,7 @@ test_expect_success 'trailing empty lines (1)' '
 
        rm -f .gitattributes &&
        test_must_fail git diff --check >output &&
-       grep "ends with blank lines." output &&
+       grep "new blank line at" output &&
        grep "trailing whitespace" output
 
 '
@@ -190,4 +190,13 @@ test_expect_success 'do not color trailing cr in context' '
 
 '
 
+test_expect_success 'color new trailing blank lines' '
+       { echo a; echo b; echo; echo; } >x &&
+       git add x &&
+       { echo a; echo; echo; echo; echo c; echo; echo; echo; echo; } >x &&
+       git diff --color x >output &&
+       cnt=$(grep "${blue_grep}" output | wc -l) &&
+       test $cnt = 2
+'
+
 test_done
index 4508effcaacd3dbc8fadb13c7be0d631f4c946f1..21db6e95c4dd7ccf2f25d887fc2c42f3adcd4124 100755 (executable)
@@ -63,6 +63,26 @@ test_expect_success 'word diff with runs of whitespace' '
 
 '
 
+cat > expect <<\EOF
+<WHITE>diff --git a/pre b/post<RESET>
+<WHITE>index 330b04f..5ed8eff 100644<RESET>
+<WHITE>--- a/pre<RESET>
+<WHITE>+++ b/post<RESET>
+<BROWN>@@ -1 +1 @@<RESET>
+<RED>h(4)<RESET><GREEN>h(4),hh[44]<RESET>
+<BROWN>@@ -3,0 +4,4 @@ a = b + c<RESET>
+
+<GREEN>aa = a<RESET>
+
+<GREEN>aeff = aeff * ( aaa )<RESET>
+EOF
+
+test_expect_success 'word diff without context' '
+
+       word_diff --color-words --unified=0
+
+'
+
 cat > expect <<\EOF
 <WHITE>diff --git a/pre b/post<RESET>
 <WHITE>index 330b04f..5ed8eff 100644<RESET>
diff --git a/t/t4041-diff-submodule.sh b/t/t4041-diff-submodule.sh
new file mode 100755 (executable)
index 0000000..5bb4fed
--- /dev/null
@@ -0,0 +1,260 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Jens Lehmann, based on t7401 by Ping Yin
+#
+
+test_description='Support for verbose submodule differences in git diff
+
+This test tries to verify the sanity of the --submodule option of git diff.
+'
+
+. ./test-lib.sh
+
+add_file () {
+       sm=$1
+       shift
+       owd=$(pwd)
+       cd "$sm"
+       for name; do
+               echo "$name" > "$name" &&
+               git add "$name" &&
+               test_tick &&
+               git commit -m "Add $name"
+       done >/dev/null
+       git rev-parse --verify HEAD | cut -c1-7
+       cd "$owd"
+}
+commit_file () {
+       test_tick &&
+       git commit "$@" -m "Commit $*" >/dev/null
+}
+
+test_create_repo sm1 &&
+add_file . foo >/dev/null
+
+head1=$(add_file sm1 foo1 foo2)
+
+test_expect_success 'added submodule' "
+       git add sm1 &&
+       git diff-index -p --submodule=log HEAD >actual &&
+       diff actual - <<-EOF
+Submodule sm1 0000000...$head1 (new submodule)
+EOF
+"
+
+commit_file sm1 &&
+head2=$(add_file sm1 foo3)
+
+test_expect_success 'modified submodule(forward)' "
+       git diff-index -p --submodule=log HEAD >actual &&
+       diff actual - <<-EOF
+Submodule sm1 $head1..$head2:
+  > Add foo3
+EOF
+"
+
+test_expect_success 'modified submodule(forward)' "
+       git diff --submodule=log >actual &&
+       diff actual - <<-EOF
+Submodule sm1 $head1..$head2:
+  > Add foo3
+EOF
+"
+
+test_expect_success 'modified submodule(forward) --submodule' "
+       git diff --submodule >actual &&
+       diff actual - <<-EOF
+Submodule sm1 $head1..$head2:
+  > Add foo3
+EOF
+"
+
+fullhead1=$(cd sm1; git rev-list --max-count=1 $head1)
+fullhead2=$(cd sm1; git rev-list --max-count=1 $head2)
+test_expect_success 'modified submodule(forward) --submodule=short' "
+       git diff --submodule=short >actual &&
+       diff actual - <<-EOF
+diff --git a/sm1 b/sm1
+index $head1..$head2 160000
+--- a/sm1
++++ b/sm1
+@@ -1 +1 @@
+-Subproject commit $fullhead1
++Subproject commit $fullhead2
+EOF
+"
+
+commit_file sm1 &&
+cd sm1 &&
+git reset --hard HEAD~2 >/dev/null &&
+head3=$(git rev-parse --verify HEAD | cut -c1-7) &&
+cd ..
+
+test_expect_success 'modified submodule(backward)' "
+       git diff-index -p --submodule=log HEAD >actual &&
+       diff actual - <<-EOF
+Submodule sm1 $head2..$head3 (rewind):
+  < Add foo3
+  < Add foo2
+EOF
+"
+
+head4=$(add_file sm1 foo4 foo5) &&
+head4_full=$(GIT_DIR=sm1/.git git rev-parse --verify HEAD)
+test_expect_success 'modified submodule(backward and forward)' "
+       git diff-index -p --submodule=log HEAD >actual &&
+       diff actual - <<-EOF
+Submodule sm1 $head2...$head4:
+  > Add foo5
+  > Add foo4
+  < Add foo3
+  < Add foo2
+EOF
+"
+
+commit_file sm1 &&
+mv sm1 sm1-bak &&
+echo sm1 >sm1 &&
+head5=$(git hash-object sm1 | cut -c1-7) &&
+git add sm1 &&
+rm -f sm1 &&
+mv sm1-bak sm1
+
+test_expect_success 'typechanged submodule(submodule->blob), --cached' "
+       git diff --submodule=log --cached >actual &&
+       diff actual - <<-EOF
+Submodule sm1 41fbea9...0000000 (submodule deleted)
+diff --git a/sm1 b/sm1
+new file mode 100644
+index 0000000..9da5fb8
+--- /dev/null
++++ b/sm1
+@@ -0,0 +1 @@
++sm1
+EOF
+"
+
+test_expect_success 'typechanged submodule(submodule->blob)' "
+       git diff --submodule=log >actual &&
+       diff actual - <<-EOF
+diff --git a/sm1 b/sm1
+deleted file mode 100644
+index 9da5fb8..0000000
+--- a/sm1
++++ /dev/null
+@@ -1 +0,0 @@
+-sm1
+Submodule sm1 0000000...$head4 (new submodule)
+EOF
+"
+
+rm -rf sm1 &&
+git checkout-index sm1
+test_expect_success 'typechanged submodule(submodule->blob)' "
+       git diff-index -p --submodule=log HEAD >actual &&
+       diff actual - <<-EOF
+Submodule sm1 $head4...0000000 (submodule deleted)
+diff --git a/sm1 b/sm1
+new file mode 100644
+index 0000000..$head5
+--- /dev/null
++++ b/sm1
+@@ -0,0 +1 @@
++sm1
+EOF
+"
+
+rm -f sm1 &&
+test_create_repo sm1 &&
+head6=$(add_file sm1 foo6 foo7)
+fullhead6=$(cd sm1; git rev-list --max-count=1 $head6)
+test_expect_success 'nonexistent commit' "
+       git diff-index -p --submodule=log HEAD >actual &&
+       diff actual - <<-EOF
+Submodule sm1 $head4...$head6 (commits not present)
+EOF
+"
+
+commit_file
+test_expect_success 'typechanged submodule(blob->submodule)' "
+       git diff-index -p --submodule=log HEAD >actual &&
+       diff actual - <<-EOF
+diff --git a/sm1 b/sm1
+deleted file mode 100644
+index $head5..0000000
+--- a/sm1
++++ /dev/null
+@@ -1 +0,0 @@
+-sm1
+Submodule sm1 0000000...$head6 (new submodule)
+EOF
+"
+
+commit_file sm1 &&
+rm -rf sm1
+test_expect_success 'deleted submodule' "
+       git diff-index -p --submodule=log HEAD >actual &&
+       diff actual - <<-EOF
+Submodule sm1 $head6...0000000 (submodule deleted)
+EOF
+"
+
+test_create_repo sm2 &&
+head7=$(add_file sm2 foo8 foo9) &&
+git add sm2
+
+test_expect_success 'multiple submodules' "
+       git diff-index -p --submodule=log HEAD >actual &&
+       diff actual - <<-EOF
+Submodule sm1 $head6...0000000 (submodule deleted)
+Submodule sm2 0000000...$head7 (new submodule)
+EOF
+"
+
+test_expect_success 'path filter' "
+       git diff-index -p --submodule=log HEAD sm2 >actual &&
+       diff actual - <<-EOF
+Submodule sm2 0000000...$head7 (new submodule)
+EOF
+"
+
+commit_file sm2
+test_expect_success 'given commit' "
+       git diff-index -p --submodule=log HEAD^ >actual &&
+       diff actual - <<-EOF
+Submodule sm1 $head6...0000000 (submodule deleted)
+Submodule sm2 0000000...$head7 (new submodule)
+EOF
+"
+
+test_expect_success 'given commit --submodule' "
+       git diff-index -p --submodule HEAD^ >actual &&
+       diff actual - <<-EOF
+Submodule sm1 $head6...0000000 (submodule deleted)
+Submodule sm2 0000000...$head7 (new submodule)
+EOF
+"
+
+fullhead7=$(cd sm2; git rev-list --max-count=1 $head7)
+
+test_expect_success 'given commit --submodule=short' "
+       git diff-index -p --submodule=short HEAD^ >actual &&
+       diff actual - <<-EOF
+diff --git a/sm1 b/sm1
+deleted file mode 160000
+index $head6..0000000
+--- a/sm1
++++ /dev/null
+@@ -1 +0,0 @@
+-Subproject commit $fullhead6
+diff --git a/sm2 b/sm2
+new file mode 160000
+index 0000000..$head7
+--- /dev/null
++++ b/sm2
+@@ -0,0 +1 @@
++Subproject commit $fullhead7
+EOF
+"
+
+test_done
index fac2093d7f20d502f41f895d2ccdfccd5e639e2b..ca26397590f3d79455c41894203fbff7bb6a9c3c 100755 (executable)
@@ -170,4 +170,95 @@ test_expect_success 'trailing whitespace & no newline at the end of file' '
        grep "^$" target
 '
 
+test_expect_success 'blank at EOF with --whitespace=fix (1)' '
+       : these can fail depending on what we did before
+       git config --unset core.whitespace
+       rm -f .gitattributes
+
+       { echo a; echo b; echo c; } >one &&
+       git add one &&
+       { echo a; echo b; echo c; } >expect &&
+       { cat expect; echo; } >one &&
+       git diff -- one >patch &&
+
+       git checkout one &&
+       git apply --whitespace=fix patch &&
+       test_cmp expect one
+'
+
+test_expect_success 'blank at EOF with --whitespace=fix (2)' '
+       { echo a; echo b; echo c; } >one &&
+       git add one &&
+       { echo a; echo c; } >expect &&
+       { cat expect; echo; echo; } >one &&
+       git diff -- one >patch &&
+
+       git checkout one &&
+       git apply --whitespace=fix patch &&
+       test_cmp expect one
+'
+
+test_expect_success 'blank at EOF with --whitespace=fix (3)' '
+       { echo a; echo b; echo; } >one &&
+       git add one &&
+       { echo a; echo c; echo; } >expect &&
+       { cat expect; echo; echo; } >one &&
+       git diff -- one >patch &&
+
+       git checkout one &&
+       git apply --whitespace=fix patch &&
+       test_cmp expect one
+'
+
+test_expect_success 'blank at end of hunk, not at EOF with --whitespace=fix' '
+       { echo a; echo b; echo; echo; echo; echo; echo; echo d; } >one &&
+       git add one &&
+       { echo a; echo c; echo; echo; echo; echo; echo; echo; echo d; } >expect &&
+       cp expect one &&
+       git diff -- one >patch &&
+
+       git checkout one &&
+       git apply --whitespace=fix patch &&
+       test_cmp expect one
+'
+
+test_expect_success 'blank at EOF with --whitespace=warn' '
+       { echo a; echo b; echo c; } >one &&
+       git add one &&
+       echo >>one &&
+       cat one >expect &&
+       git diff -- one >patch &&
+
+       git checkout one &&
+       git apply --whitespace=warn patch 2>error &&
+       test_cmp expect one &&
+       grep "new blank line at EOF" error
+'
+
+test_expect_success 'blank at EOF with --whitespace=error' '
+       { echo a; echo b; echo c; } >one &&
+       git add one &&
+       cat one >expect &&
+       echo >>one &&
+       git diff -- one >patch &&
+
+       git checkout one &&
+       test_must_fail git apply --whitespace=error patch 2>error &&
+       test_cmp expect one &&
+       grep "new blank line at EOF" error
+'
+
+test_expect_success 'blank but not empty at EOF' '
+       { echo a; echo b; echo c; } >one &&
+       git add one &&
+       echo "   " >>one &&
+       cat one >expect &&
+       git diff -- one >patch &&
+
+       git checkout one &&
+       git apply --whitespace=warn patch 2>error &&
+       test_cmp expect one &&
+       grep "new blank line at EOF" error
+'
+
 test_done
diff --git a/t/t5100/.gitattributes b/t/t5100/.gitattributes
new file mode 100644 (file)
index 0000000..c93f514
--- /dev/null
@@ -0,0 +1,4 @@
+msg*   encoding=UTF-8
+info*  encoding=UTF-8
+rfc2047-info-* encoding=UTF-8
+sample.mbox    encoding=UTF-8
diff --git a/t/t5100/0010 b/t/t5100/0010
deleted file mode 100644 (file)
index f5892c9..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-From b9704a518e21158433baa2cc2d591fea687967f6 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Lukas=20Sandstr=C3=B6m?= <lukass@etek.chalmers.se>
-Date: Thu, 10 Jul 2008 23:41:33 +0200
-Subject: Re: discussion that lead to this patch
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-[PATCH] git-mailinfo: Fix getting the subject from the body
-
-"Subject: " isn't in the static array "header", and thus
-memcmp("Subject: ", header[i], 7) will never match.
-
-Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>
-Signed-off-by: Junio C Hamano <gitster@pobox.com>
----
- builtin-mailinfo.c |    2 +-
- 1 files changed, 1 insertions(+), 1 deletions(-)
-
-diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c
-index 962aa34..2d1520f 100644
---- a/builtin-mailinfo.c
-+++ b/builtin-mailinfo.c
-@@ -334,7 +334,7 @@ static int check_header(char *line, unsigned linesize, char **hdr_data, int over
-               return 1;
-       if (!memcmp("[PATCH]", line, 7) && isspace(line[7])) {
-               for (i = 0; header[i]; i++) {
--                      if (!memcmp("Subject: ", header[i], 9)) {
-+                      if (!memcmp("Subject", header[i], 7)) {
-                               if (! handle_header(line, hdr_data[i], 0)) {
-                                       return 1;
-                               }
--- 
-1.5.6.2.455.g1efb2
-
index 5132d4130968691bb115f5fc08cd0d2fd64ce669..5f6cd4f3332f600888c402d2f1b72ddc8840b8cf 100755 (executable)
@@ -275,4 +275,13 @@ test_expect_success \
      git cat-file blob $blob_2 > /dev/null &&
      git cat-file blob $blob_3 > /dev/null'
 
+test_expect_success \
+    'corrupting header to have too small output buffer fails unpack' \
+    'create_new_pack &&
+     git prune-packed &&
+     printf "\262\001" | do_corrupt_object $blob_1 0 &&
+     test_must_fail git cat-file blob $blob_1 > /dev/null &&
+     test_must_fail git cat-file blob $blob_2 > /dev/null &&
+     test_must_fail git cat-file blob $blob_3 > /dev/null'
+
 test_done
index 852ccb5d7d649a71eeab25eadce6940b9c2a6f63..220b6a341377fadfef34208dd7316bbb7e39e12d 100755 (executable)
@@ -158,7 +158,7 @@ cat > test/expect << EOF
     another
     master
   Local refs configured for 'git push':
-    ahead  forces to master  (fast forwardable)
+    ahead  forces to master  (fast-forwardable)
     master pushes to another (up to date)
 EOF
 
index d13c806624bcc8a404be97d61500e8e1d4614c6b..169af1edde557f054ea76b8de681c6dd74e436f2 100755 (executable)
@@ -341,4 +341,15 @@ test_expect_success 'fetch into the current branch with --update-head-ok' '
 
 '
 
+test_expect_success "should be able to fetch with duplicate refspecs" '
+        mkdir dups &&
+        cd dups &&
+        git init &&
+        git config branch.master.remote three &&
+        git config remote.three.url ../three/.git &&
+        git config remote.three.fetch +refs/heads/*:refs/remotes/origin/* &&
+        git config --add remote.three.fetch +refs/heads/*:refs/remotes/origin/* &&
+        git fetch three
+'
+
 test_done
index c6bc65faa06adeaced0733064fb09eb82add585e..c2060bb870f35a3819fabb19c97e921e0ae43349 100755 (executable)
@@ -22,7 +22,7 @@ test_expect_success setup '
        git commit -a -m next
 '
 
-test_expect_success 'non fast forward fetch' '
+test_expect_success 'non-fast-forward fetch' '
 
        test_must_fail git fetch . master:side
 
index 59d1f6283bec5cf7740d988dfd090c1463389c71..7f61ab0e522fd28c5e10594f03ed9076f9f5ce42 100755 (executable)
@@ -162,4 +162,22 @@ test_expect_success 'empty email' '
        }
 '
 
+test_expect_success '"%h %gD: %gs" is same as git-reflog' '
+       git reflog >expect &&
+       git log -g --format="%h %gD: %gs" >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success '"%h %gD: %gs" is same as git-reflog (with date)' '
+       git reflog --date=raw >expect &&
+       git log -g --format="%h %gD: %gs" --date=raw >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success '%gd shortens ref name' '
+       echo "master@{0}" >expect.gd-short &&
+       git log -g -1 --format=%gd refs/heads/master >actual.gd-short &&
+       test_cmp expect.gd-short actual.gd-short
+'
+
 test_done
index f8f3e3ff2c00df468f5703a4e0ac31f52e42e06d..a91644e3b2ac3490cfe49d5e67c9736197cd56a1 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-test_description='merge fast forward and up to date'
+test_description='merge fast-forward and up to date'
 
 . ./test-lib.sh
 
index 8b8bd81c099964d188c8152f670a5b45e8739954..d4818b430aad556cec959d8be221eb7548a55707 100755 (executable)
@@ -70,6 +70,13 @@ test_expect_success 'replace the author' '
      git show $HASH2 | grep "O Thor"
 '
 
+test_expect_success 'test --no-replace-objects option' '
+     git cat-file commit $HASH2 | grep "author O Thor" &&
+     git --no-replace-objects cat-file commit $HASH2 | grep "author A U Thor" &&
+     git show $HASH2 | grep "O Thor" &&
+     git --no-replace-objects show $HASH2 | grep "A U Thor"
+'
+
 cat >tag.sig <<EOF
 object $HASH2
 type commit
index 8c7e081c53eec31d38844d8efb9b942893107b09..065deadc29eb3838f391ce758c4b188249dc87f9 100755 (executable)
@@ -34,6 +34,8 @@ test_expect_success setup '
        echo one >file && git add file && git commit -m initial &&
        one=$(git rev-parse HEAD) &&
 
+       git describe --always HEAD &&
+
        test_tick &&
        echo two >file && git add file && git commit -m second &&
        two=$(git rev-parse HEAD) &&
@@ -90,12 +92,18 @@ check_describe A-* HEAD^
 check_describe D-* HEAD^^
 check_describe A-* HEAD^^2
 check_describe B HEAD^^2^
+check_describe D-* HEAD^^^
 
 check_describe c-* --tags HEAD
 check_describe c-* --tags HEAD^
 check_describe e-* --tags HEAD^^
 check_describe c-* --tags HEAD^^2
 check_describe B --tags HEAD^^2^
+check_describe e --tags HEAD^^^
+
+check_describe heads/master --all HEAD
+check_describe tags/c-* --all HEAD^
+check_describe tags/e --all HEAD^^^
 
 check_describe B-0-* --long HEAD^^2^
 check_describe A-3-* --long HEAD^^2
@@ -123,6 +131,20 @@ test_expect_success 'rename tag Q back to A' '
 test_expect_success 'pack tag refs' 'git pack-refs'
 check_describe A-* HEAD
 
+check_describe "A-*[0-9a-f]" --dirty
+
+test_expect_success 'set-up dirty work tree' '
+       echo >>file
+'
+
+check_describe "A-*[0-9a-f]-dirty" --dirty
+
+check_describe "A-*[0-9a-f].mod" --dirty=.mod
+
+test_expect_success 'describe --dirty HEAD' '
+       test_must_fail git describe --dirty HEAD
+'
+
 test_expect_success 'set-up matching pattern tests' '
        git tag -a -m test-annotated test-annotated &&
        echo >>file &&
index ae56a36eacbc2d9a796742c974fa498705f71104..ae5290ab43e8b51b32331768371e2a67d700064d 100755 (executable)
@@ -213,6 +213,72 @@ test_expect_success 'grep -e A --and --not -e B' '
        test_cmp expected actual
 '
 
+test_expect_success 'grep -f, non-existent file' '
+       test_must_fail git grep -f patterns
+'
+
+cat >expected <<EOF
+file:foo mmap bar
+file:foo_mmap bar
+file:foo_mmap bar mmap
+file:foo mmap bar_mmap
+file:foo_mmap bar mmap baz
+EOF
+
+cat >pattern <<EOF
+mmap
+EOF
+
+test_expect_success 'grep -f, one pattern' '
+       git grep -f pattern >actual &&
+       test_cmp expected actual
+'
+
+cat >expected <<EOF
+file:foo mmap bar
+file:foo_mmap bar
+file:foo_mmap bar mmap
+file:foo mmap bar_mmap
+file:foo_mmap bar mmap baz
+t/a/v:vvv
+t/v:vvv
+v:vvv
+EOF
+
+cat >patterns <<EOF
+mmap
+vvv
+EOF
+
+test_expect_success 'grep -f, multiple patterns' '
+       git grep -f patterns >actual &&
+       test_cmp expected actual
+'
+
+cat >expected <<EOF
+file:foo mmap bar
+file:foo_mmap bar
+file:foo_mmap bar mmap
+file:foo mmap bar_mmap
+file:foo_mmap bar mmap baz
+t/a/v:vvv
+t/v:vvv
+v:vvv
+EOF
+
+cat >patterns <<EOF
+
+mmap
+
+vvv
+
+EOF
+
+test_expect_success 'grep -f, ignore empty lines' '
+       git grep -f patterns >actual &&
+       test_cmp expected actual
+'
+
 cat >expected <<EOF
 y:y yy
 --
index 329c851685b1c663ee88d45a5d21d452a293fa8e..9503875e97e09ad94283e63ae298551453e5787a 100755 (executable)
@@ -288,4 +288,22 @@ test_expect_success 'Prune empty commits' '
        test_cmp expect actual
 '
 
+test_expect_success '--remap-to-ancestor with filename filters' '
+       git checkout master &&
+       git reset --hard A &&
+       test_commit add-foo foo 1 &&
+       git branch moved-foo &&
+       test_commit add-bar bar a &&
+       git branch invariant &&
+       orig_invariant=$(git rev-parse invariant) &&
+       git branch moved-bar &&
+       test_commit change-foo foo 2 &&
+       git filter-branch -f --remap-to-ancestor \
+               moved-foo moved-bar A..master \
+               -- -- foo &&
+       test $(git rev-parse moved-foo) = $(git rev-parse moved-bar) &&
+       test $(git rev-parse moved-foo) = $(git rev-parse master^) &&
+       test $orig_invariant = $(git rev-parse invariant)
+'
+
 test_done
index 0f2ccc6cf0123951d9bdbb880931868f29de5b4e..a0cc99ab9f5b262851a1075193f5529b5582fd0a 100755 (executable)
@@ -306,4 +306,20 @@ test_expect_success 'submodule <invalid-path> warns' '
 
 '
 
+test_expect_success 'add submodules without specifying an explicit path' '
+       mkdir repo &&
+       cd repo &&
+       git init &&
+       echo r >r &&
+       git add r &&
+       git commit -m "repo commit 1" &&
+       cd .. &&
+       git clone --bare repo/ bare.git &&
+       cd addtest &&
+       git submodule add "$submodurl/repo" &&
+       git config -f .gitmodules submodule.repo.path repo &&
+       git submodule add "$submodurl/bare.git" &&
+       git config -f .gitmodules submodule.bare.path bare
+'
+
 test_done
index e2ef53228ecc6162afdcce78109d426e154b7caa..d2de57679f9ee347a5e77e751ae7767f9980f84e 100755 (executable)
@@ -247,6 +247,47 @@ $existing" &&
 
 '
 
+test_expect_success 'signoff gap' '
+
+       echo 3 >positive &&
+       git add positive &&
+       alt="Alt-RFC-822-Header: Value" &&
+       git commit -s -m "welcome
+
+$alt" &&
+       git cat-file commit HEAD | sed -e "1,/^\$/d" > actual &&
+       (
+               echo welcome
+               echo
+               echo $alt
+               git var GIT_COMMITTER_IDENT |
+               sed -e "s/>.*/>/" -e "s/^/Signed-off-by: /"
+       ) >expected &&
+       test_cmp expected actual
+'
+
+test_expect_success 'signoff gap 2' '
+
+       echo 4 >positive &&
+       git add positive &&
+       alt="fixed: 34" &&
+       git commit -s -m "welcome
+
+We have now
+$alt" &&
+       git cat-file commit HEAD | sed -e "1,/^\$/d" > actual &&
+       (
+               echo welcome
+               echo
+               echo We have now
+               echo $alt
+               echo
+               git var GIT_COMMITTER_IDENT |
+               sed -e "s/>.*/>/" -e "s/^/Signed-off-by: /"
+       ) >expected &&
+       test_cmp expected actual
+'
+
 test_expect_success 'multiple -m' '
 
        >negative &&
index 56cd866019dcc871e5dea684f1d879fcf2c1b884..fe94552296bb98ef78dbc51e8b1f7d4a665cf0a4 100755 (executable)
@@ -258,4 +258,13 @@ test_expect_success 'Hand committing of a redundant merge removes dups' '
 
 '
 
+test_expect_success 'A single-liner subject with a token plus colon is not a footer' '
+
+       git reset --hard &&
+       git commit -s -m "hello: kitty" --allow-empty &&
+       git cat-file commit HEAD | sed -e "1,/^$/d" >actual &&
+       test $(wc -l <actual) = 3
+
+'
+
 test_done
index e5b210bc960c8433d6758f3932a86647208297ef..57f6d2bae7c63f13ee18e11737dbdcc0c080ab10 100755 (executable)
@@ -243,6 +243,16 @@ test_expect_success 'merge c0 with c1' '
 
 test_debug 'gitk --all'
 
+test_expect_success 'merge c0 with c1 with --ff-only' '
+       git reset --hard c0 &&
+       git merge --ff-only c1 &&
+       git merge --ff-only HEAD c0 c1 &&
+       verify_merge file result.1 &&
+       verify_head "$c1"
+'
+
+test_debug 'gitk --all'
+
 test_expect_success 'merge c1 with c2' '
        git reset --hard c1 &&
        test_tick &&
@@ -263,6 +273,14 @@ test_expect_success 'merge c1 with c2 and c3' '
 
 test_debug 'gitk --all'
 
+test_expect_success 'failing merges with --ff-only' '
+       git reset --hard c1 &&
+       test_tick &&
+       test_must_fail git merge --ff-only c2 &&
+       test_must_fail git merge --ff-only c3 &&
+       test_must_fail git merge --ff-only c2 c3
+'
+
 test_expect_success 'merge c0 with c1 (no-commit)' '
        git reset --hard c0 &&
        git merge --no-commit c1 &&
@@ -303,6 +321,17 @@ test_expect_success 'merge c0 with c1 (squash)' '
 
 test_debug 'gitk --all'
 
+test_expect_success 'merge c0 with c1 (squash, ff-only)' '
+       git reset --hard c0 &&
+       git merge --squash --ff-only c1 &&
+       verify_merge file result.1 &&
+       verify_head $c0 &&
+       verify_no_mergehead &&
+       verify_diff squash.1 .git/SQUASH_MSG "[OOPS] bad squash message"
+'
+
+test_debug 'gitk --all'
+
 test_expect_success 'merge c1 with c2 (squash)' '
        git reset --hard c1 &&
        git merge --squash c2 &&
@@ -314,6 +343,13 @@ test_expect_success 'merge c1 with c2 (squash)' '
 
 test_debug 'gitk --all'
 
+test_expect_success 'unsuccesful merge of c1 with c2 (squash, ff-only)' '
+       git reset --hard c1 &&
+       test_must_fail git merge --squash --ff-only c2
+'
+
+test_debug 'gitk --all'
+
 test_expect_success 'merge c1 with c2 and c3 (squash)' '
        git reset --hard c1 &&
        git merge --squash c2 c3 &&
@@ -432,6 +468,11 @@ test_expect_success 'combining --squash and --no-ff is refused' '
        test_must_fail git merge --no-ff --squash c1
 '
 
+test_expect_success 'combining --ff-only and --no-ff is refused' '
+       test_must_fail git merge --ff-only --no-ff c1 &&
+       test_must_fail git merge --no-ff --ff-only c1
+'
+
 test_expect_success 'merge c0 with c1 (ff overrides no-ff)' '
        git reset --hard c0 &&
        git config branch.master.mergeoptions "--no-ff" &&
index ebdccf9a1eb9f9bb4918fc5adee8bdb8fd682608..fff6a6d0eab4b27d5bc7ff4636913cb10296ab7b 100755 (executable)
@@ -136,7 +136,7 @@ test_expect_success 'GIT_DIFFTOOL_PROMPT variable' '
        GIT_DIFFTOOL_PROMPT=true &&
        export GIT_DIFFTOOL_PROMPT &&
 
-       prompt=$(echo | git difftool --prompt branch | tail -1) &&
+       prompt=$(echo | git difftool branch | tail -1) &&
        prompt_given "$prompt" &&
 
        restore_test_defaults
index fb606a9f05bd6964c588f1ba9e5422e757d12387..84a7f03d46ac4a624afd7d6d0d3c6198e41219c1 100755 (executable)
@@ -103,10 +103,18 @@ cat >expected-show-all-headers <<\EOF
 Dry-OK. Log says:
 Server: relay.example.com
 MAIL FROM:<from@example.com>
-RCPT TO:<to@example.com>,<cc@example.com>,<author@example.com>,<one@example.com>,<two@example.com>,<bcc@example.com>
+RCPT TO:<to@example.com>
+RCPT TO:<cc@example.com>
+RCPT TO:<author@example.com>
+RCPT TO:<one@example.com>
+RCPT TO:<two@example.com>
+RCPT TO:<bcc@example.com>
 From: Example <from@example.com>
 To: to@example.com
-Cc: cc@example.com, A <author@example.com>, One <one@example.com>, two@example.com
+Cc: cc@example.com,
+       A <author@example.com>,
+       One <one@example.com>,
+       two@example.com
 Subject: [PATCH 1/1] Second.
 Date: DATE-STRING
 Message-Id: MESSAGE-ID-STRING
@@ -164,7 +172,7 @@ test_expect_success 'cccmd works' '
                --smtp-server="$(pwd)/fake.sendmail" \
                cccmd.patch \
                &&
-       grep ^Cc:.*cccmd@example.com msgtxt1
+       grep "^ cccmd@example.com" msgtxt1
 '
 
 z8=zzzzzzzz
@@ -278,10 +286,17 @@ cat >expected-suppress-sob <<\EOF
 Dry-OK. Log says:
 Server: relay.example.com
 MAIL FROM:<from@example.com>
-RCPT TO:<to@example.com>,<cc@example.com>,<author@example.com>,<one@example.com>,<two@example.com>
+RCPT TO:<to@example.com>
+RCPT TO:<cc@example.com>
+RCPT TO:<author@example.com>
+RCPT TO:<one@example.com>
+RCPT TO:<two@example.com>
 From: Example <from@example.com>
 To: to@example.com
-Cc: cc@example.com, A <author@example.com>, One <one@example.com>, two@example.com
+Cc: cc@example.com,
+       A <author@example.com>,
+       One <one@example.com>,
+       two@example.com
 Subject: [PATCH 1/1] Second.
 Date: DATE-STRING
 Message-Id: MESSAGE-ID-STRING
@@ -318,10 +333,15 @@ cat >expected-suppress-sob <<\EOF
 Dry-OK. Log says:
 Server: relay.example.com
 MAIL FROM:<from@example.com>
-RCPT TO:<to@example.com>,<author@example.com>,<one@example.com>,<two@example.com>
+RCPT TO:<to@example.com>
+RCPT TO:<author@example.com>
+RCPT TO:<one@example.com>
+RCPT TO:<two@example.com>
 From: Example <from@example.com>
 To: to@example.com
-Cc: A <author@example.com>, One <one@example.com>, two@example.com
+Cc: A <author@example.com>,
+       One <one@example.com>,
+       two@example.com
 Subject: [PATCH 1/1] Second.
 Date: DATE-STRING
 Message-Id: MESSAGE-ID-STRING
@@ -344,10 +364,17 @@ cat >expected-suppress-cccmd <<\EOF
 Dry-OK. Log says:
 Server: relay.example.com
 MAIL FROM:<from@example.com>
-RCPT TO:<to@example.com>,<author@example.com>,<one@example.com>,<two@example.com>,<committer@example.com>
+RCPT TO:<to@example.com>
+RCPT TO:<author@example.com>
+RCPT TO:<one@example.com>
+RCPT TO:<two@example.com>
+RCPT TO:<committer@example.com>
 From: Example <from@example.com>
 To: to@example.com
-Cc: A <author@example.com>, One <one@example.com>, two@example.com, C O Mitter <committer@example.com>
+Cc: A <author@example.com>,
+       One <one@example.com>,
+       two@example.com,
+       C O Mitter <committer@example.com>
 Subject: [PATCH 1/1] Second.
 Date: DATE-STRING
 Message-Id: MESSAGE-ID-STRING
@@ -392,10 +419,17 @@ cat >expected-suppress-body <<\EOF
 Dry-OK. Log says:
 Server: relay.example.com
 MAIL FROM:<from@example.com>
-RCPT TO:<to@example.com>,<author@example.com>,<one@example.com>,<two@example.com>,<cc-cmd@example.com>
+RCPT TO:<to@example.com>
+RCPT TO:<author@example.com>
+RCPT TO:<one@example.com>
+RCPT TO:<two@example.com>
+RCPT TO:<cc-cmd@example.com>
 From: Example <from@example.com>
 To: to@example.com
-Cc: A <author@example.com>, One <one@example.com>, two@example.com, cc-cmd@example.com
+Cc: A <author@example.com>,
+       One <one@example.com>,
+       two@example.com,
+       cc-cmd@example.com
 Subject: [PATCH 1/1] Second.
 Date: DATE-STRING
 Message-Id: MESSAGE-ID-STRING
@@ -416,10 +450,15 @@ cat >expected-suppress-body-cccmd <<\EOF
 Dry-OK. Log says:
 Server: relay.example.com
 MAIL FROM:<from@example.com>
-RCPT TO:<to@example.com>,<author@example.com>,<one@example.com>,<two@example.com>
+RCPT TO:<to@example.com>
+RCPT TO:<author@example.com>
+RCPT TO:<one@example.com>
+RCPT TO:<two@example.com>
 From: Example <from@example.com>
 To: to@example.com
-Cc: A <author@example.com>, One <one@example.com>, two@example.com
+Cc: A <author@example.com>,
+       One <one@example.com>,
+       two@example.com
 Subject: [PATCH 1/1] Second.
 Date: DATE-STRING
 Message-Id: MESSAGE-ID-STRING
@@ -440,10 +479,15 @@ cat >expected-suppress-sob <<\EOF
 Dry-OK. Log says:
 Server: relay.example.com
 MAIL FROM:<from@example.com>
-RCPT TO:<to@example.com>,<author@example.com>,<one@example.com>,<two@example.com>
+RCPT TO:<to@example.com>
+RCPT TO:<author@example.com>
+RCPT TO:<one@example.com>
+RCPT TO:<two@example.com>
 From: Example <from@example.com>
 To: to@example.com
-Cc: A <author@example.com>, One <one@example.com>, two@example.com
+Cc: A <author@example.com>,
+       One <one@example.com>,
+       two@example.com
 Subject: [PATCH 1/1] Second.
 Date: DATE-STRING
 Message-Id: MESSAGE-ID-STRING
@@ -466,10 +510,17 @@ cat >expected-suppress-bodycc <<\EOF
 Dry-OK. Log says:
 Server: relay.example.com
 MAIL FROM:<from@example.com>
-RCPT TO:<to@example.com>,<author@example.com>,<one@example.com>,<two@example.com>,<committer@example.com>
+RCPT TO:<to@example.com>
+RCPT TO:<author@example.com>
+RCPT TO:<one@example.com>
+RCPT TO:<two@example.com>
+RCPT TO:<committer@example.com>
 From: Example <from@example.com>
 To: to@example.com
-Cc: A <author@example.com>, One <one@example.com>, two@example.com, C O Mitter <committer@example.com>
+Cc: A <author@example.com>,
+       One <one@example.com>,
+       two@example.com,
+       C O Mitter <committer@example.com>
 Subject: [PATCH 1/1] Second.
 Date: DATE-STRING
 Message-Id: MESSAGE-ID-STRING
@@ -489,10 +540,13 @@ cat >expected-suppress-cc <<\EOF
 Dry-OK. Log says:
 Server: relay.example.com
 MAIL FROM:<from@example.com>
-RCPT TO:<to@example.com>,<author@example.com>,<committer@example.com>
+RCPT TO:<to@example.com>
+RCPT TO:<author@example.com>
+RCPT TO:<committer@example.com>
 From: Example <from@example.com>
 To: to@example.com
-Cc: A <author@example.com>, C O Mitter <committer@example.com>
+Cc: A <author@example.com>,
+       C O Mitter <committer@example.com>
 Subject: [PATCH 1/1] Second.
 Date: DATE-STRING
 Message-Id: MESSAGE-ID-STRING
@@ -605,7 +659,7 @@ test_expect_success 'utf8 Cc is rfc2047 encoded' '
        --to=nobody@example.com \
        --smtp-server="$(pwd)/fake.sendmail" \
        outdir/*.patch &&
-       grep "^Cc:" msgtxt1 |
+       grep "^ " msgtxt1 |
        grep "=?UTF-8?q?=C3=A0=C3=A9=C3=AC=C3=B6=C3=BA?= <utf8@example.com>"
 '
 
index 9be7aefaeea0af4d988ca656b3df0008f04a58d3..767799e7a70b91ef6f4e3f4007529f1cb0fd919c 100755 (executable)
@@ -19,7 +19,7 @@ test_expect_success 'init and fetch repository' '
        '
 
 test_expect_success 'create file in existing ugly and empty dir' '
-       mkdir "#{bad_directory_name}" &&
+       mkdir -p "#{bad_directory_name}" &&
        echo hi > "#{bad_directory_name}/ foo" &&
        git update-index --add "#{bad_directory_name}/ foo" &&
        git commit -m "new file in ugly parent" &&
@@ -37,7 +37,7 @@ test_expect_success 'rename pretty file' '
        git update-index --add pretty &&
        git commit -m "pretty :x" &&
        git svn dcommit &&
-       mkdir regular_dir_name &&
+       mkdir -p regular_dir_name &&
        git mv pretty regular_dir_name/pretty &&
        git commit -m "moved pretty file" &&
        git svn dcommit
index f5abdb3c7fd24033f1538db51c957345ab86e341..134411e0a56142930a418ca15bd0902837c7bdc1 100755 (executable)
@@ -91,4 +91,27 @@ test_expect_success 'fetch continues after authors-file is fixed' '
        )
        '
 
+test_expect_success 'fresh clone with svn.authors-file in config' '
+       (
+               rm -r "$GIT_DIR" &&
+               test x = x"$(git config svn.authorsfile)" &&
+               HOME="`pwd`" &&
+               export HOME &&
+               test_config="$HOME"/.gitconfig &&
+               unset GIT_CONFIG_NOGLOBAL &&
+               unset GIT_DIR &&
+               unset GIT_CONFIG &&
+               git config --global \
+                 svn.authorsfile "$HOME"/svn-authors &&
+               test x"$HOME"/svn-authors = x"$(git config svn.authorsfile)" &&
+               git svn clone "$svnrepo" gitconfig.clone &&
+               cd gitconfig.clone &&
+               nr_ex=$(git log | grep "^Author:.*example.com" | wc -l) &&
+               nr_rev=$(git rev-list HEAD | wc -l) &&
+               test $nr_rev -eq $nr_ex
+       )
+'
+
+test_debug 'GIT_DIR=gitconfig.clone/.git git log'
+
 test_done
diff --git a/t/t9146-git-svn-empty-dirs.sh b/t/t9146-git-svn-empty-dirs.sh
new file mode 100755 (executable)
index 0000000..5948544
--- /dev/null
@@ -0,0 +1,85 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Eric Wong
+
+test_description='git svn creates empty directories'
+. ./lib-git-svn.sh
+
+test_expect_success 'initialize repo' '
+       for i in a b c d d/e d/e/f "weird file name"
+       do
+               svn_cmd mkdir -m "mkdir $i" "$svnrepo"/"$i"
+       done
+'
+
+test_expect_success 'clone' 'git svn clone "$svnrepo" cloned'
+
+test_expect_success 'empty directories exist' '
+       (
+               cd cloned &&
+               for i in a b c d d/e d/e/f "weird file name"
+               do
+                       if ! test -d "$i"
+                       then
+                               echo >&2 "$i does not exist"
+                               exit 1
+                       fi
+               done
+       )
+'
+
+test_expect_success 'more emptiness' '
+       svn_cmd mkdir -m "bang bang"  "$svnrepo"/"! !"
+'
+
+test_expect_success 'git svn rebase creates empty directory' '
+       ( cd cloned && git svn rebase )
+       test -d cloned/"! !"
+'
+
+test_expect_success 'git svn mkdirs recreates empty directories' '
+       (
+               cd cloned &&
+               rm -r * &&
+               git svn mkdirs &&
+               for i in a b c d d/e d/e/f "weird file name" "! !"
+               do
+                       if ! test -d "$i"
+                       then
+                               echo >&2 "$i does not exist"
+                               exit 1
+                       fi
+               done
+       )
+'
+
+test_expect_success 'git svn mkdirs -r works' '
+       (
+               cd cloned &&
+               rm -r * &&
+               git svn mkdirs -r7 &&
+               for i in a b c d d/e d/e/f "weird file name"
+               do
+                       if ! test -d "$i"
+                       then
+                               echo >&2 "$i does not exist"
+                               exit 1
+                       fi
+               done
+
+               if test -d "! !"
+               then
+                       echo >&2 "$i should not exist"
+                       exit 1
+               fi
+
+               git svn mkdirs -r8 &&
+               if ! test -d "! !"
+               then
+                       echo >&2 "$i not exist"
+                       exit 1
+               fi
+       )
+'
+
+test_done
diff --git a/t/t9150-svk-mergetickets.sh b/t/t9150-svk-mergetickets.sh
new file mode 100755 (executable)
index 0000000..dd0c2ba
--- /dev/null
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Copyright (c) 2007 Sam Vilain
+#
+
+test_description='git-svn svk merge tickets'
+
+. ./lib-git-svn.sh
+
+test_expect_success 'load svk depot' "
+       svnadmin load -q '$rawsvnrepo' \
+         < '$TEST_DIRECTORY/t9150/svk-merge.dump' &&
+       git svn init --minimize-url -R svkmerge \
+         -T trunk -b branches '$svnrepo' &&
+       git svn fetch --all
+       "
+
+uuid=b48289b2-9c08-4d72-af37-0358a40b9c15
+
+test_expect_success 'svk merges were represented coming in' "
+       [ `git-cat-file commit HEAD | grep parent | wc -l` -eq 2 ]
+       "
+
+test_done
diff --git a/t/t9150/make-svk-dump b/t/t9150/make-svk-dump
new file mode 100644 (file)
index 0000000..2242f14
--- /dev/null
@@ -0,0 +1,57 @@
+#!/bin/sh
+#
+# this script sets up a Subversion repository for Makefile in the
+# first ever git merge, as if it were done with svk.
+#
+
+set -e
+
+svk depotmap foo ~/.svk/foo
+svk co /foo/ foo
+cd foo
+mkdir trunk
+mkdir branches
+svk add trunk branches
+svk commit -m "Setup trunk and branches"
+cd trunk
+
+git cat-file blob 6683463e:Makefile > Makefile
+svk add Makefile 
+
+svk commit -m "ancestor"
+cd ..
+svk cp trunk branches/left
+
+svk commit -m "make left branch"
+cd branches/left/
+
+git cat-file blob 5873b67e:Makefile > Makefile
+svk commit -m "left update 1"
+
+cd ../../trunk
+git cat-file blob 75118b13:Makefile > Makefile
+svk commit -m "trunk update"
+
+cd ../branches/left
+git cat-file blob b5039db6:Makefile > Makefile
+svk commit -m "left update 2"
+
+cd ../../trunk
+svk sm /foo/branches/left
+# in theory we could delete the "left" branch here, but it's not
+# required so don't do it, in case people start getting ideas ;)
+svk commit -m "merge branch 'left' into 'trunk'"
+
+git cat-file blob b51ad431:Makefile > Makefile
+
+svk diff Makefile && echo "Hey!  No differences, magic"
+
+cd ../..
+
+svnadmin dump ~/.svk/foo > svk-merge.dump
+
+svk co -d foo
+rm -rf foo
+svk depotmap -d /foo/
+rm -rf ~/.svk/foo
+
diff --git a/t/t9150/svk-merge.dump b/t/t9150/svk-merge.dump
new file mode 100644 (file)
index 0000000..42f70db
--- /dev/null
@@ -0,0 +1,616 @@
+SVN-fs-dump-format-version: 2
+
+UUID: b48289b2-9c08-4d72-af37-0358a40b9c15
+
+Revision-number: 0
+Prop-content-length: 56
+Content-length: 56
+
+K 8
+svn:date
+V 27
+2009-10-19T23:44:03.722969Z
+PROPS-END
+
+Revision-number: 1
+Prop-content-length: 123
+Content-length: 123
+
+K 7
+svn:log
+V 24
+Setup trunk and branches
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-10-19T23:44:04.927533Z
+PROPS-END
+
+Node-path: branches
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: trunk
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 2
+Prop-content-length: 106
+Content-length: 106
+
+K 7
+svn:log
+V 8
+ancestor
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-10-19T23:44:05.835585Z
+PROPS-END
+
+Node-path: trunk/Makefile
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 2401
+Text-content-md5: bfd8ff778d1492dc6758567373176a89
+Content-length: 2411
+
+PROPS-END
+# -DCOLLISION_CHECK if you believe that SHA1's
+# 1461501637330902918203684832716283019655932542976 hashes do not give you
+# enough guarantees about no collisions between objects ever hapenning.
+#
+# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
+# Note that you need some new glibc (at least >2.2.4) for this, and it will
+# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly
+# break unless your underlying filesystem supports those sub-second times
+# (my ext3 doesn't).
+CFLAGS=-g -O3 -Wall
+
+CC=gcc
+
+
+PROG=   update-cache show-diff init-db write-tree read-tree commit-tree \
+       cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
+       check-files ls-tree merge-base
+
+all: $(PROG)
+
+install: $(PROG)
+       install $(PROG) $(HOME)/bin/
+
+LIBS= -lssl -lz
+
+init-db: init-db.o
+
+update-cache: update-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS)
+
+show-diff: show-diff.o read-cache.o
+       $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS)
+
+write-tree: write-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS)
+
+read-tree: read-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS)
+
+commit-tree: commit-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS)
+
+cat-file: cat-file.o read-cache.o
+       $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS)
+
+fsck-cache: fsck-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o $(LIBS)
+
+checkout-cache: checkout-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS)
+
+diff-tree: diff-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS)
+
+rev-tree: rev-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o $(LIBS)
+
+show-files: show-files.o read-cache.o
+       $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS)
+
+check-files: check-files.o read-cache.o
+       $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS)
+
+ls-tree: ls-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS)
+
+merge-base: merge-base.o read-cache.o
+       $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o $(LIBS)
+
+read-cache.o: cache.h
+show-diff.o: cache.h
+
+clean:
+       rm -f *.o $(PROG)
+
+backup: clean
+       cd .. ; tar czvf dircache.tar.gz dir-cache
+
+
+Revision-number: 3
+Prop-content-length: 115
+Content-length: 115
+
+K 7
+svn:log
+V 16
+make left branch
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-10-19T23:44:06.719737Z
+PROPS-END
+
+Node-path: branches/left
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 2
+Node-copyfrom-path: trunk
+
+
+Revision-number: 4
+Prop-content-length: 112
+Content-length: 112
+
+K 7
+svn:log
+V 13
+left update 1
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-10-19T23:44:07.167666Z
+PROPS-END
+
+Node-path: branches/left/Makefile
+Node-kind: file
+Node-action: change
+Text-content-length: 2465
+Text-content-md5: 16e38d9753b061731650561ce01b1195
+Content-length: 2465
+
+# -DCOLLISION_CHECK if you believe that SHA1's
+# 1461501637330902918203684832716283019655932542976 hashes do not give you
+# enough guarantees about no collisions between objects ever hapenning.
+#
+# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
+# Note that you need some new glibc (at least >2.2.4) for this, and it will
+# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly
+# break unless your underlying filesystem supports those sub-second times
+# (my ext3 doesn't).
+CFLAGS=-g -O3 -Wall
+
+CC=gcc
+
+
+PROG=   update-cache show-diff init-db write-tree read-tree commit-tree \
+       cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
+       check-files ls-tree merge-base
+
+all: $(PROG)
+
+install: $(PROG)
+       install $(PROG) $(HOME)/bin/
+
+LIBS= -lssl -lz
+
+init-db: init-db.o
+
+update-cache: update-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS)
+
+show-diff: show-diff.o read-cache.o
+       $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS)
+
+write-tree: write-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS)
+
+read-tree: read-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS)
+
+commit-tree: commit-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS)
+
+cat-file: cat-file.o read-cache.o
+       $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS)
+
+fsck-cache: fsck-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o $(LIBS)
+
+checkout-cache: checkout-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS)
+
+diff-tree: diff-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS)
+
+rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o
+       $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+show-files: show-files.o read-cache.o
+       $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS)
+
+check-files: check-files.o read-cache.o
+       $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS)
+
+ls-tree: ls-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS)
+
+merge-base: merge-base.o read-cache.o
+       $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o $(LIBS)
+
+read-cache.o: cache.h
+show-diff.o: cache.h
+
+clean:
+       rm -f *.o $(PROG)
+
+backup: clean
+       cd .. ; tar czvf dircache.tar.gz dir-cache
+
+
+Revision-number: 5
+Prop-content-length: 111
+Content-length: 111
+
+K 7
+svn:log
+V 12
+trunk update
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-10-19T23:44:07.619633Z
+PROPS-END
+
+Node-path: trunk/Makefile
+Node-kind: file
+Node-action: change
+Text-content-length: 2521
+Text-content-md5: 0668418a621333f4aa8b6632cd63e2a0
+Content-length: 2521
+
+# -DCOLLISION_CHECK if you believe that SHA1's
+# 1461501637330902918203684832716283019655932542976 hashes do not give you
+# enough guarantees about no collisions between objects ever hapenning.
+#
+# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
+# Note that you need some new glibc (at least >2.2.4) for this, and it will
+# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly
+# break unless your underlying filesystem supports those sub-second times
+# (my ext3 doesn't).
+CFLAGS=-g -O3 -Wall
+
+CC=gcc
+
+
+PROG=   update-cache show-diff init-db write-tree read-tree commit-tree \
+       cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
+       check-files ls-tree merge-base merge-cache
+
+all: $(PROG)
+
+install: $(PROG)
+       install $(PROG) $(HOME)/bin/
+
+LIBS= -lssl -lz
+
+init-db: init-db.o
+
+update-cache: update-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS)
+
+show-diff: show-diff.o read-cache.o
+       $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS)
+
+write-tree: write-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS)
+
+read-tree: read-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS)
+
+commit-tree: commit-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS)
+
+cat-file: cat-file.o read-cache.o
+       $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS)
+
+fsck-cache: fsck-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o $(LIBS)
+
+checkout-cache: checkout-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS)
+
+diff-tree: diff-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS)
+
+rev-tree: rev-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o $(LIBS)
+
+show-files: show-files.o read-cache.o
+       $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS)
+
+check-files: check-files.o read-cache.o
+       $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS)
+
+ls-tree: ls-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS)
+
+merge-base: merge-base.o read-cache.o
+       $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o $(LIBS)
+
+merge-cache: merge-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o merge-cache merge-cache.o read-cache.o $(LIBS)
+
+read-cache.o: cache.h
+show-diff.o: cache.h
+
+clean:
+       rm -f *.o $(PROG)
+
+backup: clean
+       cd .. ; tar czvf dircache.tar.gz dir-cache
+
+
+Revision-number: 6
+Prop-content-length: 112
+Content-length: 112
+
+K 7
+svn:log
+V 13
+left update 2
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-10-19T23:44:08.067554Z
+PROPS-END
+
+Node-path: branches/left/Makefile
+Node-kind: file
+Node-action: change
+Text-content-length: 2593
+Text-content-md5: 5ccff689fb290e00b85fe18ee50c54ba
+Content-length: 2593
+
+# -DCOLLISION_CHECK if you believe that SHA1's
+# 1461501637330902918203684832716283019655932542976 hashes do not give you
+# enough guarantees about no collisions between objects ever hapenning.
+#
+# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
+# Note that you need some new glibc (at least >2.2.4) for this, and it will
+# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly
+# break unless your underlying filesystem supports those sub-second times
+# (my ext3 doesn't).
+CFLAGS=-g -O3 -Wall
+
+CC=gcc
+
+
+PROG=   update-cache show-diff init-db write-tree read-tree commit-tree \
+       cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
+       check-files ls-tree merge-base
+
+all: $(PROG)
+
+install: $(PROG)
+       install $(PROG) $(HOME)/bin/
+
+LIBS= -lssl -lz
+
+init-db: init-db.o
+
+update-cache: update-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS)
+
+show-diff: show-diff.o read-cache.o
+       $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS)
+
+write-tree: write-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS)
+
+read-tree: read-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS)
+
+commit-tree: commit-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS)
+
+cat-file: cat-file.o read-cache.o
+       $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS)
+
+fsck-cache: fsck-cache.o read-cache.o object.o commit.o tree.o blob.o
+       $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+checkout-cache: checkout-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS)
+
+diff-tree: diff-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS)
+
+rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o
+       $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+show-files: show-files.o read-cache.o
+       $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS)
+
+check-files: check-files.o read-cache.o
+       $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS)
+
+ls-tree: ls-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS)
+
+merge-base: merge-base.o read-cache.o object.o commit.o tree.o blob.o
+       $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+read-cache.o: cache.h
+show-diff.o: cache.h
+
+clean:
+       rm -f *.o $(PROG)
+
+backup: clean
+       cd .. ; tar czvf dircache.tar.gz dir-cache
+
+
+Revision-number: 7
+Prop-content-length: 131
+Content-length: 131
+
+K 7
+svn:log
+V 32
+merge branch 'left' into 'trunk'
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-10-19T23:44:08.971801Z
+PROPS-END
+
+Node-path: trunk
+Node-kind: dir
+Node-action: change
+Prop-content-length: 83
+Content-length: 83
+
+K 9
+svk:merge
+V 53
+b48289b2-9c08-4d72-af37-0358a40b9c15:/branches/left:6
+PROPS-END
+
+
+Node-path: trunk/Makefile
+Node-kind: file
+Node-action: change
+Text-content-length: 2713
+Text-content-md5: 0afbe34f244cd662b1f97d708c687f90
+Content-length: 2713
+
+# -DCOLLISION_CHECK if you believe that SHA1's
+# 1461501637330902918203684832716283019655932542976 hashes do not give you
+# enough guarantees about no collisions between objects ever hapenning.
+#
+# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
+# Note that you need some new glibc (at least >2.2.4) for this, and it will
+# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly
+# break unless your underlying filesystem supports those sub-second times
+# (my ext3 doesn't).
+CFLAGS=-g -O3 -Wall
+
+CC=gcc
+
+
+PROG=   update-cache show-diff init-db write-tree read-tree commit-tree \
+       cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
+       check-files ls-tree merge-base merge-cache
+
+all: $(PROG)
+
+install: $(PROG)
+       install $(PROG) $(HOME)/bin/
+
+LIBS= -lssl -lz
+
+init-db: init-db.o
+
+update-cache: update-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS)
+
+show-diff: show-diff.o read-cache.o
+       $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS)
+
+write-tree: write-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS)
+
+read-tree: read-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS)
+
+commit-tree: commit-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS)
+
+cat-file: cat-file.o read-cache.o
+       $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS)
+
+fsck-cache: fsck-cache.o read-cache.o object.o commit.o tree.o blob.o
+       $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+checkout-cache: checkout-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS)
+
+diff-tree: diff-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS)
+
+rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o
+       $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+show-files: show-files.o read-cache.o
+       $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS)
+
+check-files: check-files.o read-cache.o
+       $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS)
+
+ls-tree: ls-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS)
+
+merge-base: merge-base.o read-cache.o object.o commit.o tree.o blob.o
+       $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+merge-cache: merge-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o merge-cache merge-cache.o read-cache.o $(LIBS)
+
+read-cache.o: cache.h
+show-diff.o: cache.h
+
+clean:
+       rm -f *.o $(PROG)
+
+backup: clean
+       cd .. ; tar czvf dircache.tar.gz dir-cache
+
+
diff --git a/t/t9151-svn-mergeinfo.sh b/t/t9151-svn-mergeinfo.sh
new file mode 100755 (executable)
index 0000000..f57daf4
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# Copyright (c) 2007, 2009 Sam Vilain
+#
+
+test_description='git-svn svn mergeinfo properties'
+
+. ./lib-git-svn.sh
+
+test_expect_success 'load svn dump' "
+       svnadmin load -q '$rawsvnrepo' \
+         < '$TEST_DIRECTORY/t9151/svn-mergeinfo.dump' &&
+       git svn init --minimize-url -R svnmerge \
+         -T trunk -b branches '$svnrepo' &&
+       git svn fetch --all
+       "
+
+test_expect_success 'represent svn merges without intervening commits' "
+       [ `git cat-file commit HEAD^1 | grep parent | wc -l` -eq 2 ]
+       "
+
+test_expect_success 'represent svn merges with intervening commits' "
+       [ `git cat-file commit HEAD | grep parent | wc -l` -eq 2 ]
+       "
+
+test_done
diff --git a/t/t9151/.gitignore b/t/t9151/.gitignore
new file mode 100644 (file)
index 0000000..587c37d
--- /dev/null
@@ -0,0 +1,2 @@
+foo
+foo.svn
diff --git a/t/t9151/make-svnmerge-dump b/t/t9151/make-svnmerge-dump
new file mode 100644 (file)
index 0000000..7e3da75
--- /dev/null
@@ -0,0 +1,103 @@
+#!/bin/sh
+#
+# this script sets up a Subversion repository for Makefile in the
+# first ever git merge, as if it were done with svnmerge (SVN 1.5+)
+#
+
+rm -rf foo.svn foo
+set -e
+
+mkdir foo.svn
+svnadmin create foo.svn
+svn co file://`pwd`/foo.svn foo
+
+cd foo
+mkdir trunk
+mkdir branches
+svn add trunk branches
+svn commit -m "Setup trunk and branches"
+cd trunk
+
+git cat-file blob 6683463e:Makefile > Makefile
+svn add Makefile 
+
+echo "Committing ANCESTOR"
+svn commit -m "ancestor"
+cd ..
+svn cp trunk branches/left
+
+echo "Committing BRANCH POINT"
+svn commit -m "make left branch"
+svn cp trunk branches/right
+
+echo "Committing other BRANCH POINT"
+svn commit -m "make right branch"
+cd branches/left/
+
+#$sm init
+#svn commit -m "init svnmerge"
+
+git cat-file blob 5873b67e:Makefile > Makefile
+echo "Committing BRANCH UPDATE 1"
+svn commit -m "left update 1"
+cd ../..
+
+cd trunk
+git cat-file blob 75118b13:Makefile > Makefile
+echo "Committing TRUNK UPDATE"
+svn commit -m "trunk update"
+
+cd ../branches/left
+git cat-file blob ff5ebe39:Makefile > Makefile
+echo "Committing BRANCH UPDATE 2"
+svn commit -m "left update 2"
+
+git cat-file blob b5039db6:Makefile > Makefile
+echo "Committing BRANCH UPDATE 3"
+svn commit -m "left update 3"
+
+# merge to trunk
+
+cd ../..
+svn update
+cd trunk
+
+svn merge ../branches/left --accept postpone
+
+git cat-file blob b51ad431:Makefile > Makefile
+
+svn resolved Makefile
+
+svn commit -m "Merge trunk 1"
+
+# create commits on both branches
+
+cd ../branches/left
+git cat-file blob ff5ebe39:Makefile > Makefile
+echo "Committing BRANCH UPDATE 4"
+svn commit -m "left update 4"
+
+cd ../right
+git cat-file blob b5039db6:Makefile > Makefile
+echo "Committing other BRANCH UPDATE 1"
+svn commit -m "right update 1"
+
+# merge to trun again
+
+cd ../..
+svn update
+cd trunk
+
+svn merge ../branches/left --accept postpone
+
+git cat-file blob b51ad431:Makefile > Makefile
+
+svn resolved Makefile
+
+svn commit -m "Merge trunk 2"
+
+cd ../..
+
+svnadmin dump foo.svn > svn-mergeinfo.dump
+
+rm -rf foo foo.svn
diff --git a/t/t9151/svn-mergeinfo.dump b/t/t9151/svn-mergeinfo.dump
new file mode 100644 (file)
index 0000000..11a883f
--- /dev/null
@@ -0,0 +1,1010 @@
+SVN-fs-dump-format-version: 2
+
+UUID: 1530d5a2-a1dc-4438-8ad5-d95e96db8945
+
+Revision-number: 0
+Prop-content-length: 56
+Content-length: 56
+
+K 8
+svn:date
+V 27
+2009-11-12T20:29:38.812226Z
+PROPS-END
+
+Revision-number: 1
+Prop-content-length: 127
+Content-length: 127
+
+K 7
+svn:log
+V 24
+Setup trunk and branches
+K 10
+svn:author
+V 8
+tallsopp
+K 8
+svn:date
+V 27
+2009-11-12T20:29:39.045856Z
+PROPS-END
+
+Node-path: branches
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: trunk
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 2
+Prop-content-length: 110
+Content-length: 110
+
+K 7
+svn:log
+V 8
+ancestor
+K 10
+svn:author
+V 8
+tallsopp
+K 8
+svn:date
+V 27
+2009-11-12T20:29:40.079587Z
+PROPS-END
+
+Node-path: trunk/Makefile
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 2401
+Text-content-md5: bfd8ff778d1492dc6758567373176a89
+Text-content-sha1: 103205ce331f7d64086dba497574734f78439590
+Content-length: 2411
+
+PROPS-END
+# -DCOLLISION_CHECK if you believe that SHA1's
+# 1461501637330902918203684832716283019655932542976 hashes do not give you
+# enough guarantees about no collisions between objects ever hapenning.
+#
+# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
+# Note that you need some new glibc (at least >2.2.4) for this, and it will
+# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly
+# break unless your underlying filesystem supports those sub-second times
+# (my ext3 doesn't).
+CFLAGS=-g -O3 -Wall
+
+CC=gcc
+
+
+PROG=   update-cache show-diff init-db write-tree read-tree commit-tree \
+       cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
+       check-files ls-tree merge-base
+
+all: $(PROG)
+
+install: $(PROG)
+       install $(PROG) $(HOME)/bin/
+
+LIBS= -lssl -lz
+
+init-db: init-db.o
+
+update-cache: update-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS)
+
+show-diff: show-diff.o read-cache.o
+       $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS)
+
+write-tree: write-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS)
+
+read-tree: read-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS)
+
+commit-tree: commit-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS)
+
+cat-file: cat-file.o read-cache.o
+       $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS)
+
+fsck-cache: fsck-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o $(LIBS)
+
+checkout-cache: checkout-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS)
+
+diff-tree: diff-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS)
+
+rev-tree: rev-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o $(LIBS)
+
+show-files: show-files.o read-cache.o
+       $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS)
+
+check-files: check-files.o read-cache.o
+       $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS)
+
+ls-tree: ls-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS)
+
+merge-base: merge-base.o read-cache.o
+       $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o $(LIBS)
+
+read-cache.o: cache.h
+show-diff.o: cache.h
+
+clean:
+       rm -f *.o $(PROG)
+
+backup: clean
+       cd .. ; tar czvf dircache.tar.gz dir-cache
+
+
+Revision-number: 3
+Prop-content-length: 119
+Content-length: 119
+
+K 7
+svn:log
+V 16
+make left branch
+K 10
+svn:author
+V 8
+tallsopp
+K 8
+svn:date
+V 27
+2009-11-12T20:29:42.084439Z
+PROPS-END
+
+Node-path: branches/left
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 1
+Node-copyfrom-path: trunk
+
+
+Node-path: branches/left/Makefile
+Node-kind: file
+Node-action: add
+Node-copyfrom-rev: 2
+Node-copyfrom-path: trunk/Makefile
+Text-copy-source-md5: bfd8ff778d1492dc6758567373176a89
+Text-copy-source-sha1: 103205ce331f7d64086dba497574734f78439590
+
+
+Revision-number: 4
+Prop-content-length: 120
+Content-length: 120
+
+K 7
+svn:log
+V 17
+make right branch
+K 10
+svn:author
+V 8
+tallsopp
+K 8
+svn:date
+V 27
+2009-11-12T20:29:44.065452Z
+PROPS-END
+
+Node-path: branches/right
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 1
+Node-copyfrom-path: trunk
+
+
+Node-path: branches/right/Makefile
+Node-kind: file
+Node-action: add
+Node-copyfrom-rev: 2
+Node-copyfrom-path: trunk/Makefile
+Text-copy-source-md5: bfd8ff778d1492dc6758567373176a89
+Text-copy-source-sha1: 103205ce331f7d64086dba497574734f78439590
+
+
+Revision-number: 5
+Prop-content-length: 116
+Content-length: 116
+
+K 7
+svn:log
+V 13
+left update 1
+K 10
+svn:author
+V 8
+tallsopp
+K 8
+svn:date
+V 27
+2009-11-12T20:29:45.066262Z
+PROPS-END
+
+Node-path: branches/left/Makefile
+Node-kind: file
+Node-action: change
+Text-content-length: 2465
+Text-content-md5: 16e38d9753b061731650561ce01b1195
+Text-content-sha1: 36da4b84ea9b64218ab48171dfc5c48ae025f38b
+Content-length: 2465
+
+# -DCOLLISION_CHECK if you believe that SHA1's
+# 1461501637330902918203684832716283019655932542976 hashes do not give you
+# enough guarantees about no collisions between objects ever hapenning.
+#
+# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
+# Note that you need some new glibc (at least >2.2.4) for this, and it will
+# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly
+# break unless your underlying filesystem supports those sub-second times
+# (my ext3 doesn't).
+CFLAGS=-g -O3 -Wall
+
+CC=gcc
+
+
+PROG=   update-cache show-diff init-db write-tree read-tree commit-tree \
+       cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
+       check-files ls-tree merge-base
+
+all: $(PROG)
+
+install: $(PROG)
+       install $(PROG) $(HOME)/bin/
+
+LIBS= -lssl -lz
+
+init-db: init-db.o
+
+update-cache: update-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS)
+
+show-diff: show-diff.o read-cache.o
+       $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS)
+
+write-tree: write-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS)
+
+read-tree: read-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS)
+
+commit-tree: commit-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS)
+
+cat-file: cat-file.o read-cache.o
+       $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS)
+
+fsck-cache: fsck-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o $(LIBS)
+
+checkout-cache: checkout-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS)
+
+diff-tree: diff-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS)
+
+rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o
+       $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+show-files: show-files.o read-cache.o
+       $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS)
+
+check-files: check-files.o read-cache.o
+       $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS)
+
+ls-tree: ls-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS)
+
+merge-base: merge-base.o read-cache.o
+       $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o $(LIBS)
+
+read-cache.o: cache.h
+show-diff.o: cache.h
+
+clean:
+       rm -f *.o $(PROG)
+
+backup: clean
+       cd .. ; tar czvf dircache.tar.gz dir-cache
+
+
+Revision-number: 6
+Prop-content-length: 115
+Content-length: 115
+
+K 7
+svn:log
+V 12
+trunk update
+K 10
+svn:author
+V 8
+tallsopp
+K 8
+svn:date
+V 27
+2009-11-12T20:29:46.278498Z
+PROPS-END
+
+Node-path: trunk/Makefile
+Node-kind: file
+Node-action: change
+Text-content-length: 2521
+Text-content-md5: 0668418a621333f4aa8b6632cd63e2a0
+Text-content-sha1: 4f29afd038e52f45acb5ef8c41acfc70062a741a
+Content-length: 2521
+
+# -DCOLLISION_CHECK if you believe that SHA1's
+# 1461501637330902918203684832716283019655932542976 hashes do not give you
+# enough guarantees about no collisions between objects ever hapenning.
+#
+# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
+# Note that you need some new glibc (at least >2.2.4) for this, and it will
+# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly
+# break unless your underlying filesystem supports those sub-second times
+# (my ext3 doesn't).
+CFLAGS=-g -O3 -Wall
+
+CC=gcc
+
+
+PROG=   update-cache show-diff init-db write-tree read-tree commit-tree \
+       cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
+       check-files ls-tree merge-base merge-cache
+
+all: $(PROG)
+
+install: $(PROG)
+       install $(PROG) $(HOME)/bin/
+
+LIBS= -lssl -lz
+
+init-db: init-db.o
+
+update-cache: update-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS)
+
+show-diff: show-diff.o read-cache.o
+       $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS)
+
+write-tree: write-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS)
+
+read-tree: read-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS)
+
+commit-tree: commit-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS)
+
+cat-file: cat-file.o read-cache.o
+       $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS)
+
+fsck-cache: fsck-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o $(LIBS)
+
+checkout-cache: checkout-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS)
+
+diff-tree: diff-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS)
+
+rev-tree: rev-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o $(LIBS)
+
+show-files: show-files.o read-cache.o
+       $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS)
+
+check-files: check-files.o read-cache.o
+       $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS)
+
+ls-tree: ls-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS)
+
+merge-base: merge-base.o read-cache.o
+       $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o $(LIBS)
+
+merge-cache: merge-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o merge-cache merge-cache.o read-cache.o $(LIBS)
+
+read-cache.o: cache.h
+show-diff.o: cache.h
+
+clean:
+       rm -f *.o $(PROG)
+
+backup: clean
+       cd .. ; tar czvf dircache.tar.gz dir-cache
+
+
+Revision-number: 7
+Prop-content-length: 116
+Content-length: 116
+
+K 7
+svn:log
+V 13
+left update 2
+K 10
+svn:author
+V 8
+tallsopp
+K 8
+svn:date
+V 27
+2009-11-12T20:29:47.069090Z
+PROPS-END
+
+Node-path: branches/left/Makefile
+Node-kind: file
+Node-action: change
+Text-content-length: 2529
+Text-content-md5: f6b197cc3f2e89a83e545d4bb003de73
+Text-content-sha1: 2f656677cfec0bceec85e53036ffb63e25126f8e
+Content-length: 2529
+
+# -DCOLLISION_CHECK if you believe that SHA1's
+# 1461501637330902918203684832716283019655932542976 hashes do not give you
+# enough guarantees about no collisions between objects ever hapenning.
+#
+# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
+# Note that you need some new glibc (at least >2.2.4) for this, and it will
+# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly
+# break unless your underlying filesystem supports those sub-second times
+# (my ext3 doesn't).
+CFLAGS=-g -O3 -Wall
+
+CC=gcc
+
+
+PROG=   update-cache show-diff init-db write-tree read-tree commit-tree \
+       cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
+       check-files ls-tree merge-base
+
+all: $(PROG)
+
+install: $(PROG)
+       install $(PROG) $(HOME)/bin/
+
+LIBS= -lssl -lz
+
+init-db: init-db.o
+
+update-cache: update-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS)
+
+show-diff: show-diff.o read-cache.o
+       $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS)
+
+write-tree: write-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS)
+
+read-tree: read-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS)
+
+commit-tree: commit-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS)
+
+cat-file: cat-file.o read-cache.o
+       $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS)
+
+fsck-cache: fsck-cache.o read-cache.o object.o commit.o tree.o blob.o
+       $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+checkout-cache: checkout-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS)
+
+diff-tree: diff-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS)
+
+rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o
+       $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+show-files: show-files.o read-cache.o
+       $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS)
+
+check-files: check-files.o read-cache.o
+       $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS)
+
+ls-tree: ls-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS)
+
+merge-base: merge-base.o read-cache.o
+       $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o $(LIBS)
+
+read-cache.o: cache.h
+show-diff.o: cache.h
+
+clean:
+       rm -f *.o $(PROG)
+
+backup: clean
+       cd .. ; tar czvf dircache.tar.gz dir-cache
+
+
+Revision-number: 8
+Prop-content-length: 116
+Content-length: 116
+
+K 7
+svn:log
+V 13
+left update 3
+K 10
+svn:author
+V 8
+tallsopp
+K 8
+svn:date
+V 27
+2009-11-12T20:29:48.053835Z
+PROPS-END
+
+Node-path: branches/left/Makefile
+Node-kind: file
+Node-action: change
+Text-content-length: 2593
+Text-content-md5: 5ccff689fb290e00b85fe18ee50c54ba
+Text-content-sha1: a13de8e23f1483efca3e57b2b64b0ae6f740ce10
+Content-length: 2593
+
+# -DCOLLISION_CHECK if you believe that SHA1's
+# 1461501637330902918203684832716283019655932542976 hashes do not give you
+# enough guarantees about no collisions between objects ever hapenning.
+#
+# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
+# Note that you need some new glibc (at least >2.2.4) for this, and it will
+# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly
+# break unless your underlying filesystem supports those sub-second times
+# (my ext3 doesn't).
+CFLAGS=-g -O3 -Wall
+
+CC=gcc
+
+
+PROG=   update-cache show-diff init-db write-tree read-tree commit-tree \
+       cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
+       check-files ls-tree merge-base
+
+all: $(PROG)
+
+install: $(PROG)
+       install $(PROG) $(HOME)/bin/
+
+LIBS= -lssl -lz
+
+init-db: init-db.o
+
+update-cache: update-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS)
+
+show-diff: show-diff.o read-cache.o
+       $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS)
+
+write-tree: write-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS)
+
+read-tree: read-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS)
+
+commit-tree: commit-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS)
+
+cat-file: cat-file.o read-cache.o
+       $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS)
+
+fsck-cache: fsck-cache.o read-cache.o object.o commit.o tree.o blob.o
+       $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+checkout-cache: checkout-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS)
+
+diff-tree: diff-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS)
+
+rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o
+       $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+show-files: show-files.o read-cache.o
+       $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS)
+
+check-files: check-files.o read-cache.o
+       $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS)
+
+ls-tree: ls-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS)
+
+merge-base: merge-base.o read-cache.o object.o commit.o tree.o blob.o
+       $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+read-cache.o: cache.h
+show-diff.o: cache.h
+
+clean:
+       rm -f *.o $(PROG)
+
+backup: clean
+       cd .. ; tar czvf dircache.tar.gz dir-cache
+
+
+Revision-number: 9
+Prop-content-length: 116
+Content-length: 116
+
+K 7
+svn:log
+V 13
+Merge trunk 1
+K 10
+svn:author
+V 8
+tallsopp
+K 8
+svn:date
+V 27
+2009-11-12T20:29:51.098306Z
+PROPS-END
+
+Node-path: trunk
+Node-kind: dir
+Node-action: change
+Prop-content-length: 53
+Content-length: 53
+
+K 13
+svn:mergeinfo
+V 18
+/branches/left:2-8
+PROPS-END
+
+
+Node-path: trunk/Makefile
+Node-kind: file
+Node-action: change
+Text-content-length: 2713
+Text-content-md5: 0afbe34f244cd662b1f97d708c687f90
+Text-content-sha1: 46d9377d783e67a9b581da110352e799517c8a14
+Content-length: 2713
+
+# -DCOLLISION_CHECK if you believe that SHA1's
+# 1461501637330902918203684832716283019655932542976 hashes do not give you
+# enough guarantees about no collisions between objects ever hapenning.
+#
+# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
+# Note that you need some new glibc (at least >2.2.4) for this, and it will
+# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly
+# break unless your underlying filesystem supports those sub-second times
+# (my ext3 doesn't).
+CFLAGS=-g -O3 -Wall
+
+CC=gcc
+
+
+PROG=   update-cache show-diff init-db write-tree read-tree commit-tree \
+       cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
+       check-files ls-tree merge-base merge-cache
+
+all: $(PROG)
+
+install: $(PROG)
+       install $(PROG) $(HOME)/bin/
+
+LIBS= -lssl -lz
+
+init-db: init-db.o
+
+update-cache: update-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS)
+
+show-diff: show-diff.o read-cache.o
+       $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS)
+
+write-tree: write-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS)
+
+read-tree: read-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS)
+
+commit-tree: commit-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS)
+
+cat-file: cat-file.o read-cache.o
+       $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS)
+
+fsck-cache: fsck-cache.o read-cache.o object.o commit.o tree.o blob.o
+       $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+checkout-cache: checkout-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS)
+
+diff-tree: diff-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS)
+
+rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o
+       $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+show-files: show-files.o read-cache.o
+       $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS)
+
+check-files: check-files.o read-cache.o
+       $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS)
+
+ls-tree: ls-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS)
+
+merge-base: merge-base.o read-cache.o object.o commit.o tree.o blob.o
+       $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+merge-cache: merge-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o merge-cache merge-cache.o read-cache.o $(LIBS)
+
+read-cache.o: cache.h
+show-diff.o: cache.h
+
+clean:
+       rm -f *.o $(PROG)
+
+backup: clean
+       cd .. ; tar czvf dircache.tar.gz dir-cache
+
+
+Revision-number: 10
+Prop-content-length: 116
+Content-length: 116
+
+K 7
+svn:log
+V 13
+left update 4
+K 10
+svn:author
+V 8
+tallsopp
+K 8
+svn:date
+V 27
+2009-11-12T20:29:52.081644Z
+PROPS-END
+
+Node-path: branches/left/Makefile
+Node-kind: file
+Node-action: change
+Text-content-length: 2529
+Text-content-md5: f6b197cc3f2e89a83e545d4bb003de73
+Text-content-sha1: 2f656677cfec0bceec85e53036ffb63e25126f8e
+Content-length: 2529
+
+# -DCOLLISION_CHECK if you believe that SHA1's
+# 1461501637330902918203684832716283019655932542976 hashes do not give you
+# enough guarantees about no collisions between objects ever hapenning.
+#
+# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
+# Note that you need some new glibc (at least >2.2.4) for this, and it will
+# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly
+# break unless your underlying filesystem supports those sub-second times
+# (my ext3 doesn't).
+CFLAGS=-g -O3 -Wall
+
+CC=gcc
+
+
+PROG=   update-cache show-diff init-db write-tree read-tree commit-tree \
+       cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
+       check-files ls-tree merge-base
+
+all: $(PROG)
+
+install: $(PROG)
+       install $(PROG) $(HOME)/bin/
+
+LIBS= -lssl -lz
+
+init-db: init-db.o
+
+update-cache: update-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS)
+
+show-diff: show-diff.o read-cache.o
+       $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS)
+
+write-tree: write-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS)
+
+read-tree: read-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS)
+
+commit-tree: commit-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS)
+
+cat-file: cat-file.o read-cache.o
+       $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS)
+
+fsck-cache: fsck-cache.o read-cache.o object.o commit.o tree.o blob.o
+       $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+checkout-cache: checkout-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS)
+
+diff-tree: diff-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS)
+
+rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o
+       $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+show-files: show-files.o read-cache.o
+       $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS)
+
+check-files: check-files.o read-cache.o
+       $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS)
+
+ls-tree: ls-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS)
+
+merge-base: merge-base.o read-cache.o
+       $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o $(LIBS)
+
+read-cache.o: cache.h
+show-diff.o: cache.h
+
+clean:
+       rm -f *.o $(PROG)
+
+backup: clean
+       cd .. ; tar czvf dircache.tar.gz dir-cache
+
+
+Revision-number: 11
+Prop-content-length: 117
+Content-length: 117
+
+K 7
+svn:log
+V 14
+right update 1
+K 10
+svn:author
+V 8
+tallsopp
+K 8
+svn:date
+V 27
+2009-11-12T20:29:53.059636Z
+PROPS-END
+
+Node-path: branches/right/Makefile
+Node-kind: file
+Node-action: change
+Text-content-length: 2593
+Text-content-md5: 5ccff689fb290e00b85fe18ee50c54ba
+Text-content-sha1: a13de8e23f1483efca3e57b2b64b0ae6f740ce10
+Content-length: 2593
+
+# -DCOLLISION_CHECK if you believe that SHA1's
+# 1461501637330902918203684832716283019655932542976 hashes do not give you
+# enough guarantees about no collisions between objects ever hapenning.
+#
+# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
+# Note that you need some new glibc (at least >2.2.4) for this, and it will
+# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly
+# break unless your underlying filesystem supports those sub-second times
+# (my ext3 doesn't).
+CFLAGS=-g -O3 -Wall
+
+CC=gcc
+
+
+PROG=   update-cache show-diff init-db write-tree read-tree commit-tree \
+       cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
+       check-files ls-tree merge-base
+
+all: $(PROG)
+
+install: $(PROG)
+       install $(PROG) $(HOME)/bin/
+
+LIBS= -lssl -lz
+
+init-db: init-db.o
+
+update-cache: update-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS)
+
+show-diff: show-diff.o read-cache.o
+       $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS)
+
+write-tree: write-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS)
+
+read-tree: read-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS)
+
+commit-tree: commit-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS)
+
+cat-file: cat-file.o read-cache.o
+       $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS)
+
+fsck-cache: fsck-cache.o read-cache.o object.o commit.o tree.o blob.o
+       $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+checkout-cache: checkout-cache.o read-cache.o
+       $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS)
+
+diff-tree: diff-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS)
+
+rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o
+       $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+show-files: show-files.o read-cache.o
+       $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS)
+
+check-files: check-files.o read-cache.o
+       $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS)
+
+ls-tree: ls-tree.o read-cache.o
+       $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS)
+
+merge-base: merge-base.o read-cache.o object.o commit.o tree.o blob.o
+       $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+read-cache.o: cache.h
+show-diff.o: cache.h
+
+clean:
+       rm -f *.o $(PROG)
+
+backup: clean
+       cd .. ; tar czvf dircache.tar.gz dir-cache
+
+
+Revision-number: 12
+Prop-content-length: 116
+Content-length: 116
+
+K 7
+svn:log
+V 13
+Merge trunk 2
+K 10
+svn:author
+V 8
+tallsopp
+K 8
+svn:date
+V 27
+2009-11-12T20:29:56.083003Z
+PROPS-END
+
+Node-path: trunk
+Node-kind: dir
+Node-action: change
+Prop-content-length: 54
+Content-length: 54
+
+K 13
+svn:mergeinfo
+V 19
+/branches/left:2-11
+PROPS-END
+
+
index a12c6e214e65d39136b1ed41a8ff0ea25e28f91b..408f0137a8342414eedba3a02372ea1ad6050117 100644 (file)
@@ -50,4 +50,4 @@ clean:
 install: all
        $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(template_instdir_SQ)'
        (cd blt && $(TAR) cf - .) | \
-       (cd '$(DESTDIR_SQ)$(template_instdir_SQ)' && umask 022 && $(TAR) xfo -)
+       (cd '$(DESTDIR_SQ)$(template_instdir_SQ)' && umask 022 && $(TAR) xof -)
index 043970a751f0a85cfa99684be5d610b33b15a358..439eefda510ca8de9f55c63616f2113ac36c8b6b 100755 (executable)
@@ -7,6 +7,14 @@
 #
 # To enable this hook, rename this file to "pre-commit".
 
+if git-rev-parse --verify HEAD >/dev/null 2>&1
+then
+       against=HEAD
+else
+       # Initial commit: diff against an empty tree object
+       against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
+fi
+
 # If you want to allow non-ascii filenames set this variable to true.
 allownonascii=$(git config hooks.allownonascii)
 
@@ -17,7 +25,7 @@ if [ "$allownonascii" != "true" ] &&
        # Note that the use of brackets around a tr range is ok here, (it's
        # even required, for portability to Solaris 10's /usr/bin/tr), since
        # the square bracket bytes happen to fall in the designated range.
-       test "$(git diff --cached --name-only --diff-filter=A -z |
+       test "$(git diff --cached --name-only --diff-filter=A -z $against |
          LC_ALL=C tr -d '[ -~]\0')"
 then
        echo "Error: Attempt to add a non-ascii file name."
@@ -35,12 +43,4 @@ then
        exit 1
 fi
 
-if git-rev-parse --verify HEAD >/dev/null 2>&1
-then
-       against=HEAD
-else
-       # Initial commit: diff against an empty tree object
-       against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
-fi
-
 exec git diff-index --check --cached $against --
index 644a30a0b200b339d291f4cc3d35b2268d12facd..d249203eac88810ffef1cdd646e112a082d2c8b8 100644 (file)
@@ -668,7 +668,7 @@ static int print_one_push_status(struct ref *ref, const char *dest, int count, i
                break;
        case REF_STATUS_REJECT_NONFASTFORWARD:
                print_ref_status('!', "[rejected]", ref, ref->peer_ref,
-                                                "non-fast forward", porcelain);
+                                                "non-fast-forward", porcelain);
                break;
        case REF_STATUS_REMOTE_REJECT:
                print_ref_status('!', "[remote rejected]", ref,
@@ -812,6 +812,9 @@ struct transport *transport_get(struct remote *remote, const char *url)
 {
        struct transport *ret = xcalloc(1, sizeof(*ret));
 
+       if (!remote)
+               die("No remote provided to transport_get()");
+
        ret->remote = remote;
        ret->url = url;
 
@@ -849,10 +852,10 @@ struct transport *transport_get(struct remote *remote, const char *url)
                data->thin = 1;
                data->conn = NULL;
                data->uploadpack = "git-upload-pack";
-               if (remote && remote->uploadpack)
+               if (remote->uploadpack)
                        data->uploadpack = remote->uploadpack;
                data->receivepack = "git-receive-pack";
-               if (remote && remote->receivepack)
+               if (remote->receivepack)
                        data->receivepack = remote->receivepack;
        }
 
index ac9cbf7cd8ed1367151de0e8b96668f498b7f1a1..e9d8934691822ad81a4c32481d82790e9d7ca5b0 100644 (file)
@@ -28,7 +28,7 @@ int main(int argc, char **argv)
 
        git_extract_argv0_path(argv[0]);
 
-       if (argc != 2)
+       if (argc != 2 || !strcmp(argv[1], "-h"))
                usage("git unpack-file <sha1>");
        if (get_sha1(argv[1], sha1))
                die("Not a valid object name %s", argv[1]);
index 720f7a161651126872b7357173c10d69d1db7636..157d5d001fe3014def96e3660df7ee5b1b98c275 100644 (file)
@@ -895,7 +895,7 @@ int threeway_merge(struct cache_entry **stages, struct unpack_trees_options *o)
  * Two-way merge.
  *
  * The rule is to "carry forward" what is in the index without losing
- * information across a "fast forward", favoring a successful merge
+ * information across a "fast-forward", favoring a successful merge
  * over a merge failure when it makes sense.  For details of the
  * "carry forward" rule, please see <Documentation/git-read-tree.txt>.
  *
index 38ddac2e8607f4cc6a801eeb49ba755dd89ee81c..953ebe1a6030d8476fbebd0b060d3651cfde8f2f 100644 (file)
@@ -308,6 +308,23 @@ static void create_pack_file(void)
                        }
                        continue;
                }
+               if (0 <= pe && (pfd[pe].revents & (POLLIN|POLLHUP))) {
+                       /* Status ready; we ship that in the side-band
+                        * or dump to the standard error.
+                        */
+                       sz = xread(pack_objects.err, progress,
+                                 sizeof(progress));
+                       if (0 < sz)
+                               send_client_data(2, progress, sz);
+                       else if (sz == 0) {
+                               close(pack_objects.err);
+                               pack_objects.err = -1;
+                       }
+                       else
+                               goto fail;
+                       /* give priority to status messages */
+                       continue;
+               }
                if (0 <= pu && (pfd[pu].revents & (POLLIN|POLLHUP))) {
                        /* Data ready; we keep the last byte to ourselves
                         * in case we detect broken rev-list, so that we
@@ -345,21 +362,6 @@ static void create_pack_file(void)
                        if (sz < 0)
                                goto fail;
                }
-               if (0 <= pe && (pfd[pe].revents & (POLLIN|POLLHUP))) {
-                       /* Status ready; we ship that in the side-band
-                        * or dump to the standard error.
-                        */
-                       sz = xread(pack_objects.err, progress,
-                                 sizeof(progress));
-                       if (0 < sz)
-                               send_client_data(2, progress, sz);
-                       else if (sz == 0) {
-                               close(pack_objects.err);
-                               pack_objects.err = -1;
-                       }
-                       else
-                               goto fail;
-               }
        }
 
        if (finish_command(&pack_objects)) {
diff --git a/usage.c b/usage.c
index c488f3afcd6d612e786c13c86241b2a01eb97a2a..e307e01b99ccc55a82040066499ad3651cd2407a 100644 (file)
--- a/usage.c
+++ b/usage.c
@@ -12,9 +12,9 @@ static void report(const char *prefix, const char *err, va_list params)
        fprintf(stderr, "%s%s\n", prefix, msg);
 }
 
-static NORETURN void usage_builtin(const char *err)
+static NORETURN void usage_builtin(const char *err, va_list params)
 {
-       fprintf(stderr, "usage: %s\n", err);
+       report("usage: ", err, params);
        exit(129);
 }
 
@@ -36,7 +36,7 @@ static void warn_builtin(const char *warn, va_list params)
 
 /* If we are in a dlopen()ed .so write to a global variable would segfault
  * (ugh), so keep things static. */
-static NORETURN_PTR void (*usage_routine)(const char *err) = usage_builtin;
+static NORETURN_PTR void (*usage_routine)(const char *err, va_list params) = usage_builtin;
 static NORETURN_PTR void (*die_routine)(const char *err, va_list params) = die_builtin;
 static void (*error_routine)(const char *err, va_list params) = error_builtin;
 static void (*warn_routine)(const char *err, va_list params) = warn_builtin;
@@ -46,9 +46,18 @@ void set_die_routine(NORETURN_PTR void (*routine)(const char *err, va_list param
        die_routine = routine;
 }
 
+void usagef(const char *err, ...)
+{
+       va_list params;
+
+       va_start(params, err);
+       usage_routine(err, params);
+       va_end(params);
+}
+
 void usage(const char *err)
 {
-       usage_routine(err);
+       usagef("%s", err);
 }
 
 void die(const char *err, ...)
diff --git a/utf8.c b/utf8.c
index db706ac4ed6f033091cfaeb7b23c07ca7fd71675..5c18f0c28107c91d9b2ec124ea2896d20945aa58 100644 (file)
--- a/utf8.c
+++ b/utf8.c
@@ -1,4 +1,5 @@
 #include "git-compat-util.h"
+#include "strbuf.h"
 #include "utf8.h"
 
 /* This code is originally from http://www.cl.cam.ac.uk/~mgk25/ucs/ */
@@ -279,14 +280,22 @@ int is_utf8(const char *text)
        return 1;
 }
 
-static void print_spaces(int count)
+static inline void strbuf_write(struct strbuf *sb, const char *buf, int len)
+{
+       if (sb)
+               strbuf_insert(sb, sb->len, buf, len);
+       else
+               fwrite(buf, len, 1, stdout);
+}
+
+static void print_spaces(struct strbuf *buf, int count)
 {
        static const char s[] = "                    ";
        while (count >= sizeof(s)) {
-               fwrite(s, sizeof(s) - 1, 1, stdout);
+               strbuf_write(buf, s, sizeof(s) - 1);
                count -= sizeof(s) - 1;
        }
-       fwrite(s, count, 1, stdout);
+       strbuf_write(buf, s, count);
 }
 
 /*
@@ -295,11 +304,25 @@ static void print_spaces(int count)
  * If indent is negative, assume that already -indent columns have been
  * consumed (and no extra indent is necessary for the first line).
  */
-int print_wrapped_text(const char *text, int indent, int indent2, int width)
+int strbuf_add_wrapped_text(struct strbuf *buf,
+               const char *text, int indent, int indent2, int width)
 {
        int w = indent, assume_utf8 = is_utf8(text);
        const char *bol = text, *space = NULL;
 
+       if (width <= 0) {
+               /* just indent */
+               while (*text) {
+                       const char *eol = strchrnul(text, '\n');
+                       if (*eol == '\n')
+                               eol++;
+                       print_spaces(buf, indent);
+                       strbuf_write(buf, text, eol-text);
+                       text = eol;
+               }
+               return 1;
+       }
+
        if (indent < 0) {
                w = -indent;
                space = text;
@@ -310,21 +333,35 @@ int print_wrapped_text(const char *text, int indent, int indent2, int width)
                if (!c || isspace(c)) {
                        if (w < width || !space) {
                                const char *start = bol;
+                               if (!c && text == start)
+                                       return w;
                                if (space)
                                        start = space;
                                else
-                                       print_spaces(indent);
-                               fwrite(start, text - start, 1, stdout);
+                                       print_spaces(buf, indent);
+                               strbuf_write(buf, start, text - start);
                                if (!c)
                                        return w;
-                               else if (c == '\t')
-                                       w |= 0x07;
                                space = text;
+                               if (c == '\t')
+                                       w |= 0x07;
+                               else if (c == '\n') {
+                                       space++;
+                                       if (*space == '\n') {
+                                               strbuf_write(buf, "\n", 1);
+                                               goto new_line;
+                                       }
+                                       else if (!isalnum(*space))
+                                               goto new_line;
+                                       else
+                                               strbuf_write(buf, " ", 1);
+                               }
                                w++;
                                text++;
                        }
                        else {
-                               putchar('\n');
+new_line:
+                               strbuf_write(buf, "\n", 1);
                                text = bol = space + isspace(*space);
                                space = NULL;
                                w = indent = indent2;
@@ -340,6 +377,11 @@ int print_wrapped_text(const char *text, int indent, int indent2, int width)
        }
 }
 
+int print_wrapped_text(const char *text, int indent, int indent2, int width)
+{
+       return strbuf_add_wrapped_text(NULL, text, indent, indent2, width);
+}
+
 int is_encoding_utf8(const char *name)
 {
        if (!name)
diff --git a/utf8.h b/utf8.h
index 2f1b14ff49ef3c73bee6f298ba396b96120c34b7..ae30ae4c6e501e4766db93c94253fd404cd29357 100644 (file)
--- a/utf8.h
+++ b/utf8.h
@@ -10,6 +10,8 @@ int is_utf8(const char *text);
 int is_encoding_utf8(const char *name);
 
 int print_wrapped_text(const char *text, int indent, int indent2, int len);
+int strbuf_add_wrapped_text(struct strbuf *buf,
+               const char *text, int indent, int indent2, int width);
 
 #ifndef NO_ICONV
 char *reencode_string(const char *in, const char *out_encoding, const char *in_encoding);
diff --git a/ws.c b/ws.c
index 59d0883c1f3a46edcbb2e45b172c9eac3b9d5e35..760b5743fa11f25dd4facf8beeb02e7aa28d09e1 100644 (file)
--- a/ws.c
+++ b/ws.c
@@ -16,6 +16,8 @@ static struct whitespace_rule {
        { "space-before-tab", WS_SPACE_BEFORE_TAB, 0 },
        { "indent-with-non-tab", WS_INDENT_WITH_NON_TAB, 0 },
        { "cr-at-eol", WS_CR_AT_EOL, 1 },
+       { "blank-at-eol", WS_BLANK_AT_EOL, 0 },
+       { "blank-at-eof", WS_BLANK_AT_EOF, 0 },
 };
 
 unsigned parse_whitespace_rule(const char *string)
@@ -102,8 +104,17 @@ unsigned whitespace_rule(const char *pathname)
 char *whitespace_error_string(unsigned ws)
 {
        struct strbuf err = STRBUF_INIT;
-       if (ws & WS_TRAILING_SPACE)
+       if ((ws & WS_TRAILING_SPACE) == WS_TRAILING_SPACE)
                strbuf_addstr(&err, "trailing whitespace");
+       else {
+               if (ws & WS_BLANK_AT_EOL)
+                       strbuf_addstr(&err, "trailing whitespace");
+               if (ws & WS_BLANK_AT_EOF) {
+                       if (err.len)
+                               strbuf_addstr(&err, ", ");
+                       strbuf_addstr(&err, "new blank line at EOF");
+               }
+       }
        if (ws & WS_SPACE_BEFORE_TAB) {
                if (err.len)
                        strbuf_addstr(&err, ", ");
@@ -141,11 +152,11 @@ static unsigned ws_check_emit_1(const char *line, int len, unsigned ws_rule,
        }
 
        /* Check for trailing whitespace. */
-       if (ws_rule & WS_TRAILING_SPACE) {
+       if (ws_rule & WS_BLANK_AT_EOL) {
                for (i = len - 1; i >= 0; i--) {
                        if (isspace(line[i])) {
                                trailing_whitespace = i;
-                               result |= WS_TRAILING_SPACE;
+                               result |= WS_BLANK_AT_EOL;
                        }
                        else
                                break;
@@ -261,7 +272,7 @@ int ws_fix_copy(char *dst, const char *src, int len, unsigned ws_rule, int *erro
        /*
         * Strip trailing whitespace
         */
-       if (ws_rule & WS_TRAILING_SPACE) {
+       if (ws_rule & WS_BLANK_AT_EOL) {
                if (0 < len && src[len - 1] == '\n') {
                        add_nl_to_tail = 1;
                        len--;