Merge branch 'ah/misc-message-fixes'
authorJunio C Hamano <gitster@pobox.com>
Thu, 15 Sep 2016 21:11:15 +0000 (14:11 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 15 Sep 2016 21:11:15 +0000 (14:11 -0700)
Message cleanup.

* ah/misc-message-fixes:
unpack-trees: do not capitalize "working"
git-merge-octopus: do not capitalize "octopus"
git-rebase--interactive: fix English grammar
cat-file: put spaces around pipes in usage string
am: put spaces around pipe in usage string

90 files changed:
Documentation/RelNotes/2.11.0.txt [new file with mode: 0644]
Documentation/RelNotes/2.9.4.txt [new file with mode: 0644]
Documentation/SubmittingPatches
Documentation/config.txt
Documentation/diff-config.txt
Documentation/diff-options.txt
Documentation/git-clone.txt
Documentation/git-index-pack.txt
Documentation/git-receive-pack.txt
Documentation/git-status.txt
Documentation/git-unpack-objects.txt
Documentation/gitk.txt
Documentation/gitrevisions.txt
Documentation/pretty-formats.txt
Documentation/rev-list-options.txt
Documentation/revisions.txt
GIT-VERSION-GEN
Makefile
RelNotes
builtin/am.c
builtin/clone.c
builtin/commit.c
builtin/help.c
builtin/index-pack.c
builtin/log.c
builtin/pack-objects.c
builtin/receive-pack.c
builtin/rev-list.c
builtin/submodule--helper.c
builtin/symbolic-ref.c
builtin/unpack-objects.c
cache.h
color.c
compat/nedmalloc/nedmalloc.c
compat/strdup.c [new file with mode: 0644]
contrib/diff-highlight/Makefile [new file with mode: 0644]
contrib/diff-highlight/diff-highlight
contrib/diff-highlight/t/.gitignore [new file with mode: 0644]
contrib/diff-highlight/t/Makefile [new file with mode: 0644]
contrib/diff-highlight/t/t9400-diff-highlight.sh [new file with mode: 0755]
diff.c
diff.h
git-compat-util.h
git-gui/po/ja.po
git-submodule.sh
git.c
graph.c
graph.h
hex.c
log-tree.c
path.c
pkt-line.c
po/TEAMS
po/pt_PT.po
po/zh_CN.po
pretty.c
ref-filter.c
refs/files-backend.c
sha1_file.c
submodule.c
submodule.h
t/perf/p0003-delta-base-cache.sh [new file with mode: 0755]
t/t0012-help.sh [new file with mode: 0755]
t/t1401-symbolic-ref.sh
t/t4013-diff-various.sh
t/t4013/diff.diff_--line-prefix=abc_master_master^_side [new file with mode: 0644]
t/t4013/diff.diff_--line-prefix_--cached_--_file0 [new file with mode: 0644]
t/t4021-format-patch-numbered.sh
t/t4059-diff-submodule-not-initialized.sh [new file with mode: 0755]
t/t4060-diff-submodule-option-diff-format.sh [new file with mode: 0755]
t/t4202-log.sh
t/t5305-include-tag.sh
t/t5526-fetch-submodules.sh
t/t5541-http-push-smart.sh
t/t5546-receive-limits.sh [new file with mode: 0755]
t/t5550-http-fetch-dumb.sh
t/t5551-http-fetch-smart.sh
t/t6026-merge-attr.sh
t/t7060-wtstatus.sh
t/t7064-wtstatus-pv2.sh [new file with mode: 0755]
t/t7408-submodule-reference.sh
t/t9903-bash-prompt.sh
t/test-lib-functions.sh
t/test-lib.sh
transport.c
url.c
usage.c
wt-status.c
wt-status.h
xdiff/xemit.c
diff --git a/Documentation/RelNotes/2.11.0.txt b/Documentation/RelNotes/2.11.0.txt
new file mode 100644 (file)
index 0000000..6bb69db
--- /dev/null
@@ -0,0 +1,97 @@
+Git 2.11 Release Notes
+======================
+
+Updates since v2.10
+-------------------
+
+UI, Workflows & Features
+
+ * "git format-patch --cover-letter HEAD^" to format a single patch
+   with a separate cover letter now numbers the output as [PATCH 0/1]
+   and [PATCH 1/1] by default.
+
+ * An incoming "git push" that attempts to push too many bytes can now
+   be rejected by setting a new configuration variable at the receiving
+   end.
+
+ * "git nosuchcommand --help" said "No manual entry for gitnosuchcommand",
+   which was not intuitive, given that "git nosuchcommand" said "git:
+   'nosuchcommand' is not a git command".
+
+ * "git clone --resurse-submodules --reference $path $URL" is a way to
+   reduce network transfer cost by borrowing objects in an existing
+   $path repository when cloning the superproject from $URL; it
+   learned to also peek into $path for presense of corresponding
+   repositories of submodules and borrow objects from there when able.
+
+ * The "git diff --submodule={short,log}" mechanism has been enhanced
+   to allow "--submodule=diff" to show the patch between the submodule
+   commits bound to the superproject.
+
+
+Performance, Internal Implementation, Development Support etc.
+
+ * The delta-base-cache mechanism has been a key to the performance in
+   a repository with a tightly packed packfile, but it did not scale
+   well even with a larger value of core.deltaBaseCacheLimit.
+
+ * Enhance "git status --porcelain" output by collecting more data on
+   the state of the index and the working tree files, which may
+   further be used to teach git-prompt (in contrib/) to make fewer
+   calls to git.
+
+ * Extract a small helper out of the function that reads the authors
+   script file "git am" internally uses.
+   (merge a77598e jc/am-read-author-file later to maint).
+
+
+Also contains various documentation updates and code clean-ups.
+
+
+Fixes since v2.10
+-----------------
+
+Unless otherwise noted, all the fixes since v2.9 in the maintenance
+track are contained in this release (see the maintenance releases'
+notes for details).
+
+ * Clarify various ways to specify the "revision ranges" in the
+   documentation.
+   (merge a117be4 po/range-doc later to maint).
+
+ * "diff-highlight" script (in contrib/) learned to work better with
+   "git log -p --graph" output.
+   (merge 3dbfe2b bh/diff-highlight-graph later to maint).
+
+ * The test framework left the number of tests and success/failure
+   count in the t/test-results directory, keyed by the name of the
+   test script plus the process ID.  The latter however turned out not
+   to serve any useful purpose.  The process ID part of the filename
+   has been removed.
+   (merge 5c885c1 jk/test-lib-drop-pid-from-results later to maint).
+
+ * Having a submodule whose ".git" repository is somehow corrupt
+   caused a few commands that recurse into submodules loop forever.
+   (merge 10f5c52 jc/submodule-anchor-git-dir later to maint).
+
+ * "git symbolic-ref -d HEAD" happily removes the symbolic ref, but
+   the resulting repository becomes an invalid one.  Teach the command
+   to forbid removal of HEAD.
+   (merge 12cfa79 jc/forbid-symbolic-ref-d-HEAD later to maint).
+
+ * A test spawned a short-lived background process, which sometimes
+   prevented the test directory from getting removed at the end of the
+   script on some platforms.
+   (merge 5babb5b js/t6026-clean-up later to maint).
+
+ * Update a few tests that used to use GIT_CURL_VERBOSE to use the
+   newer GIT_TRACE_CURL.
+   (merge 14e2411 ep/use-git-trace-curl-in-tests later to maint).
+
+ * Other minor doc, test and build updates and code cleanups.
+   (merge 3e1952e jk/squelch-false-warning-from-gcc-o3 later to maint).
+   (merge ca2baa3 rs/compat-strdup later to maint).
+   (merge d233097 rs/hex2chr later to maint).
+   (merge c00bfc9 js/t9903-chaining later to maint).
+   (merge 5e4e5bb sb/xdiff-remove-unused-static-decl later to maint).
+   (merge 5cb5fe4 sb/transport-report-missing-submodule-on-stderr later to maint).
diff --git a/Documentation/RelNotes/2.9.4.txt b/Documentation/RelNotes/2.9.4.txt
new file mode 100644 (file)
index 0000000..01e8642
--- /dev/null
@@ -0,0 +1,83 @@
+Git v2.9.4 Release Notes
+========================
+
+Fixes since v2.9.3
+------------------
+
+ * There are certain house-keeping tasks that need to be performed at
+   the very beginning of any Git program, and programs that are not
+   built-in commands had to do them exactly the same way as "git"
+   potty does.  It was easy to make mistakes in one-off standalone
+   programs (like test helpers).  A common "main()" function that
+   calls cmd_main() of individual program has been introduced to
+   make it harder to make mistakes.
+
+ * "git merge" with renormalization did not work well with
+   merge-recursive, due to "safer crlf" conversion kicking in when it
+   shouldn't.
+
+ * The reflog output format is documented better, and a new format
+   --date=unix to report the seconds-since-epoch (without timezone)
+   has been added.
+
+ * "git push --force-with-lease" already had enough logic to allow
+   ensuring that such a push results in creation of a ref (i.e. the
+   receiving end did not have another push from sideways that would be
+   discarded by our force-pushing), but didn't expose this possibility
+   to the users.  It does so now.
+
+ * "import-tars" fast-import script (in contrib/) used to ignore a
+   hardlink target and replaced it with an empty file, which has been
+   corrected to record the same blob as the other file the hardlink is
+   shared with.
+
+ * "git mv dir non-existing-dir/" did not work in some environments
+   the same way as existing mainstream platforms.  The code now moves
+   "dir" to "non-existing-dir", without relying on rename("A", "B/")
+   that strips the trailing slash of '/'.
+
+ * The "t/" hierarchy is prone to get an unusual pathname; "make test"
+   has been taught to make sure they do not contain paths that cannot
+   be checked out on Windows (and the mechanism can be reusable to
+   catch pathnames that are not portable to other platforms as need
+   arises).
+
+ * When "git merge-recursive" works on history with many criss-cross
+   merges in "verbose" mode, the names the command assigns to the
+   virtual merge bases could have overwritten each other by unintended
+   reuse of the same piece of memory.
+
+ * "git checkout --detach <branch>" used to give the same advice
+   message as that is issued when "git checkout <tag>" (or anything
+   that is not a branch name) is given, but asking with "--detach" is
+   an explicit enough sign that the user knows what is going on.  The
+   advice message has been squelched in this case.
+
+ * "git difftool" by default ignores the error exit from the backend
+   commands it spawns, because often they signal that they found
+   differences by exiting with a non-zero status code just like "diff"
+   does; the exit status codes 126 and above however are special in
+   that they are used to signal that the command is not executable,
+   does not exist, or killed by a signal.  "git difftool" has been
+   taught to notice these exit status codes.
+
+ * On Windows, help.browser configuration variable used to be ignored,
+   which has been corrected.
+
+ * The "git -c var[=val] cmd" facility to append a configuration
+   variable definition at the end of the search order was described in
+   git(1) manual page, but not in git-config(1), which was more likely
+   place for people to look for when they ask "can I make a one-shot
+   override, and if so how?"
+
+ * The tempfile (hence its user lockfile) API lets the caller to open
+   a file descriptor to a temporary file, write into it and then
+   finalize it by first closing the filehandle and then either
+   removing or renaming the temporary file.  When the process spawns a
+   subprocess after obtaining the file descriptor, and if the
+   subprocess has not exited when the attempt to remove or rename is
+   made, the last step fails on Windows, because the subprocess has
+   the file descriptor still open.  Open tempfile with O_CLOEXEC flag
+   to avoid this (on Windows, this is mapped to O_NOINHERIT).
+
+Also contains minor documentation updates and code clean-ups.
index 500230c054be697d507cfa8e800e657803e6ab0d..08352deaae4763791b70bd172682c1fe5380f7b4 100644 (file)
@@ -122,9 +122,14 @@ without external resources. Instead of giving a URL to a mailing list
 archive, summarize the relevant points of the discussion.
 
 If you want to reference a previous commit in the history of a stable
-branch use the format "abbreviated sha1 (subject, date)". So for example
-like this: "Commit f86a374 (pack-bitmap.c: fix a memleak, 2015-03-30)
-noticed [...]".
+branch, use the format "abbreviated sha1 (subject, date)",
+with the subject enclosed in a pair of double-quotes, like this:
+
+    Commit f86a374 ("pack-bitmap.c: fix a memleak", 2015-03-30)
+    noticed that ...
+
+The "Copy commit summary" command of gitk can be used to obtain this
+format.
 
 
 (3) Generate your patch using Git tools out of your commits.
index 0bcb6790d6efbb2a812bc90b6f64e323cb3ec393..32f065ca6a9382ba7b496d9c6606a72941dc0c1f 100644 (file)
@@ -2517,6 +2517,12 @@ receive.unpackLimit::
        especially on slow filesystems.  If not set, the value of
        `transfer.unpackLimit` is used instead.
 
+receive.maxInputSize::
+       If the size of the incoming pack stream is larger than this
+       limit, then git-receive-pack will error out, instead of
+       accepting the pack file. If not set or set to 0, then the size
+       is unlimited.
+
 receive.denyDeletes::
        If set to true, git-receive-pack will deny a ref update that deletes
        the ref. Use this to prevent such a ref deletion via a push.
@@ -2847,6 +2853,18 @@ submodule.fetchJobs::
        in parallel. A value of 0 will give some reasonable default.
        If unset, it defaults to 1.
 
+submodule.alternateLocation::
+       Specifies how the submodules obtain alternates when submodules are
+       cloned. Possible values are `no`, `superproject`.
+       By default `no` is assumed, which doesn't add references. When the
+       value is set to `superproject` the submodule to be cloned computes
+       its alternates location relative to the superprojects alternate.
+
+submodule.alternateErrorStrategy
+       Specifies how to treat errors with the alternates for a submodule
+       as computed via `submodule.alternateLocation`. Possible values are
+       `ignore`, `info`, `die`. Default is `die`.
+
 tag.forceSignAnnotated::
        A boolean to specify whether annotated tags created should be GPG signed.
        If `--annotate` is specified on the command line, it takes
index d5a5b17d508839bc379821ee1a318400a3557fe9..0eded24034b57a511425f60c92b5d9119e8950fa 100644 (file)
@@ -122,10 +122,11 @@ diff.suppressBlankEmpty::
 
 diff.submodule::
        Specify the format in which differences in submodules are
-       shown.  The "log" format lists the commits in the range like
-       linkgit:git-submodule[1] `summary` does.  The "short" format
-       format just shows the names of the commits at the beginning
-       and end of the range.  Defaults to short.
+       shown.  The "short" format just shows the names of the commits
+       at the beginning and end of the range. The "log" format lists
+       the commits in the range like linkgit:git-submodule[1] `summary`
+       does. The "diff" format shows an inline diff of the changed
+       contents of the submodule. Defaults to "short".
 
 diff.wordRegex::
        A POSIX Extended Regular Expression used to determine what is a "word"
index 705a8739420067d433817c0f855c5cb4ee99559b..7805a0ccadf27e4fea46dcd95796c570e893e6b3 100644 (file)
@@ -210,13 +210,16 @@ any of those replacements occurred.
        of the `--diff-filter` option on what the status letters mean.
 
 --submodule[=<format>]::
-       Specify how differences in submodules are shown.  When `--submodule`
-       or `--submodule=log` is given, the 'log' format is used.  This format lists
-       the commits in the range like linkgit:git-submodule[1] `summary` does.
-       Omitting the `--submodule` option or specifying `--submodule=short`,
-       uses the 'short' format. This format just shows the names of the commits
-       at the beginning and end of the range.  Can be tweaked via the
-       `diff.submodule` configuration variable.
+       Specify how differences in submodules are shown.  When specifying
+       `--submodule=short` the 'short' format is used.  This format just
+       shows the names of the commits at the beginning and end of the range.
+       When `--submodule` or `--submodule=log` is specified, the 'log'
+       format is used.  This format lists the commits in the range like
+       linkgit:git-submodule[1] `summary` does.  When `--submodule=diff`
+       is specified, the 'diff' format is used.  This format shows an
+       inline diff of the changes in the submodule contents between the
+       commit range.  Defaults to `diff.submodule` or the 'short' format
+       if the config option is unset.
 
 --color[=<when>]::
        Show colored diff.
@@ -569,5 +572,8 @@ endif::git-format-patch[]
 --no-prefix::
        Do not show any source or destination prefix.
 
+--line-prefix=<prefix>::
+       Prepend an additional prefix to every line of output.
+
 For more detailed explanation on these common options, see also
 linkgit:gitdiffcore[7].
index ec41d3d698a1bcffac3b3a21489b61cc74f9d8d0..e316c4bd51a64fb9df87ce003f2edffad38b63ad 100644 (file)
@@ -90,13 +90,16 @@ If you want to break the dependency of a repository cloned with `-s` on
 its source repository, you can simply run `git repack -a` to copy all
 objects from the source repository into a pack in the cloned repository.
 
---reference <repository>::
+--reference[-if-able] <repository>::
        If the reference repository is on the local machine,
        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.
+       When using the `--reference-if-able`, a non existing
+       directory is skipped with a warning instead of aborting
+       the clone.
 +
 *NOTE*: see the NOTE for the `--shared` option, and also the
 `--dissociate` option.
index 7a4e0555205be5d8bb26e5a183f1552cc057637a..1b4b65d6657b003079e0407d1da8d8c239933267 100644 (file)
@@ -87,6 +87,8 @@ OPTIONS
        Specifying 0 will cause Git to auto-detect the number of CPU's
        and use maximum 3 threads.
 
+--max-input-size=<size>::
+       Die, if the pack is larger than <size>.
 
 Note
 ----
index 000ee8dba2ab3069e0459defe3df9d7140541a59..0ccd5fbc781deb3adcca4d28ec8a4ed0d9db9977 100644 (file)
@@ -33,6 +33,9 @@ post-update hooks found in the Documentation/howto directory.
 option, which tells it if updates to a ref should be denied if they
 are not fast-forwards.
 
+A number of other receive.* config options are available to tweak
+its behavior, see linkgit:git-config[1].
+
 OPTIONS
 -------
 <directory>::
index e1e8f57cdd217b43b9b04bc54381e9b155d9cbde..725065ef2d7b6b3c7c6c29a434a8996a7e1ae559 100644 (file)
@@ -32,11 +32,14 @@ OPTIONS
 --branch::
        Show the branch and tracking info even in short-format.
 
---porcelain::
+--porcelain[=<version>]::
        Give the output in an easy-to-parse format for scripts.
        This is similar to the short output, but will remain stable
        across Git versions and regardless of user configuration. See
        below for details.
++
+The version parameter is used to specify the format version.
+This is optional and defaults to the original version 'v1' format.
 
 --long::
        Give the output in the long-format. This is the default.
@@ -96,7 +99,7 @@ configuration variable documented in linkgit:git-config[1].
 
 -z::
        Terminate entries with NUL, instead of LF.  This implies
-       the `--porcelain` output format if no other format is given.
+       the `--porcelain=v1` output format if no other format is given.
 
 --column[=<options>]::
 --no-column::
@@ -180,12 +183,12 @@ in which case `XY` are `!!`.
 
 If -b is used the short-format status is preceded by a line
 
-## branchname tracking info
+    ## branchname tracking info
 
-Porcelain Format
-~~~~~~~~~~~~~~~~
+Porcelain Format Version 1
+~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-The porcelain format is similar to the short format, but is guaranteed
+Version 1 porcelain format is similar to the short format, but is guaranteed
 not to change in a backwards-incompatible way between Git versions or
 based on user configuration. This makes it ideal for parsing by scripts.
 The description of the short format above also describes the porcelain
@@ -207,6 +210,124 @@ field from the first filename).  Third, filenames containing special
 characters are not specially formatted; no quoting or
 backslash-escaping is performed.
 
+Porcelain Format Version 2
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Version 2 format adds more detailed information about the state of
+the worktree and changed items.  Version 2 also defines an extensible
+set of easy to parse optional headers.
+
+Header lines start with "#" and are added in response to specific
+command line arguments.  Parsers should ignore headers they
+don't recognize.
+
+### Branch Headers
+
+If `--branch` is given, a series of header lines are printed with
+information about the current branch.
+
+    Line                                     Notes
+    ------------------------------------------------------------
+    # branch.oid <commit> | (initial)        Current commit.
+    # branch.head <branch> | (detached)      Current branch.
+    # branch.upstream <upstream_branch>      If upstream is set.
+    # branch.ab +<ahead> -<behind>           If upstream is set and
+                                            the commit is present.
+    ------------------------------------------------------------
+
+### Changed Tracked Entries
+
+Following the headers, a series of lines are printed for tracked
+entries.  One of three different line formats may be used to describe
+an entry depending on the type of change.  Tracked entries are printed
+in an undefined order; parsers should allow for a mixture of the 3
+line types in any order.
+
+Ordinary changed entries have the following format:
+
+    1 <XY> <sub> <mH> <mI> <mW> <hH> <hI> <path>
+
+Renamed or copied entries have the following format:
+
+    2 <XY> <sub> <mH> <mI> <mW> <hH> <hI> <X><score> <path><sep><origPath>
+
+    Field       Meaning
+    --------------------------------------------------------
+    <XY>        A 2 character field containing the staged and
+               unstaged XY values described in the short format,
+               with unchanged indicated by a "." rather than
+               a space.
+    <sub>       A 4 character field describing the submodule state.
+               "N..." when the entry is not a submodule.
+               "S<c><m><u>" when the entry is a submodule.
+               <c> is "C" if the commit changed; otherwise ".".
+               <m> is "M" if it has tracked changes; otherwise ".".
+               <u> is "U" if there are untracked changes; otherwise ".".
+    <mH>        The octal file mode in HEAD.
+    <mI>        The octal file mode in the index.
+    <mW>        The octal file mode in the worktree.
+    <hH>        The object name in HEAD.
+    <hI>        The object name in the index.
+    <X><score>  The rename or copy score (denoting the percentage
+               of similarity between the source and target of the
+               move or copy). For example "R100" or "C75".
+    <path>      The pathname.  In a renamed/copied entry, this
+               is the path in the index and in the working tree.
+    <sep>       When the `-z` option is used, the 2 pathnames are separated
+               with a NUL (ASCII 0x00) byte; otherwise, a tab (ASCII 0x09)
+               byte separates them.
+    <origPath>  The pathname in the commit at HEAD.  This is only
+               present in a renamed/copied entry, and tells
+               where the renamed/copied contents came from.
+    --------------------------------------------------------
+
+Unmerged entries have the following format; the first character is
+a "u" to distinguish from ordinary changed entries.
+
+    u <xy> <sub> <m1> <m2> <m3> <mW> <h1> <h2> <h3> <path>
+
+    Field       Meaning
+    --------------------------------------------------------
+    <XY>        A 2 character field describing the conflict type
+               as described in the short format.
+    <sub>       A 4 character field describing the submodule state
+               as described above.
+    <m1>        The octal file mode in stage 1.
+    <m2>        The octal file mode in stage 2.
+    <m3>        The octal file mode in stage 3.
+    <mW>        The octal file mode in the worktree.
+    <h1>        The object name in stage 1.
+    <h2>        The object name in stage 2.
+    <h3>        The object name in stage 3.
+    <path>      The pathname.
+    --------------------------------------------------------
+
+### Other Items
+
+Following the tracked entries (and if requested), a series of
+lines will be printed for untracked and then ignored items
+found in the worktree.
+
+Untracked items have the following format:
+
+    ? <path>
+
+Ignored items have the following format:
+
+    ! <path>
+
+### Pathname Format Notes and -z
+
+When the `-z` option is given, pathnames are printed as is and
+without any quoting and lines are terminated with a NUL (ASCII 0x00)
+byte.
+
+Otherwise, all pathnames will be "C-quoted" if they contain any tab,
+linefeed, double quote, or backslash characters. In C-quoting, these
+characters will be replaced with the corresponding C-style escape
+sequences and the resulting pathname will be double quoted.
+
+
 CONFIGURATION
 -------------
 
index 3e887d16109c48f4f906d8a7c5c0c860bbd6123d..b3de50d7106819f4dee92b3508c7713d170832ce 100644 (file)
@@ -44,6 +44,9 @@ OPTIONS
 --strict::
        Don't write objects with broken content or links.
 
+--max-input-size=<size>::
+       Die, if the pack is larger than <size>.
+
 GIT
 ---
 Part of the linkgit:git[1] suite
index a68d860fa3e9b63bf8ae76b93011bd9b49ecda25..e382dd96dfded769a27c2295ebc096c15214713b 100644 (file)
@@ -70,7 +70,7 @@ linkgit:git-rev-list[1] for a complete list.
 
 --left-right::
 
-       Mark which side of a symmetric diff a commit is reachable
+       Mark which side of a symmetric difference a commit is reachable
        from.  Commits from the left side are prefixed with a `<`
        symbol and those from the right with a `>` symbol.
 
index e903eb786049b4742e9d7c766b8448a503cbb6a3..27dec5b91d08bbdb114400dd3c86a8cf515e8774 100644 (file)
@@ -15,9 +15,9 @@ DESCRIPTION
 
 Many Git commands take revision parameters as arguments. Depending on
 the command, they denote a specific commit or, for commands which
-walk the revision graph (such as linkgit:git-log[1]), all commits which can
-be reached from that commit. In the latter case one can also specify a
-range of revisions explicitly.
+walk the revision graph (such as linkgit:git-log[1]), all commits which are
+reachable from that commit. For commands that walk the revision graph one can
+also specify a range of revisions explicitly.
 
 In addition, some Git commands (such as linkgit:git-show[1]) also take
 revision parameters which denote other objects than commits, e.g. blobs
index b95d67ec01f130417af9ff0d7bd0d2377008146c..a942d57f73a8502903b888d65d09a677816a5f0f 100644 (file)
@@ -172,7 +172,7 @@ endif::git-rev-list[]
   respecting the `auto` settings of the former if we are going to a
   terminal). `auto` alone (i.e. `%C(auto)`) will turn on auto coloring
   on the next placeholders until the color is switched again.
-- '%m': left, right or boundary mark
+- '%m': left (`<`), right (`>`) or boundary (`-`) mark
 - '%n': newline
 - '%%': a raw '%'
 - '%x00': print a byte from a hex code
index a779c9dfec0ed962e7274577b1c53daa0ecff1d9..7e462d3841daa1e7c11af224a98c6d7cf0b801a4 100644 (file)
@@ -225,7 +225,7 @@ excluded from the output.
 
 --left-only::
 --right-only::
-       List only commits on the respective side of a symmetric range,
+       List only commits on the respective side of a symmetric difference,
        i.e. only those which would be marked `<` resp. `>` by
        `--left-right`.
 +
@@ -796,7 +796,7 @@ ifdef::git-rev-list[]
 endif::git-rev-list[]
 
 --left-right::
-       Mark which side of a symmetric diff a commit is reachable from.
+       Mark which side of a symmetric difference a commit is reachable from.
        Commits from the left side are prefixed with `<` and those from
        the right with `>`.  If combined with `--boundary`, those
        commits are prefixed with `-`.
index abae36398351491db4bab57db6363e3597ade79d..4bed5b1ab741d9c86f5a9443f980080a56b84629 100644 (file)
@@ -237,48 +237,74 @@ SPECIFYING RANGES
 -----------------
 
 History traversing commands such as `git log` operate on a set
-of commits, not just a single commit.  To these commands,
-specifying a single revision with the notation described in the
-previous section means the set of commits reachable from that
-commit, following the commit ancestry chain.
-
-To exclude commits reachable from a commit, a prefix '{caret}'
-notation is used.  E.g. '{caret}r1 r2' means commits reachable
-from 'r2' but exclude the ones reachable from 'r1'.
-
-This set operation appears so often that there is a shorthand
-for it.  When you have two commits 'r1' and 'r2' (named according
-to the syntax explained in SPECIFYING REVISIONS above), you can ask
-for commits that are reachable from r2 excluding those that are reachable
-from r1 by '{caret}r1 r2' and it can be written as 'r1..r2'.
-
-A similar notation 'r1\...r2' is called symmetric difference
-of 'r1' and 'r2' and is defined as
-'r1 r2 --not $(git merge-base --all r1 r2)'.
-It is the set of commits that are reachable from either one of
-'r1' or 'r2' but not from both.
-
-In these two shorthands, you can omit one end and let it default to HEAD.
+of commits, not just a single commit.
+
+For these commands,
+specifying a single revision, using the notation described in the
+previous section, means the set of commits `reachable` from the given
+commit.
+
+A commit's reachable set is the commit itself and the commits in
+its ancestry chain.
+
+
+Commit Exclusions
+~~~~~~~~~~~~~~~~~
+
+'{caret}<rev>' (caret) Notation::
+ To exclude commits reachable from a commit, a prefix '{caret}'
+ notation is used.  E.g. '{caret}r1 r2' means commits reachable
+ from 'r2' but exclude the ones reachable from 'r1' (i.e. 'r1' and
+ its ancestors).
+
+Dotted Range Notations
+~~~~~~~~~~~~~~~~~~~~~~
+
+The '..' (two-dot) Range Notation::
+ The '{caret}r1 r2' set operation appears so often that there is a shorthand
+ for it.  When you have two commits 'r1' and 'r2' (named according
+ to the syntax explained in SPECIFYING REVISIONS above), you can ask
+ for commits that are reachable from r2 excluding those that are reachable
+ from r1 by '{caret}r1 r2' and it can be written as 'r1..r2'.
+
+The '...' (three dot) Symmetric Difference Notation::
+ A similar notation 'r1\...r2' is called symmetric difference
+ of 'r1' and 'r2' and is defined as
+ 'r1 r2 --not $(git merge-base --all r1 r2)'.
+ It is the set of commits that are reachable from either one of
+ 'r1' (left side) or 'r2' (right side) but not from both.
+
+In these two shorthand notations, you can omit one end and let it default to HEAD.
 For example, 'origin..' is a shorthand for 'origin..HEAD' and asks "What
 did I do since I forked from the origin branch?"  Similarly, '..origin'
 is a shorthand for 'HEAD..origin' and asks "What did the origin do since
 I forked from them?"  Note that '..' would mean 'HEAD..HEAD' which is an
 empty range that is both reachable and unreachable from HEAD.
 
-Two other shorthands for naming a set that is formed by a commit
-and its parent commits exist.  The 'r1{caret}@' notation means all
-parents of 'r1'.  'r1{caret}!' includes commit 'r1' but excludes
-all of its parents.
+Other <rev>{caret} Parent Shorthand Notations
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Two other shorthands exist, particularly useful for merge commits,
+for naming a set that is formed by a commit and its parent commits.
+
+The 'r1{caret}@' notation means all parents of 'r1'.
+
+The 'r1{caret}!' notation includes commit 'r1' but excludes all of its parents.
+By itself, this notation denotes the single commit 'r1'.
+
+While '<rev>{caret}<n>' was about specifying a single commit parent, these
+two notations consider all its parents. For example you can say
+'HEAD{caret}2{caret}@', however you cannot say 'HEAD{caret}@{caret}2'.
 
-To summarize:
+Revision Range Summary
+----------------------
 
 '<rev>'::
-       Include commits that are reachable from (i.e. ancestors of)
-       <rev>.
+       Include commits that are reachable from <rev> (i.e. <rev> and its
+       ancestors).
 
 '{caret}<rev>'::
-       Exclude commits that are reachable from (i.e. ancestors of)
-       <rev>.
+       Exclude commits that are reachable from <rev> (i.e. <rev> and its
+       ancestors).
 
 '<rev1>..<rev2>'::
        Include commits that are reachable from <rev2> but exclude
@@ -300,16 +326,27 @@ To summarize:
   as giving commit '<rev>' and then all its parents prefixed with
   '{caret}' to exclude them (and their ancestors).
 
-Here are a handful of examples:
-
-   D                G H D
-   D F              G H I J D F
-   ^G D             H D
-   ^D B             E I J F B
-   B..C             C
-   B...C            G H D E B C
-   ^D B C           E I J F B C
-   C                I J F C
-   C^@              I J F
-   C^!              C
-   F^! D            G H D F
+Here are a handful of examples using the Loeliger illustration above,
+with each step in the notation's expansion and selection carefully
+spelt out:
+
+   Args   Expanded arguments    Selected commits
+   D                            G H D
+   D F                          G H I J D F
+   ^G D                         H D
+   ^D B                         E I J F B
+   ^D B C                       E I J F B C
+   C                            I J F C
+   B..C   = ^B C                C
+   B...C  = B ^F C              G H D E B C
+   C^@    = C^1
+         = F                   I J F
+   B^@    = B^1 B^2 B^3
+         = D E F               D G H E F I J
+   C^!    = C ^C^@
+         = C ^C^1
+         = C ^F                C
+   B^!    = B ^B^@
+         = B ^B^1 ^B^2 ^B^3
+         = B ^D ^E ^F          B
+   F^! D  = F ^I ^J D           G H D F
index 6754ab076e649f0d728230869afcc45bcf6a4b3d..55e88b02d43e6972fc813ac840cfec39ba555362 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.10.0
+DEF_VER=v2.10.0.GIT
 
 LF='
 '
index d96ecb7141a12f1fe47246805c5d4e4e562a5c86..7f184923ddc6fa5089b64ced3cdca405758468e1 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -296,6 +296,11 @@ all::
 # Define USE_NED_ALLOCATOR if you want to replace the platforms default
 # memory allocators with the nedmalloc allocator written by Niall Douglas.
 #
+# Define OVERRIDE_STRDUP to override the libc version of strdup(3).
+# This is necessary when using a custom allocator in order to avoid
+# crashes due to allocation and free working on different 'heaps'.
+# It's defined automatically if USE_NED_ALLOCATOR is set.
+#
 # Define NO_REGEX if you have no or inferior regex support in your C library.
 #
 # Define HAVE_DEV_TTY if your system can open /dev/tty to interact with the
@@ -1456,8 +1461,14 @@ ifdef NATIVE_CRLF
 endif
 
 ifdef USE_NED_ALLOCATOR
-       COMPAT_CFLAGS += -Icompat/nedmalloc
-       COMPAT_OBJS += compat/nedmalloc/nedmalloc.o
+       COMPAT_CFLAGS += -Icompat/nedmalloc
+       COMPAT_OBJS += compat/nedmalloc/nedmalloc.o
+       OVERRIDE_STRDUP = YesPlease
+endif
+
+ifdef OVERRIDE_STRDUP
+       COMPAT_CFLAGS += -DOVERRIDE_STRDUP
+       COMPAT_OBJS += compat/strdup.o
 endif
 
 ifdef GIT_TEST_CMP_USE_COPIED_CONTEXT
@@ -2029,7 +2040,7 @@ endif
 
 ifdef USE_NED_ALLOCATOR
 compat/nedmalloc/nedmalloc.sp compat/nedmalloc/nedmalloc.o: EXTRA_CPPFLAGS = \
-       -DNDEBUG -DOVERRIDE_STRDUP -DREPLACE_SYSTEM_ALLOCATOR
+       -DNDEBUG -DREPLACE_SYSTEM_ALLOCATOR
 compat/nedmalloc/nedmalloc.sp: SPARSE_FLAGS += -Wno-non-pointer-null
 endif
 
index 62615ffa4e97803da96aefbc798ab50f949a8db7..b54330f7cdb37630dc47d6bdb71e847b8a947c17 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.10.0.txt
\ No newline at end of file
+Documentation/RelNotes/2.11.0.txt
\ No newline at end of file
index 9e2ae5cba40ece7fa8c489a18ba610ab2f4f6e2f..9daeb27225c04c28e33adc7b8e9071d825a490de 100644 (file)
@@ -28,6 +28,7 @@
 #include "rerere.h"
 #include "prompt.h"
 #include "mailinfo.h"
+#include "string-list.h"
 
 /**
  * Returns 1 if the file is empty or does not exist, 0 otherwise.
@@ -258,38 +259,29 @@ static int read_state_file(struct strbuf *sb, const struct am_state *state,
 }
 
 /**
- * Reads a KEY=VALUE shell variable assignment from `fp`, returning the VALUE
- * as a newly-allocated string. VALUE must be a quoted string, and the KEY must
- * match `key`. Returns NULL on failure.
- *
- * This is used by read_author_script() to read the GIT_AUTHOR_* variables from
- * the author-script.
+ * Take a series of KEY='VALUE' lines where VALUE part is
+ * sq-quoted, and append <KEY, VALUE> at the end of the string list
  */
-static char *read_shell_var(FILE *fp, const char *key)
+static int parse_key_value_squoted(char *buf, struct string_list *list)
 {
-       struct strbuf sb = STRBUF_INIT;
-       const char *str;
-
-       if (strbuf_getline_lf(&sb, fp))
-               goto fail;
-
-       if (!skip_prefix(sb.buf, key, &str))
-               goto fail;
-
-       if (!skip_prefix(str, "=", &str))
-               goto fail;
-
-       strbuf_remove(&sb, 0, str - sb.buf);
-
-       str = sq_dequote(sb.buf);
-       if (!str)
-               goto fail;
-
-       return strbuf_detach(&sb, NULL);
-
-fail:
-       strbuf_release(&sb);
-       return NULL;
+       while (*buf) {
+               struct string_list_item *item;
+               char *np;
+               char *cp = strchr(buf, '=');
+               if (!cp)
+                       return -1;
+               np = strchrnul(cp, '\n');
+               *cp++ = '\0';
+               item = string_list_append(list, buf);
+
+               buf = np + (*np == '\n');
+               *np = '\0';
+               cp = sq_dequote(cp);
+               if (!cp)
+                       return -1;
+               item->util = xstrdup(cp);
+       }
+       return 0;
 }
 
 /**
@@ -311,44 +303,39 @@ static char *read_shell_var(FILE *fp, const char *key)
 static int read_author_script(struct am_state *state)
 {
        const char *filename = am_path(state, "author-script");
-       FILE *fp;
+       struct strbuf buf = STRBUF_INIT;
+       struct string_list kv = STRING_LIST_INIT_DUP;
+       int retval = -1; /* assume failure */
+       int fd;
 
        assert(!state->author_name);
        assert(!state->author_email);
        assert(!state->author_date);
 
-       fp = fopen(filename, "r");
-       if (!fp) {
+       fd = open(filename, O_RDONLY);
+       if (fd < 0) {
                if (errno == ENOENT)
                        return 0;
                die_errno(_("could not open '%s' for reading"), filename);
        }
+       strbuf_read(&buf, fd, 0);
+       close(fd);
+       if (parse_key_value_squoted(buf.buf, &kv))
+               goto finish;
 
-       state->author_name = read_shell_var(fp, "GIT_AUTHOR_NAME");
-       if (!state->author_name) {
-               fclose(fp);
-               return -1;
-       }
-
-       state->author_email = read_shell_var(fp, "GIT_AUTHOR_EMAIL");
-       if (!state->author_email) {
-               fclose(fp);
-               return -1;
-       }
-
-       state->author_date = read_shell_var(fp, "GIT_AUTHOR_DATE");
-       if (!state->author_date) {
-               fclose(fp);
-               return -1;
-       }
-
-       if (fgetc(fp) != EOF) {
-               fclose(fp);
-               return -1;
-       }
-
-       fclose(fp);
-       return 0;
+       if (kv.nr != 3 ||
+           strcmp(kv.items[0].string, "GIT_AUTHOR_NAME") ||
+           strcmp(kv.items[1].string, "GIT_AUTHOR_EMAIL") ||
+           strcmp(kv.items[2].string, "GIT_AUTHOR_DATE"))
+               goto finish;
+       state->author_name = kv.items[0].util;
+       state->author_email = kv.items[1].util;
+       state->author_date = kv.items[2].util;
+       retval = 0;
+finish:
+       string_list_clear(&kv, !!retval);
+       strbuf_release(&buf);
+       return retval;
 }
 
 /**
index f044a8c27f542c94c0b7f2458de1590e0d02fae2..404c5e80226c81a8f051e63fa8e40286fea95a18 100644 (file)
@@ -50,7 +50,8 @@ static int option_verbosity;
 static int option_progress = -1;
 static enum transport_family family;
 static struct string_list option_config = STRING_LIST_INIT_NODUP;
-static struct string_list option_reference = STRING_LIST_INIT_NODUP;
+static struct string_list option_required_reference = STRING_LIST_INIT_NODUP;
+static struct string_list option_optional_reference = STRING_LIST_INIT_NODUP;
 static int option_dissociate;
 static int max_jobs = -1;
 
@@ -79,8 +80,10 @@ static struct option builtin_clone_options[] = {
                    N_("number of submodules cloned in parallel")),
        OPT_STRING(0, "template", &option_template, N_("template-directory"),
                   N_("directory from which templates will be used")),
-       OPT_STRING_LIST(0, "reference", &option_reference, N_("repo"),
+       OPT_STRING_LIST(0, "reference", &option_required_reference, N_("repo"),
                        N_("reference repository")),
+       OPT_STRING_LIST(0, "reference-if-able", &option_optional_reference,
+                       N_("repo"), N_("reference repository")),
        OPT_BOOL(0, "dissociate", &option_dissociate,
                 N_("use --reference only while cloning")),
        OPT_STRING('o', "origin", &option_origin, N_("name"),
@@ -282,50 +285,37 @@ static void strip_trailing_slashes(char *dir)
 
 static int add_one_reference(struct string_list_item *item, void *cb_data)
 {
-       char *ref_git;
-       const char *repo;
-       struct strbuf alternate = STRBUF_INIT;
-
-       /* Beware: read_gitfile(), real_path() and mkpath() return static buffer */
-       ref_git = xstrdup(real_path(item->string));
-
-       repo = read_gitfile(ref_git);
-       if (!repo)
-               repo = read_gitfile(mkpath("%s/.git", ref_git));
-       if (repo) {
-               free(ref_git);
-               ref_git = xstrdup(repo);
-       }
+       struct strbuf err = STRBUF_INIT;
+       int *required = cb_data;
+       char *ref_git = compute_alternate_path(item->string, &err);
 
-       if (!repo && is_directory(mkpath("%s/.git/objects", ref_git))) {
-               char *ref_git_git = mkpathdup("%s/.git", ref_git);
-               free(ref_git);
-               ref_git = ref_git_git;
-       } else if (!is_directory(mkpath("%s/objects", ref_git))) {
+       if (!ref_git) {
+               if (*required)
+                       die("%s", err.buf);
+               else
+                       fprintf(stderr,
+                               _("info: Could not add alternate for '%s': %s\n"),
+                               item->string, err.buf);
+       } else {
                struct strbuf sb = STRBUF_INIT;
-               if (get_common_dir(&sb, ref_git))
-                       die(_("reference repository '%s' as a linked checkout is not supported yet."),
-                           item->string);
-               die(_("reference repository '%s' is not a local repository."),
-                   item->string);
+               strbuf_addf(&sb, "%s/objects", ref_git);
+               add_to_alternates_file(sb.buf);
+               strbuf_release(&sb);
        }
 
-       if (!access(mkpath("%s/shallow", ref_git), F_OK))
-               die(_("reference repository '%s' is shallow"), item->string);
-
-       if (!access(mkpath("%s/info/grafts", ref_git), F_OK))
-               die(_("reference repository '%s' is grafted"), item->string);
-
-       strbuf_addf(&alternate, "%s/objects", ref_git);
-       add_to_alternates_file(alternate.buf);
-       strbuf_release(&alternate);
+       strbuf_release(&err);
        free(ref_git);
        return 0;
 }
 
 static void setup_reference(void)
 {
-       for_each_string_list(&option_reference, add_one_reference, NULL);
+       int required = 1;
+       for_each_string_list(&option_required_reference,
+                            add_one_reference, &required);
+       required = 0;
+       for_each_string_list(&option_optional_reference,
+                            add_one_reference, &required);
 }
 
 static void copy_alternates(struct strbuf *src, struct strbuf *dst,
@@ -957,6 +947,25 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
                else
                        fprintf(stderr, _("Cloning into '%s'...\n"), dir);
        }
+
+       if (option_recursive) {
+               if (option_required_reference.nr &&
+                   option_optional_reference.nr)
+                       die(_("clone --recursive is not compatible with "
+                             "both --reference and --reference-if-able"));
+               else if (option_required_reference.nr) {
+                       string_list_append(&option_config,
+                               "submodule.alternateLocation=superproject");
+                       string_list_append(&option_config,
+                               "submodule.alternateErrorStrategy=die");
+               } else if (option_optional_reference.nr) {
+                       string_list_append(&option_config,
+                               "submodule.alternateLocation=superproject");
+                       string_list_append(&option_config,
+                               "submodule.alternateErrorStrategy=info");
+               }
+       }
+
        init_db(option_template, INIT_DB_QUIET);
        write_config(&option_config);
 
@@ -977,7 +986,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
        git_config_set(key.buf, repo);
        strbuf_reset(&key);
 
-       if (option_reference.nr)
+       if (option_required_reference.nr || option_optional_reference.nr)
                setup_reference();
 
        fetch_pattern = value.buf;
index 77e3dc849419e697abe8f2f4c7d753cce17634a8..bb9f79b6ef4b5cd01cafac551bb6665a433334aa 100644 (file)
@@ -142,14 +142,24 @@ static int show_ignored_in_status, have_option_m;
 static const char *only_include_assumed;
 static struct strbuf message = STRBUF_INIT;
 
-static enum status_format {
-       STATUS_FORMAT_NONE = 0,
-       STATUS_FORMAT_LONG,
-       STATUS_FORMAT_SHORT,
-       STATUS_FORMAT_PORCELAIN,
+static enum wt_status_format status_format = STATUS_FORMAT_UNSPECIFIED;
 
-       STATUS_FORMAT_UNSPECIFIED
-} status_format = STATUS_FORMAT_UNSPECIFIED;
+static int opt_parse_porcelain(const struct option *opt, const char *arg, int unset)
+{
+       enum wt_status_format *value = (enum wt_status_format *)opt->value;
+       if (unset)
+               *value = STATUS_FORMAT_NONE;
+       else if (!arg)
+               *value = STATUS_FORMAT_PORCELAIN;
+       else if (!strcmp(arg, "v1") || !strcmp(arg, "1"))
+               *value = STATUS_FORMAT_PORCELAIN;
+       else if (!strcmp(arg, "v2") || !strcmp(arg, "2"))
+               *value = STATUS_FORMAT_PORCELAIN_V2;
+       else
+               die("unsupported porcelain version '%s'", arg);
+
+       return 0;
+}
 
 static int opt_parse_m(const struct option *opt, const char *arg, int unset)
 {
@@ -500,24 +510,13 @@ static int run_status(FILE *fp, const char *index_file, const char *prefix, int
        s->fp = fp;
        s->nowarn = nowarn;
        s->is_initial = get_sha1(s->reference, sha1) ? 1 : 0;
+       if (!s->is_initial)
+               hashcpy(s->sha1_commit, sha1);
+       s->status_format = status_format;
+       s->ignore_submodule_arg = ignore_submodule_arg;
 
        wt_status_collect(s);
-
-       switch (status_format) {
-       case STATUS_FORMAT_SHORT:
-               wt_shortstatus_print(s);
-               break;
-       case STATUS_FORMAT_PORCELAIN:
-               wt_porcelain_print(s);
-               break;
-       case STATUS_FORMAT_UNSPECIFIED:
-               die("BUG: finalize_deferred_config() should have been called");
-               break;
-       case STATUS_FORMAT_NONE:
-       case STATUS_FORMAT_LONG:
-               wt_status_print(s);
-               break;
-       }
+       wt_status_print(s);
 
        return s->commitable;
 }
@@ -1099,7 +1098,7 @@ static const char *read_commit_message(const char *name)
  * is not in effect here.
  */
 static struct status_deferred_config {
-       enum status_format status_format;
+       enum wt_status_format status_format;
        int show_branch;
 } status_deferred_config = {
        STATUS_FORMAT_UNSPECIFIED,
@@ -1109,6 +1108,7 @@ static struct status_deferred_config {
 static void finalize_deferred_config(struct wt_status *s)
 {
        int use_deferred_config = (status_format != STATUS_FORMAT_PORCELAIN &&
+                                  status_format != STATUS_FORMAT_PORCELAIN_V2 &&
                                   !s->null_termination);
 
        if (s->null_termination) {
@@ -1336,9 +1336,9 @@ int cmd_status(int argc, const char **argv, const char *prefix)
                            N_("show status concisely"), STATUS_FORMAT_SHORT),
                OPT_BOOL('b', "branch", &s.show_branch,
                         N_("show branch information")),
-               OPT_SET_INT(0, "porcelain", &status_format,
-                           N_("machine-readable output"),
-                           STATUS_FORMAT_PORCELAIN),
+               { OPTION_CALLBACK, 0, "porcelain", &status_format,
+                 N_("version"), N_("machine-readable output"),
+                 PARSE_OPT_OPTARG, opt_parse_porcelain },
                OPT_SET_INT(0, "long", &status_format,
                            N_("show status in long format (default)"),
                            STATUS_FORMAT_LONG),
@@ -1380,7 +1380,13 @@ int cmd_status(int argc, const char **argv, const char *prefix)
        fd = hold_locked_index(&index_lock, 0);
 
        s.is_initial = get_sha1(s.reference, sha1) ? 1 : 0;
+       if (!s.is_initial)
+               hashcpy(s.sha1_commit, sha1);
+
        s.ignore_submodule_arg = ignore_submodule_arg;
+       s.status_format = status_format;
+       s.verbose = verbose;
+
        wt_status_collect(&s);
 
        if (0 <= fd)
@@ -1389,23 +1395,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
        if (s.relative_paths)
                s.prefix = prefix;
 
-       switch (status_format) {
-       case STATUS_FORMAT_SHORT:
-               wt_shortstatus_print(&s);
-               break;
-       case STATUS_FORMAT_PORCELAIN:
-               wt_porcelain_print(&s);
-               break;
-       case STATUS_FORMAT_UNSPECIFIED:
-               die("BUG: finalize_deferred_config() should have been called");
-               break;
-       case STATUS_FORMAT_NONE:
-       case STATUS_FORMAT_LONG:
-               s.verbose = verbose;
-               s.ignore_submodule_arg = ignore_submodule_arg;
-               wt_status_print(&s);
-               break;
-       }
+       wt_status_print(&s);
        return 0;
 }
 
index e8f79d7af54bce18e8d503dea182146da0fbd456..49f7a07f85db1e36d959749adf2eb1962940fb19 100644 (file)
@@ -37,8 +37,10 @@ static int show_all = 0;
 static int show_guides = 0;
 static unsigned int colopts;
 static enum help_format help_format = HELP_FORMAT_NONE;
+static int exclude_guides;
 static struct option builtin_help_options[] = {
        OPT_BOOL('a', "all", &show_all, N_("print all available commands")),
+       OPT_HIDDEN_BOOL(0, "exclude-guides", &exclude_guides, N_("exclude guides")),
        OPT_BOOL('g', "guides", &show_guides, N_("print list of useful guides")),
        OPT_SET_INT('m', "man", &help_format, N_("show man page"), HELP_FORMAT_MAN),
        OPT_SET_INT('w', "web", &help_format, N_("show manual in web browser"),
@@ -426,10 +428,29 @@ static void list_common_guides_help(void)
        putchar('\n');
 }
 
+static const char *check_git_cmd(const char* cmd)
+{
+       char *alias;
+
+       if (is_git_command(cmd))
+               return cmd;
+
+       alias = alias_lookup(cmd);
+       if (alias) {
+               printf_ln(_("`git %s' is aliased to `%s'"), cmd, alias);
+               free(alias);
+               exit(0);
+       }
+
+       if (exclude_guides)
+               return help_unknown_cmd(cmd);
+
+       return cmd;
+}
+
 int cmd_help(int argc, const char **argv, const char *prefix)
 {
        int nongit;
-       char *alias;
        enum help_format parsed_help_format;
 
        argc = parse_options(argc, argv, prefix, builtin_help_options,
@@ -469,12 +490,7 @@ int cmd_help(int argc, const char **argv, const char *prefix)
        if (help_format == HELP_FORMAT_NONE)
                help_format = parse_help_format(DEFAULT_HELP_FORMAT);
 
-       alias = alias_lookup(argv[0]);
-       if (alias && !is_git_command(argv[0])) {
-               printf_ln(_("`git %s' is aliased to `%s'"), argv[0], alias);
-               free(alias);
-               return 0;
-       }
+       argv[0] = check_git_cmd(argv[0]);
 
        switch (help_format) {
        case HELP_FORMAT_NONE:
index 1d2ea583a45507935ec2007d6c44f5e968a1aed5..4a8b4aebbac7d3992082b4440957f11aeffc39f5 100644 (file)
@@ -87,6 +87,7 @@ static struct progress *progress;
 static unsigned char input_buffer[4096];
 static unsigned int input_offset, input_len;
 static off_t consumed_bytes;
+static off_t max_input_size;
 static unsigned deepest_delta;
 static git_SHA_CTX input_ctx;
 static uint32_t input_crc32;
@@ -297,6 +298,8 @@ static void use(int bytes)
        if (signed_add_overflows(consumed_bytes, bytes))
                die(_("pack too large for current definition of off_t"));
        consumed_bytes += bytes;
+       if (max_input_size && consumed_bytes > max_input_size)
+               die(_("pack exceeds maximum allowed size"));
 }
 
 static const char *open_pack_file(const char *pack_name)
@@ -1714,6 +1717,8 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
                                        opts.off32_limit = strtoul(c+1, &c, 0);
                                if (*c || opts.off32_limit & 0x80000000)
                                        die(_("bad %s"), arg);
+                       } else if (skip_prefix(arg, "--max-input-size=", &arg)) {
+                               max_input_size = strtoumax(arg, NULL, 10);
                        } else
                                usage(index_pack_usage);
                        continue;
index 92dc34dcb0cc54df27b99c91d08786b6c0d5b62a..49aa534f4a018aaaa650a9dc27718f8ed2f00c6e 100644 (file)
@@ -1676,16 +1676,16 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                /* nothing to do */
                return 0;
        total = nr;
-       if (!keep_subject && auto_number && total > 1)
-               numbered = 1;
-       if (numbered)
-               rev.total = total + start_number - 1;
        if (cover_letter == -1) {
                if (config_cover_letter == COVER_AUTO)
                        cover_letter = (total > 1);
                else
                        cover_letter = (config_cover_letter == COVER_ON);
        }
+       if (!keep_subject && auto_number && (total > 1 || cover_letter))
+               numbered = 1;
+       if (numbered)
+               rev.total = total + start_number - 1;
 
        if (!signature) {
                ; /* --no-signature inhibits all signatures */
index 4a63398960c42d91821c4278a4cfbd11c1f1a7a4..0954375be9ea5fe2b416d4142b6987ff2b5ec94f 100644 (file)
@@ -2123,6 +2123,35 @@ static void ll_find_deltas(struct object_entry **list, unsigned list_size,
 #define ll_find_deltas(l, s, w, d, p)  find_deltas(l, &s, w, d, p)
 #endif
 
+static void add_tag_chain(const struct object_id *oid)
+{
+       struct tag *tag;
+
+       /*
+        * We catch duplicates already in add_object_entry(), but we'd
+        * prefer to do this extra check to avoid having to parse the
+        * tag at all if we already know that it's being packed (e.g., if
+        * it was included via bitmaps, we would not have parsed it
+        * previously).
+        */
+       if (packlist_find(&to_pack, oid->hash, NULL))
+               return;
+
+       tag = lookup_tag(oid->hash);
+       while (1) {
+               if (!tag || parse_tag(tag) || !tag->tagged)
+                       die("unable to pack objects reachable from tag %s",
+                           oid_to_hex(oid));
+
+               add_object_entry(tag->object.oid.hash, OBJ_TAG, NULL, 0);
+
+               if (tag->tagged->type != OBJ_TAG)
+                       return;
+
+               tag = (struct tag *)tag->tagged;
+       }
+}
+
 static int add_ref_tag(const char *path, const struct object_id *oid, int flag, void *cb_data)
 {
        struct object_id peeled;
@@ -2130,7 +2159,7 @@ static int add_ref_tag(const char *path, const struct object_id *oid, int flag,
        if (starts_with(path, "refs/tags/") && /* is a tag? */
            !peel_ref(path, peeled.hash)    && /* peelable? */
            packlist_find(&to_pack, peeled.hash, NULL))      /* object packed? */
-               add_object_entry(oid->hash, OBJ_TAG, NULL, 0);
+               add_tag_chain(oid);
        return 0;
 }
 
index 011db00d31709408a21b97abfb5742b97b54238d..f1ce05ce282361d8c49b1a447db90c13d5186674 100644 (file)
@@ -46,6 +46,7 @@ static int transfer_unpack_limit = -1;
 static int advertise_atomic_push = 1;
 static int advertise_push_options;
 static int unpack_limit = 100;
+static off_t max_input_size;
 static int report_status;
 static int use_sideband;
 static int use_atomic;
@@ -212,6 +213,11 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
                return 0;
        }
 
+       if (strcmp(var, "receive.maxinputsize") == 0) {
+               max_input_size = git_config_int64(var, value);
+               return 0;
+       }
+
        return git_default_config(var, value, cb);
 }
 
@@ -1648,6 +1654,9 @@ static const char *unpack(int err_fd, struct shallow_info *si)
                if (fsck_objects)
                        argv_array_pushf(&child.args, "--strict%s",
                                fsck_msg_types.buf);
+               if (max_input_size)
+                       argv_array_pushf(&child.args, "--max-input-size=%"PRIuMAX,
+                               (uintmax_t)max_input_size);
                child.no_stdout = 1;
                child.err = err_fd;
                child.git_cmd = 1;
@@ -1676,6 +1685,9 @@ static const char *unpack(int err_fd, struct shallow_info *si)
                                fsck_msg_types.buf);
                if (!reject_thin)
                        argv_array_push(&child.args, "--fix-thin");
+               if (max_input_size)
+                       argv_array_pushf(&child.args, "--max-input-size=%"PRIuMAX,
+                               (uintmax_t)max_input_size);
                child.out = -1;
                child.err = err_fd;
                child.git_cmd = 1;
index 0ba82b1635b6380d9a7d9fd9a31471b8c8ac9f20..8479f6ed28aa75d01350fc17eafbded0b52dca84 100644 (file)
@@ -122,48 +122,40 @@ static void show_commit(struct commit *commit, void *data)
                ctx.fmt = revs->commit_format;
                ctx.output_encoding = get_log_output_encoding();
                pretty_print_commit(&ctx, commit, &buf);
-               if (revs->graph) {
-                       if (buf.len) {
-                               if (revs->commit_format != CMIT_FMT_ONELINE)
-                                       graph_show_oneline(revs->graph);
-
-                               graph_show_commit_msg(revs->graph, &buf);
-
-                               /*
-                                * Add a newline after the commit message.
-                                *
-                                * Usually, this newline produces a blank
-                                * padding line between entries, in which case
-                                * we need to add graph padding on this line.
-                                *
-                                * However, the commit message may not end in a
-                                * newline.  In this case the newline simply
-                                * ends the last line of the commit message,
-                                * and we don't need any graph output.  (This
-                                * always happens with CMIT_FMT_ONELINE, and it
-                                * happens with CMIT_FMT_USERFORMAT when the
-                                * format doesn't explicitly end in a newline.)
-                                */
-                               if (buf.len && buf.buf[buf.len - 1] == '\n')
-                                       graph_show_padding(revs->graph);
-                               putchar('\n');
-                       } else {
-                               /*
-                                * If the message buffer is empty, just show
-                                * the rest of the graph output for this
-                                * commit.
-                                */
-                               if (graph_show_remainder(revs->graph))
-                                       putchar('\n');
-                               if (revs->commit_format == CMIT_FMT_ONELINE)
-                                       putchar('\n');
-                       }
+               if (buf.len) {
+                       if (revs->commit_format != CMIT_FMT_ONELINE)
+                               graph_show_oneline(revs->graph);
+
+                       graph_show_commit_msg(revs->graph, stdout, &buf);
+
+                       /*
+                        * Add a newline after the commit message.
+                        *
+                        * Usually, this newline produces a blank
+                        * padding line between entries, in which case
+                        * we need to add graph padding on this line.
+                        *
+                        * However, the commit message may not end in a
+                        * newline.  In this case the newline simply
+                        * ends the last line of the commit message,
+                        * and we don't need any graph output.  (This
+                        * always happens with CMIT_FMT_ONELINE, and it
+                        * happens with CMIT_FMT_USERFORMAT when the
+                        * format doesn't explicitly end in a newline.)
+                        */
+                       if (buf.len && buf.buf[buf.len - 1] == '\n')
+                               graph_show_padding(revs->graph);
+                       putchar('\n');
                } else {
-                       if (revs->commit_format != CMIT_FMT_USERFORMAT ||
-                           buf.len) {
-                               fwrite(buf.buf, 1, buf.len, stdout);
-                               putchar(info->hdr_termination);
-                       }
+                       /*
+                        * If the message buffer is empty, just show
+                        * the rest of the graph output for this
+                        * commit.
+                        */
+                       if (graph_show_remainder(revs->graph))
+                               putchar('\n');
+                       if (revs->commit_format == CMIT_FMT_ONELINE)
+                               putchar('\n');
                }
                strbuf_release(&buf);
        } else {
index e79790f0bdc9f19cb9d9773d1a9bdb10044bbb8d..9d79f1994a43efed3883ccb80898292a687c4d76 100644 (file)
@@ -442,7 +442,7 @@ static int module_name(int argc, const char **argv, const char *prefix)
 }
 
 static int clone_submodule(const char *path, const char *gitdir, const char *url,
-                          const char *depth, const char *reference, int quiet)
+                          const char *depth, struct string_list *reference, int quiet)
 {
        struct child_process cp = CHILD_PROCESS_INIT;
 
@@ -452,8 +452,12 @@ static int clone_submodule(const char *path, const char *gitdir, const char *url
                argv_array_push(&cp.args, "--quiet");
        if (depth && *depth)
                argv_array_pushl(&cp.args, "--depth", depth, NULL);
-       if (reference && *reference)
-               argv_array_pushl(&cp.args, "--reference", reference, NULL);
+       if (reference->nr) {
+               struct string_list_item *item;
+               for_each_string_list_item(item, reference)
+                       argv_array_pushl(&cp.args, "--reference",
+                                        item->string, NULL);
+       }
        if (gitdir && *gitdir)
                argv_array_pushl(&cp.args, "--separate-git-dir", gitdir, NULL);
 
@@ -467,15 +471,114 @@ static int clone_submodule(const char *path, const char *gitdir, const char *url
        return run_command(&cp);
 }
 
+struct submodule_alternate_setup {
+       const char *submodule_name;
+       enum SUBMODULE_ALTERNATE_ERROR_MODE {
+               SUBMODULE_ALTERNATE_ERROR_DIE,
+               SUBMODULE_ALTERNATE_ERROR_INFO,
+               SUBMODULE_ALTERNATE_ERROR_IGNORE
+       } error_mode;
+       struct string_list *reference;
+};
+#define SUBMODULE_ALTERNATE_SETUP_INIT { NULL, \
+       SUBMODULE_ALTERNATE_ERROR_IGNORE, NULL }
+
+static int add_possible_reference_from_superproject(
+               struct alternate_object_database *alt, void *sas_cb)
+{
+       struct submodule_alternate_setup *sas = sas_cb;
+
+       /* directory name, minus trailing slash */
+       size_t namelen = alt->name - alt->base - 1;
+       struct strbuf name = STRBUF_INIT;
+       strbuf_add(&name, alt->base, namelen);
+
+       /*
+        * If the alternate object store is another repository, try the
+        * standard layout with .git/modules/<name>/objects
+        */
+       if (ends_with(name.buf, ".git/objects")) {
+               char *sm_alternate;
+               struct strbuf sb = STRBUF_INIT;
+               struct strbuf err = STRBUF_INIT;
+               strbuf_add(&sb, name.buf, name.len - strlen("objects"));
+               /*
+                * We need to end the new path with '/' to mark it as a dir,
+                * otherwise a submodule name containing '/' will be broken
+                * as the last part of a missing submodule reference would
+                * be taken as a file name.
+                */
+               strbuf_addf(&sb, "modules/%s/", sas->submodule_name);
+
+               sm_alternate = compute_alternate_path(sb.buf, &err);
+               if (sm_alternate) {
+                       string_list_append(sas->reference, xstrdup(sb.buf));
+                       free(sm_alternate);
+               } else {
+                       switch (sas->error_mode) {
+                       case SUBMODULE_ALTERNATE_ERROR_DIE:
+                               die(_("submodule '%s' cannot add alternate: %s"),
+                                   sas->submodule_name, err.buf);
+                       case SUBMODULE_ALTERNATE_ERROR_INFO:
+                               fprintf(stderr, _("submodule '%s' cannot add alternate: %s"),
+                                       sas->submodule_name, err.buf);
+                       case SUBMODULE_ALTERNATE_ERROR_IGNORE:
+                               ; /* nothing */
+                       }
+               }
+               strbuf_release(&sb);
+       }
+
+       strbuf_release(&name);
+       return 0;
+}
+
+static void prepare_possible_alternates(const char *sm_name,
+               struct string_list *reference)
+{
+       char *sm_alternate = NULL, *error_strategy = NULL;
+       struct submodule_alternate_setup sas = SUBMODULE_ALTERNATE_SETUP_INIT;
+
+       git_config_get_string("submodule.alternateLocation", &sm_alternate);
+       if (!sm_alternate)
+               return;
+
+       git_config_get_string("submodule.alternateErrorStrategy", &error_strategy);
+
+       if (!error_strategy)
+               error_strategy = xstrdup("die");
+
+       sas.submodule_name = sm_name;
+       sas.reference = reference;
+       if (!strcmp(error_strategy, "die"))
+               sas.error_mode = SUBMODULE_ALTERNATE_ERROR_DIE;
+       else if (!strcmp(error_strategy, "info"))
+               sas.error_mode = SUBMODULE_ALTERNATE_ERROR_INFO;
+       else if (!strcmp(error_strategy, "ignore"))
+               sas.error_mode = SUBMODULE_ALTERNATE_ERROR_IGNORE;
+       else
+               die(_("Value '%s' for submodule.alternateErrorStrategy is not recognized"), error_strategy);
+
+       if (!strcmp(sm_alternate, "superproject"))
+               foreach_alt_odb(add_possible_reference_from_superproject, &sas);
+       else if (!strcmp(sm_alternate, "no"))
+               ; /* do nothing */
+       else
+               die(_("Value '%s' for submodule.alternateLocation is not recognized"), sm_alternate);
+
+       free(sm_alternate);
+       free(error_strategy);
+}
+
 static int module_clone(int argc, const char **argv, const char *prefix)
 {
-       const char *name = NULL, *url = NULL;
-       const char *reference = NULL, *depth = NULL;
+       const char *name = NULL, *url = NULL, *depth = NULL;
        int quiet = 0;
        FILE *submodule_dot_git;
        char *p, *path = NULL, *sm_gitdir;
        struct strbuf rel_path = STRBUF_INIT;
        struct strbuf sb = STRBUF_INIT;
+       struct string_list reference = STRING_LIST_INIT_NODUP;
 
        struct option module_clone_options[] = {
                OPT_STRING(0, "prefix", &prefix,
@@ -490,8 +593,8 @@ static int module_clone(int argc, const char **argv, const char *prefix)
                OPT_STRING(0, "url", &url,
                           N_("string"),
                           N_("url where to clone the submodule from")),
-               OPT_STRING(0, "reference", &reference,
-                          N_("string"),
+               OPT_STRING_LIST(0, "reference", &reference,
+                          N_("repo"),
                           N_("reference repository")),
                OPT_STRING(0, "depth", &depth,
                           N_("string"),
@@ -527,7 +630,10 @@ static int module_clone(int argc, const char **argv, const char *prefix)
        if (!file_exists(sm_gitdir)) {
                if (safe_create_leading_directories_const(sm_gitdir) < 0)
                        die(_("could not create directory '%s'"), sm_gitdir);
-               if (clone_submodule(path, sm_gitdir, url, depth, reference, quiet))
+
+               prepare_possible_alternates(name, &reference);
+
+               if (clone_submodule(path, sm_gitdir, url, depth, &reference, quiet))
                        die(_("clone of '%s' into submodule path '%s' failed"),
                            url, path);
        } else {
@@ -579,7 +685,7 @@ struct submodule_update_clone {
        /* configuration parameters which are passed on to the children */
        int quiet;
        int recommend_shallow;
-       const char *reference;
+       struct string_list references;
        const char *depth;
        const char *recursive_prefix;
        const char *prefix;
@@ -595,7 +701,8 @@ struct submodule_update_clone {
        int failed_clones_nr, failed_clones_alloc;
 };
 #define SUBMODULE_UPDATE_CLONE_INIT {0, MODULE_LIST_INIT, 0, \
-       SUBMODULE_UPDATE_STRATEGY_INIT, 0, -1, NULL, NULL, NULL, NULL, \
+       SUBMODULE_UPDATE_STRATEGY_INIT, 0, -1, STRING_LIST_INIT_DUP, \
+       NULL, NULL, NULL, \
        STRING_LIST_INIT_DUP, 0, NULL, 0, 0}
 
 
@@ -705,8 +812,11 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
        argv_array_pushl(&child->args, "--path", sub->path, NULL);
        argv_array_pushl(&child->args, "--name", sub->name, NULL);
        argv_array_pushl(&child->args, "--url", url, NULL);
-       if (suc->reference)
-               argv_array_push(&child->args, suc->reference);
+       if (suc->references.nr) {
+               struct string_list_item *item;
+               for_each_string_list_item(item, &suc->references)
+                       argv_array_pushl(&child->args, "--reference", item->string, NULL);
+       }
        if (suc->depth)
                argv_array_push(&child->args, suc->depth);
 
@@ -829,7 +939,7 @@ static int update_clone(int argc, const char **argv, const char *prefix)
                OPT_STRING(0, "update", &update,
                           N_("string"),
                           N_("rebase, merge, checkout or none")),
-               OPT_STRING(0, "reference", &suc.reference, N_("repo"),
+               OPT_STRING_LIST(0, "reference", &suc.references, N_("repo"),
                           N_("reference repository")),
                OPT_STRING(0, "depth", &suc.depth, "<depth>",
                           N_("Create a shallow clone truncated to the "
index 9c29a64e4331e1e45b4467829ba950006b673818..96eed944683a45c33fa5d4a05414ae56406fafca 100644 (file)
@@ -56,6 +56,8 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
                ret = check_symref(argv[0], 1, 0, 0);
                if (ret)
                        die("Cannot delete %s, not a symbolic ref", argv[0]);
+               if (!strcmp(argv[0], "HEAD"))
+                       die("deleting '%s' is not allowed", argv[0]);
                return delete_ref(argv[0], NULL, REF_NODEREF);
        }
 
index 172470bf241e4da731c5741567555d7e01691c74..4532aa083154ae7e9be07014d3761821fa6c4ddc 100644 (file)
@@ -19,6 +19,7 @@ static const char unpack_usage[] = "git unpack-objects [-n] [-q] [-r] [--strict]
 static unsigned char buffer[4096];
 static unsigned int offset, len;
 static off_t consumed_bytes;
+static off_t max_input_size;
 static git_SHA_CTX ctx;
 static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT;
 
@@ -87,6 +88,8 @@ static void use(int bytes)
        if (signed_add_overflows(consumed_bytes, bytes))
                die("pack too large for current definition of off_t");
        consumed_bytes += bytes;
+       if (max_input_size && consumed_bytes > max_input_size)
+               die(_("pack exceeds maximum allowed size"));
 }
 
 static void *get_data(unsigned long size)
@@ -550,6 +553,10 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix)
                                len = sizeof(*hdr);
                                continue;
                        }
+                       if (skip_prefix(arg, "--max-input-size=", &arg)) {
+                               max_input_size = strtoumax(arg, NULL, 10);
+                               continue;
+                       }
                        usage(unpack_usage);
                }
 
diff --git a/cache.h b/cache.h
index b780a91a567143ca2cd1283dd441dcc0e00673d4..35563266bf54c49cb9e2ae1efbed7a26fbca3519 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -819,8 +819,8 @@ extern void strbuf_git_common_path(struct strbuf *sb, const char *fmt, ...)
        __attribute__((format (printf, 2, 3)));
 extern char *git_path_buf(struct strbuf *buf, const char *fmt, ...)
        __attribute__((format (printf, 2, 3)));
-extern void strbuf_git_path_submodule(struct strbuf *sb, const char *path,
-                                     const char *fmt, ...)
+extern int strbuf_git_path_submodule(struct strbuf *sb, const char *path,
+                                    const char *fmt, ...)
        __attribute__((format (printf, 3, 4)));
 extern char *git_pathdup(const char *fmt, ...)
        __attribute__((format (printf, 1, 2)));
@@ -953,22 +953,39 @@ static inline void oidclr(struct object_id *oid)
 #define EMPTY_TREE_SHA1_BIN_LITERAL \
         "\x4b\x82\x5d\xc6\x42\xcb\x6e\xb9\xa0\x60" \
         "\xe5\x4b\xf8\xd6\x92\x88\xfb\xee\x49\x04"
-#define EMPTY_TREE_SHA1_BIN \
-        ((const unsigned char *) EMPTY_TREE_SHA1_BIN_LITERAL)
+extern const struct object_id empty_tree_oid;
+#define EMPTY_TREE_SHA1_BIN (empty_tree_oid.hash)
 
 #define EMPTY_BLOB_SHA1_HEX \
        "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"
 #define EMPTY_BLOB_SHA1_BIN_LITERAL \
        "\xe6\x9d\xe2\x9b\xb2\xd1\xd6\x43\x4b\x8b" \
        "\x29\xae\x77\x5a\xd8\xc2\xe4\x8c\x53\x91"
-#define EMPTY_BLOB_SHA1_BIN \
-       ((const unsigned char *) EMPTY_BLOB_SHA1_BIN_LITERAL)
+extern const struct object_id empty_blob_oid;
+#define EMPTY_BLOB_SHA1_BIN (empty_blob_oid.hash)
+
 
 static inline int is_empty_blob_sha1(const unsigned char *sha1)
 {
        return !hashcmp(sha1, EMPTY_BLOB_SHA1_BIN);
 }
 
+static inline int is_empty_blob_oid(const struct object_id *oid)
+{
+       return !hashcmp(oid->hash, EMPTY_BLOB_SHA1_BIN);
+}
+
+static inline int is_empty_tree_sha1(const unsigned char *sha1)
+{
+       return !hashcmp(sha1, EMPTY_TREE_SHA1_BIN);
+}
+
+static inline int is_empty_tree_oid(const struct object_id *oid)
+{
+       return !hashcmp(oid->hash, EMPTY_TREE_SHA1_BIN);
+}
+
+
 int git_mkstemp(char *path, size_t n, const char *template);
 
 /* set default permissions by passing mode arguments to open(2) */
@@ -1139,6 +1156,16 @@ static inline unsigned int hexval(unsigned char c)
        return hexval_table[c];
 }
 
+/*
+ * Convert two consecutive hexadecimal digits into a char.  Return a
+ * negative value on error.  Don't run over the end of short strings.
+ */
+static inline int hex2chr(const char *s)
+{
+       int val = hexval(s[0]);
+       return (val < 0) ? val : (val << 4) | hexval(s[1]);
+}
+
 /* Convert to/from hex/sha1 representation */
 #define MINIMUM_ABBREV minimum_abbrev
 #define DEFAULT_ABBREV default_abbrev
@@ -1344,6 +1371,7 @@ extern struct alternate_object_database {
 } *alt_odb_list;
 extern void prepare_alt_odb(void);
 extern void read_info_alternates(const char * relative_base, int depth);
+extern char *compute_alternate_path(const char *path, struct strbuf *err);
 extern void add_to_alternates_file(const char *reference);
 typedef int alt_odb_fn(struct alternate_object_database *, void *);
 extern int foreach_alt_odb(alt_odb_fn, void*);
diff --git a/color.c b/color.c
index 81c26767239f9e028057c1843f57b77640db6c26..1b95e6b2a7bb1601fa5862de8989775e197c7b41 100644 (file)
--- a/color.c
+++ b/color.c
@@ -215,7 +215,7 @@ int color_parse_mem(const char *value, int value_len, char *dst)
        /* [fg [bg]] [attr]... */
        while (len > 0) {
                const char *word = ptr;
-               struct color c;
+               struct color c = { COLOR_UNSPECIFIED };
                int val, wordlen = 0;
 
                while (len > 0 && !isspace(word[wordlen])) {
index 2d4ef59013823d3c7caac8b705fbd4916cfe8fd6..1cc31c350223b84cd97939afccf1bcc1caa070b4 100644 (file)
@@ -948,22 +948,6 @@ void **nedpindependent_comalloc(nedpool *p, size_t elems, size_t *sizes, void **
        return ret;
 }
 
-#ifdef OVERRIDE_STRDUP
-/*
- * This implementation is purely there to override the libc version, to
- * avoid a crash due to allocation and free on different 'heaps'.
- */
-char *strdup(const char *s1)
-{
-       size_t len = strlen(s1) + 1;
-       char *s2 = malloc(len);
-
-       if (s2)
-               memcpy(s2, s1, len);
-       return s2;
-}
-#endif
-
 #if defined(__cplusplus)
 }
 #endif
diff --git a/compat/strdup.c b/compat/strdup.c
new file mode 100644 (file)
index 0000000..f3fb978
--- /dev/null
@@ -0,0 +1,11 @@
+#include "../git-compat-util.h"
+
+char *gitstrdup(const char *s1)
+{
+       size_t len = strlen(s1) + 1;
+       char *s2 = malloc(len);
+
+       if (s2)
+               memcpy(s2, s1, len);
+       return s2;
+}
diff --git a/contrib/diff-highlight/Makefile b/contrib/diff-highlight/Makefile
new file mode 100644 (file)
index 0000000..9018724
--- /dev/null
@@ -0,0 +1,5 @@
+# nothing to build
+all:
+
+test:
+       $(MAKE) -C t
index ffefc31a98a26dfd65d188bbb547cc114231c13d..81bd8040e3cbd34a8b247f23a94eee891fc44296 100755 (executable)
@@ -21,6 +21,10 @@ my $RESET = "\x1b[m";
 my $COLOR = qr/\x1b\[[0-9;]*m/;
 my $BORING = qr/$COLOR|\s/;
 
+# The patch portion of git log -p --graph should only ever have preceding | and
+# not / or \ as merge history only shows up on the commit line.
+my $GRAPH = qr/$COLOR?\|$COLOR?\s+/;
+
 my @removed;
 my @added;
 my $in_hunk;
@@ -32,12 +36,12 @@ $SIG{PIPE} = 'DEFAULT';
 while (<>) {
        if (!$in_hunk) {
                print;
-               $in_hunk = /^$COLOR*\@/;
+               $in_hunk = /^$GRAPH*$COLOR*\@\@ /;
        }
-       elsif (/^$COLOR*-/) {
+       elsif (/^$GRAPH*$COLOR*-/) {
                push @removed, $_;
        }
-       elsif (/^$COLOR*\+/) {
+       elsif (/^$GRAPH*$COLOR*\+/) {
                push @added, $_;
        }
        else {
@@ -46,7 +50,7 @@ while (<>) {
                @added = ();
 
                print;
-               $in_hunk = /^$COLOR*[\@ ]/;
+               $in_hunk = /^$GRAPH*$COLOR*[\@ ]/;
        }
 
        # Most of the time there is enough output to keep things streaming,
@@ -163,6 +167,9 @@ sub highlight_pair {
        }
 }
 
+# we split either by $COLOR or by character. This has the side effect of
+# leaving in graph cruft. It works because the graph cruft does not contain "-"
+# or "+"
 sub split_line {
        local $_ = shift;
        return utf8::decode($_) ?
@@ -211,8 +218,8 @@ sub is_pair_interesting {
        my $suffix_a = join('', @$a[($sa+1)..$#$a]);
        my $suffix_b = join('', @$b[($sb+1)..$#$b]);
 
-       return $prefix_a !~ /^$COLOR*-$BORING*$/ ||
-              $prefix_b !~ /^$COLOR*\+$BORING*$/ ||
+       return $prefix_a !~ /^$GRAPH*$COLOR*-$BORING*$/ ||
+              $prefix_b !~ /^$GRAPH*$COLOR*\+$BORING*$/ ||
               $suffix_a !~ /^$BORING*$/ ||
               $suffix_b !~ /^$BORING*$/;
 }
diff --git a/contrib/diff-highlight/t/.gitignore b/contrib/diff-highlight/t/.gitignore
new file mode 100644 (file)
index 0000000..7dcbb23
--- /dev/null
@@ -0,0 +1,2 @@
+/trash directory*
+/test-results
diff --git a/contrib/diff-highlight/t/Makefile b/contrib/diff-highlight/t/Makefile
new file mode 100644 (file)
index 0000000..5ff5275
--- /dev/null
@@ -0,0 +1,22 @@
+-include ../../../config.mak.autogen
+-include ../../../config.mak
+
+# copied from ../../t/Makefile
+SHELL_PATH ?= $(SHELL)
+SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
+T = $(wildcard t[0-9][0-9][0-9][0-9]-*.sh)
+
+all: test
+test: $(T)
+
+.PHONY: help clean all test $(T)
+
+help:
+       @echo 'Run "$(MAKE) test" to launch test scripts'
+       @echo 'Run "$(MAKE) clean" to remove trash folders'
+
+$(T):
+       @echo "*** $@ ***"; '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS)
+
+clean:
+       $(RM) -r 'trash directory'.*
diff --git a/contrib/diff-highlight/t/t9400-diff-highlight.sh b/contrib/diff-highlight/t/t9400-diff-highlight.sh
new file mode 100755 (executable)
index 0000000..3b43dbe
--- /dev/null
@@ -0,0 +1,296 @@
+#!/bin/sh
+
+test_description='Test diff-highlight'
+
+CURR_DIR=$(pwd)
+TEST_OUTPUT_DIRECTORY=$(pwd)
+TEST_DIRECTORY="$CURR_DIR"/../../../t
+DIFF_HIGHLIGHT="$CURR_DIR"/../diff-highlight
+
+CW="$(printf "\033[7m")"       # white
+CR="$(printf "\033[27m")"      # reset
+
+. "$TEST_DIRECTORY"/test-lib.sh
+
+if ! test_have_prereq PERL
+then
+       skip_all='skipping diff-highlight tests; perl not available'
+       test_done
+fi
+
+# dh_test is a test helper function which takes 3 file names as parameters. The
+# first 2 files are used to generate diff and commit output, which is then
+# piped through diff-highlight. The 3rd file should contain the expected output
+# of diff-highlight (minus the diff/commit header, ie. everything after and
+# including the first @@ line).
+dh_test () {
+       a="$1" b="$2" &&
+
+       cat >patch.exp &&
+
+       {
+               cat "$a" >file &&
+               git add file &&
+               git commit -m "Add a file" &&
+
+               cat "$b" >file &&
+               git diff file >diff.raw &&
+               git commit -a -m "Update a file" &&
+               git show >commit.raw
+       } >/dev/null &&
+
+       "$DIFF_HIGHLIGHT" <diff.raw | test_strip_patch_header >diff.act &&
+       "$DIFF_HIGHLIGHT" <commit.raw | test_strip_patch_header >commit.act &&
+       test_cmp patch.exp diff.act &&
+       test_cmp patch.exp commit.act
+}
+
+test_strip_patch_header () {
+       sed -n '/^@@/,$p' $*
+}
+
+# dh_test_setup_history generates a contrived graph such that we have at least
+# 1 nesting (E) and 2 nestings (F).
+#
+#            A branch
+#           /
+#      D---E---F master
+#
+#      git log --all --graph
+#      * commit
+#      |    A
+#      | * commit
+#      | |    F
+#      | * commit
+#      |/
+#      |    E
+#      * commit
+#           D
+#
+dh_test_setup_history () {
+       echo "file1" >file1 &&
+       echo "file2" >file2 &&
+       echo "file3" >file3 &&
+
+       cat file1 >file &&
+       git add file &&
+       git commit -m "D" &&
+
+       git checkout -b branch &&
+       cat file2 >file &&
+       git commit -a -m "A" &&
+
+       git checkout master &&
+       cat file2 >file &&
+       git commit -a -m "E" &&
+
+       cat file3 >file &&
+       git commit -a -m "F"
+}
+
+left_trim () {
+       "$PERL_PATH" -pe 's/^\s+//'
+}
+
+trim_graph () {
+       # graphs start with * or |
+       # followed by a space or / or \
+       "$PERL_PATH" -pe 's@^((\*|\|)( |/|\\))+@@'
+}
+
+test_expect_success 'diff-highlight highlights the beginning of a line' '
+       cat >a <<-\EOF &&
+               aaa
+               bbb
+               ccc
+       EOF
+
+       cat >b <<-\EOF &&
+               aaa
+               0bb
+               ccc
+       EOF
+
+       dh_test a b <<-EOF
+               @@ -1,3 +1,3 @@
+                aaa
+               -${CW}b${CR}bb
+               +${CW}0${CR}bb
+                ccc
+       EOF
+'
+
+test_expect_success 'diff-highlight highlights the end of a line' '
+       cat >a <<-\EOF &&
+               aaa
+               bbb
+               ccc
+       EOF
+
+       cat >b <<-\EOF &&
+               aaa
+               bb0
+               ccc
+       EOF
+
+       dh_test a b <<-EOF
+               @@ -1,3 +1,3 @@
+                aaa
+               -bb${CW}b${CR}
+               +bb${CW}0${CR}
+                ccc
+       EOF
+'
+
+test_expect_success 'diff-highlight highlights the middle of a line' '
+       cat >a <<-\EOF &&
+               aaa
+               bbb
+               ccc
+       EOF
+
+       cat >b <<-\EOF &&
+               aaa
+               b0b
+               ccc
+       EOF
+
+       dh_test a b <<-EOF
+               @@ -1,3 +1,3 @@
+                aaa
+               -b${CW}b${CR}b
+               +b${CW}0${CR}b
+                ccc
+       EOF
+'
+
+test_expect_success 'diff-highlight does not highlight whole line' '
+       cat >a <<-\EOF &&
+               aaa
+               bbb
+               ccc
+       EOF
+
+       cat >b <<-\EOF &&
+               aaa
+               000
+               ccc
+       EOF
+
+       dh_test a b <<-EOF
+               @@ -1,3 +1,3 @@
+                aaa
+               -bbb
+               +000
+                ccc
+       EOF
+'
+
+test_expect_failure 'diff-highlight highlights mismatched hunk size' '
+       cat >a <<-\EOF &&
+               aaa
+               bbb
+       EOF
+
+       cat >b <<-\EOF &&
+               aaa
+               b0b
+               ccc
+       EOF
+
+       dh_test a b <<-EOF
+               @@ -1,3 +1,3 @@
+                aaa
+               -b${CW}b${CR}b
+               +b${CW}0${CR}b
+               +ccc
+       EOF
+'
+
+# These two code points share the same leading byte in UTF-8 representation;
+# a naive byte-wise diff would highlight only the second byte.
+#
+#   - U+00f3 ("o" with acute)
+o_accent=$(printf '\303\263')
+#   - U+00f8 ("o" with stroke)
+o_stroke=$(printf '\303\270')
+
+test_expect_success 'diff-highlight treats multibyte utf-8 as a unit' '
+       echo "unic${o_accent}de" >a &&
+       echo "unic${o_stroke}de" >b &&
+       dh_test a b <<-EOF
+               @@ -1 +1 @@
+               -unic${CW}${o_accent}${CR}de
+               +unic${CW}${o_stroke}${CR}de
+       EOF
+'
+
+# Unlike the UTF-8 above, these are combining code points which are meant
+# to modify the character preceding them:
+#
+#   - U+0301 (combining acute accent)
+combine_accent=$(printf '\314\201')
+#   - U+0302 (combining circumflex)
+combine_circum=$(printf '\314\202')
+
+test_expect_failure 'diff-highlight treats combining code points as a unit' '
+       echo "unico${combine_accent}de" >a &&
+       echo "unico${combine_circum}de" >b &&
+       dh_test a b <<-EOF
+               @@ -1 +1 @@
+               -unic${CW}o${combine_accent}${CR}de
+               +unic${CW}o${combine_circum}${CR}de
+       EOF
+'
+
+test_expect_success 'diff-highlight works with the --graph option' '
+       dh_test_setup_history &&
+
+       # topo-order so that the order of the commits is the same as with --graph
+       # trim graph elements so we can do a diff
+       # trim leading space because our trim_graph is not perfect
+       git log --branches -p --topo-order |
+               "$DIFF_HIGHLIGHT" | left_trim >graph.exp &&
+       git log --branches -p --graph |
+               "$DIFF_HIGHLIGHT" | trim_graph | left_trim >graph.act &&
+       test_cmp graph.exp graph.act
+'
+
+# Most combined diffs won't meet diff-highlight's line-number filter. So we
+# create one here where one side drops a line and the other modifies it. That
+# should result in a diff like:
+#
+#    - modified content
+#    ++resolved content
+#
+# which naively looks like one side added "+resolved".
+test_expect_success 'diff-highlight ignores combined diffs' '
+       echo "content" >file &&
+       git add file &&
+       git commit -m base &&
+
+       >file &&
+       git commit -am master &&
+
+       git checkout -b other HEAD^ &&
+       echo "modified content" >file &&
+       git commit -am other &&
+
+       test_must_fail git merge master &&
+       echo "resolved content" >file &&
+       git commit -am resolved &&
+
+       cat >expect <<-\EOF &&
+       --- a/file
+       +++ b/file
+       @@@ -1,1 -1,0 +1,1 @@@
+       - modified content
+       ++resolved content
+       EOF
+
+       git show -c | "$DIFF_HIGHLIGHT" >actual.raw &&
+       sed -n "/^---/,\$p" <actual.raw >actual &&
+       test_cmp expect actual
+'
+
+test_done
diff --git a/diff.c b/diff.c
index 534c12e28ea8b077c9fa305a634f7a73cf30589d..b38d95eb249c8dabc906cf426a7fd33abd37c4f7 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -18,6 +18,7 @@
 #include "ll-merge.h"
 #include "string-list.h"
 #include "argv-array.h"
+#include "graph.h"
 
 #ifdef NO_FAST_WORKING_DIRECTORY
 #define FAST_WORKING_DIRECTORY 0
@@ -131,9 +132,11 @@ static int parse_dirstat_params(struct diff_options *options, const char *params
 static int parse_submodule_params(struct diff_options *options, const char *value)
 {
        if (!strcmp(value, "log"))
-               DIFF_OPT_SET(options, SUBMODULE_LOG);
+               options->submodule_format = DIFF_SUBMODULE_LOG;
        else if (!strcmp(value, "short"))
-               DIFF_OPT_CLR(options, SUBMODULE_LOG);
+               options->submodule_format = DIFF_SUBMODULE_SHORT;
+       else if (!strcmp(value, "diff"))
+               options->submodule_format = DIFF_SUBMODULE_INLINE_DIFF;
        else
                return -1;
        return 0;
@@ -1625,7 +1628,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
         */
 
        if (options->stat_width == -1)
-               width = term_columns() - options->output_prefix_length;
+               width = term_columns() - strlen(line_prefix);
        else
                width = options->stat_width ? options->stat_width : 80;
        number_width = decimal_width(max_change) > number_width ?
@@ -2299,17 +2302,37 @@ static void builtin_diff(const char *name_a,
        struct strbuf header = STRBUF_INIT;
        const char *line_prefix = diff_line_prefix(o);
 
-       if (DIFF_OPT_TST(o, SUBMODULE_LOG) &&
-                       (!one->mode || S_ISGITLINK(one->mode)) &&
-                       (!two->mode || S_ISGITLINK(two->mode))) {
+       diff_set_mnemonic_prefix(o, "a/", "b/");
+       if (DIFF_OPT_TST(o, REVERSE_DIFF)) {
+               a_prefix = o->b_prefix;
+               b_prefix = o->a_prefix;
+       } else {
+               a_prefix = o->a_prefix;
+               b_prefix = o->b_prefix;
+       }
+
+       if (o->submodule_format == DIFF_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->path ? one->path : two->path,
                                line_prefix,
-                               one->oid.hash, two->oid.hash,
+                               &one->oid, &two->oid,
                                two->dirty_submodule,
                                meta, del, add, reset);
                return;
+       } else if (o->submodule_format == DIFF_SUBMODULE_INLINE_DIFF &&
+                  (!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_inline_diff(o->file, one->path ? one->path : two->path,
+                               line_prefix,
+                               &one->oid, &two->oid,
+                               two->dirty_submodule,
+                               meta, del, add, reset, o);
+               return;
        }
 
        if (DIFF_OPT_TST(o, ALLOW_TEXTCONV)) {
@@ -2317,15 +2340,6 @@ static void builtin_diff(const char *name_a,
                textconv_two = get_textconv(two);
        }
 
-       diff_set_mnemonic_prefix(o, "a/", "b/");
-       if (DIFF_OPT_TST(o, REVERSE_DIFF)) {
-               a_prefix = o->b_prefix;
-               b_prefix = o->a_prefix;
-       } else {
-               a_prefix = o->a_prefix;
-               b_prefix = o->b_prefix;
-       }
-
        /* Never use a non-valid filename anywhere if at all possible */
        name_a = DIFF_FILE_VALID(one) ? name_a : name_b;
        name_b = DIFF_FILE_VALID(two) ? name_b : name_a;
@@ -3915,7 +3929,7 @@ int diff_opt_parse(struct diff_options *options,
                DIFF_OPT_SET(options, OVERRIDE_SUBMODULE_CONFIG);
                handle_ignore_submodules_arg(options, arg);
        } else if (!strcmp(arg, "--submodule"))
-               DIFF_OPT_SET(options, SUBMODULE_LOG);
+               options->submodule_format = DIFF_SUBMODULE_LOG;
        else if (skip_prefix(arg, "--submodule=", &arg))
                return parse_submodule_opt(options, arg);
        else if (skip_prefix(arg, "--ws-error-highlight=", &arg))
@@ -3966,6 +3980,12 @@ int diff_opt_parse(struct diff_options *options,
                options->a_prefix = optarg;
                return argcount;
        }
+       else if ((argcount = parse_long_opt("line-prefix", av, &optarg))) {
+               options->line_prefix = optarg;
+               options->line_prefix_length = strlen(options->line_prefix);
+               graph_setup_line_prefix(options);
+               return argcount;
+       }
        else if ((argcount = parse_long_opt("dst-prefix", av, &optarg))) {
                options->b_prefix = optarg;
                return argcount;
diff --git a/diff.h b/diff.h
index 7883729edf10ae2888ebc672f62f6015dee21550..ec76a90522ea88354882666a5a6d336dfa8963fd 100644 (file)
--- a/diff.h
+++ b/diff.h
@@ -83,7 +83,6 @@ typedef struct strbuf *(*diff_prefix_fn_t)(struct diff_options *opt, void *data)
 #define DIFF_OPT_DIRSTAT_BY_FILE     (1 << 20)
 #define DIFF_OPT_ALLOW_TEXTCONV      (1 << 21)
 #define DIFF_OPT_DIFF_FROM_CONTENTS  (1 << 22)
-#define DIFF_OPT_SUBMODULE_LOG       (1 << 23)
 #define DIFF_OPT_DIRTY_SUBMODULES    (1 << 24)
 #define DIFF_OPT_IGNORE_UNTRACKED_IN_SUBMODULES (1 << 25)
 #define DIFF_OPT_IGNORE_DIRTY_SUBMODULES (1 << 26)
@@ -110,11 +109,19 @@ enum diff_words_type {
        DIFF_WORDS_COLOR
 };
 
+enum diff_submodule_format {
+       DIFF_SUBMODULE_SHORT = 0,
+       DIFF_SUBMODULE_LOG,
+       DIFF_SUBMODULE_INLINE_DIFF
+};
+
 struct diff_options {
        const char *orderfile;
        const char *pickaxe;
        const char *single_follow;
        const char *a_prefix, *b_prefix;
+       const char *line_prefix;
+       size_t line_prefix_length;
        unsigned flags;
        unsigned touched_flags;
 
@@ -155,6 +162,7 @@ struct diff_options {
        int stat_count;
        const char *word_regex;
        enum diff_words_type word_diff;
+       enum diff_submodule_format submodule_format;
 
        /* this is set by diffcore for DIFF_FORMAT_PATCH */
        int found_changes;
@@ -174,7 +182,6 @@ struct diff_options {
        diff_format_fn_t format_callback;
        void *format_callback_data;
        diff_prefix_fn_t output_prefix;
-       int output_prefix_length;
        void *output_prefix_data;
 
        int diff_path_counter;
index db89ba774891a9608531e52252de19d552cbf535..68615b1a6a4db0f4ba7b4ce543e00e31e3b1705e 100644 (file)
@@ -436,6 +436,7 @@ static inline int const_error(void)
        return -1;
 }
 #define error(...) (error(__VA_ARGS__), const_error())
+#define error_errno(...) (error_errno(__VA_ARGS__), const_error())
 #endif
 
 extern void set_die_routine(NORETURN_PTR void (*routine)(const char *err, va_list params));
@@ -663,6 +664,14 @@ void *gitmemmem(const void *haystack, size_t haystacklen,
                 const void *needle, size_t needlelen);
 #endif
 
+#ifdef OVERRIDE_STRDUP
+#ifdef strdup
+#undef strdup
+#endif
+#define strdup gitstrdup
+char *gitstrdup(const char *s);
+#endif
+
 #ifdef NO_GETPAGESIZE
 #define getpagesize() sysconf(_SC_PAGESIZE)
 #endif
index 9aff249d5f533638170e7e14e03930a560978f46..208651c1afc1bdb6d8f7ee9ec8f2b9f08e7439b3 100644 (file)
@@ -1,47 +1,50 @@
 # Translation of git-gui to Japanese
 # Copyright (C) 2007 Shawn Pearce
 # This file is distributed under the same license as the git-gui package.
+#
 # しらいし ななこ <nanako3@bluebottle.com>, 2007.
+# Satoshi Yasushima <s.yasushima@gmail.com>, 2016.
 #
 msgid ""
 msgstr ""
 "Project-Id-Version: git-gui\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2010-01-26 15:47-0800\n"
-"PO-Revision-Date: 2010-02-02 19:03+0900\n"
-"Last-Translator: しらいし ななこ <nanako3@lavabit.com>\n"
+"POT-Creation-Date: 2016-05-27 17:52+0900\n"
+"PO-Revision-Date: 2016-06-22 12:50+0900\n"
+"Last-Translator: Satoshi Yasushima <s.yasushima@gmail.com>\n"
 "Language-Team: Japanese\n"
+"Language: ja\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: git-gui.sh:41 git-gui.sh:793 git-gui.sh:807 git-gui.sh:820 git-gui.sh:903
-#: git-gui.sh:922
-msgid "git-gui: fatal error"
-msgstr "git-gui: 致命的なエラー"
-
-#: git-gui.sh:743
+#: git-gui.sh:861
 #, tcl-format
 msgid "Invalid font specified in %s:"
 msgstr "%s に無効なフォントが指定されています:"
 
-#: git-gui.sh:779
+#: git-gui.sh:915
 msgid "Main Font"
 msgstr "主フォント"
 
-#: git-gui.sh:780
+#: git-gui.sh:916
 msgid "Diff/Console Font"
 msgstr "diff/コンソール・フォント"
 
-#: git-gui.sh:794
+#: git-gui.sh:931 git-gui.sh:945 git-gui.sh:958 git-gui.sh:1048 git-gui.sh:1067
+#: git-gui.sh:3125
+msgid "git-gui: fatal error"
+msgstr "git-gui: 致命的なエラー"
+
+#: git-gui.sh:932
 msgid "Cannot find git in PATH."
 msgstr "PATH 中に git が見つかりません"
 
-#: git-gui.sh:821
+#: git-gui.sh:959
 msgid "Cannot parse Git version string:"
 msgstr "Git バージョン名が理解できません:"
 
-#: git-gui.sh:839
+#: git-gui.sh:984
 #, tcl-format
 msgid ""
 "Git version cannot be determined.\n"
@@ -60,475 +63,502 @@ msgstr ""
 "\n"
 "'%s' はバージョン 1.5.0 と思って良いですか?\n"
 
-#: git-gui.sh:1128
+#: git-gui.sh:1281
 msgid "Git directory not found:"
 msgstr "Git ディレクトリが見つかりません:"
 
-#: git-gui.sh:1146
+#: git-gui.sh:1315
 msgid "Cannot move to top of working directory:"
 msgstr "作業ディレクトリの最上位に移動できません"
 
-#: git-gui.sh:1154
+#: git-gui.sh:1323
 msgid "Cannot use bare repository:"
 msgstr "裸のリポジトリは使えません:"
 
-#: git-gui.sh:1162
+#: git-gui.sh:1331
 msgid "No working directory"
 msgstr "作業ディレクトリがありません"
 
-#: git-gui.sh:1334 lib/checkout_op.tcl:306
+#: git-gui.sh:1503 lib/checkout_op.tcl:306
 msgid "Refreshing file status..."
 msgstr "ファイル状態を更新しています…"
 
-#: git-gui.sh:1390
+#: git-gui.sh:1563
 msgid "Scanning for modified files ..."
 msgstr "変更されたファイルをスキャンしています…"
 
-#: git-gui.sh:1454
+#: git-gui.sh:1639
 msgid "Calling prepare-commit-msg hook..."
 msgstr "prepare-commit-msg フックを実行中・・・"
 
-#: git-gui.sh:1471
+#: git-gui.sh:1656
 msgid "Commit declined by prepare-commit-msg hook."
 msgstr "prepare-commit-msg フックがコミットを拒否しました"
 
-#: git-gui.sh:1629 lib/browser.tcl:246
+#: git-gui.sh:1814 lib/browser.tcl:252
 msgid "Ready."
 msgstr "準備完了"
 
-#: git-gui.sh:1787
+#: git-gui.sh:1978
 #, tcl-format
-msgid "Displaying only %s of %s files."
-msgstr "全体で%s個の内の%sファイルだけ表示しています"
+msgid ""
+"Display limit (gui.maxfilesdisplayed = %s) reached, not showing all %s files."
+msgstr ""
+"表示可能な限界 (gui.maxfilesdisplayed = %s) に達しため、全体で%s個のファイル"
+"を表示できません"
 
-#: git-gui.sh:1913
+#: git-gui.sh:2101
 msgid "Unmodified"
 msgstr "変更無し"
 
-#: git-gui.sh:1915
+#: git-gui.sh:2103
 msgid "Modified, not staged"
 msgstr "変更あり、コミット未予定"
 
-#: git-gui.sh:1916 git-gui.sh:1924
+#: git-gui.sh:2104 git-gui.sh:2116
 msgid "Staged for commit"
 msgstr "コミット予定済"
 
-#: git-gui.sh:1917 git-gui.sh:1925
+#: git-gui.sh:2105 git-gui.sh:2117
 msgid "Portions staged for commit"
 msgstr "部分的にコミット予定済"
 
-#: git-gui.sh:1918 git-gui.sh:1926
+#: git-gui.sh:2106 git-gui.sh:2118
 msgid "Staged for commit, missing"
 msgstr "コミット予定済、ファイル無し"
 
-#: git-gui.sh:1920
+#: git-gui.sh:2108
 msgid "File type changed, not staged"
 msgstr "ファイル型変更、コミット未予定"
 
-#: git-gui.sh:1921
+#: git-gui.sh:2109 git-gui.sh:2110
+msgid "File type changed, old type staged for commit"
+msgstr "ファイル型変更、旧型コミット予定済"
+
+#: git-gui.sh:2111
 msgid "File type changed, staged"
 msgstr "ファイル型変更、コミット予定済"
 
-#: git-gui.sh:1923
+#: git-gui.sh:2112
+msgid "File type change staged, modification not staged"
+msgstr "ファイル型変更コミット予定済、変更コミット未予定"
+
+#: git-gui.sh:2113
+msgid "File type change staged, file missing"
+msgstr "ファイル型変更コミット予定済、ファイル無し"
+
+#: git-gui.sh:2115
 msgid "Untracked, not staged"
 msgstr "管理外、コミット未予定"
 
-#: git-gui.sh:1928
+#: git-gui.sh:2120
 msgid "Missing"
 msgstr "ファイル無し"
 
-#: git-gui.sh:1929
+#: git-gui.sh:2121
 msgid "Staged for removal"
 msgstr "削除予定済"
 
-#: git-gui.sh:1930
+#: git-gui.sh:2122
 msgid "Staged for removal, still present"
 msgstr "削除予定済、ファイル未削除"
 
-#: git-gui.sh:1932 git-gui.sh:1933 git-gui.sh:1934 git-gui.sh:1935
-#: git-gui.sh:1936 git-gui.sh:1937
+#: git-gui.sh:2124 git-gui.sh:2125 git-gui.sh:2126 git-gui.sh:2127
+#: git-gui.sh:2128 git-gui.sh:2129
 msgid "Requires merge resolution"
 msgstr "要マージ解決"
 
-#: git-gui.sh:1972
+#: git-gui.sh:2164
 msgid "Starting gitk... please wait..."
 msgstr "gitk を起動中…お待ち下さい…"
 
-#: git-gui.sh:1984
+#: git-gui.sh:2176
 msgid "Couldn't find gitk in PATH"
 msgstr "PATH 中に gitk が見つかりません"
 
-#: git-gui.sh:2043
+#: git-gui.sh:2235
 msgid "Couldn't find git gui in PATH"
 msgstr "PATH 中に git gui が見つかりません"
 
-#: git-gui.sh:2455 lib/choose_repository.tcl:36
+#: git-gui.sh:2654 lib/choose_repository.tcl:41
 msgid "Repository"
 msgstr "リポジトリ"
 
-#: git-gui.sh:2456
+#: git-gui.sh:2655
 msgid "Edit"
 msgstr "編集"
 
-#: git-gui.sh:2458 lib/choose_rev.tcl:561
+#: git-gui.sh:2657 lib/choose_rev.tcl:567
 msgid "Branch"
 msgstr "ブランチ"
 
-#: git-gui.sh:2461 lib/choose_rev.tcl:548
+#: git-gui.sh:2660 lib/choose_rev.tcl:554
 msgid "Commit@@noun"
 msgstr "コミット"
 
-#: git-gui.sh:2464 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168
+#: git-gui.sh:2663 lib/merge.tcl:123 lib/merge.tcl:152 lib/merge.tcl:170
 msgid "Merge"
 msgstr "マージ"
 
-#: git-gui.sh:2465 lib/choose_rev.tcl:557
+#: git-gui.sh:2664 lib/choose_rev.tcl:563
 msgid "Remote"
 msgstr "リモート"
 
-#: git-gui.sh:2468
+#: git-gui.sh:2667
 msgid "Tools"
 msgstr "ツール"
 
-#: git-gui.sh:2477
+#: git-gui.sh:2676
 msgid "Explore Working Copy"
 msgstr "ワーキングコピーをブラウズ"
 
-#: git-gui.sh:2483
+#: git-gui.sh:2682
+msgid "Git Bash"
+msgstr ""
+
+#: git-gui.sh:2692
 msgid "Browse Current Branch's Files"
 msgstr "現在のブランチのファイルを見る"
 
-#: git-gui.sh:2487
+#: git-gui.sh:2696
 msgid "Browse Branch Files..."
 msgstr "ブランチのファイルを見る…"
 
-#: git-gui.sh:2492
+#: git-gui.sh:2701
 msgid "Visualize Current Branch's History"
 msgstr "現在のブランチの履歴を見る"
 
-#: git-gui.sh:2496
+#: git-gui.sh:2705
 msgid "Visualize All Branch History"
 msgstr "全てのブランチの履歴を見る"
 
-#: git-gui.sh:2503
+#: git-gui.sh:2712
 #, tcl-format
 msgid "Browse %s's Files"
 msgstr "ブランチ %s のファイルを見る"
 
-#: git-gui.sh:2505
+#: git-gui.sh:2714
 #, tcl-format
 msgid "Visualize %s's History"
 msgstr "ブランチ %s の履歴を見る"
 
-#: git-gui.sh:2510 lib/database.tcl:27 lib/database.tcl:67
+#: git-gui.sh:2719 lib/database.tcl:40 lib/database.tcl:66
 msgid "Database Statistics"
 msgstr "データベース統計"
 
-#: git-gui.sh:2513 lib/database.tcl:34
+#: git-gui.sh:2722 lib/database.tcl:33
 msgid "Compress Database"
 msgstr "データベース圧縮"
 
-#: git-gui.sh:2516
+#: git-gui.sh:2725
 msgid "Verify Database"
 msgstr "データベース検証"
 
-#: git-gui.sh:2523 git-gui.sh:2527 git-gui.sh:2531 lib/shortcut.tcl:8
+#: git-gui.sh:2732 git-gui.sh:2736 git-gui.sh:2740 lib/shortcut.tcl:8
 #: lib/shortcut.tcl:40 lib/shortcut.tcl:72
 msgid "Create Desktop Icon"
 msgstr "デスクトップ・アイコンを作る"
 
-#: git-gui.sh:2539 lib/choose_repository.tcl:183 lib/choose_repository.tcl:191
+#: git-gui.sh:2748 lib/choose_repository.tcl:193 lib/choose_repository.tcl:201
 msgid "Quit"
 msgstr "終了"
 
-#: git-gui.sh:2547
+#: git-gui.sh:2756
 msgid "Undo"
 msgstr "元に戻す"
 
-#: git-gui.sh:2550
+#: git-gui.sh:2759
 msgid "Redo"
 msgstr "やり直し"
 
-#: git-gui.sh:2554 git-gui.sh:3109
+#: git-gui.sh:2763 git-gui.sh:3368
 msgid "Cut"
 msgstr "切り取り"
 
-#: git-gui.sh:2557 git-gui.sh:3112 git-gui.sh:3186 git-gui.sh:3259
+#: git-gui.sh:2766 git-gui.sh:3371 git-gui.sh:3445 git-gui.sh:3530
 #: lib/console.tcl:69
 msgid "Copy"
 msgstr "コピー"
 
-#: git-gui.sh:2560 git-gui.sh:3115
+#: git-gui.sh:2769 git-gui.sh:3374
 msgid "Paste"
 msgstr "貼り付け"
 
-#: git-gui.sh:2563 git-gui.sh:3118 lib/branch_delete.tcl:26
-#: lib/remote_branch_delete.tcl:38
+#: git-gui.sh:2772 git-gui.sh:3377 lib/remote_branch_delete.tcl:39
+#: lib/branch_delete.tcl:28
 msgid "Delete"
 msgstr "削除"
 
-#: git-gui.sh:2567 git-gui.sh:3122 git-gui.sh:3263 lib/console.tcl:71
+#: git-gui.sh:2776 git-gui.sh:3381 git-gui.sh:3534 lib/console.tcl:71
 msgid "Select All"
 msgstr "全て選択"
 
-#: git-gui.sh:2576
+#: git-gui.sh:2785
 msgid "Create..."
 msgstr "作成…"
 
-#: git-gui.sh:2582
+#: git-gui.sh:2791
 msgid "Checkout..."
 msgstr "チェックアウト"
 
-#: git-gui.sh:2588
+#: git-gui.sh:2797
 msgid "Rename..."
 msgstr "名前変更…"
 
-#: git-gui.sh:2593
+#: git-gui.sh:2802
 msgid "Delete..."
 msgstr "削除…"
 
-#: git-gui.sh:2598
+#: git-gui.sh:2807
 msgid "Reset..."
 msgstr "リセット…"
 
-#: git-gui.sh:2608
+#: git-gui.sh:2817
 msgid "Done"
 msgstr "完了"
 
-#: git-gui.sh:2610
+#: git-gui.sh:2819
 msgid "Commit@@verb"
 msgstr "コミット"
 
-#: git-gui.sh:2619 git-gui.sh:3050
+#: git-gui.sh:2828 git-gui.sh:3309
 msgid "New Commit"
 msgstr "新規コミット"
 
-#: git-gui.sh:2627 git-gui.sh:3057
+#: git-gui.sh:2836 git-gui.sh:3316
 msgid "Amend Last Commit"
 msgstr "最新コミットを訂正"
 
-#: git-gui.sh:2637 git-gui.sh:3011 lib/remote_branch_delete.tcl:99
+#: git-gui.sh:2846 git-gui.sh:3270 lib/remote_branch_delete.tcl:101
 msgid "Rescan"
 msgstr "再スキャン"
 
-#: git-gui.sh:2643
+#: git-gui.sh:2852
 msgid "Stage To Commit"
 msgstr "コミット予定する"
 
-#: git-gui.sh:2649
+#: git-gui.sh:2858
 msgid "Stage Changed Files To Commit"
 msgstr "変更されたファイルをコミット予定"
 
-#: git-gui.sh:2655
+#: git-gui.sh:2864
 msgid "Unstage From Commit"
 msgstr "コミットから降ろす"
 
-#: git-gui.sh:2661 lib/index.tcl:412
+#: git-gui.sh:2870 lib/index.tcl:442
 msgid "Revert Changes"
 msgstr "変更を元に戻す"
 
-#: git-gui.sh:2669 git-gui.sh:3310 git-gui.sh:3341
+#: git-gui.sh:2878 git-gui.sh:3581 git-gui.sh:3612
 msgid "Show Less Context"
 msgstr "文脈を少なく"
 
-#: git-gui.sh:2673 git-gui.sh:3314 git-gui.sh:3345
+#: git-gui.sh:2882 git-gui.sh:3585 git-gui.sh:3616
 msgid "Show More Context"
 msgstr "文脈を多く"
 
-#: git-gui.sh:2680 git-gui.sh:3024 git-gui.sh:3133
+#: git-gui.sh:2889 git-gui.sh:3283 git-gui.sh:3392
 msgid "Sign Off"
 msgstr "署名"
 
-#: git-gui.sh:2696
+#: git-gui.sh:2905
 msgid "Local Merge..."
 msgstr "ローカル・マージ…"
 
-#: git-gui.sh:2701
+#: git-gui.sh:2910
 msgid "Abort Merge..."
 msgstr "マージ中止…"
 
-#: git-gui.sh:2713 git-gui.sh:2741
+#: git-gui.sh:2922 git-gui.sh:2950
 msgid "Add..."
 msgstr "追加"
 
-#: git-gui.sh:2717
+#: git-gui.sh:2926
 msgid "Push..."
 msgstr "プッシュ…"
 
-#: git-gui.sh:2721
+#: git-gui.sh:2930
 msgid "Delete Branch..."
 msgstr "ブランチ削除..."
 
-#: git-gui.sh:2731 git-gui.sh:3292
+#: git-gui.sh:2940 git-gui.sh:3563
 msgid "Options..."
 msgstr "オプション…"
 
-#: git-gui.sh:2742
+#: git-gui.sh:2951
 msgid "Remove..."
 msgstr "削除..."
 
-#: git-gui.sh:2751 lib/choose_repository.tcl:50
+#: git-gui.sh:2960 lib/choose_repository.tcl:55
 msgid "Help"
 msgstr "ヘルプ"
 
-#: git-gui.sh:2755 git-gui.sh:2759 lib/about.tcl:14
-#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:53
+#: git-gui.sh:2964 git-gui.sh:2968 lib/about.tcl:14
+#: lib/choose_repository.tcl:49 lib/choose_repository.tcl:58
 #, tcl-format
 msgid "About %s"
 msgstr "%s について"
 
-#: git-gui.sh:2783
+#: git-gui.sh:2992
 msgid "Online Documentation"
 msgstr "オンライン・ドキュメント"
 
-#: git-gui.sh:2786 lib/choose_repository.tcl:47 lib/choose_repository.tcl:56
+#: git-gui.sh:2995 lib/choose_repository.tcl:52 lib/choose_repository.tcl:61
 msgid "Show SSH Key"
 msgstr "SSH キーを表示"
 
-#: git-gui.sh:2893
+#: git-gui.sh:3014 git-gui.sh:3146
+msgid "Usage"
+msgstr "使い方"
+
+#: git-gui.sh:3095 lib/blame.tcl:573
+msgid "Error"
+msgstr "エラー"
+
+#: git-gui.sh:3126
 #, tcl-format
 msgid "fatal: cannot stat path %s: No such file or directory"
 msgstr ""
 "致命的: パス %s が stat できません。そのようなファイルやディレクトリはありま"
 "せん"
 
-#: git-gui.sh:2926
+#: git-gui.sh:3159
 msgid "Current Branch:"
 msgstr "現在のブランチ"
 
-#: git-gui.sh:2947
+#: git-gui.sh:3185
 msgid "Staged Changes (Will Commit)"
 msgstr "ステージングされた(コミット予定済の)変更"
 
-#: git-gui.sh:2967
+#: git-gui.sh:3205
 msgid "Unstaged Changes"
 msgstr "コミット予定に入っていない変更"
 
-#: git-gui.sh:3017
+#: git-gui.sh:3276
 msgid "Stage Changed"
 msgstr "変更をコミット予定に入れる"
 
-#: git-gui.sh:3036 lib/transport.tcl:104 lib/transport.tcl:193
+#: git-gui.sh:3295 lib/transport.tcl:137 lib/transport.tcl:229
 msgid "Push"
 msgstr "プッシュ"
 
-#: git-gui.sh:3071
+#: git-gui.sh:3330
 msgid "Initial Commit Message:"
 msgstr "最初のコミットメッセージ:"
 
-#: git-gui.sh:3072
+#: git-gui.sh:3331
 msgid "Amended Commit Message:"
 msgstr "訂正したコミットメッセージ:"
 
-#: git-gui.sh:3073
+#: git-gui.sh:3332
 msgid "Amended Initial Commit Message:"
 msgstr "訂正した最初のコミットメッセージ:"
 
-#: git-gui.sh:3074
+#: git-gui.sh:3333
 msgid "Amended Merge Commit Message:"
 msgstr "訂正したマージコミットメッセージ:"
 
-#: git-gui.sh:3075
+#: git-gui.sh:3334
 msgid "Merge Commit Message:"
 msgstr "マージコミットメッセージ:"
 
-#: git-gui.sh:3076
+#: git-gui.sh:3335
 msgid "Commit Message:"
 msgstr "コミットメッセージ:"
 
-#: git-gui.sh:3125 git-gui.sh:3267 lib/console.tcl:73
+#: git-gui.sh:3384 git-gui.sh:3538 lib/console.tcl:73
 msgid "Copy All"
 msgstr "全てコピー"
 
-#: git-gui.sh:3149 lib/blame.tcl:104
+#: git-gui.sh:3408 lib/blame.tcl:105
 msgid "File:"
 msgstr "ファイル:"
 
-#: git-gui.sh:3255
+#: git-gui.sh:3526
 msgid "Refresh"
 msgstr "再読み込み"
 
-#: git-gui.sh:3276
+#: git-gui.sh:3547
 msgid "Decrease Font Size"
 msgstr "フォントを小さく"
 
-#: git-gui.sh:3280
+#: git-gui.sh:3551
 msgid "Increase Font Size"
 msgstr "フォントを大きく"
 
-#: git-gui.sh:3288 lib/blame.tcl:281
+#: git-gui.sh:3559 lib/blame.tcl:294
 msgid "Encoding"
 msgstr "エンコーディング"
 
-#: git-gui.sh:3299
+#: git-gui.sh:3570
 msgid "Apply/Reverse Hunk"
 msgstr "パッチを適用/取り消す"
 
-#: git-gui.sh:3304
+#: git-gui.sh:3575
 msgid "Apply/Reverse Line"
 msgstr "パッチ行を適用/取り消す"
 
-#: git-gui.sh:3323
+#: git-gui.sh:3594
 msgid "Run Merge Tool"
 msgstr "マージツールを起動"
 
-#: git-gui.sh:3328
+#: git-gui.sh:3599
 msgid "Use Remote Version"
 msgstr "リモートの方を採用"
 
-#: git-gui.sh:3332
+#: git-gui.sh:3603
 msgid "Use Local Version"
 msgstr "ローカルの方を採用"
 
-#: git-gui.sh:3336
+#: git-gui.sh:3607
 msgid "Revert To Base"
 msgstr "ベース版を採用"
 
-#: git-gui.sh:3354
+#: git-gui.sh:3625
 msgid "Visualize These Changes In The Submodule"
 msgstr "サブモジュール内のこれらの変更を見る"
 
-#: git-gui.sh:3358
+#: git-gui.sh:3629
 msgid "Visualize Current Branch History In The Submodule"
 msgstr "サブモジュール内で現在のブランチの履歴を見る"
 
-#: git-gui.sh:3362
+#: git-gui.sh:3633
 msgid "Visualize All Branch History In The Submodule"
 msgstr "サブモジュール内で全てのブランチの履歴を見る"
 
-#: git-gui.sh:3367
+#: git-gui.sh:3638
 msgid "Start git gui In The Submodule"
 msgstr "サブモジュール内でgit guiを起動する"
 
-#: git-gui.sh:3389
+#: git-gui.sh:3673
 msgid "Unstage Hunk From Commit"
 msgstr "パッチをコミット予定から外す"
 
-#: git-gui.sh:3391
+#: git-gui.sh:3675
 msgid "Unstage Lines From Commit"
 msgstr "コミット予定から行を外す"
 
-#: git-gui.sh:3393
+#: git-gui.sh:3677
 msgid "Unstage Line From Commit"
 msgstr "コミット予定から行を外す"
 
-#: git-gui.sh:3396
+#: git-gui.sh:3680
 msgid "Stage Hunk For Commit"
 msgstr "パッチをコミット予定に加える"
 
-#: git-gui.sh:3398
+#: git-gui.sh:3682
 msgid "Stage Lines For Commit"
 msgstr "パッチ行をコミット予定に加える"
 
-#: git-gui.sh:3400
+#: git-gui.sh:3684
 msgid "Stage Line For Commit"
 msgstr "パッチ行をコミット予定に加える"
 
-#: git-gui.sh:3424
+#: git-gui.sh:3709
 msgid "Initializing..."
 msgstr "初期化しています…"
 
-#: git-gui.sh:3541
+#: git-gui.sh:3852
 #, tcl-format
 msgid ""
 "Possible environment issues exist.\n"
@@ -543,7 +573,7 @@ msgstr ""
 "以下の環境変数は %s が起動する Git サブプロセスによって無視されるでしょう:\n"
 "\n"
 
-#: git-gui.sh:3570
+#: git-gui.sh:3881
 msgid ""
 "\n"
 "This is due to a known issue with the\n"
@@ -553,7 +583,7 @@ msgstr ""
 "これは Cygwin で配布されている Tcl バイナリに\n"
 "関しての既知の問題によります"
 
-#: git-gui.sh:3575
+#: git-gui.sh:3886
 #, tcl-format
 msgid ""
 "\n"
@@ -568,249 +598,294 @@ msgstr ""
 "個人的な ~/.gitconfig ファイル内で user.name と user.email の値を設定\n"
 "するのが、%s の良い代用となります\n"
 
-#: lib/about.tcl:26
-msgid "git-gui - a graphical user interface for Git."
-msgstr "Git のグラフィカルUI git-gui"
+#: 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/blame.tcl:72
-msgid "File Viewer"
-msgstr "ファイルピューワ"
+#: 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/blame.tcl:78
-msgid "Commit:"
-msgstr "コミット:"
+#: lib/merge.tcl:45
+#, 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/blame.tcl:271
-msgid "Copy Commit"
-msgstr "コミットをコピー"
+#: lib/merge.tcl:55
+#, 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/blame.tcl:275
-msgid "Find Text..."
-msgstr "テキストを検索"
+#: lib/merge.tcl:108
+#, tcl-format
+msgid "%s of %s"
+msgstr "%s の %s ブランチ"
 
-#: lib/blame.tcl:284
-msgid "Do Full Copy Detection"
-msgstr "コピー検知"
+#: lib/merge.tcl:122
+#, tcl-format
+msgid "Merging %s and %s..."
+msgstr "%s と %s をマージ中・・・"
 
-#: lib/blame.tcl:288
-msgid "Show History Context"
-msgstr "文脈を見せる"
+#: lib/merge.tcl:133
+msgid "Merge completed successfully."
+msgstr "マージが完了しました"
 
-#: lib/blame.tcl:291
-msgid "Blame Parent Commit"
-msgstr "親コミットを註釈"
+#: lib/merge.tcl:135
+msgid "Merge failed.  Conflict resolution is required."
+msgstr "マージが失敗しました。衝突の解決が必要です。"
 
-#: lib/blame.tcl:450
+#: lib/merge.tcl:160
 #, tcl-format
-msgid "Reading %s..."
-msgstr "%s ã\82\92読ã\82\93ã\81§ã\81\84ã\81¾ã\81\99â\80¦"
+msgid "Merge Into %s"
+msgstr "%s ã\81«ã\83\9eã\83¼ã\82¸"
 
-#: lib/blame.tcl:557
-msgid "Loading copy/move tracking annotations..."
-msgstr "コピー・移動追跡データを読んでいます…"
+#: lib/merge.tcl:166 lib/checkout_op.tcl:567 lib/tools_dlg.tcl:336
+msgid "Visualize"
+msgstr "可視化"
 
-#: lib/blame.tcl:577
-msgid "lines annotated"
-msgstr "行を注釈しました"
+#: lib/merge.tcl:174 lib/remote_branch_delete.tcl:43 lib/branch_delete.tcl:34
+#: lib/checkout_op.tcl:579 lib/branch_rename.tcl:32 lib/tools_dlg.tcl:41
+#: lib/tools_dlg.tcl:202 lib/tools_dlg.tcl:345 lib/option.tcl:127
+#: lib/transport.tcl:141 lib/choose_font.tcl:45 lib/branch_checkout.tcl:30
+#: lib/browser.tcl:292 lib/remote_add.tcl:34 lib/branch_create.tcl:37
+msgid "Cancel"
+msgstr "中止"
 
-#: lib/blame.tcl:769
-msgid "Loading original location annotations..."
-msgstr "元位置行の注釈データを読んでいます…"
+#: lib/merge.tcl:179
+msgid "Revision To Merge"
+msgstr "マージするリビジョン"
 
-#: lib/blame.tcl:772
-msgid "Annotation complete."
-msgstr "注釈完了しました"
+#: lib/merge.tcl:214
+msgid ""
+"Cannot abort while amending.\n"
+"\n"
+"You must finish amending this commit.\n"
+msgstr ""
+"訂正中には中止できません。\n"
+"\n"
+"まず今のコミット訂正を完了させて下さい。\n"
 
-#: lib/blame.tcl:802
-msgid "Busy"
-msgstr "実行中"
+#: lib/merge.tcl:224
+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/blame.tcl:803
-msgid "Annotation process is already running."
-msgstr "すでに blame プロセスを実行中です。"
+#: lib/merge.tcl:230
+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/blame.tcl:842
-msgid "Running thorough copy detection..."
-msgstr "コピー検知を実行中…"
+#: lib/merge.tcl:241
+msgid "Aborting"
+msgstr "中断しています"
 
-#: lib/blame.tcl:910
-msgid "Loading annotation..."
-msgstr "注釈を読み込んでいます…"
+#: lib/merge.tcl:241
+msgid "files reset"
+msgstr "リセットしたファイル"
 
-#: lib/blame.tcl:963
-msgid "Author:"
-msgstr "ä½\9cè\80\85:"
+#: lib/merge.tcl:269
+msgid "Abort failed."
+msgstr "中æ\96­ã\81«å¤±æ\95\97ã\81\97ã\81¾ã\81\97ã\81\9fã\80\82"
 
-#: lib/blame.tcl:967
-msgid "Committer:"
-msgstr "コミット者:"
+#: lib/merge.tcl:271
+msgid "Abort completed.  Ready."
+msgstr "中断完了。"
 
-#: lib/blame.tcl:972
-msgid "Original File:"
-msgstr "元ファイル"
+#: lib/error.tcl:20 lib/error.tcl:116
+msgid "error"
+msgstr "エラー"
 
-#: lib/blame.tcl:1020
-msgid "Cannot find HEAD commit:"
-msgstr "HEAD コミットが見つかりません"
+#: lib/error.tcl:36
+msgid "warning"
+msgstr "警告"
 
-#: lib/blame.tcl:1075
-msgid "Cannot find parent commit:"
-msgstr "親コミットが見つかりません:"
+#: lib/error.tcl:96
+msgid "You must correct the above errors before committing."
+msgstr "コミットする前に、以上のエラーを修正して下さい"
 
-#: lib/blame.tcl:1090
-msgid "Unable to display parent"
-msgstr "親を表示できません"
+#: lib/date.tcl:25
+#, tcl-format
+msgid "Invalid date from Git: %s"
+msgstr "Git から出た無効な日付: %s"
 
-#: lib/blame.tcl:1091 lib/diff.tcl:320
-msgid "Error loading diff:"
-msgstr "diff を読む際のエラーです:"
+#: lib/encoding.tcl:443
+msgid "Default"
+msgstr "デフォールト"
 
-#: lib/blame.tcl:1231
-msgid "Originally By:"
-msgstr "原作者:"
+#: lib/encoding.tcl:448
+#, tcl-format
+msgid "System (%s)"
+msgstr "システム (%s)"
 
-#: lib/blame.tcl:1237
-msgid "In File:"
-msgstr "ã\83\95ã\82¡ã\82¤ã\83«:"
+#: lib/encoding.tcl:459 lib/encoding.tcl:465
+msgid "Other"
+msgstr "ã\81\9dã\81®ä»\96"
 
-#: lib/blame.tcl:1242
-msgid "Copied Or Moved Here By:"
-msgstr "複写・移動者:"
+#: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34
+msgid "Delete Branch Remotely"
+msgstr "リモートブランチ削除"
 
-#: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19
-msgid "Checkout Branch"
-msgstr "ブランチをチェックアウト"
+#: lib/remote_branch_delete.tcl:48
+msgid "From Repository"
+msgstr "元のリポジトリ"
 
-#: lib/branch_checkout.tcl:23
-msgid "Checkout"
-msgstr "ã\83\81ã\82§ã\83\83ã\82¯ã\82¢ã\82¦ã\83\88"
+#: lib/remote_branch_delete.tcl:51 lib/transport.tcl:165
+msgid "Remote:"
+msgstr "ã\83ªã\83¢ã\83¼ã\83\88:"
 
-#: 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:579 lib/choose_font.tcl:43 lib/merge.tcl:172
-#: lib/option.tcl:125 lib/remote_add.tcl:32 lib/remote_branch_delete.tcl:42
-#: lib/tools_dlg.tcl:40 lib/tools_dlg.tcl:204 lib/tools_dlg.tcl:352
-#: lib/transport.tcl:108
-msgid "Cancel"
-msgstr "中止"
+#: lib/remote_branch_delete.tcl:72 lib/transport.tcl:187
+msgid "Arbitrary Location:"
+msgstr "任意の位置:"
 
-#: lib/branch_checkout.tcl:32 lib/browser.tcl:287 lib/tools_dlg.tcl:328
-msgid "Revision"
-msgstr "ã\83ªã\83\93ã\82¸ã\83§ã\83³"
+#: lib/remote_branch_delete.tcl:88
+msgid "Branches"
+msgstr "ã\83\96ã\83©ã\83³ã\83\81"
 
-#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:280
-msgid "Options"
-msgstr "オプション"
+#: lib/remote_branch_delete.tcl:110
+msgid "Delete Only If"
+msgstr "条件付で削除"
 
-#: lib/branch_checkout.tcl:39 lib/branch_create.tcl:92
-msgid "Fetch Tracking Branch"
-msgstr "ã\83\88ã\83©ã\83\83ã\82­ã\83³ã\82°ã\83»ã\83\96ã\83©ã\83³ã\83\81ã\82\92ã\83\95ã\82§ã\83\83ã\83\81"
+#: lib/remote_branch_delete.tcl:112
+msgid "Merged Into:"
+msgstr "ã\83\9eã\83¼ã\82¸å\85\88:"
 
-#: lib/branch_checkout.tcl:44
-msgid "Detach From Local Branch"
-msgstr "ローカル・ブランチから削除"
+#: lib/remote_branch_delete.tcl:120 lib/branch_delete.tcl:53
+msgid "Always (Do not perform merge checks)"
+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:381
-msgid "Create"
-msgstr "作成"
-
-#: lib/branch_create.tcl:40
-msgid "Branch Name"
-msgstr "ブランチ名"
-
-#: lib/branch_create.tcl:43 lib/remote_add.tcl:39 lib/tools_dlg.tcl:50
-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
-msgid "No"
-msgstr "いいえ"
+#: lib/remote_branch_delete.tcl:153
+msgid "A branch is required for 'Merged Into'."
+msgstr "'マージ先' にはブランチが必要です。"
 
-#: lib/branch_create.tcl:80
-msgid "Fast Forward Only"
-msgstr "早送りのみ"
+#: lib/remote_branch_delete.tcl:185
+#, tcl-format
+msgid ""
+"The following branches are not completely merged into %s:\n"
+"\n"
+" - %s"
+msgstr ""
+"以下のブランチは %s に完全にマージされていません:\n"
+"\n"
+" - %s"
 
-#: lib/branch_create.tcl:85 lib/checkout_op.tcl:571
-msgid "Reset"
-msgstr "リセット"
+#: lib/remote_branch_delete.tcl:190
+#, 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/branch_create.tcl:97
-msgid "Checkout After Creation"
-msgstr "作成してすぐチェックアウト"
+#: lib/remote_branch_delete.tcl:208
+msgid "Please select one or more branches to delete."
+msgstr "削除するブランチを選択して下さい。"
 
-#: lib/branch_create.tcl:131
-msgid "Please select a tracking branch."
-msgstr "トラッキング・ブランチを選択して下さい。"
+#: lib/remote_branch_delete.tcl:218 lib/branch_delete.tcl:115
+msgid ""
+"Recovering deleted branches is difficult.\n"
+"\n"
+"Delete the selected branches?"
+msgstr ""
+"削除したブランチを回復するのは困難です。\n"
+"\n"
+"選択したブランチを削除して良いですか?"
 
-#: lib/branch_create.tcl:140
+#: lib/remote_branch_delete.tcl:227
 #, tcl-format
-msgid "Tracking branch %s is not a branch in the remote repository."
-msgstr "トラッキング・ブランチ %s は遠隔リポジトリのブランチではありません。"
+msgid "Deleting branches from %s"
+msgstr "%s からブランチを削除しています。"
 
-#: lib/branch_create.tcl:153 lib/branch_rename.tcl:86
-msgid "Please supply a branch name."
-msgstr "ã\83\96ã\83©ã\83³ã\83\81å\90\8dã\82\92æ\8c\87å®\9aã\81\97ã\81¦ä¸\8bã\81\95ã\81\84。"
+#: lib/remote_branch_delete.tcl:300
+msgid "No repository selected."
+msgstr "ã\83ªã\83\9dã\82¸ã\83\88ã\83ªã\81\8cé\81¸æ\8a\9eã\81\95ã\82\8cã\81¦ã\81\84ã\81¾ã\81\9bã\82\93。"
 
-#: lib/branch_create.tcl:164 lib/branch_rename.tcl:106
+#: lib/remote_branch_delete.tcl:305
 #, tcl-format
-msgid "'%s' is not an acceptable branch name."
-msgstr "'%s' はブランチ名に使えません。"
+msgid "Scanning %s..."
+msgstr "%s をスキャンしています…"
 
-#: lib/branch_delete.tcl:15
+#: lib/branch_delete.tcl:16
 msgid "Delete Branch"
 msgstr "ブランチ削除"
 
-#: lib/branch_delete.tcl:20
+#: lib/branch_delete.tcl:21
 msgid "Delete Local Branch"
 msgstr "ローカル・ブランチを削除"
 
-#: lib/branch_delete.tcl:37
+#: lib/branch_delete.tcl:39
 msgid "Local Branches"
 msgstr "ローカル・ブランチ"
 
-#: lib/branch_delete.tcl:52
+#: lib/branch_delete.tcl:51
 msgid "Delete Only If Merged Into"
 msgstr "マージ済みの時のみ削除"
 
-#: lib/branch_delete.tcl:54 lib/remote_branch_delete.tcl:119
-msgid "Always (Do not perform merge checks)"
-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 lib/remote_branch_delete.tcl:217
-msgid ""
-"Recovering deleted branches is difficult.\n"
-"\n"
-"Delete the selected branches?"
-msgstr ""
-"削除したブランチを回復するのは困難です。\n"
-"\n"
-"選択したブランチを削除して良いですか?"
-
 #: lib/branch_delete.tcl:141
 #, tcl-format
 msgid ""
@@ -820,62 +895,63 @@ msgstr ""
 "以下のブランチを削除できません:\n"
 "%s"
 
-#: lib/branch_rename.tcl:14 lib/branch_rename.tcl:22
-msgid "Rename Branch"
-msgstr "ブランチの名前変更"
+#: lib/choose_rev.tcl:52
+msgid "This Detached Checkout"
+msgstr "分離されたチェックアウト"
 
-#: lib/branch_rename.tcl:26
-msgid "Rename"
-msgstr "名前変更"
+#: lib/choose_rev.tcl:60
+msgid "Revision Expression:"
+msgstr "リビジョン式:"
 
-#: lib/branch_rename.tcl:36
-msgid "Branch:"
-msgstr "ã\83\96ã\83©ã\83³ã\83\81:"
+#: lib/choose_rev.tcl:72
+msgid "Local Branch"
+msgstr "ã\83­ã\83¼ã\82«ã\83«ã\83»ã\83\96ã\83©ã\83³ã\83\81"
 
-#: lib/branch_rename.tcl:39
-msgid "New Name:"
-msgstr "新しい名前:"
+#: lib/choose_rev.tcl:77
+msgid "Tracking Branch"
+msgstr "トラッキング・ブランチ"
 
-#: lib/branch_rename.tcl:75
-msgid "Please select a branch to rename."
-msgstr "名前を変更するブランチを選んで下さい。"
+#: lib/choose_rev.tcl:82 lib/choose_rev.tcl:544
+msgid "Tag"
+msgstr "タグ"
 
-#: lib/branch_rename.tcl:96 lib/checkout_op.tcl:202
+#: lib/choose_rev.tcl:321
 #, tcl-format
-msgid "Branch '%s' already exists."
-msgstr "'%s'というブランチは既に存在します。"
+msgid "Invalid revision: %s"
+msgstr "無効なリビジョン: %s"
 
-#: lib/branch_rename.tcl:117
-#, tcl-format
-msgid "Failed to rename '%s'."
-msgstr "'%s'の名前変更に失敗しました。"
+#: lib/choose_rev.tcl:342
+msgid "No revision selected."
+msgstr "リビジョンが未選択です。"
 
-#: lib/browser.tcl:17
-msgid "Starting..."
-msgstr "起動中…"
+#: lib/choose_rev.tcl:350
+msgid "Revision expression is empty."
+msgstr "リビジョン式が空です。"
 
-#: lib/browser.tcl:26
-msgid "File Browser"
-msgstr "ファイル・ブラウザ"
+#: lib/choose_rev.tcl:537
+msgid "Updated"
+msgstr "更新しました"
 
-#: lib/browser.tcl:126 lib/browser.tcl:143
-#, tcl-format
-msgid "Loading %s..."
-msgstr "%s をロード中…"
+#: lib/choose_rev.tcl:565
+msgid "URL"
+msgstr "URL"
 
-#: lib/browser.tcl:187
-msgid "[Up To Parent]"
-msgstr "[上位フォルダへ]"
+#: lib/console.tcl:59
+msgid "Working... please wait..."
+msgstr "実行中…お待ち下さい…"
 
-#: lib/browser.tcl:267 lib/browser.tcl:273
-msgid "Browse Branch Files"
-msgstr "現在のブランチのファイルを見る"
+#: lib/console.tcl:81 lib/checkout_op.tcl:146 lib/database.tcl:30
+#: lib/sshkey.tcl:55
+msgid "Close"
+msgstr "閉じる"
 
-#: lib/browser.tcl:278 lib/choose_repository.tcl:398
-#: lib/choose_repository.tcl:486 lib/choose_repository.tcl:497
-#: lib/choose_repository.tcl:1028
-msgid "Browse"
-msgstr "ブラウズ"
+#: lib/console.tcl:186
+msgid "Success"
+msgstr "成功"
+
+#: lib/console.tcl:200
+msgid "Error: Command Failed"
+msgstr "エラー: コマンドが失敗しました"
 
 #: lib/checkout_op.tcl:85
 #, tcl-format
@@ -887,11 +963,6 @@ msgstr "%s から %s をフェッチしています"
 msgid "fatal: Cannot resolve %s"
 msgstr "致命的エラー: %s を解決できません"
 
-#: lib/checkout_op.tcl:146 lib/console.tcl:81 lib/database.tcl:31
-#: lib/sshkey.tcl:53
-msgid "Close"
-msgstr "閉じる"
-
 #: lib/checkout_op.tcl:175
 #, tcl-format
 msgid "Branch '%s' does not exist."
@@ -902,6 +973,11 @@ msgstr "ブランチ'%s'は存在しません。"
 msgid "Failed to configure simplified git-pull for '%s'."
 msgstr "'%s' に簡易 git-pull を設定できませんでした"
 
+#: lib/checkout_op.tcl:202 lib/branch_rename.tcl:102
+#, tcl-format
+msgid "Branch '%s' already exists."
+msgstr "'%s'というブランチは既に存在します。"
+
 #: lib/checkout_op.tcl:229
 #, tcl-format
 msgid ""
@@ -999,9 +1075,9 @@ msgstr "失なわれたコミットを回復するのは簡単ではありませ
 msgid "Reset '%s'?"
 msgstr "'%s' をリセットしますか?"
 
-#: lib/checkout_op.tcl:567 lib/merge.tcl:164 lib/tools_dlg.tcl:343
-msgid "Visualize"
-msgstr "可視化"
+#: lib/checkout_op.tcl:571 lib/branch_create.tcl:85
+msgid "Reset"
+msgstr "リセット"
 
 #: lib/checkout_op.tcl:635
 #, tcl-format
@@ -1019,1537 +1095,1590 @@ msgstr ""
 "ましたが、 Git の内部データを更新できませんでした。\n"
 "起こるはずのないエラーです。あきらめて %s を終了します。"
 
-#: lib/choose_font.tcl:39
-msgid "Select"
-msgstr "選択"
+#: lib/blame.tcl:73
+msgid "File Viewer"
+msgstr "ファイルピューワ"
 
-#: lib/choose_font.tcl:53
-msgid "Font Family"
-msgstr "ã\83\95ã\82©ã\83³ã\83\88ã\83»ã\83\95ã\82¡ã\83\9fã\83ªã\83¼"
+#: lib/blame.tcl:79
+msgid "Commit:"
+msgstr "ã\82³ã\83\9fã\83\83ã\83\88:"
 
-#: lib/choose_font.tcl:74
-msgid "Font Size"
-msgstr "ã\83\95ã\82©ã\83³ã\83\88ã\81®å¤§ã\81\8dã\81\95"
+#: lib/blame.tcl:280
+msgid "Copy Commit"
+msgstr "ã\82³ã\83\9fã\83\83ã\83\88ã\82\92ã\82³ã\83\94ã\83¼"
 
-#: lib/choose_font.tcl:91
-msgid "Font Example"
-msgstr "ã\83\95ã\82©ã\83³ã\83\88ã\83»ã\82µã\83³ã\83\97ã\83«"
+#: lib/blame.tcl:284
+msgid "Find Text..."
+msgstr "ã\83\86ã\82­ã\82¹ã\83\88ã\82\92æ¤\9cç´¢"
 
-#: lib/choose_font.tcl:103
-msgid ""
-"This is example text.\n"
-"If you like this text, it can be your font."
-msgstr ""
-"これはサンプル文です。\n"
-"このフォントが気に入ればお使いになれます。"
+#: lib/blame.tcl:288
+msgid "Goto Line..."
+msgstr "指定行に移動…"
 
-#: lib/choose_repository.tcl:28
-msgid "Git Gui"
-msgstr "Git GUI"
+#: lib/blame.tcl:297
+msgid "Do Full Copy Detection"
+msgstr "コピー検知"
 
-#: lib/choose_repository.tcl:87 lib/choose_repository.tcl:386
-msgid "Create New Repository"
-msgstr "æ\96°ã\81\97ã\81\84ã\83ªã\83\9dã\82¸ã\83\88ã\83ªã\82\92ä½\9cる"
+#: lib/blame.tcl:301
+msgid "Show History Context"
+msgstr "æ\96\87è\84\88ã\82\92è¦\8bã\81\9bる"
 
-#: lib/choose_repository.tcl:93
-msgid "New..."
-msgstr "新規…"
+#: lib/blame.tcl:304
+msgid "Blame Parent Commit"
+msgstr "親コミットを注釈"
 
-#: lib/choose_repository.tcl:100 lib/choose_repository.tcl:471
-msgid "Clone Existing Repository"
-msgstr "既存リポジトリを複製する"
+#: lib/blame.tcl:466
+#, tcl-format
+msgid "Reading %s..."
+msgstr "%s を読んでいます…"
 
-#: lib/choose_repository.tcl:106
-msgid "Clone..."
-msgstr "複製…"
+#: lib/blame.tcl:594
+msgid "Loading copy/move tracking annotations..."
+msgstr "コピー・移動追跡データを読んでいます…"
 
-#: lib/choose_repository.tcl:113 lib/choose_repository.tcl:1016
-msgid "Open Existing Repository"
-msgstr "既存リポジトリを開く"
+#: lib/blame.tcl:614
+msgid "lines annotated"
+msgstr "行を注釈しました"
 
-#: lib/choose_repository.tcl:119
-msgid "Open..."
-msgstr "開く…"
+#: lib/blame.tcl:806
+msgid "Loading original location annotations..."
+msgstr "元位置行の注釈データを読んでいます…"
 
-#: lib/choose_repository.tcl:132
-msgid "Recent Repositories"
-msgstr "æ\9c\80è¿\91使ã\81£ã\81\9fã\83ªã\83\9dã\82¸ã\83\88ã\83ª"
+#: lib/blame.tcl:809
+msgid "Annotation complete."
+msgstr "注é\87\88å®\8cäº\86ã\81\97ã\81¾ã\81\97ã\81\9f"
 
-#: lib/choose_repository.tcl:138
-msgid "Open Recent Repository:"
-msgstr "最近使ったリポジトリを開く"
+#: lib/blame.tcl:839
+msgid "Busy"
+msgstr "実行中"
 
-#: lib/choose_repository.tcl:306 lib/choose_repository.tcl:313
-#: lib/choose_repository.tcl:320
-#, tcl-format
-msgid "Failed to create repository %s:"
-msgstr "リポジトリ %s を作製できません:"
+#: lib/blame.tcl:840
+msgid "Annotation process is already running."
+msgstr "すでに blame プロセスを実行中です。"
 
-#: lib/choose_repository.tcl:391
-msgid "Directory:"
-msgstr "ã\83\87ã\82£ã\83¬ã\82¯ã\83\88ã\83ª:"
+#: lib/blame.tcl:879
+msgid "Running thorough copy detection..."
+msgstr "ã\82³ã\83\94ã\83¼æ¤\9cç\9f¥ã\82\92å®\9fè¡\8c中â\80¦"
 
-#: lib/choose_repository.tcl:423 lib/choose_repository.tcl:550
-#: lib/choose_repository.tcl:1052
-msgid "Git Repository"
-msgstr "GIT リポジトリ"
+#: lib/blame.tcl:947
+msgid "Loading annotation..."
+msgstr "注釈を読み込んでいます…"
 
-#: lib/choose_repository.tcl:448
-#, tcl-format
-msgid "Directory %s already exists."
-msgstr "ディレクトリ '%s' は既に存在します。"
+#: lib/blame.tcl:1000
+msgid "Author:"
+msgstr "作者:"
 
-#: lib/choose_repository.tcl:452
-#, tcl-format
-msgid "File %s already exists."
-msgstr "ファイル '%s' は既に存在します。"
+#: lib/blame.tcl:1004
+msgid "Committer:"
+msgstr "コミット者:"
 
-#: lib/choose_repository.tcl:466
-msgid "Clone"
-msgstr "複製"
+#: lib/blame.tcl:1009
+msgid "Original File:"
+msgstr "元ファイル"
 
-#: lib/choose_repository.tcl:479
-msgid "Source Location:"
-msgstr "ソースの位置"
+#: lib/blame.tcl:1057
+msgid "Cannot find HEAD commit:"
+msgstr "HEAD コミットが見つかりません"
 
-#: lib/choose_repository.tcl:490
-msgid "Target Directory:"
-msgstr "先ディレクトリ:"
+#: lib/blame.tcl:1112
+msgid "Cannot find parent commit:"
+msgstr "親コミットが見つかりません:"
+
+#: lib/blame.tcl:1127
+msgid "Unable to display parent"
+msgstr "親を表示できません"
+
+#: lib/blame.tcl:1128 lib/diff.tcl:356
+msgid "Error loading diff:"
+msgstr "diff を読む際のエラーです:"
+
+#: lib/blame.tcl:1269
+msgid "Originally By:"
+msgstr "原作者:"
+
+#: lib/blame.tcl:1275
+msgid "In File:"
+msgstr "ファイル:"
+
+#: lib/blame.tcl:1280
+msgid "Copied Or Moved Here By:"
+msgstr "複写・移動者:"
+
+#: lib/about.tcl:26
+msgid "git-gui - a graphical user interface for Git."
+msgstr "Git のグラフィカルUI git-gui"
+
+#: lib/choose_repository.tcl:33
+msgid "Git Gui"
+msgstr "Git GUI"
+
+#: lib/choose_repository.tcl:92 lib/choose_repository.tcl:412
+msgid "Create New Repository"
+msgstr "新しいリポジトリを作る"
+
+#: lib/choose_repository.tcl:98
+msgid "New..."
+msgstr "新規…"
+
+#: lib/choose_repository.tcl:105 lib/choose_repository.tcl:496
+msgid "Clone Existing Repository"
+msgstr "既存リポジトリを複製する"
+
+#: lib/choose_repository.tcl:116
+msgid "Clone..."
+msgstr "複製…"
+
+#: lib/choose_repository.tcl:123 lib/choose_repository.tcl:1064
+msgid "Open Existing Repository"
+msgstr "既存リポジトリを開く"
+
+#: lib/choose_repository.tcl:129
+msgid "Open..."
+msgstr "開く…"
+
+#: lib/choose_repository.tcl:142
+msgid "Recent Repositories"
+msgstr "最近使ったリポジトリ"
+
+#: lib/choose_repository.tcl:148
+msgid "Open Recent Repository:"
+msgstr "最近使ったリポジトリを開く"
+
+#: lib/choose_repository.tcl:316 lib/choose_repository.tcl:323
+#: lib/choose_repository.tcl:330
+#, tcl-format
+msgid "Failed to create repository %s:"
+msgstr "リポジトリ %s を作製できません:"
+
+#: lib/choose_repository.tcl:407 lib/branch_create.tcl:33
+msgid "Create"
+msgstr "作成"
+
+#: lib/choose_repository.tcl:417
+msgid "Directory:"
+msgstr "ディレクトリ:"
+
+#: lib/choose_repository.tcl:422 lib/choose_repository.tcl:509
+#: lib/choose_repository.tcl:518 lib/choose_repository.tcl:1074
+#: lib/browser.tcl:288
+msgid "Browse"
+msgstr "ブラウズ"
+
+#: lib/choose_repository.tcl:447 lib/choose_repository.tcl:573
+#: lib/choose_repository.tcl:1098
+msgid "Git Repository"
+msgstr "GIT リポジトリ"
 
-#: lib/choose_repository.tcl:502
+#: lib/choose_repository.tcl:472
+#, tcl-format
+msgid "Directory %s already exists."
+msgstr "ディレクトリ '%s' は既に存在します。"
+
+#: lib/choose_repository.tcl:476
+#, tcl-format
+msgid "File %s already exists."
+msgstr "ファイル '%s' は既に存在します。"
+
+#: lib/choose_repository.tcl:491
+msgid "Clone"
+msgstr "複製"
+
+#: lib/choose_repository.tcl:504
+msgid "Source Location:"
+msgstr "ソースの位置"
+
+#: lib/choose_repository.tcl:513
+msgid "Target Directory:"
+msgstr "先ディレクトリ:"
+
+#: lib/choose_repository.tcl:523
 msgid "Clone Type:"
 msgstr "複製方式:"
 
-#: lib/choose_repository.tcl:508
+#: lib/choose_repository.tcl:528
 msgid "Standard (Fast, Semi-Redundant, Hardlinks)"
 msgstr "標準(高速・中冗長度・ハードリンク)"
 
-#: lib/choose_repository.tcl:514
+#: lib/choose_repository.tcl:533
 msgid "Full Copy (Slower, Redundant Backup)"
 msgstr "全複写(低速・冗長バックアップ)"
 
-#: lib/choose_repository.tcl:520
+#: lib/choose_repository.tcl:538
 msgid "Shared (Fastest, Not Recommended, No Backup)"
 msgstr "共有(最高速・非推奨・バックアップ無し)"
 
-#: lib/choose_repository.tcl:556 lib/choose_repository.tcl:603
-#: lib/choose_repository.tcl:749 lib/choose_repository.tcl:819
-#: lib/choose_repository.tcl:1058 lib/choose_repository.tcl:1066
+#: lib/choose_repository.tcl:545
+msgid "Recursively clone submodules too"
+msgstr "サブモジュールも再帰的に複製する"
+
+#: lib/choose_repository.tcl:579 lib/choose_repository.tcl:626
+#: lib/choose_repository.tcl:772 lib/choose_repository.tcl:842
+#: lib/choose_repository.tcl:1104 lib/choose_repository.tcl:1112
 #, tcl-format
 msgid "Not a Git repository: %s"
 msgstr "Git リポジトリではありません: %s"
 
-#: lib/choose_repository.tcl:592
+#: lib/choose_repository.tcl:615
 msgid "Standard only available for local repository."
 msgstr "標準方式は同一計算機上のリポジトリにのみ使えます。"
 
-#: lib/choose_repository.tcl:596
+#: lib/choose_repository.tcl:619
 msgid "Shared only available for local repository."
 msgstr "共有方式は同一計算機上のリポジトリにのみ使えます。"
 
-#: lib/choose_repository.tcl:617
+#: lib/choose_repository.tcl:640
 #, tcl-format
 msgid "Location %s already exists."
 msgstr "'%s' は既に存在します。"
 
-#: lib/choose_repository.tcl:628
+#: lib/choose_repository.tcl:651
 msgid "Failed to configure origin"
 msgstr "origin を設定できませんでした"
 
-#: lib/choose_repository.tcl:640
+#: lib/choose_repository.tcl:663
 msgid "Counting objects"
 msgstr "オブジェクトを数えています"
 
-#: lib/choose_repository.tcl:641
+#: lib/choose_repository.tcl:664
 msgid "buckets"
 msgstr "バケツ"
 
-#: lib/choose_repository.tcl:665
+#: lib/choose_repository.tcl:688
 #, tcl-format
 msgid "Unable to copy objects/info/alternates: %s"
 msgstr "objects/info/alternates を複写できません: %s"
 
-#: lib/choose_repository.tcl:701
+#: lib/choose_repository.tcl:724
 #, tcl-format
 msgid "Nothing to clone from %s."
 msgstr "%s から複製する内容はありません"
 
-#: lib/choose_repository.tcl:703 lib/choose_repository.tcl:917
-#: lib/choose_repository.tcl:929
+#: lib/choose_repository.tcl:726 lib/choose_repository.tcl:940
+#: lib/choose_repository.tcl:952
 msgid "The 'master' branch has not been initialized."
 msgstr "'master' ブランチが初期化されていません"
 
-#: lib/choose_repository.tcl:716
+#: lib/choose_repository.tcl:739
 msgid "Hardlinks are unavailable.  Falling back to copying."
 msgstr "ハードリンクが作れないので、コピーします"
 
-#: lib/choose_repository.tcl:728
+#: lib/choose_repository.tcl:751
 #, tcl-format
 msgid "Cloning from %s"
 msgstr "%s から複製しています"
 
-#: lib/choose_repository.tcl:759
+#: lib/choose_repository.tcl:782
 msgid "Copying objects"
 msgstr "オブジェクトを複写しています"
 
-#: lib/choose_repository.tcl:760
+#: lib/choose_repository.tcl:783
 msgid "KiB"
 msgstr "KiB"
 
-#: lib/choose_repository.tcl:784
+#: lib/choose_repository.tcl:807
 #, tcl-format
 msgid "Unable to copy object: %s"
 msgstr "オブジェクトを複写できません: %s"
 
-#: lib/choose_repository.tcl:794
+#: lib/choose_repository.tcl:817
 msgid "Linking objects"
 msgstr "オブジェクトを連結しています"
 
-#: lib/choose_repository.tcl:795
+#: lib/choose_repository.tcl:818
 msgid "objects"
 msgstr "オブジェクト"
 
-#: lib/choose_repository.tcl:803
+#: lib/choose_repository.tcl:826
 #, tcl-format
 msgid "Unable to hardlink object: %s"
 msgstr "オブジェクトをハードリンクできません: %s"
 
-#: lib/choose_repository.tcl:858
+#: lib/choose_repository.tcl:881
 msgid "Cannot fetch branches and objects.  See console output for details."
 msgstr "ブランチやオブジェクトを取得できません。コンソール出力を見て下さい"
 
-#: lib/choose_repository.tcl:869
+#: lib/choose_repository.tcl:892
 msgid "Cannot fetch tags.  See console output for details."
 msgstr "タグを取得できません。コンソール出力を見て下さい"
 
-#: lib/choose_repository.tcl:893
+#: lib/choose_repository.tcl:916
 msgid "Cannot determine HEAD.  See console output for details."
 msgstr "HEAD を確定できません。コンソール出力を見て下さい"
 
-#: lib/choose_repository.tcl:902
+#: lib/choose_repository.tcl:925
 #, tcl-format
 msgid "Unable to cleanup %s"
 msgstr "%s を掃除できません"
 
-#: lib/choose_repository.tcl:908
+#: lib/choose_repository.tcl:931
 msgid "Clone failed."
 msgstr "複写に失敗しました。"
 
-#: lib/choose_repository.tcl:915
+#: lib/choose_repository.tcl:938
 msgid "No default branch obtained."
 msgstr "デフォールト・ブランチが取得されませんでした"
 
-#: lib/choose_repository.tcl:926
+#: lib/choose_repository.tcl:949
 #, tcl-format
 msgid "Cannot resolve %s as a commit."
 msgstr "%s をコミットとして解釈できません"
 
-#: lib/choose_repository.tcl:938
+#: lib/choose_repository.tcl:961
 msgid "Creating working directory"
 msgstr "作業ディレクトリを作成しています"
 
-#: lib/choose_repository.tcl:939 lib/index.tcl:67 lib/index.tcl:130
-#: lib/index.tcl:198
+#: lib/choose_repository.tcl:962 lib/index.tcl:70 lib/index.tcl:136
+#: lib/index.tcl:207
 msgid "files"
 msgstr "ファイル"
 
-#: lib/choose_repository.tcl:968
+#: lib/choose_repository.tcl:981
+msgid "Cannot clone submodules."
+msgstr "サブモジュールが複製できません。"
+
+#: lib/choose_repository.tcl:990
+msgid "Cloning submodules"
+msgstr "サブモジュールを複製しています"
+
+#: lib/choose_repository.tcl:1015
 msgid "Initial file checkout failed."
 msgstr "初期チェックアウトに失敗しました"
 
-#: lib/choose_repository.tcl:1011
+#: lib/choose_repository.tcl:1059
 msgid "Open"
 msgstr "開く"
 
-#: lib/choose_repository.tcl:1021
+#: lib/choose_repository.tcl:1069
 msgid "Repository:"
 msgstr "リポジトリ:"
 
-#: lib/choose_repository.tcl:1072
+#: lib/choose_repository.tcl:1118
 #, tcl-format
 msgid "Failed to open repository %s:"
 msgstr "リポジトリ %s を開けません:"
 
-#: lib/choose_rev.tcl:53
-msgid "This Detached Checkout"
-msgstr "分離されたチェックアウト"
+#: lib/branch_rename.tcl:15 lib/branch_rename.tcl:23
+msgid "Rename Branch"
+msgstr "ブランチの名前変更"
 
-#: lib/choose_rev.tcl:60
-msgid "Revision Expression:"
-msgstr "リビジョン式:"
+#: lib/branch_rename.tcl:28
+msgid "Rename"
+msgstr "名前変更"
 
-#: lib/choose_rev.tcl:74
-msgid "Local Branch"
-msgstr "ã\83­ã\83¼ã\82«ã\83«ã\83»ã\83\96ã\83©ã\83³ã\83\81"
+#: lib/branch_rename.tcl:38
+msgid "Branch:"
+msgstr "ã\83\96ã\83©ã\83³ã\83\81:"
 
-#: lib/choose_rev.tcl:79
-msgid "Tracking Branch"
-msgstr "トラッキング・ブランチ"
+#: lib/branch_rename.tcl:46
+msgid "New Name:"
+msgstr "新しい名前:"
 
-#: lib/choose_rev.tcl:84 lib/choose_rev.tcl:538
-msgid "Tag"
-msgstr "タグ"
+#: lib/branch_rename.tcl:81
+msgid "Please select a branch to rename."
+msgstr "名前を変更するブランチを選んで下さい。"
 
-#: lib/choose_rev.tcl:317
-#, tcl-format
-msgid "Invalid revision: %s"
-msgstr "無効なリビジョン: %s"
+#: lib/branch_rename.tcl:92 lib/branch_create.tcl:154
+msgid "Please supply a branch name."
+msgstr "ブランチ名を指定して下さい。"
 
-#: lib/choose_rev.tcl:338
-msgid "No revision selected."
-msgstr "リビジョンが未選択です。"
+#: lib/branch_rename.tcl:112 lib/branch_create.tcl:165
+#, tcl-format
+msgid "'%s' is not an acceptable branch name."
+msgstr "'%s' はブランチ名に使えません。"
 
-#: lib/choose_rev.tcl:346
-msgid "Revision expression is empty."
-msgstr "リビジョン式が空です。"
+#: lib/branch_rename.tcl:123
+#, tcl-format
+msgid "Failed to rename '%s'."
+msgstr "'%s'の名前変更に失敗しました。"
 
-#: lib/choose_rev.tcl:531
-msgid "Updated"
-msgstr "更新しました"
+#: lib/shortcut.tcl:21 lib/shortcut.tcl:62
+msgid "Cannot write shortcut:"
+msgstr "ショートカットが書けません:"
 
-#: lib/choose_rev.tcl:559
-msgid "URL"
-msgstr "URL"
+#: lib/shortcut.tcl:137
+msgid "Cannot write icon:"
+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/search.tcl:48
+msgid "Find:"
+msgstr "検索:"
 
-#: 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/search.tcl:50
+msgid "Next"
+msgstr "次"
 
-#: lib/commit.tcl:48
-msgid "Error loading commit data for amend:"
-msgstr "訂正するコミットのデータを読めません:"
+#: lib/search.tcl:51
+msgid "Prev"
+msgstr ""
 
-#: lib/commit.tcl:75
-msgid "Unable to obtain your identity:"
-msgstr "ユーザの正体を確認できません:"
+#: lib/search.tcl:52
+msgid "RegExp"
+msgstr "正規表現"
 
-#: lib/commit.tcl:80
-msgid "Invalid GIT_COMMITTER_IDENT:"
-msgstr "GIT_COMMITTER_IDENT が無効です:"
+#: lib/search.tcl:54
+msgid "Case"
+msgstr "大文字小文字を区別"
 
-#: lib/commit.tcl:129
+#: lib/status_bar.tcl:87
 #, tcl-format
-msgid "warning: Tcl does not support encoding '%s'."
-msgstr "警告: Tcl はエンコーディング '%s' をサポートしていません"
-
-#: lib/commit.tcl:149
-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"
+msgid "%s ... %*i of %*i %s (%3i%%)"
+msgstr "%1$s ... %4$*i %6$s 中の %2$*i (%7$3i%%)"
 
-#: lib/commit.tcl:172
-#, 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/tools_dlg.tcl:22
+msgid "Add Tool"
+msgstr "ツールの追加"
 
-#: lib/commit.tcl:180
-#, 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/tools_dlg.tcl:28
+msgid "Add New Tool Command"
+msgstr "新規ツールコマンドの追加"
 
-#: lib/commit.tcl:188
-msgid ""
-"No changes to commit.\n"
-"\n"
-"You must stage at least 1 file before you can commit.\n"
-msgstr ""
-"コミットする変更がありません。\n"
-"\n"
-"最低一つの変更をコミット予定に加えてからコミットして下さい。\n"
+#: lib/tools_dlg.tcl:34
+msgid "Add globally"
+msgstr "全体に追加"
 
-#: lib/commit.tcl:203
-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"
-"- 第1行: 何をしたか、を1行で要約。\n"
-"- 第2行: 空白\n"
-"- 残りの行: なぜ、この変更が良い変更か、の説明。\n"
+#: lib/tools_dlg.tcl:37 lib/remote_add.tcl:30
+msgid "Add"
+msgstr "追加"
 
-#: lib/commit.tcl:234
-msgid "Calling pre-commit hook..."
-msgstr "ã\82³ã\83\9fã\83\83ã\83\88å\89\8dã\83\95ã\83\83ã\82¯ã\82\92å®\9fè¡\8c中ã\83»ã\83»ã\83»"
+#: lib/tools_dlg.tcl:46
+msgid "Tool Details"
+msgstr "ã\83\84ã\83¼ã\83«ã\81®è©³ç´°"
 
-#: lib/commit.tcl:249
-msgid "Commit declined by pre-commit hook."
-msgstr "コミット前フックがコミットを拒否しました"
+#: lib/tools_dlg.tcl:49
+msgid "Use '/' separators to create a submenu tree:"
+msgstr "'/' でサブメニューを区切ります:"
 
-#: lib/commit.tcl:272
-msgid "Calling commit-msg hook..."
-msgstr "コミット・メッセージ・フックを実行中・・・"
+#: lib/tools_dlg.tcl:51 lib/remote_add.tcl:41 lib/branch_create.tcl:44
+msgid "Name:"
+msgstr "名前:"
 
-#: lib/commit.tcl:287
-msgid "Commit declined by commit-msg hook."
-msgstr "ã\82³ã\83\9fã\83\83ã\83\88ã\83»ã\83¡ã\83\83ã\82»ã\83¼ã\82¸ã\83»ã\83\95ã\83\83ã\82¯ã\81\8cã\82³ã\83\9fã\83\83ã\83\88ã\82\92æ\8b\92å\90¦ã\81\97ã\81¾ã\81\97ã\81\9f"
+#: lib/tools_dlg.tcl:60
+msgid "Command:"
+msgstr "ã\82³ã\83\9eã\83³ã\83\89:"
 
-#: lib/commit.tcl:300
-msgid "Committing changes..."
-msgstr "変更点をコミット中・・・"
+#: lib/tools_dlg.tcl:71
+msgid "Show a dialog before running"
+msgstr "起動する前にダイアログを表示"
 
-#: lib/commit.tcl:316
-msgid "write-tree failed:"
-msgstr "write-tree が失敗しました:"
+#: lib/tools_dlg.tcl:77
+msgid "Ask the user to select a revision (sets $REVISION)"
+msgstr "ユーザにコミットを一つ選ばせる ($REVISION にセットします)"
 
-#: lib/commit.tcl:317 lib/commit.tcl:361 lib/commit.tcl:382
-msgid "Commit failed."
-msgstr "ã\82³ã\83\9fã\83\83ã\83\88ã\81«å¤±æ\95\97ã\81\97ã\81¾ã\81\97ã\81\9fã\80\82"
+#: lib/tools_dlg.tcl:82
+msgid "Ask the user for additional arguments (sets $ARGS)"
+msgstr "ã\83¦ã\83¼ã\82¶ã\81«ä»\96ã\81®å¼\95æ\95°ã\82\92追å\8a ã\81\95ã\81\9bã\82\8b ($ARGS ã\81«ã\82»ã\83\83ã\83\88ã\81\97ã\81¾ã\81\99)"
 
-#: lib/commit.tcl:334
+#: lib/tools_dlg.tcl:89
+msgid "Don't show the command output window"
+msgstr "コマンドからの出力ウィンドウを見せない"
+
+#: lib/tools_dlg.tcl:94
+msgid "Run only if a diff is selected ($FILENAME not empty)"
+msgstr "パッチが選ばれているときだけ動かす($FILENAME が空でない)"
+
+#: lib/tools_dlg.tcl:118
+msgid "Please supply a name for the tool."
+msgstr "ツール名を指定して下さい。"
+
+#: lib/tools_dlg.tcl:126
 #, tcl-format
-msgid "Commit %s appears to be corrupt"
-msgstr "ã\82³ã\83\9fã\83\83ã\83\88 %s ã\81¯å£\8aã\82\8cã\81¦ã\81\84ã\81¾ã\81\99"
+msgid "Tool '%s' already exists."
+msgstr "ã\83\84ã\83¼ã\83« '%s' ã\81¯æ\97¢ã\81«å­\98å\9c¨ã\81\97ã\81¾ã\81\99ã\80\82"
 
-#: lib/commit.tcl:339
+#: lib/tools_dlg.tcl:148
+#, tcl-format
 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"
+"Could not add tool:\n"
+"%s"
 msgstr ""
-"コミットする変更がありません。\n"
-"\n"
-"マージでなく、また、一つも変更点がありません。\n"
-"\n"
-"自動的に再スキャンを開始します。\n"
+"ツールを追加できません:\n"
+"%s"
 
-#: lib/commit.tcl:346
-msgid "No changes to commit."
-msgstr "ã\82³ã\83\9fã\83\83ã\83\88ã\81\99ã\82\8bå¤\89æ\9b´ã\81\8cã\81\82ã\82\8aã\81¾ã\81\9bã\82\93ã\80\82"
+#: lib/tools_dlg.tcl:187
+msgid "Remove Tool"
+msgstr "ã\83\84ã\83¼ã\83«ã\81®å\89\8aé\99¤"
 
-#: lib/commit.tcl:360
-msgid "commit-tree failed:"
-msgstr "commit-tree が失敗しました:"
+#: lib/tools_dlg.tcl:193
+msgid "Remove Tool Commands"
+msgstr "ツールコマンドの削除"
 
-#: lib/commit.tcl:381
-msgid "update-ref failed:"
-msgstr "update-ref が失敗しました:"
+#: lib/tools_dlg.tcl:198
+msgid "Remove"
+msgstr "削除"
 
-#: lib/commit.tcl:469
-#, tcl-format
-msgid "Created commit %s: %s"
-msgstr "コミット %s を作成しました: %s"
+#: lib/tools_dlg.tcl:231
+msgid "(Blue denotes repository-local tools)"
+msgstr "(青色はローカルレポジトリのツールです)"
 
-#: lib/console.tcl:59
-msgid "Working... please wait..."
-msgstr "実行中…お待ち下さい…"
+#: lib/tools_dlg.tcl:292
+#, tcl-format
+msgid "Run Command: %s"
+msgstr "コマンドを起動: %s"
 
-#: lib/console.tcl:186
-msgid "Success"
-msgstr "成功"
+#: lib/tools_dlg.tcl:306
+msgid "Arguments"
+msgstr "引数"
 
-#: lib/console.tcl:200
-msgid "Error: Command Failed"
-msgstr "ã\82¨ã\83©ã\83¼: ã\82³ã\83\9eã\83³ã\83\89ã\81\8c失æ\95\97ã\81\97ã\81¾ã\81\97ã\81\9f"
+#: lib/tools_dlg.tcl:321 lib/branch_checkout.tcl:35 lib/browser.tcl:297
+msgid "Revision"
+msgstr "ã\83ªã\83\93ã\82¸ã\83§ã\83³"
 
-#: lib/database.tcl:43
-msgid "Number of loose objects"
-msgstr "ばらばらなオブジェクトの数"
+#: lib/tools_dlg.tcl:341
+msgid "OK"
+msgstr "OK"
 
-#: lib/database.tcl:44
-msgid "Disk space used by loose objects"
-msgstr "ばらばらなオブジェクトの使用するディスク量"
+#: lib/tools.tcl:75
+#, tcl-format
+msgid "Running %s requires a selected file."
+msgstr "ファイルを選択してから %s を起動してください。"
 
-#: lib/database.tcl:45
-msgid "Number of packed objects"
-msgstr "パックされたオブジェクトの数"
+#: lib/tools.tcl:91
+#, tcl-format
+msgid "Are you sure you want to run %1$s on file \"%2$s\"?"
+msgstr "本当にファイル \"%2$s\"で %1$s を起動しますか?"
 
-#: lib/database.tcl:46
-msgid "Number of packs"
-msgstr "パックの数"
+#: lib/tools.tcl:95
+#, tcl-format
+msgid "Are you sure you want to run %s?"
+msgstr "本当に %s を起動しますか?"
 
-#: lib/database.tcl:47
-msgid "Disk space used by packed objects"
-msgstr "パックされたオブジェクトの使用するディスク量"
+#: lib/tools.tcl:116
+#, tcl-format
+msgid "Tool: %s"
+msgstr "ツール: %s"
 
-#: lib/database.tcl:48
-msgid "Packed objects waiting for pruning"
-msgstr "パックに存在するので捨てて良いオブジェクトの数"
+#: lib/tools.tcl:117
+#, tcl-format
+msgid "Running: %s"
+msgstr "実行中: %s"
 
-#: lib/database.tcl:49
-msgid "Garbage files"
-msgstr "ゴミファイル"
+#: lib/tools.tcl:155
+#, tcl-format
+msgid "Tool completed successfully: %s"
+msgstr "ツールが完了しました: %s"
 
-#: lib/database.tcl:72
-msgid "Compressing the object database"
-msgstr "データベース圧縮"
+#: lib/tools.tcl:157
+#, tcl-format
+msgid "Tool failed: %s"
+msgstr "ツールが失敗しました: %s"
 
-#: lib/database.tcl:83
-msgid "Verifying the object database with fsck-objects"
-msgstr "fsck-objects でオブジェクト・データベースを検証しています"
+#: lib/mergetool.tcl:8
+msgid "Force resolution to the base version?"
+msgstr "共通の版を使いますか?"
 
-#: lib/database.tcl:107
-#, 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.\n"
-"\n"
-"Compress the database now?"
-msgstr ""
-"このリポジトリにはおおよそ %i 個の個別オブジェクトがあります\n"
-"\n"
-"最適な性能を保つために、データベースを圧縮することを推奨します\n"
-"\n"
-"データベースを圧縮しますか?"
+#: lib/mergetool.tcl:9
+msgid "Force resolution to this branch?"
+msgstr "自分の側の版を使いますか?"
 
-#: lib/date.tcl:25
-#, tcl-format
-msgid "Invalid date from Git: %s"
-msgstr "Git から出た無効な日付: %s"
+#: lib/mergetool.tcl:10
+msgid "Force resolution to the other branch?"
+msgstr "相手制の版を使いますか?"
 
-#: lib/diff.tcl:64
+#: lib/mergetool.tcl:14
 #, tcl-format
 msgid ""
-"No differences detected.\n"
-"\n"
-"%s has no changes.\n"
+"Note that the diff shows only conflicting changes.\n"
 "\n"
-"The modification date of this file was updated by another application, but "
-"the content within the file was not changed.\n"
+"%s will be overwritten.\n"
 "\n"
-"A rescan will be automatically started to find other files which may have "
-"the same state."
+"This operation can be undone only by restarting the merge."
 msgstr ""
-"変更がありません。\n"
-"\n"
-"%s には変更がありません。\n"
+"競合する変更点だけが表示されていることに注意してください。\n"
 "\n"
-"このファイルの変更時刻は他のアプリケーションによって更新されていますがファイ"
-"ル内容には変更がありません。\n"
+"%s は上書きされます。\n"
 "\n"
-"同様な状態のファイルを探すために、自動的に再スキャンを開始します。"
+"やり直すにはマージ全体をやり直してください。"
 
-#: lib/diff.tcl:104
+#: lib/mergetool.tcl:45
 #, tcl-format
-msgid "Loading diff of %s..."
-msgstr "%s の変更点をロード中…"
-
-#: lib/diff.tcl:125
-msgid ""
-"LOCAL: deleted\n"
-"REMOTE:\n"
+msgid "File %s seems to have unresolved conflicts, still stage?"
 msgstr ""
-"LOCAL: 削除\n"
-"Remote:\n"
+"ファイル %s には解決していない競合部分がまだあるようですが、いいですか?"
 
-#: lib/diff.tcl:130
-msgid ""
-"REMOTE: deleted\n"
-"LOCAL:\n"
-msgstr ""
-"REMOTE: 削除\n"
-"LOCAL:\n"
+#: lib/mergetool.tcl:60
+#, tcl-format
+msgid "Adding resolution for %s"
+msgstr "%s への解決をステージします"
 
-#: lib/diff.tcl:137
-msgid "LOCAL:\n"
-msgstr "LOCAL:\n"
+#: lib/mergetool.tcl:141
+msgid "Cannot resolve deletion or link conflicts using a tool"
+msgstr "ツールでは削除やリンク競合は扱えません"
 
-#: lib/diff.tcl:140
-msgid "REMOTE:\n"
-msgstr "REMOTE\n"
+#: lib/mergetool.tcl:146
+msgid "Conflict file does not exist"
+msgstr "競合ファイルは存在しません。"
 
-#: lib/diff.tcl:202 lib/diff.tcl:319
+#: lib/mergetool.tcl:246
 #, tcl-format
-msgid "Unable to display %s"
-msgstr "%s を表示できません"
-
-#: lib/diff.tcl:203
-msgid "Error loading file:"
-msgstr "ファイルを読む際のエラーです:"
+msgid "Not a GUI merge tool: '%s'"
+msgstr "GUI マージツールではありません: %s"
 
-#: lib/diff.tcl:210
-msgid "Git Repository (subproject)"
-msgstr "Git リポジトリ(サブプロジェクト)"
+#: lib/mergetool.tcl:275
+#, tcl-format
+msgid "Unsupported merge tool '%s'"
+msgstr "マージツール '%s' はサポートしていません"
 
-#: lib/diff.tcl:222
-msgid "* Binary file (not showing content)."
-msgstr "* バイナリファイル(内容は表示しません)"
+#: lib/mergetool.tcl:310
+msgid "Merge tool is already running, terminate it?"
+msgstr "マージツールはすでに起動しています。終了しますか?"
 
-#: lib/diff.tcl:227
+#: lib/mergetool.tcl:330
 #, tcl-format
 msgid ""
-"* Untracked file is %d bytes.\n"
-"* Showing only first %d bytes.\n"
+"Error retrieving versions:\n"
+"%s"
 msgstr ""
-"* 管理外のファイルの大きさは %d バイトです。\n"
-"* 最初の %d バイトだけ表示しています。\n"
+"版の取り出し時にエラーが出ました:\n"
+"%s"
 
-#: lib/diff.tcl:233
+#: lib/mergetool.tcl:350
 #, tcl-format
 msgid ""
+"Could not start the merge tool:\n"
 "\n"
-"* Untracked file clipped here by %s.\n"
-"* To see the entire file, use an external editor.\n"
+"%s"
 msgstr ""
+"マージツールが起動できません:\n"
 "\n"
-"\n"
-"* %s は管理外のファイルをここで切りおとしました。\n"
-"* 全体を見るには外部エディタを使ってください。\n"
-
-#: lib/diff.tcl:482
-msgid "Failed to unstage selected hunk."
-msgstr "選択されたパッチをコミット予定から外せません。"
+"%s"
 
-#: lib/diff.tcl:489
-msgid "Failed to stage selected hunk."
-msgstr "選択されたパッチをコミット予定に加えられません。"
+#: lib/mergetool.tcl:354
+msgid "Running merge tool..."
+msgstr "マージツールを実行しています..."
 
-#: lib/diff.tcl:568
-msgid "Failed to unstage selected line."
-msgstr "選択されたパッチ行をコミット予定から外せません。"
+#: lib/mergetool.tcl:382 lib/mergetool.tcl:390
+msgid "Merge tool failed."
+msgstr "マージツールが失敗しました。"
 
-#: lib/diff.tcl:576
-msgid "Failed to stage selected line."
-msgstr "選択されたパッチ行をコミット予定に加えられません。"
+#: lib/option.tcl:11
+#, tcl-format
+msgid "Invalid global encoding '%s'"
+msgstr "全体エンコーディングに 無効な %s が指定されています"
 
-#: lib/encoding.tcl:443
-msgid "Default"
-msgstr "デフォールト"
+#: lib/option.tcl:19
+#, tcl-format
+msgid "Invalid repo encoding '%s'"
+msgstr "リポジトリエンコーディングに 無効な %s が指定されています"
 
-#: lib/encoding.tcl:448
+#: lib/option.tcl:119
+msgid "Restore Defaults"
+msgstr "既定値に戻す"
+
+#: lib/option.tcl:123
+msgid "Save"
+msgstr "保存"
+
+#: lib/option.tcl:133
 #, tcl-format
-msgid "System (%s)"
-msgstr "システム (%s)"
+msgid "%s Repository"
+msgstr "%s リポジトリ"
 
-#: lib/encoding.tcl:459 lib/encoding.tcl:465
-msgid "Other"
-msgstr "その他"
+#: lib/option.tcl:134
+msgid "Global (All Repositories)"
+msgstr "大域(全てのリポジトリ)"
 
-#: lib/error.tcl:20 lib/error.tcl:114
-msgid "error"
-msgstr "ã\82¨ã\83©ã\83¼"
+#: lib/option.tcl:140
+msgid "User Name"
+msgstr "ã\83¦ã\83¼ã\82¶å\90\8d"
 
-#: lib/error.tcl:36
-msgid "warning"
-msgstr "警告"
+#: lib/option.tcl:141
+msgid "Email Address"
+msgstr "電子メールアドレス"
 
-#: lib/error.tcl:94
-msgid "You must correct the above errors before committing."
-msgstr "ã\82³ã\83\9fã\83\83ã\83\88ã\81\99ã\82\8bå\89\8dã\81«ã\80\81以ä¸\8aã\81®ã\82¨ã\83©ã\83¼ã\82\92修正ã\81\97ã\81¦ä¸\8bã\81\95ã\81\84"
+#: lib/option.tcl:143
+msgid "Summarize Merge Commits"
+msgstr "ã\83\9eã\83¼ã\82¸ã\82³ã\83\9fã\83\83ã\83\88ã\81®è¦\81ç´\84"
 
-#: lib/index.tcl:6
-msgid "Unable to unlock the index."
-msgstr "ã\82¤ã\83³ã\83\87ã\83\83ã\82¯ã\82¹ã\82\92ã\83­ã\83\83ã\82¯ã\81§ã\81\8dã\81¾ã\81\9bã\82\93"
+#: lib/option.tcl:144
+msgid "Merge Verbosity"
+msgstr "ã\83\9eã\83¼ã\82¸ã\81®å\86\97é\95·åº¦"
 
-#: lib/index.tcl:15
-msgid "Index Error"
-msgstr "索引エラー"
+#: lib/option.tcl:145
+msgid "Show Diffstat After Merge"
+msgstr "マージ後に diffstat を表示"
 
-#: lib/index.tcl:17
-msgid ""
-"Updating the Git index failed.  A rescan will be automatically started to "
-"resynchronize git-gui."
-msgstr ""
-"GIT インデックスの更新が失敗しました。git-gui と同期をとるために再スキャンし"
-"ます。"
+#: lib/option.tcl:146
+msgid "Use Merge Tool"
+msgstr "マージツールを使用"
 
-#: lib/index.tcl:28
-msgid "Continue"
-msgstr "続行"
+#: lib/option.tcl:148
+msgid "Trust File Modification Timestamps"
+msgstr "ファイル変更時刻を信頼する"
 
-#: lib/index.tcl:31
-msgid "Unlock Index"
-msgstr "ã\82¤ã\83³ã\83\87ã\83\83ã\82¯ã\82¹ã\81®ã\83­ã\83\83ã\82¯è§£é\99¤"
+#: lib/option.tcl:149
+msgid "Prune Tracking Branches During Fetch"
+msgstr "ã\83\95ã\82§ã\83\83ã\83\81中ã\81«ã\83\88ã\83©ã\83\83ã\82­ã\83³ã\82°ã\83\96ã\83©ã\83³ã\83\81ã\82\92å\88\88ã\82\8b"
 
-#: lib/index.tcl:289
-#, tcl-format
-msgid "Unstaging %s from commit"
-msgstr "コミットから '%s' を降ろす"
+#: lib/option.tcl:150
+msgid "Match Tracking Branches"
+msgstr "トラッキングブランチを合わせる"
 
-#: lib/index.tcl:328
-msgid "Ready to commit."
-msgstr "ã\82³ã\83\9fã\83\83ã\83\88æº\96å\82\99å®\8cäº\86"
+#: lib/option.tcl:151
+msgid "Use Textconv For Diffs and Blames"
+msgstr "diff ã\81¨æ³¨é\87\88ã\81« textconv ã\82\92使ã\81\86"
 
-#: lib/index.tcl:341
-#, tcl-format
-msgid "Adding %s"
-msgstr "コミットに %s を加えています"
+#: lib/option.tcl:152
+msgid "Blame Copy Only On Changed Files"
+msgstr "変更されたファイルのみコピー検知を行なう"
 
-#: lib/index.tcl:398
-#, tcl-format
-msgid "Revert changes in file %s?"
-msgstr "ファイル %s にした変更を元に戻しますか?"
+#: lib/option.tcl:153
+msgid "Maximum Length of Recent Repositories List"
+msgstr "最近使ったリポジトリ一覧の上限"
 
-#: lib/index.tcl:400
-#, tcl-format
-msgid "Revert changes in these %i files?"
-msgstr "これら %i 個のファイルにした変更を元に戻しますか?"
+#: lib/option.tcl:154
+msgid "Minimum Letters To Blame Copy On"
+msgstr "コピーを検知する最少文字数"
 
-#: lib/index.tcl:408
-msgid "Any unstaged changes will be permanently lost by the revert."
-msgstr "変更を元に戻すとコミット予定していない変更は全て失われます。"
+#: lib/option.tcl:155
+msgid "Blame History Context Radius (days)"
+msgstr "注釈する履歴半径(日数)"
 
-#: lib/index.tcl:411
-msgid "Do Nothing"
-msgstr "何もしない"
+#: lib/option.tcl:156
+msgid "Number of Diff Context Lines"
+msgstr "diff の文脈行数"
 
-#: lib/index.tcl:429
-msgid "Reverting selected files"
-msgstr "選択されたファイルにした変更を元に戻します"
+#: lib/option.tcl:157
+msgid "Additional Diff Parameters"
+msgstr "diff の追加引数"
 
-#: lib/index.tcl:433
-#, tcl-format
-msgid "Reverting %s"
-msgstr "%s にした変更を元に戻します"
+#: lib/option.tcl:158
+msgid "Commit Message Text Width"
+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/option.tcl:159
+msgid "New Branch Name Template"
+msgstr "新しいブランチ名のテンプレート"
 
-#: 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/option.tcl:160
+msgid "Default File Contents Encoding"
+msgstr "ファイル内容のデフォールトエンコーディング"
 
-#: lib/merge.tcl:45
-#, 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/option.tcl:161
+msgid "Warn before committing to a detached head"
+msgstr "分離 HEAD のコミット前に警告する"
 
-#: lib/merge.tcl:55
-#, 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/option.tcl:162
+msgid "Staging of untracked files"
+msgstr "管理外のファイルをコミット予定する"
 
-#: lib/merge.tcl:107
-#, tcl-format
-msgid "%s of %s"
-msgstr "%s の %s ブランチ"
+#: lib/option.tcl:163
+msgid "Show untracked files"
+msgstr "管理外のファイルを表示する"
 
-#: lib/merge.tcl:120
-#, tcl-format
-msgid "Merging %s and %s..."
-msgstr "%s と %s をマージ中・・・"
+#: lib/option.tcl:164
+msgid "Tab spacing"
+msgstr "タブ幅"
 
-#: lib/merge.tcl:131
-msgid "Merge completed successfully."
-msgstr "マージが完了しました"
+#: lib/option.tcl:210
+msgid "Change"
+msgstr "変更"
 
-#: lib/merge.tcl:133
-msgid "Merge failed.  Conflict resolution is required."
-msgstr "マージが失敗しました。衝突の解決が必要です。"
+#: lib/option.tcl:254
+msgid "Spelling Dictionary:"
+msgstr "スペルチェック辞書"
+
+#: lib/option.tcl:284
+msgid "Change Font"
+msgstr "フォントを変更"
 
-#: lib/merge.tcl:158
+#: lib/option.tcl:288
 #, tcl-format
-msgid "Merge Into %s"
-msgstr "%s ã\81«ã\83\9eã\83¼ã\82¸"
+msgid "Choose %s"
+msgstr "%s ã\82\92é\81¸æ\8a\9e"
 
-#: lib/merge.tcl:177
-msgid "Revision To Merge"
-msgstr "ã\83\9eã\83¼ã\82¸ã\81\99ã\82\8bã\83ªã\83\93ã\82¸ã\83§ã\83³"
+#: lib/option.tcl:294
+msgid "pt."
+msgstr "ã\83\9dã\82¤ã\83³ã\83\88"
 
-#: lib/merge.tcl:212
-msgid ""
-"Cannot abort while amending.\n"
-"\n"
-"You must finish amending this commit.\n"
-msgstr ""
-"訂正中には中止できません。\n"
-"\n"
-"まず今のコミット訂正を完了させて下さい。\n"
+#: lib/option.tcl:308
+msgid "Preferences"
+msgstr "設定"
 
-#: lib/merge.tcl:222
-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/option.tcl:310 lib/branch_checkout.tcl:39 lib/branch_create.tcl:69
+msgid "Options"
+msgstr "オプション"
 
-#: lib/merge.tcl:228
-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/option.tcl:345
+msgid "Failed to completely save options:"
+msgstr "完全にオプションを保存できません:"
 
-#: lib/merge.tcl:239
-msgid "Aborting"
-msgstr "中断しています"
+#: lib/database.tcl:42
+msgid "Number of loose objects"
+msgstr "ばらばらなオブジェクトの数"
 
-#: lib/merge.tcl:239
-msgid "files reset"
-msgstr "ã\83ªã\82»ã\83\83ã\83\88ã\81\97ã\81\9fã\83\95ã\82¡ã\82¤ã\83«"
+#: lib/database.tcl:43
+msgid "Disk space used by loose objects"
+msgstr "ã\81°ã\82\89ã\81°ã\82\89ã\81ªã\82ªã\83\96ã\82¸ã\82§ã\82¯ã\83\88ã\81®ä½¿ç\94¨ã\81\99ã\82\8bã\83\87ã\82£ã\82¹ã\82¯é\87\8f"
 
-#: lib/merge.tcl:267
-msgid "Abort failed."
-msgstr "中断に失敗しました。"
+#: lib/database.tcl:44
+msgid "Number of packed objects"
+msgstr "パックされたオブジェクトの数"
 
-#: lib/merge.tcl:269
-msgid "Abort completed.  Ready."
-msgstr "中断完了。"
+#: lib/database.tcl:45
+msgid "Number of packs"
+msgstr "パックの数"
 
-#: lib/mergetool.tcl:8
-msgid "Force resolution to the base version?"
-msgstr "共通の版を使いますか?"
+#: lib/database.tcl:46
+msgid "Disk space used by packed objects"
+msgstr "パックされたオブジェクトの使用するディスク量"
 
-#: lib/mergetool.tcl:9
-msgid "Force resolution to this branch?"
-msgstr "自分の側の版を使いますか?"
+#: lib/database.tcl:47
+msgid "Packed objects waiting for pruning"
+msgstr "パックに存在するので捨てて良いオブジェクトの数"
 
-#: lib/mergetool.tcl:10
-msgid "Force resolution to the other branch?"
-msgstr "相手制の版を使いますか?"
+#: lib/database.tcl:48
+msgid "Garbage files"
+msgstr "ゴミファイル"
 
-#: lib/mergetool.tcl:14
+#: lib/database.tcl:72
+msgid "Compressing the object database"
+msgstr "データベース圧縮"
+
+#: lib/database.tcl:83
+msgid "Verifying the object database with fsck-objects"
+msgstr "fsck-objects でオブジェクト・データベースを検証しています"
+
+#: lib/database.tcl:107
 #, tcl-format
 msgid ""
-"Note that the diff shows only conflicting changes.\n"
+"This repository currently has approximately %i loose objects.\n"
 "\n"
-"%s will be overwritten.\n"
+"To maintain optimal performance it is strongly recommended that you compress "
+"the database.\n"
 "\n"
-"This operation can be undone only by restarting the merge."
+"Compress the database now?"
 msgstr ""
-"競合する変更点だけが表示されていることに注意してください。\n"
+"このリポジトリにはおおよそ %i 個の個別オブジェクトがあります\n"
 "\n"
-"%s は上書きされます。\n"
+"最適な性能を保つために、データベースを圧縮することを推奨します\n"
 "\n"
-"やり直すにはマージ全体をやり直してください。"
-
-#: lib/mergetool.tcl:45
-#, tcl-format
-msgid "File %s seems to have unresolved conflicts, still stage?"
-msgstr ""
-"ファイル %s には解決していない競合部分がまだあるようですが、いいですか?"
+"データベースを圧縮しますか?"
 
-#: lib/mergetool.tcl:60
+#: lib/transport.tcl:6 lib/remote_add.tcl:132
 #, tcl-format
-msgid "Adding resolution for %s"
-msgstr "%s への解決をステージします"
-
-#: lib/mergetool.tcl:141
-msgid "Cannot resolve deletion or link conflicts using a tool"
-msgstr "ツールでは削除やリンク競合は扱えません"
-
-#: lib/mergetool.tcl:146
-msgid "Conflict file does not exist"
-msgstr "競合ファイルは存在しません。"
+msgid "fetch %s"
+msgstr "%s を取得"
 
-#: lib/mergetool.tcl:264
+#: lib/transport.tcl:7
 #, tcl-format
-msgid "Not a GUI merge tool: '%s'"
-msgstr "GUI マージツールではありません: %s"
+msgid "Fetching new changes from %s"
+msgstr "%s から新しい変更をフェッチしています"
 
-#: lib/mergetool.tcl:268
+#: lib/transport.tcl:18
 #, tcl-format
-msgid "Unsupported merge tool '%s'"
-msgstr "マージツール '%s' はサポートしていません"
-
-#: lib/mergetool.tcl:303
-msgid "Merge tool is already running, terminate it?"
-msgstr "マージツールはすでに起動しています。終了しますか?"
+msgid "remote prune %s"
+msgstr "リモート刈込 %s"
 
-#: lib/mergetool.tcl:323
+#: lib/transport.tcl:19
 #, tcl-format
-msgid ""
-"Error retrieving versions:\n"
-"%s"
-msgstr ""
-"版の取り出し時にエラーが出ました:\n"
-"%s"
+msgid "Pruning tracking branches deleted from %s"
+msgstr "%s から削除されたトラッキング・ブランチを刈っています"
 
-#: lib/mergetool.tcl:343
-#, tcl-format
-msgid ""
-"Could not start the merge tool:\n"
-"\n"
-"%s"
-msgstr ""
-"マージツールが起動できません:\n"
-"\n"
-"%s"
+#: lib/transport.tcl:25
+msgid "fetch all remotes"
+msgstr "すべてのリモートを取得"
 
-#: lib/mergetool.tcl:347
-msgid "Running merge tool..."
-msgstr "ã\83\9eã\83¼ã\82¸ã\83\84ã\83¼ã\83«ã\82\92å®\9fè¡\8cã\81\97ã\81¦ã\81\84ã\81¾ã\81\99..."
+#: lib/transport.tcl:26
+msgid "Fetching new changes from all remotes"
+msgstr "ã\81\99ã\81¹ã\81¦ã\81®ã\83ªã\83¢ã\83¼ã\83\88ã\81\8bã\82\89æ\96°ã\81\97ã\81\84å¤\89æ\9b´ã\82\92ã\83\95ã\82§ã\83\83ã\83\81ã\81\97ã\81¦ã\81\84ã\81¾ã\81\99"
 
-#: lib/mergetool.tcl:375 lib/mergetool.tcl:383
-msgid "Merge tool failed."
-msgstr "ã\83\9eã\83¼ã\82¸ã\83\84ã\83¼ã\83«ã\81\8c失æ\95\97ã\81\97ã\81¾ã\81\97ã\81\9fã\80\82"
+#: lib/transport.tcl:40
+msgid "remote prune all remotes"
+msgstr "ã\83ªã\83¢ã\83¼ã\83\88å\88\88è¾¼ ã\81\99ã\81¹ã\81¦ã\81®ã\83ªã\83¢ã\83¼ã\83\88"
 
-#: lib/option.tcl:11
-#, tcl-format
-msgid "Invalid global encoding '%s'"
-msgstr "全体エンコーディングに 無効な %s が指定されています"
+#: lib/transport.tcl:41
+msgid "Pruning tracking branches deleted from all remotes"
+msgstr "すべてのリモートから削除されたトラッキング・ブランチを刈っています"
 
-#: lib/option.tcl:19
+#: lib/transport.tcl:54 lib/transport.tcl:92 lib/transport.tcl:110
+#: lib/remote_add.tcl:162
 #, tcl-format
-msgid "Invalid repo encoding '%s'"
-msgstr "リポジトリエンコーディングに 無効な %s が指定されています"
+msgid "push %s"
+msgstr "%s をプッシュ"
 
-#: lib/option.tcl:117
-msgid "Restore Defaults"
-msgstr "既定値に戻す"
+#: lib/transport.tcl:55
+#, tcl-format
+msgid "Pushing changes to %s"
+msgstr "%s へ変更をプッシュしています"
 
-#: lib/option.tcl:121
-msgid "Save"
-msgstr "保存"
+#: lib/transport.tcl:93
+#, tcl-format
+msgid "Mirroring to %s"
+msgstr "%s へミラーしています"
 
-#: lib/option.tcl:131
+#: lib/transport.tcl:111
 #, tcl-format
-msgid "%s Repository"
-msgstr "%s リポジトリ"
+msgid "Pushing %s %s to %s"
+msgstr "%3$s へ %1$s %2$s をプッシュしています"
 
-#: lib/option.tcl:132
-msgid "Global (All Repositories)"
-msgstr "大域(全てのリポジトリ)"
+#: lib/transport.tcl:132
+msgid "Push Branches"
+msgstr "ブランチをプッシュ"
 
-#: lib/option.tcl:138
-msgid "User Name"
-msgstr "ユーザ名"
+#: lib/transport.tcl:147
+msgid "Source Branches"
+msgstr "元のブランチ"
 
-#: lib/option.tcl:139
-msgid "Email Address"
-msgstr "é\9b»å­\90ã\83¡ã\83¼ã\83«ã\82¢ã\83\89ã\83¬ã\82¹"
+#: lib/transport.tcl:162
+msgid "Destination Repository"
+msgstr "é\80\81ã\82\8aå\85\88ã\83ªã\83\9dã\82¸ã\83\88ã\83ª"
 
-#: lib/option.tcl:141
-msgid "Summarize Merge Commits"
-msgstr "マージコミットの要約"
+#: lib/transport.tcl:205
+msgid "Transfer Options"
+msgstr "通信オプション"
 
-#: lib/option.tcl:142
-msgid "Merge Verbosity"
-msgstr "マージの冗長度"
+#: lib/transport.tcl:207
+msgid "Force overwrite existing branch (may discard changes)"
+msgstr "既存ブランチを上書き(変更を破棄する可能性があります)"
 
-#: lib/option.tcl:143
-msgid "Show Diffstat After Merge"
-msgstr "マージ後に diffstat を表示"
+#: lib/transport.tcl:211
+msgid "Use thin pack (for slow network connections)"
+msgstr "Thin Pack を使う(遅いネットワーク接続)"
 
-#: lib/option.tcl:144
-msgid "Use Merge Tool"
-msgstr "ã\83\9eã\83¼ã\82¸ã\83\84ã\83¼ã\83«ã\82\92使ç\94¨"
+#: lib/transport.tcl:215
+msgid "Include tags"
+msgstr "ã\82¿ã\82°ã\82\92å\90«ã\82\81ã\82\8b"
 
-#: lib/option.tcl:146
-msgid "Trust File Modification Timestamps"
-msgstr "ファイル変更時刻を信頼する"
+#: lib/choose_font.tcl:41
+msgid "Select"
+msgstr "選択"
 
-#: lib/option.tcl:147
-msgid "Prune Tracking Branches During Fetch"
-msgstr "ã\83\95ã\82§ã\83\83ã\83\81中ã\81«ã\83\88ã\83©ã\83\83ã\82­ã\83³ã\82°ã\83\96ã\83©ã\83³ã\83\81ã\82\92å\88\88ã\82\8b"
+#: lib/choose_font.tcl:55
+msgid "Font Family"
+msgstr "ã\83\95ã\82©ã\83³ã\83\88ã\83»ã\83\95ã\82¡ã\83\9fã\83ªã\83¼"
 
-#: lib/option.tcl:148
-msgid "Match Tracking Branches"
-msgstr "ã\83\88ã\83©ã\83\83ã\82­ã\83³ã\82°ã\83\96ã\83©ã\83³ã\83\81ã\82\92å\90\88ã\82\8fã\81\9bã\82\8b"
+#: lib/choose_font.tcl:76
+msgid "Font Size"
+msgstr "ã\83\95ã\82©ã\83³ã\83\88ã\81®å¤§ã\81\8dã\81\95"
 
-#: lib/option.tcl:149
-msgid "Blame Copy Only On Changed Files"
-msgstr "変更されたファイルのみコピー検知を行なう"
+#: lib/choose_font.tcl:93
+msgid "Font Example"
+msgstr "フォント・サンプル"
 
-#: lib/option.tcl:150
-msgid "Minimum Letters To Blame Copy On"
-msgstr "コピーを検知する最少文字数"
+#: lib/choose_font.tcl:105
+msgid ""
+"This is example text.\n"
+"If you like this text, it can be your font."
+msgstr ""
+"これはサンプル文です。\n"
+"このフォントが気に入ればお使いになれます。"
 
-#: lib/option.tcl:151
-msgid "Blame History Context Radius (days)"
-msgstr "註釈する履歴半径(日数)"
+#: lib/remote.tcl:200
+msgid "Push to"
+msgstr "プッシュ先"
 
-#: lib/option.tcl:152
-msgid "Number of Diff Context Lines"
-msgstr "diff の文脈行数"
+#: lib/remote.tcl:218
+msgid "Remove Remote"
+msgstr "リモートを削除"
 
-#: lib/option.tcl:153
-msgid "Commit Message Text Width"
-msgstr "ã\82³ã\83\9fã\83\83ã\83\88ã\83¡ã\83\83ã\82»ã\83¼ã\82¸ã\81®ã\83\86ã\82­ã\82¹ã\83\88å¹\85"
+#: lib/remote.tcl:223
+msgid "Prune from"
+msgstr "ã\81\8bã\82\89å\88\88è¾¼ã\82\80â\80¦"
 
-#: lib/option.tcl:154
-msgid "New Branch Name Template"
-msgstr "新しいブランチ名のテンプレート"
+#: lib/remote.tcl:228
+msgid "Fetch from"
+msgstr "取得元"
 
-#: lib/option.tcl:155
-msgid "Default File Contents Encoding"
-msgstr "ファイル内容のデフォールトエンコーディング"
+#: lib/diff.tcl:77
+#, 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"
+"\n"
+"同様な状態のファイルを探すために、自動的に再スキャンを開始します。"
 
-#: lib/option.tcl:203
-msgid "Change"
-msgstr "変更"
+#: lib/diff.tcl:117
+#, tcl-format
+msgid "Loading diff of %s..."
+msgstr "%s の変更点をロード中…"
 
-#: lib/option.tcl:230
-msgid "Spelling Dictionary:"
-msgstr "スペルチェック辞書"
+#: lib/diff.tcl:140
+msgid ""
+"LOCAL: deleted\n"
+"REMOTE:\n"
+msgstr ""
+"LOCAL: 削除\n"
+"Remote:\n"
 
-#: lib/option.tcl:254
-msgid "Change Font"
-msgstr "フォントを変更"
+#: lib/diff.tcl:145
+msgid ""
+"REMOTE: deleted\n"
+"LOCAL:\n"
+msgstr ""
+"REMOTE: 削除\n"
+"LOCAL:\n"
+
+#: lib/diff.tcl:152
+msgid "LOCAL:\n"
+msgstr "LOCAL:\n"
 
-#: lib/option.tcl:258
+#: lib/diff.tcl:155
+msgid "REMOTE:\n"
+msgstr "REMOTE\n"
+
+#: lib/diff.tcl:217 lib/diff.tcl:355
 #, tcl-format
-msgid "Choose %s"
-msgstr "%s を選択"
+msgid "Unable to display %s"
+msgstr "%s を表示できません"
 
-#: lib/option.tcl:264
-msgid "pt."
-msgstr "ã\83\9dã\82¤ã\83³ã\83\88"
+#: lib/diff.tcl:218
+msgid "Error loading file:"
+msgstr "ã\83\95ã\82¡ã\82¤ã\83«ã\82\92読ã\82\80é\9a\9bã\81®ã\82¨ã\83©ã\83¼ã\81§ã\81\99:"
 
-#: lib/option.tcl:278
-msgid "Preferences"
-msgstr "設定"
+#: lib/diff.tcl:225
+msgid "Git Repository (subproject)"
+msgstr "Git リポジトリ(サブプロジェクト)"
 
-#: lib/option.tcl:314
-msgid "Failed to completely save options:"
-msgstr "完全にオプションを保存できません:"
+#: lib/diff.tcl:237
+msgid "* Binary file (not showing content)."
+msgstr "* バイナリファイル(内容は表示しません)"
 
-#: lib/remote.tcl:163
-msgid "Remove Remote"
-msgstr "リモートを削除"
+#: lib/diff.tcl:242
+#, tcl-format
+msgid ""
+"* Untracked file is %d bytes.\n"
+"* Showing only first %d bytes.\n"
+msgstr ""
+"* 管理外のファイルの大きさは %d バイトです。\n"
+"* 最初の %d バイトだけ表示しています。\n"
 
-#: lib/remote.tcl:168
-msgid "Prune from"
-msgstr "から刈込む…"
+#: lib/diff.tcl:248
+#, tcl-format
+msgid ""
+"\n"
+"* Untracked file clipped here by %s.\n"
+"* To see the entire file, use an external editor.\n"
+msgstr ""
+"\n"
+"\n"
+"* %s は管理外のファイルをここで切りおとしました。\n"
+"* 全体を見るには外部エディタを使ってください。\n"
 
-#: lib/remote.tcl:173
-msgid "Fetch from"
-msgstr "取得元"
+#: lib/diff.tcl:578
+msgid "Failed to unstage selected hunk."
+msgstr "選択されたパッチをコミット予定から外せません。"
 
-#: lib/remote.tcl:215
-msgid "Push to"
-msgstr "プッシュ先"
+#: lib/diff.tcl:585
+msgid "Failed to stage selected hunk."
+msgstr "選択されたパッチをコミット予定に加えられません。"
 
-#: lib/remote_add.tcl:19
-msgid "Add Remote"
-msgstr "リモートを追加"
+#: lib/diff.tcl:664
+msgid "Failed to unstage selected line."
+msgstr "選択されたパッチ行をコミット予定から外せません。"
 
-#: lib/remote_add.tcl:24
-msgid "Add New Remote"
-msgstr "リモートを新規に追加"
+#: lib/diff.tcl:672
+msgid "Failed to stage selected line."
+msgstr "選択されたパッチ行をコミット予定に加えられません。"
 
-#: lib/remote_add.tcl:28 lib/tools_dlg.tcl:36
-msgid "Add"
-msgstr "追加"
+#: lib/branch_checkout.tcl:16 lib/branch_checkout.tcl:21
+msgid "Checkout Branch"
+msgstr "ブランチをチェックアウト"
 
-#: lib/remote_add.tcl:37
-msgid "Remote Details"
-msgstr "ã\83ªã\83¢ã\83¼ã\83\88ã\81®è©³ç´°"
+#: lib/branch_checkout.tcl:26
+msgid "Checkout"
+msgstr "ã\83\81ã\82§ã\83\83ã\82¯ã\82¢ã\82¦ã\83\88"
 
-#: lib/remote_add.tcl:50
-msgid "Location:"
-msgstr "場所:"
+#: lib/branch_checkout.tcl:42 lib/branch_create.tcl:92
+msgid "Fetch Tracking Branch"
+msgstr "トラッキング・ブランチをフェッチ"
 
-#: lib/remote_add.tcl:62
-msgid "Further Action"
-msgstr "ã\81\9dã\81®ä»\96ã\81®å\8b\95ä½\9c"
+#: lib/branch_checkout.tcl:47
+msgid "Detach From Local Branch"
+msgstr "ã\83­ã\83¼ã\82«ã\83«ã\83»ã\83\96ã\83©ã\83³ã\83\81ã\81\8bã\82\89å\89\8aé\99¤"
 
-#: lib/remote_add.tcl:65
-msgid "Fetch Immediately"
-msgstr "即座に取得"
+#: lib/index.tcl:6
+msgid "Unable to unlock the index."
+msgstr "インデックスをロックできません"
 
-#: lib/remote_add.tcl:71
-msgid "Initialize Remote Repository and Push"
-msgstr "リモートレポジトリを初期化してプッシュ"
+#: lib/index.tcl:17
+msgid "Index Error"
+msgstr "索引エラー"
 
-#: lib/remote_add.tcl:77
-msgid "Do Nothing Else Now"
-msgstr "何もしない"
+#: lib/index.tcl:19
+msgid ""
+"Updating the Git index failed.  A rescan will be automatically started to "
+"resynchronize git-gui."
+msgstr ""
+"GIT インデックスの更新が失敗しました。git-gui と同期をとるために再スキャンし"
+"ます。"
+
+#: lib/index.tcl:30
+msgid "Continue"
+msgstr "続行"
 
-#: lib/remote_add.tcl:101
-msgid "Please supply a remote name."
-msgstr "ã\83ªã\83¢ã\83¼ã\83\88å\90\8dã\82\92æ\8c\87å®\9aã\81\97ã\81¦ä¸\8bã\81\95ã\81\84ã\80\82"
+#: lib/index.tcl:33
+msgid "Unlock Index"
+msgstr "ã\82¤ã\83³ã\83\87ã\83\83ã\82¯ã\82¹ã\81®ã\83­ã\83\83ã\82¯è§£é\99¤"
 
-#: lib/remote_add.tcl:114
+#: lib/index.tcl:298
 #, tcl-format
-msgid "'%s' is not an acceptable remote name."
-msgstr "'%s' はリモート名に使えません。"
+msgid "Unstaging %s from commit"
+msgstr "コミットから '%s' を降ろす"
 
-#: lib/remote_add.tcl:125
-#, tcl-format
-msgid "Failed to add remote '%s' of location '%s'."
-msgstr "場所 '%2$s' のリモート '%1$s'の名前変更に失敗しました。"
+#: lib/index.tcl:337
+msgid "Ready to commit."
+msgstr "コミット準備完了"
 
-#: lib/remote_add.tcl:133 lib/transport.tcl:6
+#: lib/index.tcl:350
 #, tcl-format
-msgid "fetch %s"
-msgstr "%s を取得"
+msgid "Adding %s"
+msgstr "コミットに %s を加えています"
 
-#: lib/remote_add.tcl:134
+#: lib/index.tcl:380
 #, tcl-format
-msgid "Fetching the %s"
-msgstr "%s からフェッチしています"
+msgid "Stage %d untracked files?"
+msgstr "管理外の %d ファイルをコミット予定としますか?"
 
-#: lib/remote_add.tcl:157
+#: lib/index.tcl:428
 #, tcl-format
-msgid "Do not know how to initialize repository at location '%s'."
-msgstr "ã\83ªã\83\9dã\82¸ã\83\88ã\83ª '%s' ã\82\92å\88\9dæ\9c\9få\8c\96ã\81§ã\81\8dã\81¾ã\81\9bã\82\93ã\80\82"
+msgid "Revert changes in file %s?"
+msgstr "ã\83\95ã\82¡ã\82¤ã\83« %s ã\81«ã\81\97ã\81\9få¤\89æ\9b´ã\82\92å\85\83ã\81«æ\88»ã\81\97ã\81¾ã\81\99ã\81\8bï¼\9f"
 
-#: lib/remote_add.tcl:163 lib/transport.tcl:25 lib/transport.tcl:63
-#: lib/transport.tcl:81
+#: lib/index.tcl:430
 #, tcl-format
-msgid "push %s"
-msgstr "%s をプッシュ"
+msgid "Revert changes in these %i files?"
+msgstr "これら %i 個のファイルにした変更を元に戻しますか?"
 
-#: lib/remote_add.tcl:164
-#, tcl-format
-msgid "Setting up the %s (at %s)"
-msgstr "%2$s にある %1$s をセットアップします"
+#: lib/index.tcl:438
+msgid "Any unstaged changes will be permanently lost by the revert."
+msgstr "変更を元に戻すとコミット予定していない変更は全て失われます。"
 
-#: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34
-msgid "Delete Branch Remotely"
-msgstr "遠隔でブランチ削除"
+#: lib/index.tcl:441
+msgid "Do Nothing"
+msgstr "何もしない"
 
-#: lib/remote_branch_delete.tcl:47
-msgid "From Repository"
-msgstr "元のリポジトリ"
+#: lib/index.tcl:459
+msgid "Reverting selected files"
+msgstr "選択されたファイルにした変更を元に戻します"
 
-#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:134
-msgid "Remote:"
-msgstr "リモート:"
+#: lib/index.tcl:463
+#, tcl-format
+msgid "Reverting %s"
+msgstr "%s にした変更を元に戻します"
 
-#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:149
-msgid "Arbitrary Location:"
-msgstr "任意の位置:"
+#: lib/sshkey.tcl:31
+msgid "No keys found."
+msgstr "キーがありません。"
 
-#: lib/remote_branch_delete.tcl:84
-msgid "Branches"
-msgstr "ブランチ"
+#: lib/sshkey.tcl:34
+#, tcl-format
+msgid "Found a public key in: %s"
+msgstr "公開鍵がありました: %s"
 
-#: lib/remote_branch_delete.tcl:109
-msgid "Delete Only If"
-msgstr "条件付で削除"
+#: lib/sshkey.tcl:40
+msgid "Generate Key"
+msgstr "鍵を生成"
 
-#: lib/remote_branch_delete.tcl:111
-msgid "Merged Into:"
-msgstr "ã\83\9eã\83¼ã\82¸å\85\88:"
+#: lib/sshkey.tcl:58
+msgid "Copy To Clipboard"
+msgstr "ã\82¯ã\83ªã\83\83ã\83\97ã\83\9cã\83¼ã\83\89ã\81«ã\82³ã\83\94ã\83¼"
 
-#: lib/remote_branch_delete.tcl:152
-msgid "A branch is required for 'Merged Into'."
-msgstr "'マージ先' にはブランチが必要です。"
+#: lib/sshkey.tcl:72
+msgid "Your OpenSSH Public Key"
+msgstr "あなたの OpenSSH 公開鍵"
+
+#: lib/sshkey.tcl:80
+msgid "Generating..."
+msgstr "生成中..."
 
-#: lib/remote_branch_delete.tcl:184
+#: lib/sshkey.tcl:86
 #, tcl-format
 msgid ""
-"The following branches are not completely merged into %s:\n"
+"Could not start ssh-keygen:\n"
 "\n"
-" - %s"
+"%s"
 msgstr ""
-"以下のブランチは %s に完全にマージされていません:\n"
+"ssh-keygen を起動できません:\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 "削除するブランチを選択して下さい。"
+"%s"
 
-#: lib/remote_branch_delete.tcl:226
-#, tcl-format
-msgid "Deleting branches from %s"
-msgstr "%s からブランチを削除しています。"
+#: lib/sshkey.tcl:113
+msgid "Generation failed."
+msgstr "生成に失敗しました。"
 
-#: lib/remote_branch_delete.tcl:292
-msgid "No repository selected."
-msgstr "リポジトリが選択されていません。"
+#: lib/sshkey.tcl:120
+msgid "Generation succeeded, but no keys found."
+msgstr "生成には成功しましたが、鍵が見つかりません。"
 
-#: lib/remote_branch_delete.tcl:297
+#: lib/sshkey.tcl:123
 #, tcl-format
-msgid "Scanning %s..."
-msgstr "%s をスキャンしています…"
-
-#: lib/search.tcl:21
-msgid "Find:"
-msgstr "検索:"
-
-#: lib/search.tcl:23
-msgid "Next"
-msgstr "次"
+msgid "Your key is in: %s"
+msgstr "あなたの鍵は %s にあります"
 
-#: lib/search.tcl:24
-msgid "Prev"
-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/search.tcl:25
-msgid "Case-Sensitive"
-msgstr "大文字小文字を区別"
+#: 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/shortcut.tcl:21 lib/shortcut.tcl:62
-msgid "Cannot write shortcut:"
-msgstr "ショートカットが書けません:"
+#: lib/commit.tcl:48
+msgid "Error loading commit data for amend:"
+msgstr "訂正するコミットのデータを読めません:"
 
-#: lib/shortcut.tcl:137
-msgid "Cannot write icon:"
-msgstr "ã\82¢ã\82¤ã\82³ã\83³ã\81\8cæ\9b¸ã\81\91ません:"
+#: lib/commit.tcl:75
+msgid "Unable to obtain your identity:"
+msgstr "ã\83¦ã\83¼ã\82¶ã\81®æ­£ä½\93ã\82\92確èª\8dã\81§ã\81\8dません:"
 
-#: lib/spellcheck.tcl:57
-msgid "Unsupported spell checker"
-msgstr "サポートされていないスペルチェッカーです"
+#: lib/commit.tcl:80
+msgid "Invalid GIT_COMMITTER_IDENT:"
+msgstr "GIT_COMMITTER_IDENT が無効です:"
 
-#: lib/spellcheck.tcl:65
-msgid "Spell checking is unavailable"
-msgstr "スペルチェック機能は使えません"
+#: lib/commit.tcl:129
+#, tcl-format
+msgid "warning: Tcl does not support encoding '%s'."
+msgstr "警告: Tcl はエンコーディング '%s' をサポートしていません"
 
-#: lib/spellcheck.tcl:68
-msgid "Invalid spell checking configuration"
-msgstr "スペルチェックの設定が不正です"
+#: lib/commit.tcl:149
+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/spellcheck.tcl:70
+#: lib/commit.tcl:173
 #, tcl-format
-msgid "Reverting dictionary to %s."
-msgstr "辞書を %s に巻き戻します"
-
-#: lib/spellcheck.tcl:73
-msgid "Spell checker silently failed on startup"
-msgstr "スペルチェッカーの起動に失敗しました"
+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/spellcheck.tcl:80
-msgid "Unrecognized spell checker"
-msgstr "スペルチェッカーが判別できません"
+#: lib/commit.tcl:181
+#, 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/spellcheck.tcl:186
-msgid "No Suggestions"
-msgstr "提案なし"
+#: lib/commit.tcl:189
+msgid ""
+"No changes to commit.\n"
+"\n"
+"You must stage at least 1 file before you can commit.\n"
+msgstr ""
+"コミットする変更がありません。\n"
+"\n"
+"最低一つの変更をコミット予定に加えてからコミットして下さい。\n"
 
-#: lib/spellcheck.tcl:388
-msgid "Unexpected EOF from spell checker"
-msgstr "スペルチェッカーが予想外の EOF を返しました"
+#: lib/commit.tcl:204
+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"
+"- 第1行: 何をしたか、を1行で要約。\n"
+"- 第2行: 空白\n"
+"- 残りの行: なぜ、この変更が良い変更か、の説明。\n"
 
-#: lib/spellcheck.tcl:392
-msgid "Spell Checker Failed"
-msgstr "ã\82¹ã\83\9aã\83«ã\83\81ã\82§ã\83\83ã\82¯å¤±æ\95\97"
+#: lib/commit.tcl:235
+msgid "Calling pre-commit hook..."
+msgstr "ã\82³ã\83\9fã\83\83ã\83\88å\89\8dã\83\95ã\83\83ã\82¯ã\82\92å®\9fè¡\8c中ã\83»ã\83»ã\83»"
 
-#: lib/sshkey.tcl:31
-msgid "No keys found."
-msgstr "ã\82­ã\83¼ã\81\8cã\81\82ã\82\8aã\81¾ã\81\9bã\82\93ã\80\82"
+#: lib/commit.tcl:250
+msgid "Commit declined by pre-commit hook."
+msgstr "ã\82³ã\83\9fã\83\83ã\83\88å\89\8dã\83\95ã\83\83ã\82¯ã\81\8cã\82³ã\83\9fã\83\83ã\83\88ã\82\92æ\8b\92å\90¦ã\81\97ã\81¾ã\81\97ã\81\9f"
 
-#: lib/sshkey.tcl:34
-#, tcl-format
-msgid "Found a public key in: %s"
-msgstr "公開鍵がありました: %s"
+#: lib/commit.tcl:269
+msgid ""
+"You are about to commit on a detached head. This is a potentially dangerous "
+"thing to do because if you switch to another branch you will lose your "
+"changes and it can be difficult to retrieve them later from the reflog. You "
+"should probably cancel this commit and create a new branch to continue.\n"
+" \n"
+" Do you really want to proceed with your Commit?"
+msgstr ""
+"分離 HEAD での変更をコミットしようとしています。"
+"これは潜在的に危険な行為で、理由は別のブランチへの切り替えで"
+"変更が消失し、reflog からの事後復旧も困難となるためです。"
+"おそらくこのコミットはキャンセルし新しく作成したブランチで"
+"行うべきです。\n"
+"\n"
+" 本当にコミットを続行しますか?"
 
-#: lib/sshkey.tcl:40
-msgid "Generate Key"
-msgstr "鍵を生成"
+#: lib/commit.tcl:290
+msgid "Calling commit-msg hook..."
+msgstr "コミット・メッセージ・フックを実行中・・・"
 
-#: lib/sshkey.tcl:56
-msgid "Copy To Clipboard"
-msgstr "ã\82¯ã\83ªã\83\83ã\83\97ã\83\9cã\83¼ã\83\89ã\81«ã\82³ã\83\94ã\83¼"
+#: lib/commit.tcl:305
+msgid "Commit declined by commit-msg hook."
+msgstr "ã\82³ã\83\9fã\83\83ã\83\88ã\83»ã\83¡ã\83\83ã\82»ã\83¼ã\82¸ã\83»ã\83\95ã\83\83ã\82¯ã\81\8cã\82³ã\83\9fã\83\83ã\83\88ã\82\92æ\8b\92å\90¦ã\81\97ã\81¾ã\81\97ã\81\9f"
 
-#: lib/sshkey.tcl:70
-msgid "Your OpenSSH Public Key"
-msgstr "あなたの OpenSSH 公開鍵"
+#: lib/commit.tcl:318
+msgid "Committing changes..."
+msgstr "変更点をコミット中・・・"
 
-#: lib/sshkey.tcl:78
-msgid "Generating..."
-msgstr "生成中..."
+#: lib/commit.tcl:334
+msgid "write-tree failed:"
+msgstr "write-tree が失敗しました:"
+
+#: lib/commit.tcl:335 lib/commit.tcl:379 lib/commit.tcl:400
+msgid "Commit failed."
+msgstr "コミットに失敗しました。"
 
-#: lib/sshkey.tcl:84
+#: lib/commit.tcl:352
 #, tcl-format
+msgid "Commit %s appears to be corrupt"
+msgstr "コミット %s は壊れています"
+
+#: lib/commit.tcl:357
 msgid ""
-"Could not start ssh-keygen:\n"
+"No changes to commit.\n"
 "\n"
-"%s"
+"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 ""
-"ssh-keygen を起動できません:\n"
+"コミットする変更がありません。\n"
 "\n"
-"%s"
-
-#: lib/sshkey.tcl:111
-msgid "Generation failed."
-msgstr "生成に失敗しました。"
+"マージでなく、また、一つも変更点がありません。\n"
+"\n"
+"自動的に再スキャンを開始します。\n"
 
-#: lib/sshkey.tcl:118
-msgid "Generation succeeded, but no keys found."
-msgstr "生成には成功しましたが、鍵が見つかりません。"
+#: lib/commit.tcl:364
+msgid "No changes to commit."
+msgstr "コミットする変更がありません。"
 
-#: lib/sshkey.tcl:121
-#, tcl-format
-msgid "Your key is in: %s"
-msgstr "あなたの鍵は %s にあります"
+#: lib/commit.tcl:378
+msgid "commit-tree failed:"
+msgstr "commit-tree が失敗しました:"
 
-#: lib/status_bar.tcl:83
-#, tcl-format
-msgid "%s ... %*i of %*i %s (%3i%%)"
-msgstr "%1$s ... %4$*i %6$s 中の %2$*i (%7$3i%%)"
+#: lib/commit.tcl:399
+msgid "update-ref failed:"
+msgstr "update-ref が失敗しました:"
 
-#: lib/tools.tcl:75
+#: lib/commit.tcl:492
 #, tcl-format
-msgid "Running %s requires a selected file."
-msgstr "ã\83\95ã\82¡ã\82¤ã\83«ã\82\92é\81¸æ\8a\9eã\81\97ã\81¦ã\81\8bã\82\89 %s ã\82\92èµ·å\8b\95ã\81\97ã\81¦ã\81\8fã\81 ã\81\95ã\81\84ã\80\82"
+msgid "Created commit %s: %s"
+msgstr "ã\82³ã\83\9fã\83\83ã\83\88 %s ã\82\92ä½\9cæ\88\90ã\81\97ã\81¾ã\81\97ã\81\9f: %s"
 
-#: lib/tools.tcl:90
-#, tcl-format
-msgid "Are you sure you want to run %s?"
-msgstr "本当に %s を起動しますか?"
+#: lib/browser.tcl:17
+msgid "Starting..."
+msgstr "起動中…"
 
-#: lib/tools.tcl:110
-#, tcl-format
-msgid "Tool: %s"
-msgstr "ツール: %s"
+#: lib/browser.tcl:27
+msgid "File Browser"
+msgstr "ファイル・ブラウザ"
 
-#: lib/tools.tcl:111
+#: lib/browser.tcl:132 lib/browser.tcl:149
 #, tcl-format
-msgid "Running: %s"
-msgstr "実行中: %s"
+msgid "Loading %s..."
+msgstr "%s をロード中…"
 
-#: lib/tools.tcl:149
-#, tcl-format
-msgid "Tool completed successfully: %s"
-msgstr "ツールが完了しました: %s"
+#: lib/browser.tcl:193
+msgid "[Up To Parent]"
+msgstr "[上位フォルダへ]"
 
-#: lib/tools.tcl:151
-#, tcl-format
-msgid "Tool failed: %s"
-msgstr "ツールが失敗しました: %s"
+#: lib/browser.tcl:275 lib/browser.tcl:282
+msgid "Browse Branch Files"
+msgstr "現在のブランチのファイルを見る"
 
-#: lib/tools_dlg.tcl:22
-msgid "Add Tool"
-msgstr "ã\83\84ã\83¼ã\83«ã\81®追加"
+#: lib/remote_add.tcl:20
+msgid "Add Remote"
+msgstr "ã\83ªã\83¢ã\83¼ã\83\88ã\82\92追加"
 
-#: lib/tools_dlg.tcl:28
-msgid "Add New Tool Command"
-msgstr "新規ツールコマンドの追加"
+#: lib/remote_add.tcl:25
+msgid "Add New Remote"
+msgstr "リモートを新規に追加"
 
-#: lib/tools_dlg.tcl:33
-msgid "Add globally"
-msgstr "全体に追加"
+#: lib/remote_add.tcl:39
+msgid "Remote Details"
+msgstr "リモートの詳細"
 
-#: lib/tools_dlg.tcl:45
-msgid "Tool Details"
-msgstr "ツールの詳細"
+#: lib/remote_add.tcl:50
+msgid "Location:"
+msgstr "場所:"
 
-#: lib/tools_dlg.tcl:48
-msgid "Use '/' separators to create a submenu tree:"
-msgstr "'/' でサブメニューを区切ります:"
+#: lib/remote_add.tcl:60
+msgid "Further Action"
+msgstr "その他の動作"
 
-#: lib/tools_dlg.tcl:61
-msgid "Command:"
-msgstr "コマンド:"
+#: lib/remote_add.tcl:63
+msgid "Fetch Immediately"
+msgstr "即座に取得"
 
-#: lib/tools_dlg.tcl:74
-msgid "Show a dialog before running"
-msgstr "起動する前にダイアログを表示"
+#: lib/remote_add.tcl:69
+msgid "Initialize Remote Repository and Push"
+msgstr "リモートレポジトリを初期化してプッシュ"
 
-#: lib/tools_dlg.tcl:80
-msgid "Ask the user to select a revision (sets $REVISION)"
-msgstr "ユーザにコミットを一つ選ばせる ($REVISION にセットします)"
+#: lib/remote_add.tcl:75
+msgid "Do Nothing Else Now"
+msgstr "何もしない"
 
-#: lib/tools_dlg.tcl:85
-msgid "Ask the user for additional arguments (sets $ARGS)"
-msgstr "ã\83¦ã\83¼ã\82¶ã\81«ä»\96ã\81®å¼\95æ\95°ã\82\92追å\8a ã\81\95ã\81\9bã\82\8b ($ARGS ã\81«ã\82»ã\83\83ã\83\88ã\81\97ã\81¾ã\81\99)"
+#: lib/remote_add.tcl:100
+msgid "Please supply a remote name."
+msgstr "ã\83ªã\83¢ã\83¼ã\83\88å\90\8dã\82\92æ\8c\87å®\9aã\81\97ã\81¦ä¸\8bã\81\95ã\81\84ã\80\82"
 
-#: lib/tools_dlg.tcl:92
-msgid "Don't show the command output window"
-msgstr "コマンドからの出力ウィンドウを見せない"
+#: lib/remote_add.tcl:113
+#, tcl-format
+msgid "'%s' is not an acceptable remote name."
+msgstr "'%s' はリモート名に使えません。"
 
-#: lib/tools_dlg.tcl:97
-msgid "Run only if a diff is selected ($FILENAME not empty)"
-msgstr "パッチが選ばれているときだけ動かす($FILENAME が空でない)"
+#: lib/remote_add.tcl:124
+#, tcl-format
+msgid "Failed to add remote '%s' of location '%s'."
+msgstr "場所 '%2$s' のリモート '%1$s'の名前変更に失敗しました。"
 
-#: lib/tools_dlg.tcl:121
-msgid "Please supply a name for the tool."
-msgstr "ツール名を指定して下さい。"
+#: lib/remote_add.tcl:133
+#, tcl-format
+msgid "Fetching the %s"
+msgstr "%s からフェッチしています"
 
-#: lib/tools_dlg.tcl:129
+#: lib/remote_add.tcl:156
 #, tcl-format
-msgid "Tool '%s' already exists."
-msgstr "ã\83\84ã\83¼ã\83« '%s' ã\81¯æ\97¢ã\81«å­\98å\9c¨ã\81\97ã\81¾ã\81\99。"
+msgid "Do not know how to initialize repository at location '%s'."
+msgstr "ã\83ªã\83\9dã\82¸ã\83\88ã\83ª '%s' ã\82\92å\88\9dæ\9c\9få\8c\96ã\81§ã\81\8dã\81¾ã\81\9bã\82\93。"
 
-#: lib/tools_dlg.tcl:151
+#: lib/remote_add.tcl:163
 #, tcl-format
-msgid ""
-"Could not add tool:\n"
-"%s"
-msgstr ""
-"ツールを追加できません:\n"
-"%s"
+msgid "Setting up the %s (at %s)"
+msgstr "%2$s にある %1$s をセットアップします"
 
-#: lib/tools_dlg.tcl:190
-msgid "Remove Tool"
-msgstr "ツールの削除"
+#: lib/line.tcl:17
+msgid "Goto Line:"
+msgstr "行番号"
 
-#: lib/tools_dlg.tcl:196
-msgid "Remove Tool Commands"
-msgstr "ツールコマンドの削除"
+#: lib/line.tcl:23
+msgid "Go"
+msgstr "移動"
 
-#: lib/tools_dlg.tcl:200
-msgid "Remove"
-msgstr "削除"
+#: lib/branch_create.tcl:23
+msgid "Create Branch"
+msgstr "ブランチを作成"
 
-#: lib/tools_dlg.tcl:236
-msgid "(Blue denotes repository-local tools)"
-msgstr "(青色はローカルレポジトリのツールです)"
+#: lib/branch_create.tcl:28
+msgid "Create New Branch"
+msgstr "ブランチを新規作成"
 
-#: lib/tools_dlg.tcl:297
-#, tcl-format
-msgid "Run Command: %s"
-msgstr "コマンドを起動: %s"
+#: lib/branch_create.tcl:42
+msgid "Branch Name"
+msgstr "ブランチ名"
 
-#: lib/tools_dlg.tcl:311
-msgid "Arguments"
-msgstr "引数"
+#: lib/branch_create.tcl:57
+msgid "Match Tracking Branch Name"
+msgstr "トラッキング・ブランチ名を合わせる"
 
-#: lib/tools_dlg.tcl:348
-msgid "OK"
-msgstr "OK"
+#: lib/branch_create.tcl:66
+msgid "Starting Revision"
+msgstr "初期リビジョン"
 
-#: lib/transport.tcl:7
-#, tcl-format
-msgid "Fetching new changes from %s"
-msgstr "%s から新しい変更をフェッチしています"
+#: lib/branch_create.tcl:72
+msgid "Update Existing Branch:"
+msgstr "既存のブランチを更新:"
 
-#: lib/transport.tcl:18
-#, tcl-format
-msgid "remote prune %s"
-msgstr "遠隔刈込 %s"
+#: lib/branch_create.tcl:75
+msgid "No"
+msgstr "いいえ"
 
-#: lib/transport.tcl:19
-#, tcl-format
-msgid "Pruning tracking branches deleted from %s"
-msgstr "%s から削除されたトラッキング・ブランチを刈っています"
+#: lib/branch_create.tcl:80
+msgid "Fast Forward Only"
+msgstr "早送りのみ"
 
-#: lib/transport.tcl:26
-#, tcl-format
-msgid "Pushing changes to %s"
-msgstr "%s へ変更をプッシュしています"
+#: lib/branch_create.tcl:97
+msgid "Checkout After Creation"
+msgstr "作成してすぐチェックアウト"
 
-#: lib/transport.tcl:64
-#, tcl-format
-msgid "Mirroring to %s"
-msgstr "%s へミラーしています"
+#: lib/branch_create.tcl:132
+msgid "Please select a tracking branch."
+msgstr "トラッキング・ブランチを選択して下さい。"
 
-#: lib/transport.tcl:82
+#: lib/branch_create.tcl:141
 #, tcl-format
-msgid "Pushing %s %s to %s"
-msgstr "%3$s へ %1$s %2$s をプッシュしています"
+msgid "Tracking branch %s is not a branch in the remote repository."
+msgstr ""
+"トラッキング・ブランチ %s はリモートリポジトリのブランチではありません。"
 
-#: lib/transport.tcl:100
-msgid "Push Branches"
-msgstr "ã\83\96ã\83©ã\83³ã\83\81ã\82\92ã\83\97ã\83\83ã\82·ã\83¥"
+#: lib/spellcheck.tcl:57
+msgid "Unsupported spell checker"
+msgstr "ã\82µã\83\9dã\83¼ã\83\88ã\81\95ã\82\8cã\81¦ã\81\84ã\81ªã\81\84ã\82¹ã\83\9aã\83«ã\83\81ã\82§ã\83\83ã\82«ã\83¼ã\81§ã\81\99"
 
-#: lib/transport.tcl:114
-msgid "Source Branches"
-msgstr "元のブランチ"
+#: lib/spellcheck.tcl:65
+msgid "Spell checking is unavailable"
+msgstr "スペルチェック機能は使えません"
 
-#: lib/transport.tcl:131
-msgid "Destination Repository"
-msgstr "送り先リポジトリ"
+#: lib/spellcheck.tcl:68
+msgid "Invalid spell checking configuration"
+msgstr "スペルチェックの設定が不正です"
 
-#: lib/transport.tcl:169
-msgid "Transfer Options"
-msgstr "通信オプション"
+#: lib/spellcheck.tcl:70
+#, tcl-format
+msgid "Reverting dictionary to %s."
+msgstr "辞書を %s に巻き戻します"
 
-#: lib/transport.tcl:171
-msgid "Force overwrite existing branch (may discard changes)"
-msgstr "既存ブランチを上書き(変更を破棄する可能性があります)"
+#: lib/spellcheck.tcl:73
+msgid "Spell checker silently failed on startup"
+msgstr "スペルチェッカーの起動に失敗しました"
 
-#: lib/transport.tcl:175
-msgid "Use thin pack (for slow network connections)"
-msgstr "Thin Pack を使う(遅いネットワーク接続)"
+#: lib/spellcheck.tcl:80
+msgid "Unrecognized spell checker"
+msgstr "スペルチェッカーが判別できません"
 
-#: lib/transport.tcl:179
-msgid "Include tags"
-msgstr "タグを含める"
+#: lib/spellcheck.tcl:186
+msgid "No Suggestions"
+msgstr "提案なし"
+
+#: lib/spellcheck.tcl:388
+msgid "Unexpected EOF from spell checker"
+msgstr "スペルチェッカーが予想外の EOF を返しました"
+
+#: lib/spellcheck.tcl:392
+msgid "Spell Checker Failed"
+msgstr "スペルチェック失敗"
index b57f87de658b627c48ec672faaab3dc6aac3b505..a1cc71b521b76c346509207f4ef9a24d48ead229 100755 (executable)
@@ -576,7 +576,7 @@ cmd_update()
                ${wt_prefix:+--prefix "$wt_prefix"} \
                ${prefix:+--recursive-prefix "$prefix"} \
                ${update:+--update "$update"} \
-               ${reference:+--reference "$reference"} \
+               ${reference:+"$reference"} \
                ${depth:+--depth "$depth"} \
                ${recommend_shallow:+"$recommend_shallow"} \
                ${jobs:+$jobs} \
diff --git a/git.c b/git.c
index 0f1937fd0c23da7c316540b8f9a6b05746011506..1c61151758531889e2a2e60e66799283240dc89a 100644 (file)
--- a/git.c
+++ b/git.c
@@ -522,21 +522,34 @@ static void strip_extension(const char **argv)
 
 static void handle_builtin(int argc, const char **argv)
 {
+       struct argv_array args = ARGV_ARRAY_INIT;
        const char *cmd;
        struct cmd_struct *builtin;
 
        strip_extension(argv);
        cmd = argv[0];
 
-       /* Turn "git cmd --help" into "git help cmd" */
+       /* Turn "git cmd --help" into "git help --exclude-guides cmd" */
        if (argc > 1 && !strcmp(argv[1], "--help")) {
+               int i;
+
                argv[1] = argv[0];
                argv[0] = cmd = "help";
+
+               for (i = 0; i < argc; i++) {
+                       argv_array_push(&args, argv[i]);
+                       if (!i)
+                               argv_array_push(&args, "--exclude-guides");
+               }
+
+               argc++;
+               argv = args.argv;
        }
 
        builtin = get_builtin(cmd);
        if (builtin)
                exit(run_builtin(builtin, argc, argv));
+       argv_array_clear(&args);
 }
 
 static void execv_dashed_external(const char **argv)
diff --git a/graph.c b/graph.c
index dd1720148dc51740c96da0f4b17b59b97994abac..06f1139f2e201e1319bece3865ae95060ae2522c 100644 (file)
--- a/graph.c
+++ b/graph.c
@@ -2,7 +2,6 @@
 #include "commit.h"
 #include "color.h"
 #include "graph.h"
-#include "diff.h"
 #include "revision.h"
 
 /* Internal API */
@@ -28,8 +27,15 @@ static void graph_padding_line(struct git_graph *graph, struct strbuf *sb);
  * responsible for printing this line's graph (perhaps via
  * graph_show_commit() or graph_show_oneline()) before calling
  * graph_show_strbuf().
+ *
+ * Note that unlike some other graph display functions, you must pass the file
+ * handle directly. It is assumed that this is the same file handle as the
+ * file specified by the graph diff options. This is necessary so that
+ * graph_show_strbuf can be called even with a NULL graph.
  */
-static void graph_show_strbuf(struct git_graph *graph, struct strbuf const *sb);
+static void graph_show_strbuf(struct git_graph *graph,
+                             FILE *file,
+                             struct strbuf const *sb);
 
 /*
  * TODO:
@@ -59,6 +65,17 @@ enum graph_state {
        GRAPH_COLLAPSING
 };
 
+static void graph_show_line_prefix(const struct diff_options *diffopt)
+{
+       if (!diffopt || !diffopt->line_prefix)
+               return;
+
+       fwrite(diffopt->line_prefix,
+              sizeof(char),
+              diffopt->line_prefix_length,
+              diffopt->file);
+}
+
 static const char **column_colors;
 static unsigned short column_colors_max;
 
@@ -195,14 +212,28 @@ static struct strbuf *diff_output_prefix_callback(struct diff_options *opt, void
        static struct strbuf msgbuf = STRBUF_INIT;
 
        assert(opt);
-       assert(graph);
 
-       opt->output_prefix_length = graph->width;
        strbuf_reset(&msgbuf);
-       graph_padding_line(graph, &msgbuf);
+       if (opt->line_prefix)
+               strbuf_add(&msgbuf, opt->line_prefix,
+                          opt->line_prefix_length);
+       if (graph)
+               graph_padding_line(graph, &msgbuf);
        return &msgbuf;
 }
 
+static const struct diff_options *default_diffopt;
+
+void graph_setup_line_prefix(struct diff_options *diffopt)
+{
+       default_diffopt = diffopt;
+
+       /* setup an output prefix callback if necessary */
+       if (diffopt && !diffopt->output_prefix)
+               diffopt->output_prefix = diff_output_prefix_callback;
+}
+
+
 struct git_graph *graph_init(struct rev_info *opt)
 {
        struct git_graph *graph = xmalloc(sizeof(struct git_graph));
@@ -245,7 +276,6 @@ struct git_graph *graph_init(struct rev_info *opt)
         */
        opt->diffopt.output_prefix = diff_output_prefix_callback;
        opt->diffopt.output_prefix_data = graph;
-       opt->diffopt.output_prefix_length = 0;
 
        return graph;
 }
@@ -1185,6 +1215,8 @@ void graph_show_commit(struct git_graph *graph)
        struct strbuf msgbuf = STRBUF_INIT;
        int shown_commit_line = 0;
 
+       graph_show_line_prefix(default_diffopt);
+
        if (!graph)
                return;
 
@@ -1202,8 +1234,10 @@ void graph_show_commit(struct git_graph *graph)
                shown_commit_line = graph_next_line(graph, &msgbuf);
                fwrite(msgbuf.buf, sizeof(char), msgbuf.len,
                        graph->revs->diffopt.file);
-               if (!shown_commit_line)
+               if (!shown_commit_line) {
                        putc('\n', graph->revs->diffopt.file);
+                       graph_show_line_prefix(&graph->revs->diffopt);
+               }
                strbuf_setlen(&msgbuf, 0);
        }
 
@@ -1214,6 +1248,8 @@ void graph_show_oneline(struct git_graph *graph)
 {
        struct strbuf msgbuf = STRBUF_INIT;
 
+       graph_show_line_prefix(default_diffopt);
+
        if (!graph)
                return;
 
@@ -1226,6 +1262,8 @@ void graph_show_padding(struct git_graph *graph)
 {
        struct strbuf msgbuf = STRBUF_INIT;
 
+       graph_show_line_prefix(default_diffopt);
+
        if (!graph)
                return;
 
@@ -1239,6 +1277,8 @@ int graph_show_remainder(struct git_graph *graph)
        struct strbuf msgbuf = STRBUF_INIT;
        int shown = 0;
 
+       graph_show_line_prefix(default_diffopt);
+
        if (!graph)
                return 0;
 
@@ -1252,27 +1292,24 @@ int graph_show_remainder(struct git_graph *graph)
                strbuf_setlen(&msgbuf, 0);
                shown = 1;
 
-               if (!graph_is_commit_finished(graph))
+               if (!graph_is_commit_finished(graph)) {
                        putc('\n', graph->revs->diffopt.file);
-               else
+                       graph_show_line_prefix(&graph->revs->diffopt);
+               } else {
                        break;
+               }
        }
        strbuf_release(&msgbuf);
 
        return shown;
 }
 
-
-static void graph_show_strbuf(struct git_graph *graph, struct strbuf const *sb)
+static void graph_show_strbuf(struct git_graph *graph,
+                             FILE *file,
+                             struct strbuf const *sb)
 {
        char *p;
 
-       if (!graph) {
-               fwrite(sb->buf, sizeof(char), sb->len,
-                       graph->revs->diffopt.file);
-               return;
-       }
-
        /*
         * Print the strbuf line by line,
         * and display the graph info before each line but the first.
@@ -1287,7 +1324,7 @@ static void graph_show_strbuf(struct git_graph *graph, struct strbuf const *sb)
                } else {
                        len = (sb->buf + sb->len) - p;
                }
-               fwrite(p, sizeof(char), len, graph->revs->diffopt.file);
+               fwrite(p, sizeof(char), len, file);
                if (next_p && *next_p != '\0')
                        graph_show_oneline(graph);
                p = next_p;
@@ -1295,29 +1332,20 @@ static void graph_show_strbuf(struct git_graph *graph, struct strbuf const *sb)
 }
 
 void graph_show_commit_msg(struct git_graph *graph,
+                          FILE *file,
                           struct strbuf const *sb)
 {
        int newline_terminated;
 
-       if (!graph) {
-               /*
-                * If there's no graph, just print the message buffer.
-                *
-                * The message buffer for CMIT_FMT_ONELINE and
-                * CMIT_FMT_USERFORMAT are already missing a terminating
-                * newline.  All of the other formats should have it.
-                */
-               fwrite(sb->buf, sizeof(char), sb->len,
-                       graph->revs->diffopt.file);
-               return;
-       }
-
-       newline_terminated = (sb->len && sb->buf[sb->len - 1] == '\n');
-
        /*
         * Show the commit message
         */
-       graph_show_strbuf(graph, sb);
+       graph_show_strbuf(graph, file, sb);
+
+       if (!graph)
+               return;
+
+       newline_terminated = (sb->len && sb->buf[sb->len - 1] == '\n');
 
        /*
         * If there is more output needed for this commit, show it now
@@ -1329,7 +1357,7 @@ void graph_show_commit_msg(struct git_graph *graph,
                 * new line.
                 */
                if (!newline_terminated)
-                       putc('\n', graph->revs->diffopt.file);
+                       putc('\n', file);
 
                graph_show_remainder(graph);
 
@@ -1337,6 +1365,6 @@ void graph_show_commit_msg(struct git_graph *graph,
                 * If sb ends with a newline, our output should too.
                 */
                if (newline_terminated)
-                       putc('\n', graph->revs->diffopt.file);
+                       putc('\n', file);
        }
 }
diff --git a/graph.h b/graph.h
index 3f48c19b6208712233f80c1afae3783951e967a9..af623390b6058d16677bb81223b2038148d07a6d 100644 (file)
--- a/graph.h
+++ b/graph.h
@@ -1,9 +1,22 @@
 #ifndef GRAPH_H
 #define GRAPH_H
+#include "diff.h"
 
 /* A graph is a pointer to this opaque structure */
 struct git_graph;
 
+/*
+ * Called to setup global display of line_prefix diff option.
+ *
+ * Passed a diff_options structure which indicates the line_prefix and the
+ * file to output the prefix to. This is sort of a hack used so that the
+ * line_prefix will be honored by all flows which also honor "--graph"
+ * regardless of whether a graph has actually been setup. The normal graph
+ * flow will honor the exact diff_options passed, but a NULL graph will cause
+ * display of a line_prefix to stdout.
+ */
+void graph_setup_line_prefix(struct diff_options *diffopt);
+
 /*
  * Set up a custom scheme for column colors.
  *
@@ -113,7 +126,14 @@ int graph_show_remainder(struct git_graph *graph);
  * missing a terminating newline (including if it is empty), the output
  * printed by graph_show_commit_msg() will also be missing a terminating
  * newline.
+ *
+ * Note that unlike some other graph display functions, you must pass the file
+ * handle directly. It is assumed that this is the same file handle as the
+ * file specified by the graph diff options. This is necessary so that
+ * graph_show_commit_msg can be called even with a NULL graph.
  */
-void graph_show_commit_msg(struct git_graph *graph, struct strbuf const *sb);
+void graph_show_commit_msg(struct git_graph *graph,
+                          FILE *file,
+                          struct strbuf const *sb);
 
 #endif /* GRAPH_H */
diff --git a/hex.c b/hex.c
index 9619b67af0b79c4ebae4c5e6a5f5748405bd4dea..ab2610e498615b197787a8c22cd00f979e488fc8 100644 (file)
--- a/hex.c
+++ b/hex.c
@@ -39,16 +39,8 @@ int get_sha1_hex(const char *hex, unsigned char *sha1)
 {
        int i;
        for (i = 0; i < GIT_SHA1_RAWSZ; i++) {
-               unsigned int val;
-               /*
-                * hex[1]=='\0' is caught when val is checked below,
-                * but if hex[0] is NUL we have to avoid reading
-                * past the end of the string:
-                */
-               if (!hex[0])
-                       return -1;
-               val = (hexval(hex[0]) << 4) | hexval(hex[1]);
-               if (val & ~0xff)
+               int val = hex2chr(hex);
+               if (val < 0)
                        return -1;
                *sha1++ = val;
                hex += 2;
index bfb735c84556f0c6f4d3f17dc4ed18774b8db817..8c2415747a2606aefb29fd6e0092c86da3c72589 100644 (file)
@@ -715,10 +715,7 @@ void show_log(struct rev_info *opt)
        else
                opt->missing_newline = 0;
 
-       if (opt->graph)
-               graph_show_commit_msg(opt->graph, &msgbuf);
-       else
-               fwrite(msgbuf.buf, sizeof(char), msgbuf.len, opt->diffopt.file);
+       graph_show_commit_msg(opt->graph, opt->diffopt.file, &msgbuf);
        if (opt->use_terminator && !commit_format_is_empty(opt->commit_format)) {
                if (!opt->missing_newline)
                        graph_show_padding(opt->graph);
diff --git a/path.c b/path.c
index fe3c4d96c6d82b2c8f4e1553f1a52e410c8c02d3..a8e72955f6f28f6e27e7faeee144f4f3ed492c83 100644 (file)
--- a/path.c
+++ b/path.c
@@ -6,6 +6,7 @@
 #include "string-list.h"
 #include "dir.h"
 #include "worktree.h"
+#include "submodule-config.h"
 
 static int get_st_mode_bits(const char *path, int *mode)
 {
@@ -468,12 +469,16 @@ const char *worktree_git_path(const struct worktree *wt, const char *fmt, ...)
        return pathname->buf;
 }
 
-static void do_submodule_path(struct strbuf *buf, const char *path,
-                             const char *fmt, va_list args)
+/* Returns 0 on success, negative on failure. */
+#define SUBMODULE_PATH_ERR_NOT_CONFIGURED -1
+static int do_submodule_path(struct strbuf *buf, const char *path,
+                            const char *fmt, va_list args)
 {
        const char *git_dir;
        struct strbuf git_submodule_common_dir = STRBUF_INIT;
        struct strbuf git_submodule_dir = STRBUF_INIT;
+       const struct submodule *sub;
+       int err = 0;
 
        strbuf_addstr(buf, path);
        strbuf_complete(buf, '/');
@@ -484,6 +489,17 @@ static void do_submodule_path(struct strbuf *buf, const char *path,
                strbuf_reset(buf);
                strbuf_addstr(buf, git_dir);
        }
+       if (!is_git_directory(buf->buf)) {
+               gitmodules_config();
+               sub = submodule_from_path(null_sha1, path);
+               if (!sub) {
+                       err = SUBMODULE_PATH_ERR_NOT_CONFIGURED;
+                       goto cleanup;
+               }
+               strbuf_reset(buf);
+               strbuf_git_path(buf, "%s/%s", "modules", sub->name);
+       }
+
        strbuf_addch(buf, '/');
        strbuf_addbuf(&git_submodule_dir, buf);
 
@@ -494,27 +510,38 @@ static void do_submodule_path(struct strbuf *buf, const char *path,
 
        strbuf_cleanup_path(buf);
 
+cleanup:
        strbuf_release(&git_submodule_dir);
        strbuf_release(&git_submodule_common_dir);
+
+       return err;
 }
 
 char *git_pathdup_submodule(const char *path, const char *fmt, ...)
 {
+       int err;
        va_list args;
        struct strbuf buf = STRBUF_INIT;
        va_start(args, fmt);
-       do_submodule_path(&buf, path, fmt, args);
+       err = do_submodule_path(&buf, path, fmt, args);
        va_end(args);
+       if (err) {
+               strbuf_release(&buf);
+               return NULL;
+       }
        return strbuf_detach(&buf, NULL);
 }
 
-void strbuf_git_path_submodule(struct strbuf *buf, const char *path,
-                              const char *fmt, ...)
+int strbuf_git_path_submodule(struct strbuf *buf, const char *path,
+                             const char *fmt, ...)
 {
+       int err;
        va_list args;
        va_start(args, fmt);
-       do_submodule_path(buf, path, fmt, args);
+       err = do_submodule_path(buf, path, fmt, args);
        va_end(args);
+
+       return err;
 }
 
 static void do_git_common_path(struct strbuf *buf,
index 62fdb37079fa31698846044448b5cfb398e45528..30489c60b1d3f8acc002fad31aa68b528757c8da 100644 (file)
@@ -172,27 +172,8 @@ static int get_packet_data(int fd, char **src_buf, size_t *src_size,
 
 static int packet_length(const char *linelen)
 {
-       int n;
-       int len = 0;
-
-       for (n = 0; n < 4; n++) {
-               unsigned char c = linelen[n];
-               len <<= 4;
-               if (c >= '0' && c <= '9') {
-                       len += c - '0';
-                       continue;
-               }
-               if (c >= 'a' && c <= 'f') {
-                       len += c - 'a' + 10;
-                       continue;
-               }
-               if (c >= 'A' && c <= 'F') {
-                       len += c - 'A' + 10;
-                       continue;
-               }
-               return -1;
-       }
-       return len;
+       int val = hex2chr(linelen);
+       return (val < 0) ? val : (val << 8) | hex2chr(linelen + 2);
 }
 
 int packet_read(int fd, char **src_buf, size_t *src_len,
index 56274ad4f35d8f3c9f288a2d0a3a6d0264db6d07..d3e63bc4806d1fa4547bbd743c6395ec8b9311cf 100644 (file)
--- a/po/TEAMS
+++ b/po/TEAMS
@@ -37,8 +37,9 @@ Repository:   https://github.com/changwoo/git-l10n-ko/
 Leader:                Changwoo Ryu <cwryu@debian.org>
 
 Language:      pt_PT (Portuguese - Portugal)
-Repository:    https://github.com/marcomsousa/git-l10n-pt_PT/
-Leader:                Marco Sousa <marcomsousa AT gmail.com>
+Repository:    https://github.com/vascool/git-po-pt/
+Leader:                Vasco Almeida <vascomalmeida@sapo.pt>
+Members:       Marco Sousa <marcomsousa AT gmail.com>
 
 Language:      ru (Russian)
 Repository:    https://github.com/DJm00n/git-po-ru/
index 13610a0aa983cf6a09486fe3279aa091f4a0f5d8..c8658dfd25945a4b7ceea389e137392a130dd41d 100644 (file)
@@ -9,8 +9,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: Git\n"
 "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2016-08-15 22:43+0800\n"
-"PO-Revision-Date: 2016-08-24 14:07+0000\n"
+"POT-Creation-Date: 2016-08-27 23:21+0800\n"
+"PO-Revision-Date: 2016-09-03 12:00+0000\n"
 "Last-Translator: Vasco Almeida <vascomalmeida@sapo.pt>\n"
 "Language-Team: Portuguese\n"
 "Language: pt\n"
@@ -27,7 +27,8 @@ msgstr "dica: %.*s\n"
 
 #: advice.c:83
 msgid "Cherry-picking is not possible because you have unmerged files."
-msgstr "Não é possível efetuar cherry-pick porque tem ficheiros não integrados."
+msgstr ""
+"Não é possível efetuar cherry-pick porque tem ficheiros não integrados."
 
 #: advice.c:85
 msgid "Committing is not possible because you have unmerged files."
@@ -614,145 +615,98 @@ msgstr "linha de configuração %d incorreta na linha de comandos %s"
 msgid "bad config line %d in %s"
 msgstr "linha de configuração %d incorreta em %s"
 
-#: config.c:660
-#, c-format
-msgid "bad numeric config value '%s' for '%s': out of range"
-msgstr "valor numérico '%s' da configuração '%s' incorreto: fora de intervalo"
+#: config.c:655
+msgid "out of range"
+msgstr "fora de intervalo"
+
+#: config.c:655
+msgid "invalid unit"
+msgstr "unidade inválida"
 
 #: config.c:661
 #, c-format
-msgid "bad numeric config value '%s' for '%s': invalid unit"
-msgstr "valor numérico '%s' da configuração '%s' incorreto: unidade inválida"
+msgid "bad numeric config value '%s' for '%s': %s"
+msgstr "valor numérico '%s' da configuração '%s' incorreto: %s"
 
-#: config.c:667
+#: config.c:666
 #, c-format
-msgid "bad numeric config value '%s' for '%s' in blob %s: out of range"
-msgstr ""
-"valor numérico '%s' da configuração '%s' incorreto no blob %s: fora de "
-"intervalo"
+msgid "bad numeric config value '%s' for '%s' in blob %s: %s"
+msgstr "valor numérico '%s' da configuração '%s' incorreto no blob %s: %s"
 
-#: config.c:668
+#: config.c:669
 #, c-format
-msgid "bad numeric config value '%s' for '%s' in blob %s: invalid unit"
-msgstr ""
-"valor numérico '%s' da configuração '%s' incorreto no blob %s: unidade "
-"inválida"
+msgid "bad numeric config value '%s' for '%s' in file %s: %s"
+msgstr "valor numérico '%s' da configuração '%s' incorreto no ficheiro %s: %s"
 
 #: config.c:672
 #, c-format
-msgid "bad numeric config value '%s' for '%s' in file %s: out of range"
-msgstr ""
-"valor numérico '%s' da configuração '%s' incorreto no ficheiro %s: fora de "
-"intervalo"
-
-#: config.c:673
-#, c-format
-msgid "bad numeric config value '%s' for '%s' in file %s: invalid unit"
+msgid "bad numeric config value '%s' for '%s' in standard input: %s"
 msgstr ""
-"valor numérico '%s' da configuração '%s' incorreto no ficheiro %s: unidade "
-"inválida"
+"valor numérico '%s' da configuração '%s' incorreto na entrada padrão: %s"
 
-#: config.c:677
+#: config.c:675
 #, c-format
-msgid "bad numeric config value '%s' for '%s' in standard input: out of range"
+msgid "bad numeric config value '%s' for '%s' in submodule-blob %s: %s"
 msgstr ""
-"valor numérico '%s' da configuração '%s' incorreto na entrada padrão: fora "
-"de intervalo"
+"valor numérico '%s' da configuração '%s' incorreto no submódulo-blob %s: %s"
 
 #: config.c:678
 #, c-format
-msgid "bad numeric config value '%s' for '%s' in standard input: invalid unit"
-msgstr ""
-"valor numérico '%s' da configuração '%s' incorreto na entrada padrão: "
-"unidade inválida"
-
-#: config.c:682
-#, c-format
-msgid ""
-"bad numeric config value '%s' for '%s' in submodule-blob %s: out of range"
-msgstr ""
-"valor numérico '%s' da configuração '%s' incorreto no submódulo-blob %s: "
-"fora de intervalo"
-
-#: config.c:683
-#, c-format
-msgid ""
-"bad numeric config value '%s' for '%s' in submodule-blob %s: invalid unit"
-msgstr ""
-"valor numérico '%s' da configuração '%s' incorreto no submódulo-blob %s: "
-"unidade inválida"
-
-#: config.c:687
-#, c-format
-msgid "bad numeric config value '%s' for '%s' in command line %s: out of range"
-msgstr ""
-"valor numérico '%s' da configuração '%s' incorreto na linha de comandos %s: "
-"fora de intervalo"
-
-#: config.c:688
-#, c-format
-msgid "bad numeric config value '%s' for '%s' in command line %s: invalid unit"
+msgid "bad numeric config value '%s' for '%s' in command line %s: %s"
 msgstr ""
 "valor numérico '%s' da configuração '%s' incorreto na linha de comandos %s: "
-"unidade inválida"
-
-#: config.c:692
-#, c-format
-msgid "bad numeric config value '%s' for '%s' in %s: out of range"
-msgstr ""
-"valor numérico '%s' da configuração '%s' incorreto em %s: fora de intervalo"
+"%s"
 
-#: config.c:693
+#: config.c:681
 #, c-format
-msgid "bad numeric config value '%s' for '%s' in %s: invalid unit"
-msgstr ""
-"valor numérico '%s' da configuração '%s' incorreto em %s: unidade inválida"
+msgid "bad numeric config value '%s' for '%s' in %s: %s"
+msgstr "valor numérico '%s' da configuração '%s' incorreto em %s: %s"
 
-#: config.c:780
+#: config.c:768
 #, c-format
 msgid "failed to expand user dir in: '%s'"
 msgstr "falha ao expandir diretório de utilizador em: '%s'"
 
-#: config.c:861 config.c:872
+#: config.c:849 config.c:860
 #, c-format
 msgid "bad zlib compression level %d"
 msgstr "nível de compressão zlib %d incorreto"
 
-#: config.c:990
+#: config.c:978
 #, c-format
 msgid "invalid mode for object creation: %s"
 msgstr "modo inválido para criação de objeto: %s"
 
-#: config.c:1324
+#: config.c:1312
 msgid "unable to parse command-line config"
 msgstr "não é possível analisar configuração de linha de comandos"
 
-#: config.c:1374
+#: config.c:1362
 msgid "unknown error occurred while reading the configuration files"
 msgstr ""
 "ocorreu um erro desconhecido durante a leitura dos ficheiros de configuração"
 
-#: config.c:1728
+#: config.c:1716
 #, c-format
 msgid "unable to parse '%s' from command-line config"
 msgstr "não é possível analisar '%s' da configuração de linha de comandos"
 
-#: config.c:1730
+#: config.c:1718
 #, c-format
 msgid "bad config variable '%s' in file '%s' at line %d"
 msgstr "variável de configuração '%s' incorreta no ficheiro '%s' na linha %d"
 
-#: config.c:1789
+#: config.c:1777
 #, c-format
 msgid "%s has multiple values"
 msgstr "%s tem múltiplos valores"
 
-#: config.c:2323
+#: config.c:2311
 #, c-format
 msgid "could not set '%s' to '%s'"
 msgstr "não foi possível definir '%s' como '%s'"
 
-#: config.c:2325
+#: config.c:2313
 #, c-format
 msgid "could not unset '%s'"
 msgstr "não foi possível reiniciar '%s'"
@@ -1030,73 +984,73 @@ msgstr "falha ao ler a cache"
 msgid "unable to write new index file"
 msgstr "não foi possível escrever novo ficheiro de índice"
 
-#: merge-recursive.c:212
+#: merge-recursive.c:209
 msgid "(bad commit)\n"
 msgstr "(commit incorreto)\n"
 
-#: merge-recursive.c:234
+#: merge-recursive.c:231
 #, c-format
 msgid "addinfo_cache failed for path '%s'"
 msgstr "addinfo_cache falhou no caminho '%s'"
 
-#: merge-recursive.c:304
+#: merge-recursive.c:301
 msgid "error building trees"
 msgstr "erro ao construir árvores"
 
-#: merge-recursive.c:723
+#: merge-recursive.c:720
 #, c-format
 msgid "failed to create path '%s'%s"
 msgstr "falha ao criar o caminho '%s'%s"
 
-#: merge-recursive.c:734
+#: merge-recursive.c:731
 #, c-format
 msgid "Removing %s to make room for subdirectory\n"
 msgstr "A remover %s para criar espaço para o subdiretório\n"
 
-#: merge-recursive.c:748 merge-recursive.c:767
+#: merge-recursive.c:745 merge-recursive.c:764
 msgid ": perhaps a D/F conflict?"
 msgstr ": talvez um conflito D/F?"
 
-#: merge-recursive.c:757
+#: merge-recursive.c:754
 #, c-format
 msgid "refusing to lose untracked file at '%s'"
 msgstr "perda de ficheiro não controlado em '%s' recusada"
 
-#: merge-recursive.c:799
+#: merge-recursive.c:796
 #, c-format
 msgid "cannot read object %s '%s'"
 msgstr "não é possível ler o objeto %s: '%s'"
 
-#: merge-recursive.c:801
+#: merge-recursive.c:798
 #, c-format
 msgid "blob expected for %s '%s'"
 msgstr "blob para %s '%s' esperado"
 
-#: merge-recursive.c:825
+#: merge-recursive.c:822
 #, c-format
 msgid "failed to open '%s': %s"
 msgstr "falha ao abrir '%s': %s"
 
-#: merge-recursive.c:836
+#: merge-recursive.c:833
 #, c-format
 msgid "failed to symlink '%s': %s"
 msgstr "falha ao criar a ligação simbólica '%s': %s"
 
-#: merge-recursive.c:841
+#: merge-recursive.c:838
 #, c-format
 msgid "do not know what to do with %06o %s '%s'"
 msgstr "não sei o que fazer com %06o %s '%s'"
 
-#: merge-recursive.c:981
+#: merge-recursive.c:978
 msgid "Failed to execute internal merge"
 msgstr "Falha ao executar integração interna"
 
-#: merge-recursive.c:985
+#: merge-recursive.c:982
 #, c-format
 msgid "Unable to add %s to database"
 msgstr "Não é possível adicionar %s à base de dados"
 
-#: merge-recursive.c:1084 merge-recursive.c:1098
+#: merge-recursive.c:1081 merge-recursive.c:1095
 #, c-format
 msgid ""
 "CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left "
@@ -1105,7 +1059,7 @@ msgstr ""
 "CONFLITO (%s/eliminar): %s eliminado em %s e %s em %s. Versão de %s de %s "
 "deixada na árvore."
 
-#: merge-recursive.c:1090 merge-recursive.c:1103
+#: merge-recursive.c:1087 merge-recursive.c:1100
 #, c-format
 msgid ""
 "CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left "
@@ -1114,160 +1068,160 @@ msgstr ""
 "CONFLITO (%s/eliminar): %s eliminado em %s e %s em %s. Versão de %s de %s "
 "deixada na árvore em %s."
 
-#: merge-recursive.c:1146
+#: merge-recursive.c:1143
 msgid "rename"
 msgstr "mudar nome"
 
-#: merge-recursive.c:1146
+#: merge-recursive.c:1143
 msgid "renamed"
 msgstr "nome mudado"
 
-#: merge-recursive.c:1203
+#: merge-recursive.c:1200
 #, c-format
 msgid "%s is a directory in %s adding as %s instead"
 msgstr "%s é um diretório em %s adicionando %s no seu lugar"
 
-#: merge-recursive.c:1228
+#: merge-recursive.c:1225
 #, c-format
 msgid ""
 "CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename \"%s"
 "\"->\"%s\" in \"%s\"%s"
 msgstr ""
-"CONFLITO (mudar nome/mudar nome): Mudar o nome \"%s\"->\"%s\" no ramo \"%s\" mudar "
-"o nome \"%s\"->\"%s\" em \"%s\"%s"
+"CONFLITO (mudar nome/mudar nome): Mudar o nome \"%s\"->\"%s\" no ramo \"%s\" "
+"mudar o nome \"%s\"->\"%s\" em \"%s\"%s"
 
-#: merge-recursive.c:1233
+#: merge-recursive.c:1230
 msgid " (left unresolved)"
 msgstr " (por resolver)"
 
-#: merge-recursive.c:1295
+#: merge-recursive.c:1292
 #, c-format
 msgid "CONFLICT (rename/rename): Rename %s->%s in %s. Rename %s->%s in %s"
 msgstr ""
-"CONFLITO (mudar nome/mudar nome): Mudar de nome %s->%s em %s. Mudar o nome %"
-"s->%s em %s"
+"CONFLITO (mudar nome/mudar nome): Mudar de nome %s->%s em %s. Mudar o nome "
+"%s->%s em %s"
 
-#: merge-recursive.c:1328
+#: merge-recursive.c:1325
 #, c-format
 msgid "Renaming %s to %s and %s to %s instead"
 msgstr "A mudar o nome de %s para %s e de %s para %s, em alternativa"
 
-#: merge-recursive.c:1534
+#: merge-recursive.c:1531
 #, c-format
 msgid "CONFLICT (rename/add): Rename %s->%s in %s. %s added in %s"
 msgstr ""
 "CONFLITO (mudar nome/adicionar): Mudar o nome %s->%s em %s. %s adicionado em "
 "%s"
 
-#: merge-recursive.c:1549
+#: merge-recursive.c:1546
 #, c-format
 msgid "Adding merged %s"
 msgstr "A adicionar %s integrado"
 
-#: merge-recursive.c:1556 merge-recursive.c:1769
+#: merge-recursive.c:1553 merge-recursive.c:1766
 #, c-format
 msgid "Adding as %s instead"
 msgstr "A adicionar como %s, em alternativa."
 
-#: merge-recursive.c:1613
+#: merge-recursive.c:1610
 #, c-format
 msgid "cannot read object %s"
 msgstr "não foi possível ler o objeto %s"
 
-#: merge-recursive.c:1616
+#: merge-recursive.c:1613
 #, c-format
 msgid "object %s is not a blob"
 msgstr "o objeto %s não é um blob"
 
-#: merge-recursive.c:1669
+#: merge-recursive.c:1666
 msgid "modify"
 msgstr "modificar"
 
-#: merge-recursive.c:1669
+#: merge-recursive.c:1666
 msgid "modified"
 msgstr "modificado"
 
-#: merge-recursive.c:1679
+#: merge-recursive.c:1676
 msgid "content"
 msgstr "conteúdo"
 
-#: merge-recursive.c:1686
+#: merge-recursive.c:1683
 msgid "add/add"
 msgstr "adicionar/adicionar"
 
-#: merge-recursive.c:1721
+#: merge-recursive.c:1718
 #, c-format
 msgid "Skipped %s (merged same as existing)"
 msgstr "%s ignorado (integrado é igual ao existente)"
 
-#: merge-recursive.c:1735
+#: merge-recursive.c:1732
 #, c-format
 msgid "Auto-merging %s"
 msgstr "A integrar automaticamente %s"
 
-#: merge-recursive.c:1739 git-submodule.sh:919
+#: merge-recursive.c:1736 git-submodule.sh:919
 msgid "submodule"
 msgstr "submódulo"
 
-#: merge-recursive.c:1740
+#: merge-recursive.c:1737
 #, c-format
 msgid "CONFLICT (%s): Merge conflict in %s"
 msgstr "CONFLITO (%s): conflito de integração em %s"
 
-#: merge-recursive.c:1834
+#: merge-recursive.c:1831
 #, c-format
 msgid "Removing %s"
 msgstr "A remover %s"
 
-#: merge-recursive.c:1860
+#: merge-recursive.c:1857
 msgid "file/directory"
 msgstr "ficheiro/diretório"
 
-#: merge-recursive.c:1866
+#: merge-recursive.c:1863
 msgid "directory/file"
 msgstr "diretório/ficheiro"
 
-#: merge-recursive.c:1871
+#: merge-recursive.c:1868
 #, c-format
 msgid "CONFLICT (%s): There is a directory with name %s in %s. Adding %s as %s"
 msgstr ""
 "CONFLITO (%s): Há um diretório designado %s em %s. A adicionar %s como %s"
 
-#: merge-recursive.c:1880
+#: merge-recursive.c:1877
 #, c-format
 msgid "Adding %s"
 msgstr "A adicionar %s"
 
-#: merge-recursive.c:1917
+#: merge-recursive.c:1914
 msgid "Already up-to-date!"
 msgstr "Já está atualizado!"
 
-#: merge-recursive.c:1926
+#: merge-recursive.c:1923
 #, c-format
 msgid "merging of trees %s and %s failed"
 msgstr "falha ao integrar as árvores %s e %s"
 
-#: merge-recursive.c:2009
+#: merge-recursive.c:2006
 msgid "Merging:"
 msgstr "A integrar:"
 
-#: merge-recursive.c:2022
+#: merge-recursive.c:2019
 #, c-format
 msgid "found %u common ancestor:"
 msgid_plural "found %u common ancestors:"
 msgstr[0] "%u antecessor comum encontrado:"
 msgstr[1] "%u antecessores comuns encontrados:"
 
-#: merge-recursive.c:2061
+#: merge-recursive.c:2058
 msgid "merge returned no commit"
 msgstr "a integração não retornou nenhum commit"
 
-#: merge-recursive.c:2124
+#: merge-recursive.c:2121
 #, c-format
 msgid "Could not parse object '%s'"
 msgstr "Não foi possível analisar o objeto '%s'"
 
-#: merge-recursive.c:2138 builtin/merge.c:641 builtin/merge.c:788
+#: merge-recursive.c:2135 builtin/merge.c:641 builtin/merge.c:788
 msgid "Unable to write index."
 msgstr "Não é possível escrever no índice."
 
@@ -1314,7 +1268,7 @@ msgstr "utilização: %s"
 msgid "   or: %s"
 msgstr "        ou: %s"
 
-#: parse-options.c:598
+#: parse-options.c:597
 #, c-format
 msgid "    %s"
 msgstr "         %s"
@@ -1328,7 +1282,7 @@ msgstr "-NUM"
 msgid "malformed object name '%s'"
 msgstr "nome do objeto malformado '%s'"
 
-#: path.c:796
+#: path.c:798
 #, c-format
 msgid "Could not make %s writable by group"
 msgstr "Não foi possível dar permissão de escrita ao grupo a %s"
@@ -1878,7 +1832,7 @@ msgid "git %s: failed to refresh the index"
 msgstr "git %s: falha ao atualizar o índice"
 
 #: sequencer.c:705
-msgid "Cannot revert during a another revert."
+msgid "Cannot revert during another revert."
 msgstr "Não é possível reverter durante outra reversão."
 
 #: sequencer.c:706
@@ -2309,8 +2263,8 @@ msgid ""
 "Your local changes to the following files would be overwritten by %s:\n"
 "%%sPlease commit your changes or stash them before you %s."
 msgstr ""
-"As suas alterações locais nos seguintes ficheiros seriam substituídas por %"
-"s:\n"
+"As suas alterações locais nos seguintes ficheiros seriam substituídas por "
+"%s:\n"
 "%%sSubmeta as suas alterações ou esconda-as antes de efetuar %s."
 
 #: unpack-trees.c:76
@@ -3120,7 +3074,7 @@ msgstr "ser verboso"
 msgid "interactive picking"
 msgstr "seleção interativa"
 
-#: builtin/add.c:257 builtin/checkout.c:1156 builtin/reset.c:286
+#: builtin/add.c:257 builtin/checkout.c:1157 builtin/reset.c:286
 msgid "select hunks interactively"
 msgstr "selecionar blocos interativamente"
 
@@ -4680,7 +4634,8 @@ msgstr "não faz sentido criar 'HEAD' manualmente"
 
 #: builtin/branch.c:846
 msgid "-a and -r options to 'git branch' do not make sense with a branch name"
-msgstr "as opções -a e -r de 'git branch' não fazem sentido com um nome de ramo"
+msgstr ""
+"as opções -a e -r de 'git branch' não fazem sentido com um nome de ramo"
 
 #: builtin/branch.c:849
 #, c-format
@@ -4801,7 +4756,7 @@ msgstr "ler os nomes dos ficheiros da entrada padrão"
 msgid "terminate input and output records by a NUL character"
 msgstr "terminar registos da entrada e da saída com um carácter NUL"
 
-#: builtin/check-ignore.c:18 builtin/checkout.c:1137 builtin/gc.c:325
+#: builtin/check-ignore.c:18 builtin/checkout.c:1138 builtin/gc.c:325
 msgid "suppress progress reporting"
 msgstr "suprimir informação de progresso"
 
@@ -4976,45 +4931,45 @@ msgstr "primeiro deve resolver o índice atual"
 msgid "Can not do reflog for '%s': %s\n"
 msgstr "Não é possível efetuar reflog de '%s': %s\n"
 
-#: builtin/checkout.c:663
+#: builtin/checkout.c:664
 msgid "HEAD is now at"
 msgstr "HEAD está agora em"
 
-#: builtin/checkout.c:667 builtin/clone.c:661
+#: builtin/checkout.c:668 builtin/clone.c:661
 msgid "unable to update HEAD"
 msgstr "não foi possível atualizar HEAD"
 
-#: builtin/checkout.c:671
+#: builtin/checkout.c:672
 #, c-format
 msgid "Reset branch '%s'\n"
 msgstr "Repor ramo '%s'\n"
 
-#: builtin/checkout.c:674
+#: builtin/checkout.c:675
 #, c-format
 msgid "Already on '%s'\n"
 msgstr "Já em '%s'\n"
 
-#: builtin/checkout.c:678
+#: builtin/checkout.c:679
 #, c-format
 msgid "Switched to and reset branch '%s'\n"
 msgstr "Mudou para e repôs o ramo '%s'\n"
 
-#: builtin/checkout.c:680 builtin/checkout.c:1069
+#: builtin/checkout.c:681 builtin/checkout.c:1070
 #, c-format
 msgid "Switched to a new branch '%s'\n"
 msgstr "Mudou para o novo ramo '%s'\n"
 
-#: builtin/checkout.c:682
+#: builtin/checkout.c:683
 #, c-format
 msgid "Switched to branch '%s'\n"
 msgstr "Mudou para o ramo '%s'\n"
 
-#: builtin/checkout.c:733
+#: builtin/checkout.c:734
 #, c-format
 msgid " ... and %d more.\n"
 msgstr " ... e mais %d.\n"
 
-#: builtin/checkout.c:739
+#: builtin/checkout.c:740
 #, c-format
 msgid ""
 "Warning: you are leaving %d commit behind, not connected to\n"
@@ -5035,7 +4990,7 @@ msgstr[1] ""
 "\n"
 "%s\n"
 
-#: builtin/checkout.c:758
+#: builtin/checkout.c:759
 #, c-format
 msgid ""
 "If you want to keep it by creating a new branch, this may be a good time\n"
@@ -5062,151 +5017,151 @@ msgstr[1] ""
 " git branch <nome-do-novo-ramo> %s\n"
 "\n"
 
-#: builtin/checkout.c:794
+#: builtin/checkout.c:795
 msgid "internal error in revision walk"
 msgstr "erro interno durante o curso de revisões"
 
-#: builtin/checkout.c:798
+#: builtin/checkout.c:799
 msgid "Previous HEAD position was"
 msgstr "A posição anterior de HEAD era"
 
-#: builtin/checkout.c:825 builtin/checkout.c:1064
+#: builtin/checkout.c:826 builtin/checkout.c:1065
 msgid "You are on a branch yet to be born"
 msgstr "Está num ramo ainda não criado"
 
-#: builtin/checkout.c:970
+#: builtin/checkout.c:971
 #, c-format
 msgid "only one reference expected, %d given."
 msgstr "esperava-se apenas uma referência, %d fornecidas."
 
-#: builtin/checkout.c:1010 builtin/worktree.c:214
+#: builtin/checkout.c:1011 builtin/worktree.c:214
 #, c-format
 msgid "invalid reference: %s"
 msgstr "referência inválida: %s"
 
-#: builtin/checkout.c:1039
+#: builtin/checkout.c:1040
 #, c-format
 msgid "reference is not a tree: %s"
 msgstr "a referência não é uma árvore: %s"
 
-#: builtin/checkout.c:1078
+#: builtin/checkout.c:1079
 msgid "paths cannot be used with switching branches"
 msgstr "não podem ser usados caminhos ao mudar de ramo"
 
-#: builtin/checkout.c:1081 builtin/checkout.c:1085
+#: builtin/checkout.c:1082 builtin/checkout.c:1086
 #, c-format
 msgid "'%s' cannot be used with switching branches"
 msgstr "'%s' não pode ser usado ao mudar de ramo"
 
-#: builtin/checkout.c:1089 builtin/checkout.c:1092 builtin/checkout.c:1097
-#: builtin/checkout.c:1100
+#: builtin/checkout.c:1090 builtin/checkout.c:1093 builtin/checkout.c:1098
+#: builtin/checkout.c:1101
 #, c-format
 msgid "'%s' cannot be used with '%s'"
 msgstr "'%s' não pode ser usado com '%s'"
 
-#: builtin/checkout.c:1105
+#: builtin/checkout.c:1106
 #, c-format
 msgid "Cannot switch branch to a non-commit '%s'"
 msgstr "Não é possível mudar de ramo para '%s', visto que não é um commit"
 
-#: builtin/checkout.c:1138 builtin/checkout.c:1140 builtin/clone.c:88
+#: builtin/checkout.c:1139 builtin/checkout.c:1141 builtin/clone.c:88
 #: builtin/remote.c:165 builtin/remote.c:167 builtin/worktree.c:324
 #: builtin/worktree.c:326
 msgid "branch"
 msgstr "ramo"
 
-#: builtin/checkout.c:1139
+#: builtin/checkout.c:1140
 msgid "create and checkout a new branch"
 msgstr "criar e extrair um novo ramo"
 
-#: builtin/checkout.c:1141
+#: builtin/checkout.c:1142
 msgid "create/reset and checkout a branch"
 msgstr "criar/repor e extrair um ramo"
 
-#: builtin/checkout.c:1142
+#: builtin/checkout.c:1143
 msgid "create reflog for new branch"
 msgstr "criar reflog do novo ramo"
 
-#: builtin/checkout.c:1143 builtin/worktree.c:328
+#: builtin/checkout.c:1144 builtin/worktree.c:328
 msgid "detach HEAD at named commit"
 msgstr "destacar HEAD no commit indicado"
 
-#: builtin/checkout.c:1144
+#: builtin/checkout.c:1145
 msgid "set upstream info for new branch"
 msgstr "definir a informação do ramo a montante do novo ramo"
 
-#: builtin/checkout.c:1146
+#: builtin/checkout.c:1147
 msgid "new-branch"
 msgstr "novo-ramo"
 
-#: builtin/checkout.c:1146
+#: builtin/checkout.c:1147
 msgid "new unparented branch"
 msgstr "novo ramo sem pai"
 
-#: builtin/checkout.c:1147
+#: builtin/checkout.c:1148
 msgid "checkout our version for unmerged files"
 msgstr "extrair a nossa versão dos ficheiros não integrados"
 
-#: builtin/checkout.c:1149
+#: builtin/checkout.c:1150
 msgid "checkout their version for unmerged files"
 msgstr "extrair a versão deles dos ficheiros não integrados"
 
-#: builtin/checkout.c:1151
+#: builtin/checkout.c:1152
 msgid "force checkout (throw away local modifications)"
 msgstr "forçar extração (descartar modificações locais)"
 
-#: builtin/checkout.c:1152
+#: builtin/checkout.c:1153
 msgid "perform a 3-way merge with the new branch"
 msgstr "realizar uma integração com 3 pontos com o novo ramo"
 
-#: builtin/checkout.c:1153 builtin/merge.c:231
+#: builtin/checkout.c:1154 builtin/merge.c:231
 msgid "update ignored files (default)"
 msgstr "atualizar ficheiros ignorados (predefinição)"
 
-#: builtin/checkout.c:1154 builtin/log.c:1459 parse-options.h:250
+#: builtin/checkout.c:1155 builtin/log.c:1459 parse-options.h:250
 msgid "style"
 msgstr "estilo"
 
-#: builtin/checkout.c:1155
+#: builtin/checkout.c:1156
 msgid "conflict style (merge or diff3)"
 msgstr "estilo de conflito (merge ou diff3)"
 
-#: builtin/checkout.c:1158
+#: builtin/checkout.c:1159
 msgid "do not limit pathspecs to sparse entries only"
 msgstr "não restringir especificadores de caminho a entradas esparsas"
 
-#: builtin/checkout.c:1160
+#: builtin/checkout.c:1161
 msgid "second guess 'git checkout <no-such-branch>'"
 msgstr "tentar adivinhar 'git checkout <ramo-inexistente>'"
 
-#: builtin/checkout.c:1162
+#: builtin/checkout.c:1163
 msgid "do not check if another worktree is holding the given ref"
 msgstr ""
 "não verificar se outra árvore de trabalho contém a referência fornecida"
 
-#: builtin/checkout.c:1163 builtin/clone.c:60 builtin/fetch.c:117
+#: builtin/checkout.c:1164 builtin/clone.c:60 builtin/fetch.c:117
 #: builtin/merge.c:228 builtin/pull.c:116 builtin/push.c:536
 #: builtin/send-pack.c:168
 msgid "force progress reporting"
 msgstr "forçar informação de progresso"
 
-#: builtin/checkout.c:1194
+#: builtin/checkout.c:1195
 msgid "-b, -B and --orphan are mutually exclusive"
 msgstr "-b, -B e --orphan são mutuamente exclusivos"
 
-#: builtin/checkout.c:1211
+#: builtin/checkout.c:1212
 msgid "--track needs a branch name"
 msgstr "--track requer um nome dum ramo"
 
-#: builtin/checkout.c:1216
+#: builtin/checkout.c:1217
 msgid "Missing branch name; try -b"
 msgstr "Falta um nome dum ramo; tente -b"
 
-#: builtin/checkout.c:1252
+#: builtin/checkout.c:1253
 msgid "invalid path specification"
 msgstr "especificação de caminho inválida"
 
-#: builtin/checkout.c:1259
+#: builtin/checkout.c:1260
 #, c-format
 msgid ""
 "Cannot update paths and switch to branch '%s' at the same time.\n"
@@ -5216,12 +5171,12 @@ msgstr ""
 "tempo.\n"
 "Pretendia extrair '%s' o qual não pode ser resolvido como commit?"
 
-#: builtin/checkout.c:1264
+#: builtin/checkout.c:1265
 #, c-format
 msgid "git checkout: --detach does not take a path argument '%s'"
 msgstr "git checkout: --detach não aceita um caminho como argumento '%s'"
 
-#: builtin/checkout.c:1268
+#: builtin/checkout.c:1269
 msgid ""
 "git checkout: --ours/--theirs, --force and --merge are incompatible when\n"
 "checking out of the index."
@@ -5626,7 +5581,7 @@ msgid "cannot unlink temporary alternates file"
 msgstr ""
 "não é possível invocar unlink sobre o ficheiro sobressalente temporário"
 
-#: builtin/clone.c:863 builtin/receive-pack.c:1857
+#: builtin/clone.c:863 builtin/receive-pack.c:1855
 msgid "Too many arguments."
 msgstr "Demasiados argumentos."
 
@@ -6788,7 +6743,8 @@ msgstr "número de submódulos obtidos em paralelo"
 
 #: builtin/fetch.c:108 builtin/pull.c:187
 msgid "prune remote-tracking branches no longer on remote"
-msgstr "eliminar os ramos de monitorização remotos que já não existem no remoto"
+msgstr ""
+"eliminar os ramos de monitorização remotos que já não existem no remoto"
 
 #: builtin/fetch.c:109 builtin/pull.c:190
 msgid "on-demand"
@@ -7586,49 +7542,49 @@ msgstr "nenhum visualizador de manual atendeu o pedido"
 msgid "no info viewer handled the request"
 msgstr "nenhum visualizador de info atendeu o pedido"
 
-#: builtin/help.c:408
+#: builtin/help.c:401
 msgid "Defining attributes per path"
 msgstr "Definir atributos por caminho"
 
-#: builtin/help.c:409
+#: builtin/help.c:402
 msgid "Everyday Git With 20 Commands Or So"
 msgstr "Diário Git com mais ou menos 20 Comandos"
 
-#: builtin/help.c:410
+#: builtin/help.c:403
 msgid "A Git glossary"
 msgstr "Um Glossário do Git"
 
-#: builtin/help.c:411
+#: builtin/help.c:404
 msgid "Specifies intentionally untracked files to ignore"
 msgstr ""
 "Especificar ficheiros não controlados para serem intencionalmente ignorados"
 
-#: builtin/help.c:412
+#: builtin/help.c:405
 msgid "Defining submodule properties"
 msgstr "Definir propriedades de submódulos"
 
-#: builtin/help.c:413
+#: builtin/help.c:406
 msgid "Specifying revisions and ranges for Git"
 msgstr "Especificar revisões e intervalos do Git"
 
-#: builtin/help.c:414
+#: builtin/help.c:407
 msgid "A tutorial introduction to Git (for version 1.5.1 or newer)"
 msgstr "Uma introdução ao Git (versão 1.5.1 ou mais recente)"
 
-#: builtin/help.c:415
+#: builtin/help.c:408
 msgid "An overview of recommended workflows with Git"
 msgstr "Uma descrição geral dos fluxos de trabalho recomendados para o Git"
 
-#: builtin/help.c:427
+#: builtin/help.c:420
 msgid "The common Git guides are:\n"
 msgstr "Os guias comuns do Git:\n"
 
-#: builtin/help.c:448 builtin/help.c:465
+#: builtin/help.c:441 builtin/help.c:458
 #, c-format
 msgid "usage: %s%s"
 msgstr "utilização: %s%s"
 
-#: builtin/help.c:481
+#: builtin/help.c:474
 #, c-format
 msgid "`git %s' is aliased to `%s'"
 msgstr "'git %s' é um alias de '%s'"
@@ -9066,7 +9022,8 @@ msgstr "O diretório %s está no índice porém nenhum submódulo?"
 
 #: builtin/mv.c:72 builtin/rm.c:317
 msgid "Please stage your changes to .gitmodules or stash them to proceed"
-msgstr "Prepare as suas alterações em .gitmodules ou esconda-as para prosseguir"
+msgstr ""
+"Prepare as suas alterações em .gitmodules ou esconda-as para prosseguir"
 
 #: builtin/mv.c:90
 #, c-format
@@ -9503,7 +9460,8 @@ msgid ""
 "Automatic notes merge failed. Fix conflicts in %s and commit the result with "
 "'git notes merge --commit', or abort the merge with 'git notes merge --"
 "abort'.\n"
-msgstr "A integração automática de notas falhou. Corrija os conflitos em %s e "
+msgstr ""
+"A integração automática de notas falhou. Corrija os conflitos em %s e "
 "submeta o resultado com 'git notes merge --commit' ou aborte a integração "
 "com 'git notes merge --abort'.\n"
 
@@ -10326,11 +10284,11 @@ msgstr "depurar unpack-trees"
 msgid "git receive-pack <git-dir>"
 msgstr "git receive-pack <git-dir>"
 
-#: builtin/receive-pack.c:1845
+#: builtin/receive-pack.c:1843
 msgid "quiet"
 msgstr "silencioso"
 
-#: builtin/receive-pack.c:1859
+#: builtin/receive-pack.c:1857
 msgid "You must specify a directory."
 msgstr "Deve especificar um diretório."
 
@@ -11400,7 +11358,8 @@ msgstr "imprimir estado do programa auxiliar remoto"
 
 #: builtin/shortlog.c:13
 msgid "git shortlog [<options>] [<revision-range>] [[--] [<path>...]]"
-msgstr "git shortlog [<opções>] [<intervalo-de-revisões>] [[--] [<caminho>...]]"
+msgstr ""
+"git shortlog [<opções>] [<intervalo-de-revisões>] [[--] [<caminho>...]]"
 
 #: builtin/shortlog.c:242
 msgid "sort output according to the number of commits per author"
@@ -12222,8 +12181,7 @@ msgstr "eliminar a referência"
 #: builtin/update-ref.c:365
 msgid "update <refname> not the one it points to"
 msgstr ""
-"atualizar a referência <nome-da-referência>, não a referência que esta "
-"aponta"
+"atualizar a referência <nome-da-referência>, não a referência que esta aponta"
 
 #: builtin/update-ref.c:366
 msgid "stdin has NUL-terminated arguments"
@@ -12597,7 +12555,8 @@ msgstr "HEAD incorreta - é necessário uma HEAD"
 #, sh-format
 msgid ""
 "Checking out '$start_head' failed. Try 'git bisect reset <valid-branch>'."
-msgstr "Falha ao extrair '$start_head'. Tente 'git bisect reset <ramo-válido>'."
+msgstr ""
+"Falha ao extrair '$start_head'. Tente 'git bisect reset <ramo-válido>'."
 
 #: git-bisect.sh:177
 msgid "won't bisect on cg-seek'ed tree"
@@ -12813,8 +12772,8 @@ msgid ""
 msgstr ""
 "Depois de resolver este problema, execute \"git rebase --continue\".\n"
 "Se prefere ignorar este patch, execute \"git rebase --skip\".\n"
-"Para extrair o ramo original e interromper o rebase, execute \"git rebase "
-"--abort\"."
+"Para extrair o ramo original e interromper o rebase, execute \"git rebase --"
+"abort\"."
 
 #: git-rebase.sh:156 git-rebase.sh:395
 #, sh-format
@@ -13477,167 +13436,43 @@ msgstr "Erro ao refazer integração $sha1"
 msgid "Could not pick $sha1"
 msgstr "Não foi possível apanhar $sha1"
 
-#: git-rebase--interactive.sh:408 git-rebase--interactive.sh:474
-msgid "This is the 1st commit message:"
-msgstr "Esta é a 1ª mensagem de commit:"
-
-#: git-rebase--interactive.sh:409
-msgid "This is the 2nd commit message:"
-msgstr "Esta é a 2ª mensagem de commit:"
-
-#: git-rebase--interactive.sh:410
-msgid "This is the 3rd commit message:"
-msgstr "Esta é a 3ª mensagem de commit:"
-
-#: git-rebase--interactive.sh:411
-msgid "This is the 4th commit message:"
-msgstr "Esta é a 4ª mensagem de commit:"
+#: git-rebase--interactive.sh:407
+#, sh-format
+msgid "This is the commit message #${n}:"
+msgstr "Esta é a mensagem de commit nº${n}:"
 
 #: git-rebase--interactive.sh:412
-msgid "This is the 5th commit message:"
-msgstr "Esta é a 5ª mensagem de commit:"
-
-#: git-rebase--interactive.sh:413
-msgid "This is the 6th commit message:"
-msgstr "Esta é a 6ª mensagem de commit:"
-
-#: git-rebase--interactive.sh:414
-msgid "This is the 7th commit message:"
-msgstr "Esta é a 7ª mensagem de commit:"
-
-#: git-rebase--interactive.sh:415
-msgid "This is the 8th commit message:"
-msgstr "Esta é a 8ª mensagem de commit:"
-
-#: git-rebase--interactive.sh:416
-msgid "This is the 9th commit message:"
-msgstr "Esta é a 9ª mensagem de commit:"
-
-#: git-rebase--interactive.sh:417
-msgid "This is the 10th commit message:"
-msgstr "Esta é a 10ª mensagem de commit:"
-
-#. TRANSLATORS: if the language you are translating into
-#. doesn't allow you to compose a sentence in this fashion,
-#. consider translating as if this and the following few strings
-#. were "This is the commit message ${n}:"
-#: git-rebase--interactive.sh:422
 #, sh-format
-msgid "This is the ${n}th commit message:"
-msgstr "Esta é a ${n}ª mensagem de commit:"
+msgid "The commit message #${n} will be skipped:"
+msgstr "A mensagem de commit nº${n} será ignorada:"
 
 #: git-rebase--interactive.sh:423
 #, sh-format
-msgid "This is the ${n}st commit message:"
-msgstr "Está é a ${n}ª mensagem de commit:"
-
-#: git-rebase--interactive.sh:424
-#, sh-format
-msgid "This is the ${n}nd commit message:"
-msgstr "Esta é a ${n}ª mensagem de commit:"
-
-#: git-rebase--interactive.sh:425
-#, sh-format
-msgid "This is the ${n}rd commit message:"
-msgstr "Esta é a ${n}ª mensagem de commit:"
-
-#: git-rebase--interactive.sh:426
-#, sh-format
-msgid "This is the commit message ${n}:"
-msgstr "Esta é a mensagem de commit ${n}:"
-
-#: git-rebase--interactive.sh:432
-msgid "The 1st commit message will be skipped:"
-msgstr "A 1ª mensagem de commit será ignorada:"
-
-#: git-rebase--interactive.sh:433
-msgid "The 2nd commit message will be skipped:"
-msgstr "A 2ª mensagem de commit será ignorada:"
-
-#: git-rebase--interactive.sh:434
-msgid "The 3rd commit message will be skipped:"
-msgstr "A 3ª mensagem de commit será ignorada:"
-
-#: git-rebase--interactive.sh:435
-msgid "The 4th commit message will be skipped:"
-msgstr "A 4ª mensagem de commit será ignorada:"
-
-#: git-rebase--interactive.sh:436
-msgid "The 5th commit message will be skipped:"
-msgstr "A 5ª mensagem de commit será ignorada:"
-
-#: git-rebase--interactive.sh:437
-msgid "The 6th commit message will be skipped:"
-msgstr "A 6ª mensagem de commit será ignorada:"
-
-#: git-rebase--interactive.sh:438
-msgid "The 7th commit message will be skipped:"
-msgstr "A 7ª mensagem de commit será ignorada:"
-
-#: git-rebase--interactive.sh:439
-msgid "The 8th commit message will be skipped:"
-msgstr "A 8ª mensagem de commit será ignorada:"
-
-#: git-rebase--interactive.sh:440
-msgid "The 9th commit message will be skipped:"
-msgstr "A 9ª mensagem de commit será ignorada:"
-
-#: git-rebase--interactive.sh:441
-msgid "The 10th commit message will be skipped:"
-msgstr "A 10ª mensagem de commit será ignorada:"
-
-#. TRANSLATORS: if the language you are translating into
-#. doesn't allow you to compose a sentence in this fashion,
-#. consider translating as if this and the following few strings
-#. were "The commit message ${n} will be skipped:"
-#: git-rebase--interactive.sh:446
-#, sh-format
-msgid "The ${n}th commit message will be skipped:"
-msgstr "A ${n}ª mensagem de commit será ignorada:"
-
-#: git-rebase--interactive.sh:447
-#, sh-format
-msgid "The ${n}st commit message will be skipped:"
-msgstr "A ${n}ª mensagem de commit será ignorada:"
-
-#: git-rebase--interactive.sh:448
-#, sh-format
-msgid "The ${n}nd commit message will be skipped:"
-msgstr "A ${n}ª mensagem de commit será ignorada:"
-
-#: git-rebase--interactive.sh:449
-#, sh-format
-msgid "The ${n}rd commit message will be skipped:"
-msgstr "A ${n}ª mensagem de commit será ignorada:"
-
-#: git-rebase--interactive.sh:450
-#, sh-format
-msgid "The commit message ${n} will be skipped:"
-msgstr "A mensagem de commit ${n} será ignorada:"
-
-#: git-rebase--interactive.sh:462
-#, sh-format
 msgid "This is a combination of $count commit."
 msgid_plural "This is a combination of $count commits."
 msgstr[0] "Isto é a combinação de $count commit."
 msgstr[1] "Isto é a combinação de $count commits."
 
-#: git-rebase--interactive.sh:470
+#: git-rebase--interactive.sh:431
 #, sh-format
 msgid "Cannot write $fixup_msg"
 msgstr "Não é possível escrever $fixup_msg"
 
-#: git-rebase--interactive.sh:473
+#: git-rebase--interactive.sh:434
 msgid "This is a combination of 2 commits."
 msgstr "Isto é a combinação de 2 commits."
 
-#: git-rebase--interactive.sh:514 git-rebase--interactive.sh:557
-#: git-rebase--interactive.sh:560
+#: git-rebase--interactive.sh:435
+msgid "This is the 1st commit message:"
+msgstr "Esta é a 1ª mensagem de commit:"
+
+#: git-rebase--interactive.sh:475 git-rebase--interactive.sh:518
+#: git-rebase--interactive.sh:521
 #, sh-format
 msgid "Could not apply $sha1... $rest"
 msgstr "Não foi possível aplicar $sha1... $rest"
 
-#: git-rebase--interactive.sh:588
+#: git-rebase--interactive.sh:549
 #, sh-format
 msgid ""
 "Could not amend commit after successfully picking $sha1... $rest\n"
@@ -13654,31 +13489,31 @@ msgstr ""
 "poder\n"
 "reformular a mensagem do commit."
 
-#: git-rebase--interactive.sh:603
+#: git-rebase--interactive.sh:564
 #, sh-format
 msgid "Stopped at $sha1_abbrev... $rest"
 msgstr "Parou em $sha1_abbrev... $rest"
 
-#: git-rebase--interactive.sh:618
+#: git-rebase--interactive.sh:579
 #, sh-format
 msgid "Cannot '$squash_style' without a previous commit"
 msgstr "Não é possível efetuar '$squash_style' sem um commit anterior"
 
-#: git-rebase--interactive.sh:660
+#: git-rebase--interactive.sh:621
 #, sh-format
 msgid "Executing: $rest"
 msgstr "A executar: $rest"
 
-#: git-rebase--interactive.sh:668
+#: git-rebase--interactive.sh:629
 #, sh-format
 msgid "Execution failed: $rest"
 msgstr "Falha ao executar: $rest"
 
-#: git-rebase--interactive.sh:670
+#: git-rebase--interactive.sh:631
 msgid "and made changes to the index and/or the working tree"
 msgstr "e fez alterações ao índice e/ou à árvore de trabalho"
 
-#: git-rebase--interactive.sh:672
+#: git-rebase--interactive.sh:633
 msgid ""
 "You can fix the problem, and then run\n"
 "\n"
@@ -13689,7 +13524,7 @@ msgstr ""
 "\tgit rebase --continue"
 
 #. TRANSLATORS: after these lines is a command to be issued by the user
-#: git-rebase--interactive.sh:685
+#: git-rebase--interactive.sh:646
 #, sh-format
 msgid ""
 "Execution succeeded: $rest\n"
@@ -13704,25 +13539,25 @@ msgstr ""
 "\n"
 "\tgit rebase --continue"
 
-#: git-rebase--interactive.sh:696
+#: git-rebase--interactive.sh:657
 #, sh-format
 msgid "Unknown command: $command $sha1 $rest"
 msgstr "Comando desconhecido: $command $sha1 $rest"
 
-#: git-rebase--interactive.sh:697
+#: git-rebase--interactive.sh:658
 msgid "Please fix this using 'git rebase --edit-todo'."
 msgstr "Corrija-o usando 'git rebase --edit-todo'."
 
-#: git-rebase--interactive.sh:732
+#: git-rebase--interactive.sh:693
 #, sh-format
 msgid "Successfully rebased and updated $head_name."
 msgstr "$head_name rebaseado e atualizado com sucesso."
 
-#: git-rebase--interactive.sh:779
+#: git-rebase--interactive.sh:740
 msgid "Could not skip unnecessary pick commands"
 msgstr "Não foi possível saltar comandos pick desnecessários"
 
-#: git-rebase--interactive.sh:937
+#: git-rebase--interactive.sh:898
 #, sh-format
 msgid ""
 "Warning: the SHA-1 is missing or isn't a commit in the following line:\n"
@@ -13731,7 +13566,7 @@ msgstr ""
 "Aviso: falta o SHA-1 ou a seguinte linha não tem um commit:\n"
 " - $line"
 
-#: git-rebase--interactive.sh:970
+#: git-rebase--interactive.sh:931
 #, sh-format
 msgid ""
 "Warning: the command isn't recognized in the following line:\n"
@@ -13740,11 +13575,11 @@ msgstr ""
 "Aviso: o comando não é reconhecido na seguinte linha:\n"
 " - $line"
 
-#: git-rebase--interactive.sh:1009
+#: git-rebase--interactive.sh:970
 msgid "could not detach HEAD"
 msgstr "não foi possível destacar HEAD"
 
-#: git-rebase--interactive.sh:1047
+#: git-rebase--interactive.sh:1008
 msgid ""
 "Warning: some commits may have been dropped accidentally.\n"
 "Dropped commits (newer to older):"
@@ -13752,7 +13587,7 @@ msgstr ""
 "Aviso: alguns commits podem ter sido descartados acidentalmente.\n"
 "Commits descartados (mais novo para o mais velho):"
 
-#: git-rebase--interactive.sh:1055
+#: git-rebase--interactive.sh:1016
 msgid ""
 "To avoid this message, use \"drop\" to explicitly remove a commit.\n"
 "\n"
@@ -13760,12 +13595,13 @@ msgid ""
 "warnings.\n"
 "The possible behaviours are: ignore, warn, error."
 msgstr ""
-"Para evitar esta mensagem, use \"drop\" para remover um commit explicitamente.\n"
+"Para evitar esta mensagem, use \"drop\" para remover um commit "
+"explicitamente.\n"
 "\n"
 "Use 'git config rebase.missingCommitsCheck' para mudar o nível de avisos.\n"
 "O comportamentos possíveis são: ignore, warn, error."
 
-#: git-rebase--interactive.sh:1066
+#: git-rebase--interactive.sh:1027
 #, sh-format
 msgid ""
 "Unrecognized setting $check_level for option rebase.missingCommitsCheck. "
@@ -13774,19 +13610,19 @@ msgstr ""
 "Definição $check_level desconhecida da opção rebase.missingCommitsCheck. "
 "Ignorado."
 
-#: git-rebase--interactive.sh:1083
+#: git-rebase--interactive.sh:1044
 msgid "You can fix this with 'git rebase --edit-todo'."
 msgstr "Pode corrí-lo com 'git rebase --edit-todo'."
 
-#: git-rebase--interactive.sh:1084
+#: git-rebase--interactive.sh:1045
 msgid "Or you can abort the rebase with 'git rebase --abort'."
 msgstr "Ou pode abortar o rebase com 'git rebase --abort'."
 
-#: git-rebase--interactive.sh:1108
+#: git-rebase--interactive.sh:1069
 msgid "Could not remove CHERRY_PICK_HEAD"
 msgstr "Não foi possível remover CHERRY_PICK_HEAD"
 
-#: git-rebase--interactive.sh:1113
+#: git-rebase--interactive.sh:1074
 #, sh-format
 msgid ""
 "You have staged changes in your working tree.\n"
@@ -13817,11 +13653,11 @@ msgstr ""
 "\n"
 "  git rebase --continue\n"
 
-#: git-rebase--interactive.sh:1130
+#: git-rebase--interactive.sh:1091
 msgid "Error trying to find the author identity to amend commit"
 msgstr "Erro ao tentar encontrar a identidade do autor para emendar o commit"
 
-#: git-rebase--interactive.sh:1135
+#: git-rebase--interactive.sh:1096
 msgid ""
 "You have uncommitted changes in your working tree. Please commit them\n"
 "first and then run 'git rebase --continue' again."
@@ -13829,11 +13665,11 @@ msgstr ""
 "Tem alterações por submeter na árvore de trabalho. Submeta-as primeiro\n"
 "e execute 'git rebase --continue' de novo."
 
-#: git-rebase--interactive.sh:1140 git-rebase--interactive.sh:1144
+#: git-rebase--interactive.sh:1101 git-rebase--interactive.sh:1105
 msgid "Could not commit staged changes."
 msgstr "Não foi possível submeter as alterações preparadas."
 
-#: git-rebase--interactive.sh:1168
+#: git-rebase--interactive.sh:1129
 msgid ""
 "\n"
 "You are editing the todo file of an ongoing interactive rebase.\n"
@@ -13847,44 +13683,44 @@ msgstr ""
 "    git rebase --continue\n"
 "\n"
 
-#: git-rebase--interactive.sh:1176 git-rebase--interactive.sh:1337
+#: git-rebase--interactive.sh:1137 git-rebase--interactive.sh:1298
 msgid "Could not execute editor"
 msgstr "Não foi possível executar o editor"
 
-#: git-rebase--interactive.sh:1184
+#: git-rebase--interactive.sh:1145
 msgid "You need to set your committer info first"
 msgstr "Primeiro tem de definir a sua informação de committer"
 
-#: git-rebase--interactive.sh:1192
+#: git-rebase--interactive.sh:1153
 #, sh-format
 msgid "Could not checkout $switch_to"
 msgstr "Não foi possível extrair $switch_to"
 
-#: git-rebase--interactive.sh:1197
+#: git-rebase--interactive.sh:1158
 msgid "No HEAD?"
 msgstr "Sem HEAD?"
 
-#: git-rebase--interactive.sh:1198
+#: git-rebase--interactive.sh:1159
 #, sh-format
 msgid "Could not create temporary $state_dir"
 msgstr "Não foi possível criar $state_dir temporário"
 
-#: git-rebase--interactive.sh:1200
+#: git-rebase--interactive.sh:1161
 msgid "Could not mark as interactive"
 msgstr "Não foi possível marcar como interativo"
 
-#: git-rebase--interactive.sh:1210 git-rebase--interactive.sh:1215
+#: git-rebase--interactive.sh:1171 git-rebase--interactive.sh:1176
 msgid "Could not init rewritten commits"
 msgstr "Não foi possível inicializar commits reescritos"
 
-#: git-rebase--interactive.sh:1315
+#: git-rebase--interactive.sh:1276
 #, sh-format
 msgid "Rebase $shortrevisions onto $shortonto ($todocount command)"
 msgid_plural "Rebase $shortrevisions onto $shortonto ($todocount commands)"
 msgstr[0] "Rebase $shortrevisions sobre $shortonto ($todocount comando)"
 msgstr[1] "Rebase $shortrevisions sobre $shortonto ($todocount comandos)"
 
-#: git-rebase--interactive.sh:1320
+#: git-rebase--interactive.sh:1281
 msgid ""
 "\n"
 "However, if you remove everything, the rebase will be aborted.\n"
@@ -13894,7 +13730,7 @@ msgstr ""
 "No entanto, se remover tudo, o rebase será abortado.\n"
 "\n"
 
-#: git-rebase--interactive.sh:1327
+#: git-rebase--interactive.sh:1288
 msgid "Note that empty commits are commented out"
 msgstr "Note que commits vazios são comentados"
 
@@ -13946,6 +13782,123 @@ msgstr ""
 msgid "Unable to determine absolute path of git directory"
 msgstr "Não é possível determinar o caminho absoluto do diretório git"
 
+#~ msgid "bad numeric config value '%s' for '%s': invalid unit"
+#~ msgstr ""
+#~ "valor numérico '%s' da configuração '%s' incorreto: unidade inválida"
+
+#~ msgid "bad numeric config value '%s' for '%s' in blob %s: invalid unit"
+#~ msgstr ""
+#~ "valor numérico '%s' da configuração '%s' incorreto no blob %s: unidade "
+#~ "inválida"
+
+#~ msgid "bad numeric config value '%s' for '%s' in file %s: invalid unit"
+#~ msgstr ""
+#~ "valor numérico '%s' da configuração '%s' incorreto no ficheiro %s: "
+#~ "unidade inválida"
+
+#~ msgid ""
+#~ "bad numeric config value '%s' for '%s' in standard input: invalid unit"
+#~ msgstr ""
+#~ "valor numérico '%s' da configuração '%s' incorreto na entrada padrão: "
+#~ "unidade inválida"
+
+#~ msgid ""
+#~ "bad numeric config value '%s' for '%s' in submodule-blob %s: invalid unit"
+#~ msgstr ""
+#~ "valor numérico '%s' da configuração '%s' incorreto no submódulo-blob %s: "
+#~ "unidade inválida"
+
+#~ msgid ""
+#~ "bad numeric config value '%s' for '%s' in command line %s: invalid unit"
+#~ msgstr ""
+#~ "valor numérico '%s' da configuração '%s' incorreto na linha de comandos "
+#~ "%s: unidade inválida"
+
+#~ msgid "bad numeric config value '%s' for '%s' in %s: invalid unit"
+#~ msgstr ""
+#~ "valor numérico '%s' da configuração '%s' incorreto em %s: unidade inválida"
+
+#~ msgid "This is the 2nd commit message:"
+#~ msgstr "Esta é a 2ª mensagem de commit:"
+
+#~ msgid "This is the 3rd commit message:"
+#~ msgstr "Esta é a 3ª mensagem de commit:"
+
+#~ msgid "This is the 4th commit message:"
+#~ msgstr "Esta é a 4ª mensagem de commit:"
+
+#~ msgid "This is the 5th commit message:"
+#~ msgstr "Esta é a 5ª mensagem de commit:"
+
+#~ msgid "This is the 6th commit message:"
+#~ msgstr "Esta é a 6ª mensagem de commit:"
+
+#~ msgid "This is the 7th commit message:"
+#~ msgstr "Esta é a 7ª mensagem de commit:"
+
+#~ msgid "This is the 8th commit message:"
+#~ msgstr "Esta é a 8ª mensagem de commit:"
+
+#~ msgid "This is the 9th commit message:"
+#~ msgstr "Esta é a 9ª mensagem de commit:"
+
+#~ msgid "This is the 10th commit message:"
+#~ msgstr "Esta é a 10ª mensagem de commit:"
+
+#~ msgid "This is the ${n}th commit message:"
+#~ msgstr "Esta é a ${n}ª mensagem de commit:"
+
+#~ msgid "This is the ${n}st commit message:"
+#~ msgstr "Está é a ${n}ª mensagem de commit:"
+
+#~ msgid "This is the ${n}nd commit message:"
+#~ msgstr "Esta é a ${n}ª mensagem de commit:"
+
+#~ msgid "This is the ${n}rd commit message:"
+#~ msgstr "Esta é a ${n}ª mensagem de commit:"
+
+#~ msgid "The 1st commit message will be skipped:"
+#~ msgstr "A 1ª mensagem de commit será ignorada:"
+
+#~ msgid "The 2nd commit message will be skipped:"
+#~ msgstr "A 2ª mensagem de commit será ignorada:"
+
+#~ msgid "The 3rd commit message will be skipped:"
+#~ msgstr "A 3ª mensagem de commit será ignorada:"
+
+#~ msgid "The 4th commit message will be skipped:"
+#~ msgstr "A 4ª mensagem de commit será ignorada:"
+
+#~ msgid "The 5th commit message will be skipped:"
+#~ msgstr "A 5ª mensagem de commit será ignorada:"
+
+#~ msgid "The 6th commit message will be skipped:"
+#~ msgstr "A 6ª mensagem de commit será ignorada:"
+
+#~ msgid "The 7th commit message will be skipped:"
+#~ msgstr "A 7ª mensagem de commit será ignorada:"
+
+#~ msgid "The 8th commit message will be skipped:"
+#~ msgstr "A 8ª mensagem de commit será ignorada:"
+
+#~ msgid "The 9th commit message will be skipped:"
+#~ msgstr "A 9ª mensagem de commit será ignorada:"
+
+#~ msgid "The 10th commit message will be skipped:"
+#~ msgstr "A 10ª mensagem de commit será ignorada:"
+
+#~ msgid "The ${n}th commit message will be skipped:"
+#~ msgstr "A ${n}ª mensagem de commit será ignorada:"
+
+#~ msgid "The ${n}st commit message will be skipped:"
+#~ msgstr "A ${n}ª mensagem de commit será ignorada:"
+
+#~ msgid "The ${n}nd commit message will be skipped:"
+#~ msgstr "A ${n}ª mensagem de commit será ignorada:"
+
+#~ msgid "The ${n}rd commit message will be skipped:"
+#~ msgstr "A ${n}ª mensagem de commit será ignorada:"
+
 #~ msgid "could not run gpg."
 #~ msgstr "não foi possível executar gpg."
 
@@ -14034,7 +13987,8 @@ msgstr "Não é possível determinar o caminho absoluto do diretório git"
 #~ "use the '--force' option. If the local git directory is not the correct "
 #~ "repo"
 #~ msgstr ""
-#~ "use a opção '--force'. Se o diretório git local não é o repositório correto"
+#~ "use a opção '--force'. Se o diretório git local não é o repositório "
+#~ "correto"
 
 #~ msgid ""
 #~ "or you are unsure what this means choose another name with the '--name' "
@@ -14140,7 +14094,8 @@ msgstr "Não é possível determinar o caminho absoluto do diretório git"
 #~ "Quando push.default está definido como 'matching', o Git publica\n"
 #~ "os ramos locais nos ramos remotos que já existam com o mesmo nome.\n"
 #~ "\n"
-#~ "Desde a versão 2.0, o Git assume o comportamento mais conservativo 'simple',\n"
+#~ "Desde a versão 2.0, o Git assume o comportamento mais conservativo "
+#~ "'simple',\n"
 #~ "publicando só o ramo atual no ramo remoto correspondente, que é usado\n"
 #~ "para atualizar o ramo atual com 'git pull'.\n"
 #~ "Consulte 'git help config' e procure por 'push.default' para mais "
index ac7f5b4cb1be7b0f1a542ae4fb65b2aafbd48d2a..dc312227e051e2ad919437f474f0b3de69f419e2 100644 (file)
@@ -136,7 +136,7 @@ msgstr ""
 "Project-Id-Version: Git\n"
 "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
 "POT-Creation-Date: 2016-08-27 23:21+0800\n"
-"PO-Revision-Date: 2016-08-31 00:11+0800\n"
+"PO-Revision-Date: 2016-09-05 23:36+0800\n"
 "Last-Translator: Jiang Xin <worldhello.net@gmail.com>\n"
 "Language-Team: GitHub <https://github.com/jiangxin/git/>\n"
 "Language: zh_CN\n"
@@ -319,7 +319,7 @@ msgstr "远程 git-upload-archive 命令的路径"
 
 #: archive.c:461
 msgid "Unexpected option --remote"
-msgstr "æ\84\8få¤\96ç\9a\84é\80\89项 --remote"
+msgstr "æ\9cªç\9f¥å\8f\82æ\95° --remote"
 
 #: archive.c:463
 msgid "Option --exec can only be used together with --remote"
@@ -419,7 +419,7 @@ msgstr ""
 #: bisect.c:798
 #, c-format
 msgid "Bisecting: a merge base must be tested\n"
-msgstr "二分查找中:合并基线必须要测试\n"
+msgstr "二分查找中:合并基线必须是经过测试的\n"
 
 #: bisect.c:849
 #, c-format
@@ -467,8 +467,8 @@ msgstr[1] "(大概 %d 步)"
 #, c-format
 msgid "Bisecting: %d revision left to test after this %s\n"
 msgid_plural "Bisecting: %d revisions left to test after this %s\n"
-msgstr[0] "二分查找中:在 %2$s 之后还剩下 %1$d 个版本\n"
-msgstr[1] "二分查找中:在 %2$s 之后还剩下 %1$d 个版本\n"
+msgstr[0] "二分查找中:在此之后,还剩 %d 个版本待测试 %s\n"
+msgstr[1] "二分查找中:在此之后,还剩 %d 个版本待测试 %s\n"
 
 #: branch.c:53
 #, c-format
@@ -720,7 +720,7 @@ msgstr "标准输入中错误的配置行 %d"
 #: config.c:528
 #, c-format
 msgid "bad config line %d in submodule-blob %s"
-msgstr "子模组数据 %2$s 中错误的配置行 %1$d"
+msgstr "子模组数据对象 %2$s 中错误的配置行 %1$d"
 
 #: config.c:532
 #, c-format
@@ -743,37 +743,37 @@ msgstr "无效的单位"
 #: config.c:661
 #, c-format
 msgid "bad numeric config value '%s' for '%s': %s"
-msgstr "配置变量 '%2$s' 的数字取值 '%1$s' 设置错误%3$s"
+msgstr "配置变量 '%2$s' 的数字取值 '%1$s' 设置错误%3$s"
 
 #: config.c:666
 #, c-format
 msgid "bad numeric config value '%s' for '%s' in blob %s: %s"
-msgstr "数据对象 %3$s 中配置变量 '%2$s' 错误的取值 '%1$s'%4$s"
+msgstr "数据对象 %3$s 中配置变量 '%2$s' 错误的取值 '%1$s'%4$s"
 
 #: config.c:669
 #, c-format
 msgid "bad numeric config value '%s' for '%s' in file %s: %s"
-msgstr "文件 %3$s 中配置变量 '%2$s' 错误的取值 '%1$s'%4$s"
+msgstr "文件 %3$s 中配置变量 '%2$s' 错误的取值 '%1$s'%4$s"
 
 #: config.c:672
 #, c-format
 msgid "bad numeric config value '%s' for '%s' in standard input: %s"
-msgstr "标准输入中配置变量 '%2$s' 错误的取值 '%1$s'%3$s"
+msgstr "标准输入中配置变量 '%2$s' 错误的取值 '%1$s'%3$s"
 
 #: config.c:675
 #, c-format
 msgid "bad numeric config value '%s' for '%s' in submodule-blob %s: %s"
-msgstr "子模组数据 %3$s 中配置变量 '%2$s' 错误的取值 '%1$s'%4$s"
+msgstr "子模组数据 %3$s 中配置变量 '%2$s' 错误的取值 '%1$s'%4$s"
 
 #: config.c:678
 #, c-format
 msgid "bad numeric config value '%s' for '%s' in command line %s: %s"
-msgstr "命令行 %3$s 中配置变量 '%2$s' 错误的取值 '%1$s'%4$s"
+msgstr "命令行 %3$s 中配置变量 '%2$s' 错误的取值 '%1$s'%4$s"
 
 #: config.c:681
 #, c-format
 msgid "bad numeric config value '%s' for '%s' in %s: %s"
-msgstr "在 %3$s 中配置变量 '%2$s' 错误的取值 '%1$s'%4$s"
+msgstr "在 %3$s 中配置变量 '%2$s' 错误的取值 '%1$s'%4$s"
 
 #: config.c:768
 #, c-format
@@ -949,7 +949,7 @@ msgstr "外部 diff 退出,停止在 %s"
 
 #: diff.c:3415
 msgid "--follow requires exactly one pathspec"
-msgstr "--follow 参数后只跟一个 pathspec"
+msgstr "--follow 明确要求只跟一个路径规格"
 
 #: diff.c:3578
 #, c-format
@@ -1033,7 +1033,7 @@ msgid ""
 "WARNING: You called a Git command named '%s', which does not exist.\n"
 "Continuing under the assumption that you meant '%s'"
 msgstr ""
-"è­¦å\91\8aï¼\9aæ\82¨è¿\90è¡\8cä¸\80个ä¸\8då­\98å\9c¨ç\9a\84 Git å\91½ä»¤ '%s'ã\80\82继续æ\89§è¡\8cå\81\87å®\9aæ\82¨è¦\81è¦\81è¿\90è¡\8cç\9a\84\n"
+"警告:您运行一个不存在的 Git 命令 '%s'。继续执行假定您要运行的\n"
 "是 '%s'"
 
 #: help.c:393
@@ -2059,7 +2059,7 @@ msgid ""
 "Use '--' to separate paths from revisions, like this:\n"
 "'git <command> [<revision>...] -- [<file>...]'"
 msgstr ""
-"有歧义的参数 '%s':工作区中未知的版本或路径。\n"
+"有歧义的参数 '%s':未知的版本或路径不存在于工作区中。\n"
 "使用 '--' 来分隔版本和路径,例如:\n"
 "'git <command> [<revision>...] -- [<file>...]'"
 
@@ -2070,7 +2070,7 @@ msgid ""
 "Use '--' to separate paths from revisions, like this:\n"
 "'git <command> [<revision>...] -- [<file>...]'"
 msgstr ""
-"有歧义的参数 '%s':两者均为版本和文件\n"
+"有歧义的参数 '%s':可同时是版本和文件\n"
 "使用 '--' 来分隔版本和路径,例如:\n"
 "'git <command> [<revision>...] -- [<file>...]'"
 
@@ -2107,7 +2107,7 @@ msgid ""
 "Not a git repository (or any parent up to mount point %s)\n"
 "Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set)."
 msgstr ""
-"不是一个 git 仓库(或者任何向上递归到挂载点 %s)\n"
+"不是一个 git 仓库(或者向上递归至挂载点 %s 的任何祖先目录)\n"
 "停止在文件系统边界(未设置 GIT_DISCOVERY_ACROSS_FILESYSTEM)。"
 
 #: setup.c:927
@@ -2121,7 +2121,7 @@ msgid ""
 "Problem with core.sharedRepository filemode value (0%.3o).\n"
 "The owner of files must always have read and write permissions."
 msgstr ""
-"参数 core.sharedRepository 的文件权限值有错(0%.3o)。\n"
+"参数 core.sharedRepository 的文件权限值有错(0%.3o)。\n"
 "文件属主必须始终拥有读写权限。"
 
 #: sha1_file.c:1046
@@ -2260,7 +2260,7 @@ msgstr "传输:无效的深度选项 '%s'"
 msgid ""
 "The following submodule paths contain changes that can\n"
 "not be found on any remote:\n"
-msgstr "如下的子模组路径的修改在任何远程源中都找不到:\n"
+msgstr "下列子模组路径所包含的修改在任何远程源中都找不到:\n"
 
 #: transport.c:775
 #, c-format
@@ -2286,7 +2286,7 @@ msgstr ""
 "\n"
 "\tgit push\n"
 "\n"
-"来推送到远程源。\n"
+"以推送至远程。\n"
 "\n"
 
 #: transport.c:783
@@ -6815,7 +6815,7 @@ msgstr "[已拒绝]"
 
 #: builtin/fetch.c:610
 msgid "can't fetch in current branch"
-msgstr "不能获取到当前分支"
+msgstr "当前分支下不能执行获取操作"
 
 #: builtin/fetch.c:619
 msgid "[tag update]"
@@ -7922,12 +7922,12 @@ msgstr "重新初始化已存在的 Git 仓库于 %s%s\n"
 #: builtin/init-db.c:407
 #, c-format
 msgid "Initialized empty shared Git repository in %s%s\n"
-msgstr "初始化空的共享 Git 仓库于 %s%s\n"
+msgstr "å·²å\88\9då§\8bå\8c\96空ç\9a\84å\85±äº« Git ä»\93åº\93äº\8e %s%s\n"
 
 #: builtin/init-db.c:408
 #, c-format
 msgid "Initialized empty Git repository in %s%s\n"
-msgstr "初始化空的 Git 仓库于 %s%s\n"
+msgstr "å·²å\88\9då§\8bå\8c\96空ç\9a\84 Git ä»\93åº\93äº\8e %s%s\n"
 
 #: builtin/init-db.c:455
 msgid ""
@@ -8718,7 +8718,7 @@ msgstr "对于 %s 没有来自 %s 的远程跟踪分支"
 #: builtin/merge.c:960
 #, c-format
 msgid "Bad value '%s' in environment '%s'"
-msgstr "环境 '%2$s' 坏的取值 '%1$s'"
+msgstr "环境 '%2$s' 中存在坏的取值 '%1$s'"
 
 #: builtin/merge.c:1034
 #, c-format
@@ -9378,7 +9378,7 @@ msgstr "不能混用 --commit、--abort 或 -s/--strategy"
 
 #: builtin/notes.c:797
 msgid "Must specify a notes ref to merge"
-msgstr "必须指定一个注解引用来合并"
+msgstr "必须指定一个注解引用来合并"
 
 #: builtin/notes.c:821
 #, c-format
@@ -10091,7 +10091,7 @@ msgstr "server-specific"
 
 #: builtin/push.c:546
 msgid "option to transmit"
-msgstr "传输选项"
+msgstr "传输选项"
 
 #: builtin/push.c:560
 msgid "--delete is incompatible with --all, --mirror and --tags"
@@ -11566,7 +11566,7 @@ msgstr "并发任务"
 
 #: builtin/submodule--helper.c:840
 msgid "whether the initial clone should follow the shallow recommendation"
-msgstr "是否初始克隆应该遵守推荐的浅克隆选项"
+msgstr "初始克隆是否应该遵守推荐的浅克隆选项"
 
 #: builtin/submodule--helper.c:841
 msgid "don't print cloning progress"
@@ -12422,17 +12422,17 @@ msgstr "坏的 bisect_write 参数:$state"
 #: git-bisect.sh:262
 #, sh-format
 msgid "Bad rev input: $arg"
-msgstr "输入坏的版本:$arg"
+msgstr "坏的输入版本:$arg"
 
 #: git-bisect.sh:281
 #, sh-format
 msgid "Bad rev input: $bisected_head"
-msgstr "输入坏的版本:$bisected_head"
+msgstr "坏的输入版本:$bisected_head"
 
 #: git-bisect.sh:290
 #, sh-format
 msgid "Bad rev input: $rev"
-msgstr "输入坏的版本:$rev"
+msgstr "坏的输入版本:$rev"
 
 #: git-bisect.sh:299
 #, sh-format
@@ -12579,7 +12579,7 @@ msgstr "错误:您对下列文件的本地修改将被合并操作覆盖"
 
 #: git-merge-octopus.sh:61
 msgid "Automated merge did not work."
-msgstr "自动合并不工作"
+msgstr "自动合并未生效。"
 
 #: git-merge-octopus.sh:62
 msgid "Should not be doing an Octopus."
@@ -12607,7 +12607,7 @@ msgstr "尝试和 $pretty_name 的简单合并"
 
 #: git-merge-octopus.sh:102
 msgid "Simple merge did not work, trying automatic merge."
-msgstr "简单合并不行,尝试自动合并。"
+msgstr "简单合并未生效,尝试自动合并。"
 
 #: git-rebase.sh:56
 msgid ""
@@ -12881,7 +12881,7 @@ msgstr "索引的进度没有被恢复。"
 
 #: git-stash.sh:551
 msgid "The stash is kept in case you need it again."
-msgstr "进度保存以免您再需要。"
+msgstr "暂存被保留以备您再次需要。"
 
 #: git-stash.sh:560
 #, sh-format
@@ -13003,7 +13003,7 @@ msgid ""
 "(use 'rm -rf' if you really want to remove it including all of its history)"
 msgstr ""
 "子模组工作区 '$displaypath' 包含一个 .git 目录\n"
-"(使用 'rm -rf' 命令如果您真的想删除它及其全部历史)"
+"(如果您真的想删除它及其全部历史,使用 'rm -rf' 命令)"
 
 #: git-submodule.sh:447
 #, sh-format
@@ -13047,7 +13047,7 @@ msgstr "无法在子模组路径 '$sm_path' 中获取"
 msgid ""
 "Unable to find current ${remote_name}/${branch} revision in submodule path "
 "'$sm_path'"
-msgstr "无法在子模组路径 '$sm_path' 中找到当前 ${remote_name}/${branch} 版本"
+msgstr "无法在子模组路径 '$sm_path' 中找到当前版本 ${remote_name}/${branch}"
 
 #: git-submodule.sh:645
 #, sh-format
@@ -13181,7 +13181,7 @@ msgstr ""
 " x, exec = 使用 shell 运行命令(此行剩余部分)\n"
 " d, drop = 删除提交\n"
 "\n"
-"这些行可以重新排序,从上至下地执行。\n"
+"这些行可以被重新排序;它们会被从上至下地执行。\n"
 "\n"
 
 #: git-rebase--interactive.sh:162
@@ -13194,7 +13194,7 @@ msgstr "\n不要删除任意一行。使用 'drop' 显式地删除一个提交
 msgid ""
 "\n"
 "If you remove a line here THAT COMMIT WILL BE LOST.\n"
-msgstr "\n如果您在这里删除一行,这个提交将会丢失。\n"
+msgstr "\n如果您在这里删除一行,对应的提交将会丢失。\n"
 
 #: git-rebase--interactive.sh:202
 #, sh-format
@@ -13211,7 +13211,7 @@ msgstr ""
 "\n"
 "\tgit commit --amend $gpg_sign_opt_quoted\n"
 "\n"
-"一旦您对变更满意,执行\n"
+"当您对变更感到满意,执行\n"
 "\n"
 "\tgit rebase --continue"
 
@@ -13262,12 +13262,12 @@ msgstr "不能拣选 $sha1"
 #: git-rebase--interactive.sh:407
 #, sh-format
 msgid "This is the commit message #${n}:"
-msgstr "这是提交信息 #${n}:"
+msgstr "这是提交说明 #${n}:"
 
 #: git-rebase--interactive.sh:412
 #, sh-format
 msgid "The commit message #${n} will be skipped:"
-msgstr "提交信息 #${n} 将被跳过:"
+msgstr "提交说明 #${n} 将被跳过:"
 
 #: git-rebase--interactive.sh:423
 #, sh-format
@@ -13316,7 +13316,7 @@ msgstr "停止在 $sha1_abbrev... $rest"
 #: git-rebase--interactive.sh:579
 #, sh-format
 msgid "Cannot '$squash_style' without a previous commit"
-msgstr "不能在没有前一个提交的情况下 '$squash_style'"
+msgstr "没有父提交的情况下不能 '$squash_style'"
 
 #: git-rebase--interactive.sh:621
 #, sh-format
@@ -13370,7 +13370,7 @@ msgstr "要修改请使用命令 'git rebase --edit-todo'。"
 #: git-rebase--interactive.sh:693
 #, sh-format
 msgid "Successfully rebased and updated $head_name."
-msgstr "成功变基并更新 $head_name."
+msgstr "成功变基并更新 $head_name"
 
 #: git-rebase--interactive.sh:740
 msgid "Could not skip unnecessary pick commands"
@@ -13412,17 +13412,17 @@ msgid ""
 "warnings.\n"
 "The possible behaviours are: ignore, warn, error."
 msgstr ""
-"为避免这条信息,使用 drop 指令显式地删除一个提交。\n"
+"为避免这条信息,使用 \"drop\" 指令显式地删除一个提交。\n"
 "\n"
-"使ç\94¨ 'git config rebase.missingCommitsCheck' æ\9d¥ä¿®æ\94¹è¿\99个级å\88«ç\9a\84è­¦å\91\8a。\n"
-"可以使用:ignore、warn、error。"
+"使ç\94¨ 'git config rebase.missingCommitsCheck' æ\9d¥ä¿®æ\94¹è­¦å\91\8a级å\88«。\n"
+"可选值有:ignore、warn、error。"
 
 #: git-rebase--interactive.sh:1027
 #, sh-format
 msgid ""
 "Unrecognized setting $check_level for option rebase.missingCommitsCheck. "
 "Ignoring."
-msgstr "选项 rebase.missingCommitsCheck 中无法识别的设置 $check_level。忽略。"
+msgstr "选项 rebase.missingCommitsCheck 的值 $check_level 无法被识别。已忽略。"
 
 #: git-rebase--interactive.sh:1044
 msgid "You can fix this with 'git rebase --edit-todo'."
@@ -13461,19 +13461,19 @@ msgstr ""
 "\n"
 "  git commit $gpg_sign_opt_quoted\n"
 "\n"
-"两种情况下,一旦执行完毕,继续执行:\n"
+"无论哪种情况,当您完成提交,继续执行:\n"
 "\n"
 "  git rebase --continue\n"
 
 #: git-rebase--interactive.sh:1091
 msgid "Error trying to find the author identity to amend commit"
-msgstr "å½\93å\9c¨ä¿®è¡¥æ\8f\90交中æ\9f¥æ\89¾ä½\9cè\80\85ä¿¡æ\81¯æ\97¶é\81\87å\88°é\94\99误"
+msgstr "在修补提交中查找作者信息时遇到错误"
 
 #: git-rebase--interactive.sh:1096
 msgid ""
 "You have uncommitted changes in your working tree. Please commit them\n"
 "first and then run 'git rebase --continue' again."
-msgstr "您的工作区中有未提交的变更。请先提交然后再运行 'git rebase --continue'。"
+msgstr "您的工作区中有未提交的变更。请先提交然后再运行 'git rebase --continue'。"
 
 #: git-rebase--interactive.sh:1101 git-rebase--interactive.sh:1105
 msgid "Could not commit staged changes."
@@ -13488,7 +13488,7 @@ msgid ""
 "\n"
 msgstr ""
 "\n"
-"您正在修改运行中的交互式变基的 todo 文件。编辑结束后继续变基,\n"
+"您正在修改运行中的交互式变基的 todo 文件。若要在编辑结束后继续变基,\n"
 "请执行:\n"
 "    git rebase --continue\n"
 "\n"
@@ -13549,7 +13549,7 @@ msgstr "用法:$dashless $USAGE"
 #: git-sh-setup.sh:190
 #, sh-format
 msgid "Cannot chdir to $cdup, the toplevel of the working tree"
-msgstr "不能换目录到 $cdup,工作区的顶级目录"
+msgstr "不能换目录到 $cdup,工作区的顶级目录"
 
 #: git-sh-setup.sh:199 git-sh-setup.sh:206
 #, sh-format
index 9609afb510e2486ae857501a160a9234be87661f..9788bd8f3f0ece03a6b87778a2d43bfaf3c14a9d 100644 (file)
--- a/pretty.c
+++ b/pretty.c
@@ -1065,7 +1065,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
        const struct commit *commit = c->commit;
        const char *msg = c->message;
        struct commit_list *p;
-       int h1, h2;
+       int ch;
 
        /* these are independent of the commit */
        switch (placeholder[0]) {
@@ -1089,14 +1089,11 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
                return 1;
        case 'x':
                /* %x00 == NUL, %x0a == LF, etc. */
-               if (0 <= (h1 = hexval_table[0xff & placeholder[1]]) &&
-                   h1 <= 16 &&
-                   0 <= (h2 = hexval_table[0xff & placeholder[2]]) &&
-                   h2 <= 16) {
-                       strbuf_addch(sb, (h1<<4)|h2);
-                       return 3;
-               } else
+               ch = hex2chr(placeholder + 1);
+               if (ch < 0)
                        return 0;
+               strbuf_addch(sb, ch);
+               return 3;
        case 'w':
                if (placeholder[1] == '(') {
                        unsigned long width = 0, indent1 = 0, indent2 = 0;
index bc551a752c460cd4751034b3d69d7e9b5dfc775e..9adbb8af3eaa138ccf161a91ce5b00e366fae7fa 100644 (file)
@@ -1576,24 +1576,6 @@ void ref_array_sort(struct ref_sorting *sorting, struct ref_array *array)
        qsort(array->items, array->nr, sizeof(struct ref_array_item *), compare_refs);
 }
 
-static int hex1(char ch)
-{
-       if ('0' <= ch && ch <= '9')
-               return ch - '0';
-       else if ('a' <= ch && ch <= 'f')
-               return ch - 'a' + 10;
-       else if ('A' <= ch && ch <= 'F')
-               return ch - 'A' + 10;
-       return -1;
-}
-static int hex2(const char *cp)
-{
-       if (cp[0] && cp[1])
-               return (hex1(cp[0]) << 4) | hex1(cp[1]);
-       else
-               return -1;
-}
-
 static void append_literal(const char *cp, const char *ep, struct ref_formatting_state *state)
 {
        struct strbuf *s = &state->stack->output;
@@ -1603,7 +1585,7 @@ static void append_literal(const char *cp, const char *ep, struct ref_formatting
                        if (cp[1] == '%')
                                cp++;
                        else {
-                               int ch = hex2(cp + 1);
+                               int ch = hex2chr(cp + 1);
                                if (0 <= ch) {
                                        strbuf_addch(s, ch);
                                        cp += 3;
index 12290d249643b5aaab18961ca91637910d0d7261..1f34b444af8dd5fbbacc67f0a13510005225c6cc 100644 (file)
@@ -1225,13 +1225,19 @@ static void read_loose_refs(const char *dirname, struct ref_dir *dir)
        struct strbuf refname;
        struct strbuf path = STRBUF_INIT;
        size_t path_baselen;
+       int err = 0;
 
        if (*refs->name)
-               strbuf_git_path_submodule(&path, refs->name, "%s", dirname);
+               err = strbuf_git_path_submodule(&path, refs->name, "%s", dirname);
        else
                strbuf_git_path(&path, "%s", dirname);
        path_baselen = path.len;
 
+       if (err) {
+               strbuf_release(&path);
+               return;
+       }
+
        d = opendir(path.buf);
        if (!d) {
                strbuf_release(&path);
index 3045aeabda1654e095fed3451ea4d5e5efc5c1dc..472ccb2ff96d4bcf57cba4832dc2ca7631b309eb 100644 (file)
@@ -24,6 +24,7 @@
 #include "streaming.h"
 #include "dir.h"
 #include "mru.h"
+#include "list.h"
 
 #ifndef O_NOATIME
 #if defined(__linux__) && (defined(__i386__) || defined(__PPC__))
@@ -38,6 +39,12 @@ static inline uintmax_t sz_fmt(size_t s) { return s; }
 
 const unsigned char null_sha1[20];
 const struct object_id null_oid;
+const struct object_id empty_tree_oid = {
+       EMPTY_TREE_SHA1_BIN_LITERAL
+};
+const struct object_id empty_blob_oid = {
+       EMPTY_BLOB_SHA1_BIN_LITERAL
+};
 
 /*
  * This is meant to hold a *small* number of objects that you would
@@ -418,6 +425,82 @@ void add_to_alternates_file(const char *reference)
        free(alts);
 }
 
+/*
+ * Compute the exact path an alternate is at and returns it. In case of
+ * error NULL is returned and the human readable error is added to `err`
+ * `path` may be relative and should point to $GITDIR.
+ * `err` must not be null.
+ */
+char *compute_alternate_path(const char *path, struct strbuf *err)
+{
+       char *ref_git = NULL;
+       const char *repo, *ref_git_s;
+       int seen_error = 0;
+
+       ref_git_s = real_path_if_valid(path);
+       if (!ref_git_s) {
+               seen_error = 1;
+               strbuf_addf(err, _("path '%s' does not exist"), path);
+               goto out;
+       } else
+               /*
+                * Beware: read_gitfile(), real_path() and mkpath()
+                * return static buffer
+                */
+               ref_git = xstrdup(ref_git_s);
+
+       repo = read_gitfile(ref_git);
+       if (!repo)
+               repo = read_gitfile(mkpath("%s/.git", ref_git));
+       if (repo) {
+               free(ref_git);
+               ref_git = xstrdup(repo);
+       }
+
+       if (!repo && is_directory(mkpath("%s/.git/objects", ref_git))) {
+               char *ref_git_git = mkpathdup("%s/.git", ref_git);
+               free(ref_git);
+               ref_git = ref_git_git;
+       } else if (!is_directory(mkpath("%s/objects", ref_git))) {
+               struct strbuf sb = STRBUF_INIT;
+               seen_error = 1;
+               if (get_common_dir(&sb, ref_git)) {
+                       strbuf_addf(err,
+                                   _("reference repository '%s' as a linked "
+                                     "checkout is not supported yet."),
+                                   path);
+                       goto out;
+               }
+
+               strbuf_addf(err, _("reference repository '%s' is not a "
+                                       "local repository."), path);
+               goto out;
+       }
+
+       if (!access(mkpath("%s/shallow", ref_git), F_OK)) {
+               strbuf_addf(err, _("reference repository '%s' is shallow"),
+                           path);
+               seen_error = 1;
+               goto out;
+       }
+
+       if (!access(mkpath("%s/info/grafts", ref_git), F_OK)) {
+               strbuf_addf(err,
+                           _("reference repository '%s' is grafted"),
+                           path);
+               seen_error = 1;
+               goto out;
+       }
+
+out:
+       if (seen_error) {
+               free(ref_git);
+               ref_git = NULL;
+       }
+
+       return ref_git;
+}
+
 int foreach_alt_odb(alt_odb_fn fn, void *cb)
 {
        struct alternate_object_database *ent;
@@ -2073,136 +2156,142 @@ static void *unpack_compressed_entry(struct packed_git *p,
        return buffer;
 }
 
-#define MAX_DELTA_CACHE (256)
-
+static struct hashmap delta_base_cache;
 static size_t delta_base_cached;
 
-static struct delta_base_cache_lru_list {
-       struct delta_base_cache_lru_list *prev;
-       struct delta_base_cache_lru_list *next;
-} delta_base_cache_lru = { &delta_base_cache_lru, &delta_base_cache_lru };
+static LIST_HEAD(delta_base_cache_lru);
 
-static struct delta_base_cache_entry {
-       struct delta_base_cache_lru_list lru;
-       void *data;
+struct delta_base_cache_key {
        struct packed_git *p;
        off_t base_offset;
+};
+
+struct delta_base_cache_entry {
+       struct hashmap hash;
+       struct delta_base_cache_key key;
+       struct list_head lru;
+       void *data;
        unsigned long size;
        enum object_type type;
-} delta_base_cache[MAX_DELTA_CACHE];
+};
 
-static unsigned long pack_entry_hash(struct packed_git *p, off_t base_offset)
+static unsigned int pack_entry_hash(struct packed_git *p, off_t base_offset)
 {
-       unsigned long hash;
+       unsigned int hash;
 
-       hash = (unsigned long)(intptr_t)p + (unsigned long)base_offset;
+       hash = (unsigned int)(intptr_t)p + (unsigned int)base_offset;
        hash += (hash >> 8) + (hash >> 16);
-       return hash % MAX_DELTA_CACHE;
+       return hash;
 }
 
 static struct delta_base_cache_entry *
 get_delta_base_cache_entry(struct packed_git *p, off_t base_offset)
 {
-       unsigned long hash = pack_entry_hash(p, base_offset);
-       return delta_base_cache + hash;
+       struct hashmap_entry entry;
+       struct delta_base_cache_key key;
+
+       if (!delta_base_cache.cmpfn)
+               return NULL;
+
+       hashmap_entry_init(&entry, pack_entry_hash(p, base_offset));
+       key.p = p;
+       key.base_offset = base_offset;
+       return hashmap_get(&delta_base_cache, &entry, &key);
+}
+
+static int delta_base_cache_key_eq(const struct delta_base_cache_key *a,
+                                  const struct delta_base_cache_key *b)
+{
+       return a->p == b->p && a->base_offset == b->base_offset;
 }
 
-static int eq_delta_base_cache_entry(struct delta_base_cache_entry *ent,
-                                    struct packed_git *p, off_t base_offset)
+static int delta_base_cache_hash_cmp(const void *va, const void *vb,
+                                    const void *vkey)
 {
-       return (ent->data && ent->p == p && ent->base_offset == base_offset);
+       const struct delta_base_cache_entry *a = va, *b = vb;
+       const struct delta_base_cache_key *key = vkey;
+       if (key)
+               return !delta_base_cache_key_eq(&a->key, key);
+       else
+               return !delta_base_cache_key_eq(&a->key, &b->key);
 }
 
 static int in_delta_base_cache(struct packed_git *p, off_t base_offset)
 {
-       struct delta_base_cache_entry *ent;
-       ent = get_delta_base_cache_entry(p, base_offset);
-       return eq_delta_base_cache_entry(ent, p, base_offset);
+       return !!get_delta_base_cache_entry(p, base_offset);
 }
 
-static void clear_delta_base_cache_entry(struct delta_base_cache_entry *ent)
+/*
+ * Remove the entry from the cache, but do _not_ free the associated
+ * entry data. The caller takes ownership of the "data" buffer, and
+ * should copy out any fields it wants before detaching.
+ */
+static void detach_delta_base_cache_entry(struct delta_base_cache_entry *ent)
 {
-       ent->data = NULL;
-       ent->lru.next->prev = ent->lru.prev;
-       ent->lru.prev->next = ent->lru.next;
+       hashmap_remove(&delta_base_cache, ent, &ent->key);
+       list_del(&ent->lru);
        delta_base_cached -= ent->size;
+       free(ent);
 }
 
 static void *cache_or_unpack_entry(struct packed_git *p, off_t base_offset,
-       unsigned long *base_size, enum object_type *type, int keep_cache)
+       unsigned long *base_size, enum object_type *type)
 {
        struct delta_base_cache_entry *ent;
-       void *ret;
 
        ent = get_delta_base_cache_entry(p, base_offset);
-
-       if (!eq_delta_base_cache_entry(ent, p, base_offset))
+       if (!ent)
                return unpack_entry(p, base_offset, type, base_size);
 
-       ret = ent->data;
-
-       if (!keep_cache)
-               clear_delta_base_cache_entry(ent);
-       else
-               ret = xmemdupz(ent->data, ent->size);
        *type = ent->type;
        *base_size = ent->size;
-       return ret;
+       return xmemdupz(ent->data, ent->size);
 }
 
 static inline void release_delta_base_cache(struct delta_base_cache_entry *ent)
 {
-       if (ent->data) {
-               free(ent->data);
-               ent->data = NULL;
-               ent->lru.next->prev = ent->lru.prev;
-               ent->lru.prev->next = ent->lru.next;
-               delta_base_cached -= ent->size;
-       }
+       free(ent->data);
+       detach_delta_base_cache_entry(ent);
 }
 
 void clear_delta_base_cache(void)
 {
-       unsigned long p;
-       for (p = 0; p < MAX_DELTA_CACHE; p++)
-               release_delta_base_cache(&delta_base_cache[p]);
+       struct hashmap_iter iter;
+       struct delta_base_cache_entry *entry;
+       for (entry = hashmap_iter_first(&delta_base_cache, &iter);
+            entry;
+            entry = hashmap_iter_next(&iter)) {
+               release_delta_base_cache(entry);
+       }
 }
 
 static void add_delta_base_cache(struct packed_git *p, off_t base_offset,
        void *base, unsigned long base_size, enum object_type type)
 {
-       unsigned long hash = pack_entry_hash(p, base_offset);
-       struct delta_base_cache_entry *ent = delta_base_cache + hash;
-       struct delta_base_cache_lru_list *lru;
+       struct delta_base_cache_entry *ent = xmalloc(sizeof(*ent));
+       struct list_head *lru;
 
-       release_delta_base_cache(ent);
        delta_base_cached += base_size;
 
-       for (lru = delta_base_cache_lru.next;
-            delta_base_cached > delta_base_cache_limit
-            && lru != &delta_base_cache_lru;
-            lru = lru->next) {
-               struct delta_base_cache_entry *f = (void *)lru;
-               if (f->type == OBJ_BLOB)
-                       release_delta_base_cache(f);
-       }
-       for (lru = delta_base_cache_lru.next;
-            delta_base_cached > delta_base_cache_limit
-            && lru != &delta_base_cache_lru;
-            lru = lru->next) {
-               struct delta_base_cache_entry *f = (void *)lru;
+       list_for_each(lru, &delta_base_cache_lru) {
+               struct delta_base_cache_entry *f =
+                       list_entry(lru, struct delta_base_cache_entry, lru);
+               if (delta_base_cached <= delta_base_cache_limit)
+                       break;
                release_delta_base_cache(f);
        }
 
-       ent->p = p;
-       ent->base_offset = base_offset;
+       ent->key.p = p;
+       ent->key.base_offset = base_offset;
        ent->type = type;
        ent->data = base;
        ent->size = base_size;
-       ent->lru.next = &delta_base_cache_lru;
-       ent->lru.prev = delta_base_cache_lru.prev;
-       delta_base_cache_lru.prev->next = &ent->lru;
-       delta_base_cache_lru.prev = &ent->lru;
+       list_add_tail(&ent->lru, &delta_base_cache_lru);
+
+       if (!delta_base_cache.cmpfn)
+               hashmap_init(&delta_base_cache, delta_base_cache_hash_cmp, 0);
+       hashmap_entry_init(ent, pack_entry_hash(p, base_offset));
+       hashmap_add(&delta_base_cache, ent);
 }
 
 static void *read_object(const unsigned char *sha1, enum object_type *type,
@@ -2246,11 +2335,11 @@ void *unpack_entry(struct packed_git *p, off_t obj_offset,
                struct delta_base_cache_entry *ent;
 
                ent = get_delta_base_cache_entry(p, curpos);
-               if (eq_delta_base_cache_entry(ent, p, curpos)) {
+               if (ent) {
                        type = ent->type;
                        data = ent->data;
                        size = ent->size;
-                       clear_delta_base_cache_entry(ent);
+                       detach_delta_base_cache_entry(ent);
                        base_from_cache = 1;
                        break;
                }
@@ -2755,7 +2844,7 @@ static void *read_packed_sha1(const unsigned char *sha1,
 
        if (!find_pack_entry(sha1, &e))
                return NULL;
-       data = cache_or_unpack_entry(e.p, e.offset, size, type, 1);
+       data = cache_or_unpack_entry(e.p, e.offset, size, type);
        if (!data) {
                /*
                 * We're probably in deep shit, but let's try to fetch
index 1b5cdfb7e784d646c15e59afb2fb43587a8ff8e9..0ef2ff4321d1723d05e9328e564313437ec8476e 100644 (file)
@@ -127,7 +127,9 @@ static int add_submodule_odb(const char *path)
        int ret = 0;
        size_t alloc;
 
-       strbuf_git_path_submodule(&objects_directory, path, "objects/");
+       ret = strbuf_git_path_submodule(&objects_directory, path, "objects/");
+       if (ret)
+               goto done;
        if (!is_directory(objects_directory.buf)) {
                ret = -1;
                goto done;
@@ -278,9 +280,9 @@ void handle_ignore_submodules_arg(struct diff_options *diffopt,
 
 static int prepare_submodule_summary(struct rev_info *rev, const char *path,
                struct commit *left, struct commit *right,
-               int *fast_forward, int *fast_backward)
+               struct commit_list *merge_bases)
 {
-       struct commit_list *merge_bases, *list;
+       struct commit_list *list;
 
        init_revisions(rev, NULL);
        setup_revisions(0, NULL, rev, NULL);
@@ -289,13 +291,6 @@ static int prepare_submodule_summary(struct rev_info *rev, const char *path,
        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);
-       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,
@@ -333,31 +328,23 @@ static void print_submodule_summary(struct rev_info *rev, FILE *f,
        strbuf_release(&sb);
 }
 
-void show_submodule_summary(FILE *f, const char *path,
+/* Helper function to display the submodule header line prior to the full
+ * summary output. If it can locate the submodule objects directory it will
+ * attempt to lookup both the left and right commits and put them into the
+ * left and right pointers.
+ */
+static void show_submodule_header(FILE *f, const char *path,
                const char *line_prefix,
-               unsigned char one[20], unsigned char two[20],
+               struct object_id *one, struct object_id *two,
                unsigned dirty_submodule, const char *meta,
-               const char *del, const char *add, const char *reset)
+               const char *reset,
+               struct commit **left, struct commit **right,
+               struct commit_list **merge_bases)
 {
-       struct rev_info rev;
-       struct commit *left = NULL, *right = NULL;
        const char *message = NULL;
        struct strbuf sb = STRBUF_INIT;
        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)";
-       else if (prepare_submodule_summary(&rev, path, left, right,
-                                          &fast_forward, &fast_backward))
-               message = "(revision walker failed)";
-
        if (dirty_submodule & DIRTY_SUBMODULE_UNTRACKED)
                fprintf(f, "%sSubmodule %s contains untracked content\n",
                        line_prefix, path);
@@ -365,30 +352,163 @@ void show_submodule_summary(FILE *f, const char *path,
                fprintf(f, "%sSubmodule %s contains modified content\n",
                        line_prefix, path);
 
-       if (!hashcmp(one, two)) {
+       if (is_null_oid(one))
+               message = "(new submodule)";
+       else if (is_null_oid(two))
+               message = "(submodule deleted)";
+
+       if (add_submodule_odb(path)) {
+               if (!message)
+                       message = "(not initialized)";
+               goto output_header;
+       }
+
+       /*
+        * Attempt to lookup the commit references, and determine if this is
+        * a fast forward or fast backwards update.
+        */
+       *left = lookup_commit_reference(one->hash);
+       *right = lookup_commit_reference(two->hash);
+
+       /*
+        * Warn about missing commits in the submodule project, but only if
+        * they aren't null.
+        */
+       if ((!is_null_oid(one) && !*left) ||
+            (!is_null_oid(two) && !*right))
+               message = "(commits not present)";
+
+       *merge_bases = get_merge_bases(*left, *right);
+       if (*merge_bases) {
+               if ((*merge_bases)->item == *left)
+                       fast_forward = 1;
+               else if ((*merge_bases)->item == *right)
+                       fast_backward = 1;
+       }
+
+       if (!oidcmp(one, two)) {
                strbuf_release(&sb);
                return;
        }
 
+output_header:
        strbuf_addf(&sb, "%s%sSubmodule %s %s..", line_prefix, meta, path,
-                       find_unique_abbrev(one, DEFAULT_ABBREV));
+                       find_unique_abbrev(one->hash, DEFAULT_ABBREV));
        if (!fast_backward && !fast_forward)
                strbuf_addch(&sb, '.');
-       strbuf_addf(&sb, "%s", find_unique_abbrev(two, DEFAULT_ABBREV));
+       strbuf_addf(&sb, "%s", find_unique_abbrev(two->hash, DEFAULT_ABBREV));
        if (message)
                strbuf_addf(&sb, " %s%s\n", message, reset);
        else
                strbuf_addf(&sb, "%s:%s\n", fast_backward ? " (rewind)" : "", reset);
        fwrite(sb.buf, sb.len, 1, f);
 
-       if (!message) /* only NULL if we succeeded in setting up the walk */
-               print_submodule_summary(&rev, f, line_prefix, del, add, reset);
+       strbuf_release(&sb);
+}
+
+void show_submodule_summary(FILE *f, const char *path,
+               const char *line_prefix,
+               struct object_id *one, struct object_id *two,
+               unsigned dirty_submodule, const char *meta,
+               const char *del, const char *add, const char *reset)
+{
+       struct rev_info rev;
+       struct commit *left = NULL, *right = NULL;
+       struct commit_list *merge_bases = NULL;
+
+       show_submodule_header(f, path, line_prefix, one, two, dirty_submodule,
+                             meta, reset, &left, &right, &merge_bases);
+
+       /*
+        * If we don't have both a left and a right pointer, there is no
+        * reason to try and display a summary. The header line should contain
+        * all the information the user needs.
+        */
+       if (!left || !right)
+               goto out;
+
+       /* Treat revision walker failure the same as missing commits */
+       if (prepare_submodule_summary(&rev, path, left, right, merge_bases)) {
+               fprintf(f, "%s(revision walker failed)\n", line_prefix);
+               goto out;
+       }
+
+       print_submodule_summary(&rev, f, line_prefix, del, add, reset);
+
+out:
+       if (merge_bases)
+               free_commit_list(merge_bases);
+       clear_commit_marks(left, ~0);
+       clear_commit_marks(right, ~0);
+}
+
+void show_submodule_inline_diff(FILE *f, const char *path,
+               const char *line_prefix,
+               struct object_id *one, struct object_id *two,
+               unsigned dirty_submodule, const char *meta,
+               const char *del, const char *add, const char *reset,
+               const struct diff_options *o)
+{
+       const struct object_id *old = &empty_tree_oid, *new = &empty_tree_oid;
+       struct commit *left = NULL, *right = NULL;
+       struct commit_list *merge_bases = NULL;
+       struct strbuf submodule_dir = STRBUF_INIT;
+       struct child_process cp = CHILD_PROCESS_INIT;
+
+       show_submodule_header(f, path, line_prefix, one, two, dirty_submodule,
+                             meta, reset, &left, &right, &merge_bases);
+
+       /* We need a valid left and right commit to display a difference */
+       if (!(left || is_null_oid(one)) ||
+           !(right || is_null_oid(two)))
+               goto done;
+
+       if (left)
+               old = one;
+       if (right)
+               new = two;
+
+       fflush(f);
+       cp.git_cmd = 1;
+       cp.dir = path;
+       cp.out = dup(fileno(f));
+       cp.no_stdin = 1;
+
+       /* TODO: other options may need to be passed here. */
+       argv_array_push(&cp.args, "diff");
+       argv_array_pushf(&cp.args, "--line-prefix=%s", line_prefix);
+       if (DIFF_OPT_TST(o, REVERSE_DIFF)) {
+               argv_array_pushf(&cp.args, "--src-prefix=%s%s/",
+                                o->b_prefix, path);
+               argv_array_pushf(&cp.args, "--dst-prefix=%s%s/",
+                                o->a_prefix, path);
+       } else {
+               argv_array_pushf(&cp.args, "--src-prefix=%s%s/",
+                                o->a_prefix, path);
+               argv_array_pushf(&cp.args, "--dst-prefix=%s%s/",
+                                o->b_prefix, path);
+       }
+       argv_array_push(&cp.args, oid_to_hex(old));
+       /*
+        * If the submodule has modified content, we will diff against the
+        * work tree, under the assumption that the user has asked for the
+        * diff format and wishes to actually see all differences even if they
+        * haven't yet been committed to the submodule yet.
+        */
+       if (!(dirty_submodule & DIRTY_SUBMODULE_MODIFIED))
+               argv_array_push(&cp.args, oid_to_hex(new));
+
+       if (run_command(&cp))
+               fprintf(f, "(diff failed)\n");
+
+done:
+       strbuf_release(&submodule_dir);
+       if (merge_bases)
+               free_commit_list(merge_bases);
        if (left)
                clear_commit_marks(left, ~0);
        if (right)
                clear_commit_marks(right, ~0);
-
-       strbuf_release(&sb);
 }
 
 void set_config_fetch_recurse_submodules(int value)
@@ -1160,4 +1280,5 @@ void prepare_submodule_repo_env(struct argv_array *out)
                if (strcmp(*var, CONFIG_DATA_ENVIRONMENT))
                        argv_array_push(out, *var);
        }
+       argv_array_push(out, "GIT_DIR=.git");
 }
index 2af9390998194c7d51a3e23b14723574d6696926..d9e197a948fdab44b7a5df4161a5df9c3a2938ff 100644 (file)
@@ -43,9 +43,15 @@ const char *submodule_strategy_to_string(const struct submodule_update_strategy
 void handle_ignore_submodules_arg(struct diff_options *diffopt, const char *);
 void show_submodule_summary(FILE *f, const char *path,
                const char *line_prefix,
-               unsigned char one[20], unsigned char two[20],
+               struct object_id *one, struct object_id *two,
                unsigned dirty_submodule, const char *meta,
                const char *del, const char *add, const char *reset);
+void show_submodule_inline_diff(FILE *f, const char *path,
+               const char *line_prefix,
+               struct object_id *one, struct object_id *two,
+               unsigned dirty_submodule, const char *meta,
+               const char *del, const char *add, const char *reset,
+               const struct diff_options *opt);
 void set_config_fetch_recurse_submodules(int value);
 void check_for_new_submodule_commits(unsigned char new_sha1[20]);
 int fetch_populated_submodules(const struct argv_array *options,
diff --git a/t/perf/p0003-delta-base-cache.sh b/t/perf/p0003-delta-base-cache.sh
new file mode 100755 (executable)
index 0000000..62369ea
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+test_description='Test operations that emphasize the delta base cache.
+
+We look at both "log --raw", which should put only trees into the delta cache,
+and "log -Sfoo --raw", which should look at both trees and blobs.
+
+Any effects will be emphasized if the test repository is fully packed (loose
+objects obviously do not use the delta base cache at all). It is also
+emphasized if the pack has long delta chains (e.g., as produced by "gc
+--aggressive"), though cache is still quite noticeable even with the default
+depth of 50.
+
+The setting of core.deltaBaseCacheLimit in the source repository is also
+relevant (depending on the size of your test repo), so be sure it is consistent
+between runs.
+'
+. ./perf-lib.sh
+
+test_perf_large_repo
+
+# puts mostly trees into the delta base cache
+test_perf 'log --raw' '
+       git log --raw >/dev/null
+'
+
+test_perf 'log -S' '
+       git log --raw -Sfoo >/dev/null
+'
+
+test_done
diff --git a/t/t0012-help.sh b/t/t0012-help.sh
new file mode 100755 (executable)
index 0000000..8faba2e
--- /dev/null
@@ -0,0 +1,52 @@
+#!/bin/sh
+
+test_description='help'
+
+. ./test-lib.sh
+
+configure_help () {
+       test_config help.format html &&
+
+       # Unless the path has "://" in it, Git tries to make sure
+       # the documentation directory locally exists. Avoid it as
+       # we are only interested in seeing an attempt to correctly
+       # invoke a help browser in this test.
+       test_config help.htmlpath test://html &&
+
+       # Name a custom browser
+       test_config browser.test.cmd ./test-browser &&
+       test_config help.browser test
+}
+
+test_expect_success "setup" '
+       # Just write out which page gets requested
+       write_script test-browser <<-\EOF
+       echo "$*" >test-browser.log
+       EOF
+'
+
+test_expect_success "works for commands and guides by default" '
+       configure_help &&
+       git help status &&
+       echo "test://html/git-status.html" >expect &&
+       test_cmp expect test-browser.log &&
+       git help revisions &&
+       echo "test://html/gitrevisions.html" >expect &&
+       test_cmp expect test-browser.log
+'
+
+test_expect_success "--exclude-guides does not work for guides" '
+       >test-browser.log &&
+       test_must_fail git help --exclude-guides revisions &&
+       test_must_be_empty test-browser.log
+'
+
+test_expect_success "--help does not work for guides" "
+       cat <<-EOF >expect &&
+               git: 'revisions' is not a git command. See 'git --help'.
+       EOF
+       test_must_fail git revisions --help 2>actual &&
+       test_i18ncmp expect actual
+"
+
+test_done
index ca3fa406c34f1d41ac5d2be67804af234b996654..eec3e90f9c04e9b88ebb8c2ee6f12b96b75bac2b 100755 (executable)
@@ -33,18 +33,25 @@ test_expect_success 'symbolic-ref refuses bare sha1' '
 '
 reset_to_sane
 
-test_expect_success 'symbolic-ref deletes HEAD' '
-       git symbolic-ref -d HEAD &&
+test_expect_success 'HEAD cannot be removed' '
+       test_must_fail git symbolic-ref -d HEAD
+'
+
+reset_to_sane
+
+test_expect_success 'symbolic-ref can be deleted' '
+       git symbolic-ref NOTHEAD refs/heads/foo &&
+       git symbolic-ref -d NOTHEAD &&
        test_path_is_file .git/refs/heads/foo &&
-       test_path_is_missing .git/HEAD
+       test_path_is_missing .git/NOTHEAD
 '
 reset_to_sane
 
-test_expect_success 'symbolic-ref deletes dangling HEAD' '
-       git symbolic-ref HEAD refs/heads/missing &&
-       git symbolic-ref -d HEAD &&
+test_expect_success 'symbolic-ref can delete dangling symref' '
+       git symbolic-ref NOTHEAD refs/heads/missing &&
+       git symbolic-ref -d NOTHEAD &&
        test_path_is_missing .git/refs/heads/missing &&
-       test_path_is_missing .git/HEAD
+       test_path_is_missing .git/NOTHEAD
 '
 reset_to_sane
 
index 94ef5000e787f0898ff6ccb57661c972c765db52..566817e2efdccc4747e871f3bdabb90fa5b134ec 100755 (executable)
@@ -306,6 +306,8 @@ diff --no-index --name-status dir2 dir
 diff --no-index --name-status -- dir2 dir
 diff --no-index dir dir3
 diff master master^ side
+# Can't use spaces...
+diff --line-prefix=abc master master^ side
 diff --dirstat master~1 master~2
 diff --dirstat initial rearrange
 diff --dirstat-by-file initial rearrange
@@ -325,6 +327,10 @@ test_expect_success 'diff --cached -- file on unborn branch' '
        git diff --cached -- file0 >result &&
        test_cmp "$TEST_DIRECTORY/t4013/diff.diff_--cached_--_file0" result
 '
+test_expect_success 'diff --line-prefix with spaces' '
+       git diff --line-prefix="| | | " --cached -- file0 >result &&
+       test_cmp "$TEST_DIRECTORY/t4013/diff.diff_--line-prefix_--cached_--_file0" result
+'
 
 test_expect_success 'diff-tree --stdin with log formatting' '
        cat >expect <<-\EOF &&
diff --git a/t/t4013/diff.diff_--line-prefix=abc_master_master^_side b/t/t4013/diff.diff_--line-prefix=abc_master_master^_side
new file mode 100644 (file)
index 0000000..99f91e7
--- /dev/null
@@ -0,0 +1,29 @@
+$ git diff --line-prefix=abc master master^ side
+abcdiff --cc dir/sub
+abcindex cead32e,7289e35..992913c
+abc--- a/dir/sub
+abc+++ b/dir/sub
+abc@@@ -1,6 -1,4 +1,8 @@@
+abc  A
+abc  B
+abc +C
+abc +D
+abc +E
+abc +F
+abc+ 1
+abc+ 2
+abcdiff --cc file0
+abcindex b414108,f4615da..10a8a9f
+abc--- a/file0
+abc+++ b/file0
+abc@@@ -1,6 -1,6 +1,9 @@@
+abc  1
+abc  2
+abc  3
+abc +4
+abc +5
+abc +6
+abc+ A
+abc+ B
+abc+ C
+$
diff --git a/t/t4013/diff.diff_--line-prefix_--cached_--_file0 b/t/t4013/diff.diff_--line-prefix_--cached_--_file0
new file mode 100644 (file)
index 0000000..f41ba4d
--- /dev/null
@@ -0,0 +1,15 @@
+| | | diff --git a/file0 b/file0
+| | | new file mode 100644
+| | | index 0000000..10a8a9f
+| | | --- /dev/null
+| | | +++ b/file0
+| | | @@ -0,0 +1,9 @@
+| | | +1
+| | | +2
+| | | +3
+| | | +4
+| | | +5
+| | | +6
+| | | +A
+| | | +B
+| | | +C
index 886494b58f6739d40c2c34724064317b0d3be770..9be65fd4440a68af70e6630c8ded872d7be41f5d 100755 (executable)
@@ -36,6 +36,11 @@ test_no_numbered() {
        test_num_no_numbered $1 2
 }
 
+test_single_cover_letter_numbered() {
+       grep "^Subject: \[PATCH 0/1\]" $1 &&
+       grep "^Subject: \[PATCH 1/1\]" $1
+}
+
 test_single_numbered() {
        grep "^Subject: \[PATCH 1/1\]" $1
 }
@@ -121,4 +126,16 @@ test_expect_success '--start-number && --numbered' '
        grep "^Subject: \[PATCH 3/3\]" patch8
 '
 
+test_expect_success 'single patch with cover-letter defaults to numbers' '
+       git format-patch --cover-letter --stdout HEAD~1 >patch9.single &&
+       test_single_cover_letter_numbered patch9.single
+'
+
+test_expect_success 'Use --no-numbered and --cover-letter single patch' '
+       git format-patch --no-numbered --stdout --cover-letter HEAD~1 >patch10 &&
+       test_no_numbered patch10
+'
+
+
+
 test_done
diff --git a/t/t4059-diff-submodule-not-initialized.sh b/t/t4059-diff-submodule-not-initialized.sh
new file mode 100755 (executable)
index 0000000..cd70fd5
--- /dev/null
@@ -0,0 +1,127 @@
+#!/bin/sh
+#
+# Copyright (c) 2016 Jacob Keller, based on t4041 by Jens Lehmann
+#
+
+test_description='Test for submodule diff on non-checked out submodule
+
+This test tries to verify that add_submodule_odb works when the submodule was
+initialized previously but the checkout has since been removed.
+'
+
+. ./test-lib.sh
+
+# Tested non-UTF-8 encoding
+test_encoding="ISO8859-1"
+
+# String "added" in German (translated with Google Translate), encoded in UTF-8,
+# used in sample commit log messages in add_file() function below.
+added=$(printf "hinzugef\303\274gt")
+
+add_file () {
+       (
+               cd "$1" &&
+               shift &&
+               for name
+               do
+                       echo "$name" >"$name" &&
+                       git add "$name" &&
+                       test_tick &&
+                       # "git commit -m" would break MinGW, as Windows refuse to pass
+                       # $test_encoding encoded parameter to git.
+                       echo "Add $name ($added $name)" | iconv -f utf-8 -t $test_encoding |
+                       git -c "i18n.commitEncoding=$test_encoding" commit -F -
+               done >/dev/null &&
+               git rev-parse --short --verify HEAD
+       )
+}
+
+commit_file () {
+       test_tick &&
+       git commit "$@" -m "Commit $*" >/dev/null
+}
+
+test_expect_success 'setup - submodules' '
+       test_create_repo sm2 &&
+       add_file . foo &&
+       add_file sm2 foo1 foo2 &&
+       smhead1=$(git -C sm2 rev-parse --short --verify HEAD)
+'
+
+test_expect_success 'setup - git submodule add' '
+       git submodule add ./sm2 sm1 &&
+       commit_file sm1 .gitmodules &&
+       git diff-tree -p --no-commit-id --submodule=log HEAD -- sm1 >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 0000000...$smhead1 (new submodule)
+       EOF
+       test_cmp expected actual
+'
+
+test_expect_success 'submodule directory removed' '
+       rm -rf sm1 &&
+       git diff-tree -p --no-commit-id --submodule=log HEAD -- sm1 >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 0000000...$smhead1 (new submodule)
+       EOF
+       test_cmp expected actual
+'
+
+test_expect_success 'setup - submodule multiple commits' '
+       git submodule update --checkout sm1 &&
+       smhead2=$(add_file sm1 foo3 foo4) &&
+       commit_file sm1 &&
+       git diff-tree -p --no-commit-id --submodule=log HEAD >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 $smhead1..$smhead2:
+         > Add foo4 ($added foo4)
+         > Add foo3 ($added foo3)
+       EOF
+       test_cmp expected actual
+'
+
+test_expect_success 'submodule removed multiple commits' '
+       rm -rf sm1 &&
+       git diff-tree -p --no-commit-id --submodule=log HEAD >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 $smhead1..$smhead2:
+         > Add foo4 ($added foo4)
+         > Add foo3 ($added foo3)
+       EOF
+       test_cmp expected actual
+'
+
+test_expect_success 'submodule not initialized in new clone' '
+       git clone . sm3 &&
+       git -C sm3 diff-tree -p --no-commit-id --submodule=log HEAD >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 $smhead1...$smhead2 (not initialized)
+       EOF
+       test_cmp expected actual
+'
+
+test_expect_success 'setup submodule moved' '
+       git submodule update --checkout sm1 &&
+       git mv sm1 sm4 &&
+       commit_file sm4 &&
+       git diff-tree -p --no-commit-id --submodule=log HEAD >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm4 0000000...$smhead2 (new submodule)
+       EOF
+       test_cmp expected actual
+'
+
+test_expect_success 'submodule moved then removed' '
+       smhead3=$(add_file sm4 foo6 foo7) &&
+       commit_file sm4 &&
+       rm -rf sm4 &&
+       git diff-tree -p --no-commit-id --submodule=log HEAD >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm4 $smhead2..$smhead3:
+         > Add foo7 ($added foo7)
+         > Add foo6 ($added foo6)
+       EOF
+       test_cmp expected actual
+'
+
+test_done
diff --git a/t/t4060-diff-submodule-option-diff-format.sh b/t/t4060-diff-submodule-option-diff-format.sh
new file mode 100755 (executable)
index 0000000..7e23b55
--- /dev/null
@@ -0,0 +1,749 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Jens Lehmann, based on t7401 by Ping Yin
+# Copyright (c) 2011 Alexey Shumkin (+ non-UTF-8 commit encoding tests)
+# Copyright (c) 2016 Jacob Keller (copy + convert to --submodule=diff)
+#
+
+test_description='Support for diff format verbose submodule difference in git diff
+
+This test tries to verify the sanity of --submodule=diff option of git diff.
+'
+
+. ./test-lib.sh
+
+# Tested non-UTF-8 encoding
+test_encoding="ISO8859-1"
+
+# String "added" in German (translated with Google Translate), encoded in UTF-8,
+# used in sample commit log messages in add_file() function below.
+added=$(printf "hinzugef\303\274gt")
+
+add_file () {
+       (
+               cd "$1" &&
+               shift &&
+               for name
+               do
+                       echo "$name" >"$name" &&
+                       git add "$name" &&
+                       test_tick &&
+                       # "git commit -m" would break MinGW, as Windows refuse to pass
+                       # $test_encoding encoded parameter to git.
+                       echo "Add $name ($added $name)" | iconv -f utf-8 -t $test_encoding |
+                       git -c "i18n.commitEncoding=$test_encoding" commit -F -
+               done >/dev/null &&
+               git rev-parse --short --verify HEAD
+       )
+}
+
+commit_file () {
+       test_tick &&
+       git commit "$@" -m "Commit $*" >/dev/null
+}
+
+test_expect_success 'setup repository' '
+       test_create_repo sm1 &&
+       add_file . foo &&
+       head1=$(add_file sm1 foo1 foo2) &&
+       fullhead1=$(git -C sm1 rev-parse --verify HEAD)
+'
+
+test_expect_success 'added submodule' '
+       git add sm1 &&
+       git diff-index -p --submodule=diff HEAD >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 0000000...$head1 (new submodule)
+       diff --git a/sm1/foo1 b/sm1/foo1
+       new file mode 100644
+       index 0000000..1715acd
+       --- /dev/null
+       +++ b/sm1/foo1
+       @@ -0,0 +1 @@
+       +foo1
+       diff --git a/sm1/foo2 b/sm1/foo2
+       new file mode 100644
+       index 0000000..54b060e
+       --- /dev/null
+       +++ b/sm1/foo2
+       @@ -0,0 +1 @@
+       +foo2
+       EOF
+       test_cmp expected actual
+'
+
+test_expect_success 'added submodule, set diff.submodule' '
+       test_config diff.submodule log &&
+       git add sm1 &&
+       git diff-index -p --submodule=diff HEAD >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 0000000...$head1 (new submodule)
+       diff --git a/sm1/foo1 b/sm1/foo1
+       new file mode 100644
+       index 0000000..1715acd
+       --- /dev/null
+       +++ b/sm1/foo1
+       @@ -0,0 +1 @@
+       +foo1
+       diff --git a/sm1/foo2 b/sm1/foo2
+       new file mode 100644
+       index 0000000..54b060e
+       --- /dev/null
+       +++ b/sm1/foo2
+       @@ -0,0 +1 @@
+       +foo2
+       EOF
+       test_cmp expected actual
+'
+
+test_expect_success '--submodule=short overrides diff.submodule' '
+       test_config diff.submodule log &&
+       git add sm1 &&
+       git diff --submodule=short --cached >actual &&
+       cat >expected <<-EOF &&
+       diff --git a/sm1 b/sm1
+       new file mode 160000
+       index 0000000..$head1
+       --- /dev/null
+       +++ b/sm1
+       @@ -0,0 +1 @@
+       +Subproject commit $fullhead1
+       EOF
+       test_cmp expected actual
+'
+
+test_expect_success 'diff.submodule does not affect plumbing' '
+       test_config diff.submodule log &&
+       git diff-index -p HEAD >actual &&
+       cat >expected <<-EOF &&
+       diff --git a/sm1 b/sm1
+       new file mode 160000
+       index 0000000..$head1
+       --- /dev/null
+       +++ b/sm1
+       @@ -0,0 +1 @@
+       +Subproject commit $fullhead1
+       EOF
+       test_cmp expected actual
+'
+
+commit_file sm1 &&
+head2=$(add_file sm1 foo3)
+
+test_expect_success 'modified submodule(forward)' '
+       git diff-index -p --submodule=diff HEAD >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 $head1..$head2:
+       diff --git a/sm1/foo3 b/sm1/foo3
+       new file mode 100644
+       index 0000000..c1ec6c6
+       --- /dev/null
+       +++ b/sm1/foo3
+       @@ -0,0 +1 @@
+       +foo3
+       EOF
+       test_cmp expected actual
+'
+
+test_expect_success 'modified submodule(forward)' '
+       git diff --submodule=diff >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 $head1..$head2:
+       diff --git a/sm1/foo3 b/sm1/foo3
+       new file mode 100644
+       index 0000000..c1ec6c6
+       --- /dev/null
+       +++ b/sm1/foo3
+       @@ -0,0 +1 @@
+       +foo3
+       EOF
+       test_cmp expected actual
+'
+
+test_expect_success 'modified submodule(forward) --submodule' '
+       git diff --submodule >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 $head1..$head2:
+         > Add foo3 ($added foo3)
+       EOF
+       test_cmp expected actual
+'
+
+fullhead2=$(cd sm1; git rev-parse --verify HEAD)
+test_expect_success 'modified submodule(forward) --submodule=short' '
+       git diff --submodule=short >actual &&
+       cat >expected <<-EOF &&
+       diff --git a/sm1 b/sm1
+       index $head1..$head2 160000
+       --- a/sm1
+       +++ b/sm1
+       @@ -1 +1 @@
+       -Subproject commit $fullhead1
+       +Subproject commit $fullhead2
+       EOF
+       test_cmp expected actual
+'
+
+commit_file sm1 &&
+head3=$(
+       cd sm1 &&
+       git reset --hard HEAD~2 >/dev/null &&
+       git rev-parse --short --verify HEAD
+)
+
+test_expect_success 'modified submodule(backward)' '
+       git diff-index -p --submodule=diff HEAD >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 $head2..$head3 (rewind):
+       diff --git a/sm1/foo2 b/sm1/foo2
+       deleted file mode 100644
+       index 54b060e..0000000
+       --- a/sm1/foo2
+       +++ /dev/null
+       @@ -1 +0,0 @@
+       -foo2
+       diff --git a/sm1/foo3 b/sm1/foo3
+       deleted file mode 100644
+       index c1ec6c6..0000000
+       --- a/sm1/foo3
+       +++ /dev/null
+       @@ -1 +0,0 @@
+       -foo3
+       EOF
+       test_cmp expected actual
+'
+
+head4=$(add_file sm1 foo4 foo5)
+test_expect_success 'modified submodule(backward and forward)' '
+       git diff-index -p --submodule=diff HEAD >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 $head2...$head4:
+       diff --git a/sm1/foo2 b/sm1/foo2
+       deleted file mode 100644
+       index 54b060e..0000000
+       --- a/sm1/foo2
+       +++ /dev/null
+       @@ -1 +0,0 @@
+       -foo2
+       diff --git a/sm1/foo3 b/sm1/foo3
+       deleted file mode 100644
+       index c1ec6c6..0000000
+       --- a/sm1/foo3
+       +++ /dev/null
+       @@ -1 +0,0 @@
+       -foo3
+       diff --git a/sm1/foo4 b/sm1/foo4
+       new file mode 100644
+       index 0000000..a0016db
+       --- /dev/null
+       +++ b/sm1/foo4
+       @@ -0,0 +1 @@
+       +foo4
+       diff --git a/sm1/foo5 b/sm1/foo5
+       new file mode 100644
+       index 0000000..d6f2413
+       --- /dev/null
+       +++ b/sm1/foo5
+       @@ -0,0 +1 @@
+       +foo5
+       EOF
+       test_cmp expected actual
+'
+
+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=diff --cached >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 $head4...0000000 (submodule deleted)
+       diff --git a/sm1/foo1 b/sm1/foo1
+       deleted file mode 100644
+       index 1715acd..0000000
+       --- a/sm1/foo1
+       +++ /dev/null
+       @@ -1 +0,0 @@
+       -foo1
+       diff --git a/sm1/foo4 b/sm1/foo4
+       deleted file mode 100644
+       index a0016db..0000000
+       --- a/sm1/foo4
+       +++ /dev/null
+       @@ -1 +0,0 @@
+       -foo4
+       diff --git a/sm1/foo5 b/sm1/foo5
+       deleted file mode 100644
+       index d6f2413..0000000
+       --- a/sm1/foo5
+       +++ /dev/null
+       @@ -1 +0,0 @@
+       -foo5
+       diff --git a/sm1 b/sm1
+       new file mode 100644
+       index 0000000..9da5fb8
+       --- /dev/null
+       +++ b/sm1
+       @@ -0,0 +1 @@
+       +sm1
+       EOF
+       test_cmp expected actual
+'
+
+test_expect_success 'typechanged submodule(submodule->blob)' '
+       git diff --submodule=diff >actual &&
+       cat >expected <<-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)
+       diff --git a/sm1/foo1 b/sm1/foo1
+       new file mode 100644
+       index 0000000..1715acd
+       --- /dev/null
+       +++ b/sm1/foo1
+       @@ -0,0 +1 @@
+       +foo1
+       diff --git a/sm1/foo4 b/sm1/foo4
+       new file mode 100644
+       index 0000000..a0016db
+       --- /dev/null
+       +++ b/sm1/foo4
+       @@ -0,0 +1 @@
+       +foo4
+       diff --git a/sm1/foo5 b/sm1/foo5
+       new file mode 100644
+       index 0000000..d6f2413
+       --- /dev/null
+       +++ b/sm1/foo5
+       @@ -0,0 +1 @@
+       +foo5
+       EOF
+       test_cmp expected actual
+'
+
+rm -rf sm1 &&
+git checkout-index sm1
+test_expect_success 'typechanged submodule(submodule->blob)' '
+       git diff-index -p --submodule=diff HEAD >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 $head4...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_cmp expected actual
+'
+
+rm -f sm1 &&
+test_create_repo sm1 &&
+head6=$(add_file sm1 foo6 foo7)
+fullhead6=$(cd sm1; git rev-parse --verify HEAD)
+test_expect_success 'nonexistent commit' '
+       git diff-index -p --submodule=diff HEAD >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 $head4...$head6 (commits not present)
+       EOF
+       test_cmp expected actual
+'
+
+commit_file
+test_expect_success 'typechanged submodule(blob->submodule)' '
+       git diff-index -p --submodule=diff HEAD >actual &&
+       cat >expected <<-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...$head6 (new submodule)
+       diff --git a/sm1/foo6 b/sm1/foo6
+       new file mode 100644
+       index 0000000..462398b
+       --- /dev/null
+       +++ b/sm1/foo6
+       @@ -0,0 +1 @@
+       +foo6
+       diff --git a/sm1/foo7 b/sm1/foo7
+       new file mode 100644
+       index 0000000..6e9262c
+       --- /dev/null
+       +++ b/sm1/foo7
+       @@ -0,0 +1 @@
+       +foo7
+       EOF
+       test_cmp expected actual
+'
+
+commit_file sm1 &&
+test_expect_success 'submodule is up to date' '
+       git diff-index -p --submodule=diff HEAD >actual &&
+       cat >expected <<-EOF &&
+       EOF
+       test_cmp expected actual
+'
+
+test_expect_success 'submodule contains untracked content' '
+       echo new > sm1/new-file &&
+       git diff-index -p --submodule=diff HEAD >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 contains untracked content
+       EOF
+       test_cmp expected actual
+'
+
+test_expect_success 'submodule contains untracked content (untracked ignored)' '
+       git diff-index -p --ignore-submodules=untracked --submodule=diff HEAD >actual &&
+       ! test -s actual
+'
+
+test_expect_success 'submodule contains untracked content (dirty ignored)' '
+       git diff-index -p --ignore-submodules=dirty --submodule=diff HEAD >actual &&
+       ! test -s actual
+'
+
+test_expect_success 'submodule contains untracked content (all ignored)' '
+       git diff-index -p --ignore-submodules=all --submodule=diff HEAD >actual &&
+       ! test -s actual
+'
+
+test_expect_success 'submodule contains untracked and modified content' '
+       echo new > sm1/foo6 &&
+       git diff-index -p --submodule=diff HEAD >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 contains untracked content
+       Submodule sm1 contains modified content
+       diff --git a/sm1/foo6 b/sm1/foo6
+       index 462398b..3e75765 100644
+       --- a/sm1/foo6
+       +++ b/sm1/foo6
+       @@ -1 +1 @@
+       -foo6
+       +new
+       EOF
+       test_cmp expected actual
+'
+
+# NOT OK
+test_expect_success 'submodule contains untracked and modified content (untracked ignored)' '
+       echo new > sm1/foo6 &&
+       git diff-index -p --ignore-submodules=untracked --submodule=diff HEAD >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 contains modified content
+       diff --git a/sm1/foo6 b/sm1/foo6
+       index 462398b..3e75765 100644
+       --- a/sm1/foo6
+       +++ b/sm1/foo6
+       @@ -1 +1 @@
+       -foo6
+       +new
+       EOF
+       test_cmp expected actual
+'
+
+test_expect_success 'submodule contains untracked and modified content (dirty ignored)' '
+       echo new > sm1/foo6 &&
+       git diff-index -p --ignore-submodules=dirty --submodule=diff HEAD >actual &&
+       ! test -s actual
+'
+
+test_expect_success 'submodule contains untracked and modified content (all ignored)' '
+       echo new > sm1/foo6 &&
+       git diff-index -p --ignore-submodules --submodule=diff HEAD >actual &&
+       ! test -s actual
+'
+
+test_expect_success 'submodule contains modified content' '
+       rm -f sm1/new-file &&
+       git diff-index -p --submodule=diff HEAD >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 contains modified content
+       diff --git a/sm1/foo6 b/sm1/foo6
+       index 462398b..3e75765 100644
+       --- a/sm1/foo6
+       +++ b/sm1/foo6
+       @@ -1 +1 @@
+       -foo6
+       +new
+       EOF
+       test_cmp expected actual
+'
+
+(cd sm1; git commit -mchange foo6 >/dev/null) &&
+head8=$(cd sm1; git rev-parse --short --verify HEAD) &&
+test_expect_success 'submodule is modified' '
+       git diff-index -p --submodule=diff HEAD >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 17243c9..$head8:
+       diff --git a/sm1/foo6 b/sm1/foo6
+       index 462398b..3e75765 100644
+       --- a/sm1/foo6
+       +++ b/sm1/foo6
+       @@ -1 +1 @@
+       -foo6
+       +new
+       EOF
+       test_cmp expected actual
+'
+
+test_expect_success 'modified submodule contains untracked content' '
+       echo new > sm1/new-file &&
+       git diff-index -p --submodule=diff HEAD >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 contains untracked content
+       Submodule sm1 17243c9..$head8:
+       diff --git a/sm1/foo6 b/sm1/foo6
+       index 462398b..3e75765 100644
+       --- a/sm1/foo6
+       +++ b/sm1/foo6
+       @@ -1 +1 @@
+       -foo6
+       +new
+       EOF
+       test_cmp expected actual
+'
+
+test_expect_success 'modified submodule contains untracked content (untracked ignored)' '
+       git diff-index -p --ignore-submodules=untracked --submodule=diff HEAD >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 17243c9..$head8:
+       diff --git a/sm1/foo6 b/sm1/foo6
+       index 462398b..3e75765 100644
+       --- a/sm1/foo6
+       +++ b/sm1/foo6
+       @@ -1 +1 @@
+       -foo6
+       +new
+       EOF
+       test_cmp expected actual
+'
+
+test_expect_success 'modified submodule contains untracked content (dirty ignored)' '
+       git diff-index -p --ignore-submodules=dirty --submodule=diff HEAD >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 17243c9..cfce562:
+       diff --git a/sm1/foo6 b/sm1/foo6
+       index 462398b..3e75765 100644
+       --- a/sm1/foo6
+       +++ b/sm1/foo6
+       @@ -1 +1 @@
+       -foo6
+       +new
+       EOF
+       test_cmp expected actual
+'
+
+test_expect_success 'modified submodule contains untracked content (all ignored)' '
+       git diff-index -p --ignore-submodules=all --submodule=diff HEAD >actual &&
+       ! test -s actual
+'
+
+test_expect_success 'modified submodule contains untracked and modified content' '
+       echo modification >> sm1/foo6 &&
+       git diff-index -p --submodule=diff HEAD >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 contains untracked content
+       Submodule sm1 contains modified content
+       Submodule sm1 17243c9..cfce562:
+       diff --git a/sm1/foo6 b/sm1/foo6
+       index 462398b..dfda541 100644
+       --- a/sm1/foo6
+       +++ b/sm1/foo6
+       @@ -1 +1,2 @@
+       -foo6
+       +new
+       +modification
+       EOF
+       test_cmp expected actual
+'
+
+test_expect_success 'modified submodule contains untracked and modified content (untracked ignored)' '
+       echo modification >> sm1/foo6 &&
+       git diff-index -p --ignore-submodules=untracked --submodule=diff HEAD >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 contains modified content
+       Submodule sm1 17243c9..cfce562:
+       diff --git a/sm1/foo6 b/sm1/foo6
+       index 462398b..e20e2d9 100644
+       --- a/sm1/foo6
+       +++ b/sm1/foo6
+       @@ -1 +1,3 @@
+       -foo6
+       +new
+       +modification
+       +modification
+       EOF
+       test_cmp expected actual
+'
+
+test_expect_success 'modified submodule contains untracked and modified content (dirty ignored)' '
+       echo modification >> sm1/foo6 &&
+       git diff-index -p --ignore-submodules=dirty --submodule=diff HEAD >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 17243c9..cfce562:
+       diff --git a/sm1/foo6 b/sm1/foo6
+       index 462398b..3e75765 100644
+       --- a/sm1/foo6
+       +++ b/sm1/foo6
+       @@ -1 +1 @@
+       -foo6
+       +new
+       EOF
+       test_cmp expected actual
+'
+
+test_expect_success 'modified submodule contains untracked and modified content (all ignored)' '
+       echo modification >> sm1/foo6 &&
+       git diff-index -p --ignore-submodules --submodule=diff HEAD >actual &&
+       ! test -s actual
+'
+
+# NOT OK
+test_expect_success 'modified submodule contains modified content' '
+       rm -f sm1/new-file &&
+       git diff-index -p --submodule=diff HEAD >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 contains modified content
+       Submodule sm1 17243c9..cfce562:
+       diff --git a/sm1/foo6 b/sm1/foo6
+       index 462398b..ac466ca 100644
+       --- a/sm1/foo6
+       +++ b/sm1/foo6
+       @@ -1 +1,5 @@
+       -foo6
+       +new
+       +modification
+       +modification
+       +modification
+       +modification
+       EOF
+       test_cmp expected actual
+'
+
+rm -rf sm1
+test_expect_success 'deleted submodule' '
+       git diff-index -p --submodule=diff HEAD >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 17243c9...0000000 (submodule deleted)
+       EOF
+       test_cmp expected actual
+'
+
+test_create_repo sm2 &&
+head7=$(add_file sm2 foo8 foo9) &&
+git add sm2
+
+test_expect_success 'multiple submodules' '
+       git diff-index -p --submodule=diff HEAD >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 17243c9...0000000 (submodule deleted)
+       Submodule sm2 0000000...a5a65c9 (new submodule)
+       diff --git a/sm2/foo8 b/sm2/foo8
+       new file mode 100644
+       index 0000000..db9916b
+       --- /dev/null
+       +++ b/sm2/foo8
+       @@ -0,0 +1 @@
+       +foo8
+       diff --git a/sm2/foo9 b/sm2/foo9
+       new file mode 100644
+       index 0000000..9c3b4f6
+       --- /dev/null
+       +++ b/sm2/foo9
+       @@ -0,0 +1 @@
+       +foo9
+       EOF
+       test_cmp expected actual
+'
+
+test_expect_success 'path filter' '
+       git diff-index -p --submodule=diff HEAD sm2 >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm2 0000000...a5a65c9 (new submodule)
+       diff --git a/sm2/foo8 b/sm2/foo8
+       new file mode 100644
+       index 0000000..db9916b
+       --- /dev/null
+       +++ b/sm2/foo8
+       @@ -0,0 +1 @@
+       +foo8
+       diff --git a/sm2/foo9 b/sm2/foo9
+       new file mode 100644
+       index 0000000..9c3b4f6
+       --- /dev/null
+       +++ b/sm2/foo9
+       @@ -0,0 +1 @@
+       +foo9
+       EOF
+       test_cmp expected actual
+'
+
+commit_file sm2
+test_expect_success 'given commit' '
+       git diff-index -p --submodule=diff HEAD^ >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 17243c9...0000000 (submodule deleted)
+       Submodule sm2 0000000...a5a65c9 (new submodule)
+       diff --git a/sm2/foo8 b/sm2/foo8
+       new file mode 100644
+       index 0000000..db9916b
+       --- /dev/null
+       +++ b/sm2/foo8
+       @@ -0,0 +1 @@
+       +foo8
+       diff --git a/sm2/foo9 b/sm2/foo9
+       new file mode 100644
+       index 0000000..9c3b4f6
+       --- /dev/null
+       +++ b/sm2/foo9
+       @@ -0,0 +1 @@
+       +foo9
+       EOF
+       test_cmp expected actual
+'
+
+test_expect_success 'setup .git file for sm2' '
+       (cd sm2 &&
+        REAL="$(pwd)/../.real" &&
+        mv .git "$REAL"
+        echo "gitdir: $REAL" >.git)
+'
+
+test_expect_success 'diff --submodule=diff with .git file' '
+       git diff --submodule=diff HEAD^ >actual &&
+       cat >expected <<-EOF &&
+       Submodule sm1 17243c9...0000000 (submodule deleted)
+       Submodule sm2 0000000...a5a65c9 (new submodule)
+       diff --git a/sm2/foo8 b/sm2/foo8
+       new file mode 100644
+       index 0000000..db9916b
+       --- /dev/null
+       +++ b/sm2/foo8
+       @@ -0,0 +1 @@
+       +foo8
+       diff --git a/sm2/foo9 b/sm2/foo9
+       new file mode 100644
+       index 0000000..9c3b4f6
+       --- /dev/null
+       +++ b/sm2/foo9
+       @@ -0,0 +1 @@
+       +foo9
+       EOF
+       test_cmp expected actual
+'
+
+test_done
index e2db47c36e09e3580c53867909cd3e20bdf320f5..1ccbd5948a735f692469e181933c97e8632404b4 100755 (executable)
@@ -187,6 +187,16 @@ test_expect_success 'git log --no-walk=sorted <commits> sorts by commit time' '
        test_cmp expect actual
 '
 
+cat > expect << EOF
+=== 804a787 sixth
+=== 394ef78 fifth
+=== 5d31159 fourth
+EOF
+test_expect_success 'git log --line-prefix="=== " --no-walk <commits> sorts by commit time' '
+       git log --line-prefix="=== " --no-walk --oneline 5d31159 804a787 394ef78 > actual &&
+       test_cmp expect actual
+'
+
 cat > expect << EOF
 5d31159 fourth
 804a787 sixth
@@ -284,6 +294,21 @@ test_expect_success 'simple log --graph' '
        test_cmp expect actual
 '
 
+cat > expect <<EOF
+123 * Second
+123 * sixth
+123 * fifth
+123 * fourth
+123 * third
+123 * second
+123 * initial
+EOF
+
+test_expect_success 'simple log --graph --line-prefix="123 "' '
+       git log --graph --line-prefix="123 " --pretty=tformat:%s >actual &&
+       test_cmp expect actual
+'
+
 test_expect_success 'set up merge history' '
        git checkout -b side HEAD~4 &&
        test_commit side-1 1 1 &&
@@ -313,6 +338,27 @@ test_expect_success 'log --graph with merge' '
        test_cmp expect actual
 '
 
+cat > expect <<\EOF
+| | | *   Merge branch 'side'
+| | | |\
+| | | | * side-2
+| | | | * side-1
+| | | * | Second
+| | | * | sixth
+| | | * | fifth
+| | | * | fourth
+| | | |/
+| | | * third
+| | | * second
+| | | * initial
+EOF
+
+test_expect_success 'log --graph --line-prefix="| | | " with merge' '
+       git log --line-prefix="| | | " --graph --date-order --pretty=tformat:%s |
+               sed "s/ *\$//" >actual &&
+       test_cmp expect actual
+'
+
 test_expect_success 'log --raw --graph -m with merge' '
        git log --raw --graph --oneline -m master | head -n 500 >actual &&
        grep "initial" actual
@@ -867,6 +913,283 @@ test_expect_success 'log --graph with diff and stats' '
        test_i18ncmp expect actual.sanitized
 '
 
+cat >expect <<\EOF
+*** *   commit COMMIT_OBJECT_NAME
+*** |\  Merge: MERGE_PARENTS
+*** | | Author: A U Thor <author@example.com>
+*** | |
+*** | |     Merge HEADS DESCRIPTION
+*** | |
+*** | * commit COMMIT_OBJECT_NAME
+*** | | Author: A U Thor <author@example.com>
+*** | |
+*** | |     reach
+*** | | ---
+*** | |  reach.t | 1 +
+*** | |  1 file changed, 1 insertion(+)
+*** | |
+*** | | diff --git a/reach.t b/reach.t
+*** | | new file mode 100644
+*** | | index 0000000..10c9591
+*** | | --- /dev/null
+*** | | +++ b/reach.t
+*** | | @@ -0,0 +1 @@
+*** | | +reach
+*** | |
+*** |  \
+*** *-. \   commit COMMIT_OBJECT_NAME
+*** |\ \ \  Merge: MERGE_PARENTS
+*** | | | | Author: A U Thor <author@example.com>
+*** | | | |
+*** | | | |     Merge HEADS DESCRIPTION
+*** | | | |
+*** | | * | commit COMMIT_OBJECT_NAME
+*** | | |/  Author: A U Thor <author@example.com>
+*** | | |
+*** | | |       octopus-b
+*** | | |   ---
+*** | | |    octopus-b.t | 1 +
+*** | | |    1 file changed, 1 insertion(+)
+*** | | |
+*** | | |   diff --git a/octopus-b.t b/octopus-b.t
+*** | | |   new file mode 100644
+*** | | |   index 0000000..d5fcad0
+*** | | |   --- /dev/null
+*** | | |   +++ b/octopus-b.t
+*** | | |   @@ -0,0 +1 @@
+*** | | |   +octopus-b
+*** | | |
+*** | * | commit COMMIT_OBJECT_NAME
+*** | |/  Author: A U Thor <author@example.com>
+*** | |
+*** | |       octopus-a
+*** | |   ---
+*** | |    octopus-a.t | 1 +
+*** | |    1 file changed, 1 insertion(+)
+*** | |
+*** | |   diff --git a/octopus-a.t b/octopus-a.t
+*** | |   new file mode 100644
+*** | |   index 0000000..11ee015
+*** | |   --- /dev/null
+*** | |   +++ b/octopus-a.t
+*** | |   @@ -0,0 +1 @@
+*** | |   +octopus-a
+*** | |
+*** * | commit COMMIT_OBJECT_NAME
+*** |/  Author: A U Thor <author@example.com>
+*** |
+*** |       seventh
+*** |   ---
+*** |    seventh.t | 1 +
+*** |    1 file changed, 1 insertion(+)
+*** |
+*** |   diff --git a/seventh.t b/seventh.t
+*** |   new file mode 100644
+*** |   index 0000000..9744ffc
+*** |   --- /dev/null
+*** |   +++ b/seventh.t
+*** |   @@ -0,0 +1 @@
+*** |   +seventh
+*** |
+*** *   commit COMMIT_OBJECT_NAME
+*** |\  Merge: MERGE_PARENTS
+*** | | Author: A U Thor <author@example.com>
+*** | |
+*** | |     Merge branch 'tangle'
+*** | |
+*** | *   commit COMMIT_OBJECT_NAME
+*** | |\  Merge: MERGE_PARENTS
+*** | | | Author: A U Thor <author@example.com>
+*** | | |
+*** | | |     Merge branch 'side' (early part) into tangle
+*** | | |
+*** | * |   commit COMMIT_OBJECT_NAME
+*** | |\ \  Merge: MERGE_PARENTS
+*** | | | | Author: A U Thor <author@example.com>
+*** | | | |
+*** | | | |     Merge branch 'master' (early part) into tangle
+*** | | | |
+*** | * | | commit COMMIT_OBJECT_NAME
+*** | | | | Author: A U Thor <author@example.com>
+*** | | | |
+*** | | | |     tangle-a
+*** | | | | ---
+*** | | | |  tangle-a | 1 +
+*** | | | |  1 file changed, 1 insertion(+)
+*** | | | |
+*** | | | | diff --git a/tangle-a b/tangle-a
+*** | | | | new file mode 100644
+*** | | | | index 0000000..7898192
+*** | | | | --- /dev/null
+*** | | | | +++ b/tangle-a
+*** | | | | @@ -0,0 +1 @@
+*** | | | | +a
+*** | | | |
+*** * | | |   commit COMMIT_OBJECT_NAME
+*** |\ \ \ \  Merge: MERGE_PARENTS
+*** | | | | | Author: A U Thor <author@example.com>
+*** | | | | |
+*** | | | | |     Merge branch 'side'
+*** | | | | |
+*** | * | | | commit COMMIT_OBJECT_NAME
+*** | | |_|/  Author: A U Thor <author@example.com>
+*** | |/| |
+*** | | | |       side-2
+*** | | | |   ---
+*** | | | |    2 | 1 +
+*** | | | |    1 file changed, 1 insertion(+)
+*** | | | |
+*** | | | |   diff --git a/2 b/2
+*** | | | |   new file mode 100644
+*** | | | |   index 0000000..0cfbf08
+*** | | | |   --- /dev/null
+*** | | | |   +++ b/2
+*** | | | |   @@ -0,0 +1 @@
+*** | | | |   +2
+*** | | | |
+*** | * | | commit COMMIT_OBJECT_NAME
+*** | | | | Author: A U Thor <author@example.com>
+*** | | | |
+*** | | | |     side-1
+*** | | | | ---
+*** | | | |  1 | 1 +
+*** | | | |  1 file changed, 1 insertion(+)
+*** | | | |
+*** | | | | diff --git a/1 b/1
+*** | | | | new file mode 100644
+*** | | | | index 0000000..d00491f
+*** | | | | --- /dev/null
+*** | | | | +++ b/1
+*** | | | | @@ -0,0 +1 @@
+*** | | | | +1
+*** | | | |
+*** * | | | commit COMMIT_OBJECT_NAME
+*** | | | | Author: A U Thor <author@example.com>
+*** | | | |
+*** | | | |     Second
+*** | | | | ---
+*** | | | |  one | 1 +
+*** | | | |  1 file changed, 1 insertion(+)
+*** | | | |
+*** | | | | diff --git a/one b/one
+*** | | | | new file mode 100644
+*** | | | | index 0000000..9a33383
+*** | | | | --- /dev/null
+*** | | | | +++ b/one
+*** | | | | @@ -0,0 +1 @@
+*** | | | | +case
+*** | | | |
+*** * | | | commit COMMIT_OBJECT_NAME
+*** | |_|/  Author: A U Thor <author@example.com>
+*** |/| |
+*** | | |       sixth
+*** | | |   ---
+*** | | |    a/two | 1 -
+*** | | |    1 file changed, 1 deletion(-)
+*** | | |
+*** | | |   diff --git a/a/two b/a/two
+*** | | |   deleted file mode 100644
+*** | | |   index 9245af5..0000000
+*** | | |   --- a/a/two
+*** | | |   +++ /dev/null
+*** | | |   @@ -1 +0,0 @@
+*** | | |   -ni
+*** | | |
+*** * | | commit COMMIT_OBJECT_NAME
+*** | | | Author: A U Thor <author@example.com>
+*** | | |
+*** | | |     fifth
+*** | | | ---
+*** | | |  a/two | 1 +
+*** | | |  1 file changed, 1 insertion(+)
+*** | | |
+*** | | | diff --git a/a/two b/a/two
+*** | | | new file mode 100644
+*** | | | index 0000000..9245af5
+*** | | | --- /dev/null
+*** | | | +++ b/a/two
+*** | | | @@ -0,0 +1 @@
+*** | | | +ni
+*** | | |
+*** * | | commit COMMIT_OBJECT_NAME
+*** |/ /  Author: A U Thor <author@example.com>
+*** | |
+*** | |       fourth
+*** | |   ---
+*** | |    ein | 1 +
+*** | |    1 file changed, 1 insertion(+)
+*** | |
+*** | |   diff --git a/ein b/ein
+*** | |   new file mode 100644
+*** | |   index 0000000..9d7e69f
+*** | |   --- /dev/null
+*** | |   +++ b/ein
+*** | |   @@ -0,0 +1 @@
+*** | |   +ichi
+*** | |
+*** * | commit COMMIT_OBJECT_NAME
+*** |/  Author: A U Thor <author@example.com>
+*** |
+*** |       third
+*** |   ---
+*** |    ichi | 1 +
+*** |    one  | 1 -
+*** |    2 files changed, 1 insertion(+), 1 deletion(-)
+*** |
+*** |   diff --git a/ichi b/ichi
+*** |   new file mode 100644
+*** |   index 0000000..9d7e69f
+*** |   --- /dev/null
+*** |   +++ b/ichi
+*** |   @@ -0,0 +1 @@
+*** |   +ichi
+*** |   diff --git a/one b/one
+*** |   deleted file mode 100644
+*** |   index 9d7e69f..0000000
+*** |   --- a/one
+*** |   +++ /dev/null
+*** |   @@ -1 +0,0 @@
+*** |   -ichi
+*** |
+*** * commit COMMIT_OBJECT_NAME
+*** | Author: A U Thor <author@example.com>
+*** |
+*** |     second
+*** | ---
+*** |  one | 2 +-
+*** |  1 file changed, 1 insertion(+), 1 deletion(-)
+*** |
+*** | diff --git a/one b/one
+*** | index 5626abf..9d7e69f 100644
+*** | --- a/one
+*** | +++ b/one
+*** | @@ -1 +1 @@
+*** | -one
+*** | +ichi
+*** |
+*** * commit COMMIT_OBJECT_NAME
+***   Author: A U Thor <author@example.com>
+***
+***       initial
+***   ---
+***    one | 1 +
+***    1 file changed, 1 insertion(+)
+***
+***   diff --git a/one b/one
+***   new file mode 100644
+***   index 0000000..5626abf
+***   --- /dev/null
+***   +++ b/one
+***   @@ -0,0 +1 @@
+***   +one
+EOF
+
+test_expect_success 'log --line-prefix="*** " --graph with diff and stats' '
+       git log --line-prefix="*** " --no-renames --graph --pretty=short --stat -p >actual &&
+       sanitize_output >actual.sanitized <actual &&
+       test_i18ncmp expect actual.sanitized
+'
+
 test_expect_success 'dotdot is a parent directory' '
        mkdir -p a/b &&
        ( echo sixth && echo fifth ) >expect &&
index f314ad50791142b42c5f2807b5f086bbe9e1caad..a5eca210b8963c4881fd8be858d13b88401b9888 100755 (executable)
@@ -25,58 +25,94 @@ test_expect_success setup '
        } >obj-list
 '
 
-rm -rf clone.git
 test_expect_success 'pack without --include-tag' '
-       packname_1=$(git pack-objects \
+       packname=$(git pack-objects \
                --window=0 \
-               test-1 <obj-list)
+               test-no-include <obj-list)
 '
 
 test_expect_success 'unpack objects' '
-       (
-               GIT_DIR=clone.git &&
-               export GIT_DIR &&
-               git init &&
-               git unpack-objects -n <test-1-${packname_1}.pack &&
-               git unpack-objects <test-1-${packname_1}.pack
-       )
+       rm -rf clone.git &&
+       git init clone.git &&
+       git -C clone.git unpack-objects <test-no-include-${packname}.pack
 '
 
 test_expect_success 'check unpacked result (have commit, no tag)' '
        git rev-list --objects $commit >list.expect &&
-       (
-               test_must_fail env GIT_DIR=clone.git git cat-file -e $tag &&
-               git rev-list --objects $commit
-       ) >list.actual &&
+       test_must_fail git -C clone.git cat-file -e $tag &&
+       git -C clone.git rev-list --objects $commit >list.actual &&
        test_cmp list.expect list.actual
 '
 
-rm -rf clone.git
 test_expect_success 'pack with --include-tag' '
-       packname_1=$(git pack-objects \
+       packname=$(git pack-objects \
                --window=0 \
                --include-tag \
-               test-2 <obj-list)
+               test-include <obj-list)
 '
 
 test_expect_success 'unpack objects' '
-       (
-               GIT_DIR=clone.git &&
-               export GIT_DIR &&
-               git init &&
-               git unpack-objects -n <test-2-${packname_1}.pack &&
-               git unpack-objects <test-2-${packname_1}.pack
-       )
+       rm -rf clone.git &&
+       git init clone.git &&
+       git -C clone.git unpack-objects <test-include-${packname}.pack
 '
 
 test_expect_success 'check unpacked result (have commit, have tag)' '
        git rev-list --objects mytag >list.expect &&
-       (
-               GIT_DIR=clone.git &&
-               export GIT_DIR &&
-               git rev-list --objects $tag
-       ) >list.actual &&
+       git -C clone.git rev-list --objects $tag >list.actual &&
        test_cmp list.expect list.actual
 '
 
+# A tag of a tag, where the "inner" tag is not otherwise
+# reachable, and a full peel points to a commit reachable from HEAD.
+test_expect_success 'create hidden inner tag' '
+       test_commit commit &&
+       git tag -m inner inner HEAD &&
+       git tag -m outer outer inner &&
+       git tag -d inner
+'
+
+test_expect_success 'pack explicit outer tag' '
+       packname=$(
+               {
+                       echo HEAD &&
+                       echo outer
+               } |
+               git pack-objects --revs test-hidden-explicit
+       )
+'
+
+test_expect_success 'unpack objects' '
+       rm -rf clone.git &&
+       git init clone.git &&
+       git -C clone.git unpack-objects <test-hidden-explicit-${packname}.pack
+'
+
+test_expect_success 'check unpacked result (have all objects)' '
+       git -C clone.git rev-list --objects $(git rev-parse outer HEAD)
+'
+
+test_expect_success 'pack implied outer tag' '
+       packname=$(
+               echo HEAD |
+               git pack-objects --revs --include-tag test-hidden-implied
+       )
+'
+
+test_expect_success 'unpack objects' '
+       rm -rf clone.git &&
+       git init clone.git &&
+       git -C clone.git unpack-objects <test-hidden-implied-${packname}.pack
+'
+
+test_expect_success 'check unpacked result (have all objects)' '
+       git -C clone.git rev-list --objects $(git rev-parse outer HEAD)
+'
+
+test_expect_success 'single-branch clone can transfer tag' '
+       rm -rf clone.git &&
+       git clone --no-local --single-branch -b master . clone.git &&
+       git -C clone.git fsck
+'
+
 test_done
index 954d0e43f52375b1ed86a4edb9d274714d3b596d..f3b0a8d30afcb472398bef8623a49ba6bac7dc24 100755 (executable)
@@ -485,4 +485,39 @@ test_expect_success 'fetching submodules respects parallel settings' '
        )
 '
 
+test_expect_success 'fetching submodule into a broken repository' '
+       # Prepare src and src/sub nested in it
+       git init src &&
+       (
+               cd src &&
+               git init sub &&
+               git -C sub commit --allow-empty -m "initial in sub" &&
+               git submodule add -- ./sub sub &&
+               git commit -m "initial in top"
+       ) &&
+
+       # Clone the old-fashoned way
+       git clone src dst &&
+       git -C dst clone ../src/sub sub &&
+
+       # Make sure that old-fashoned layout is still supported
+       git -C dst status &&
+
+       # "diff" would find no change
+       git -C dst diff --exit-code &&
+
+       # Recursive-fetch works fine
+       git -C dst fetch --recurse-submodules &&
+
+       # Break the receiving submodule
+       rm -f dst/sub/.git/HEAD &&
+
+       # NOTE: without the fix the following tests will recurse forever!
+       # They should terminate with an error.
+
+       test_must_fail git -C dst status &&
+       test_must_fail git -C dst diff &&
+       test_must_fail git -C dst fetch --recurse-submodules
+'
+
 test_done
index 4840c71f02a388eeae8223c7f4e67c51ecf745b2..d38bf32470c592f89cbd31aa08a3c1de6fffe540 100755 (executable)
@@ -74,7 +74,7 @@ test_expect_success 'push to remote repository (standard)' '
        test_tick &&
        git commit -m path2 &&
        HEAD=$(git rev-parse --verify HEAD) &&
-       GIT_CURL_VERBOSE=1 git push -v -v 2>err &&
+       GIT_TRACE_CURL=true git push -v -v 2>err &&
        ! grep "Expect: 100-continue" err &&
        grep "POST git-receive-pack ([0-9]* bytes)" err &&
        (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
diff --git a/t/t5546-receive-limits.sh b/t/t5546-receive-limits.sh
new file mode 100755 (executable)
index 0000000..10cb0be
--- /dev/null
@@ -0,0 +1,55 @@
+#!/bin/sh
+
+test_description='check receive input limits'
+. ./test-lib.sh
+
+# Let's run tests with different unpack limits: 1 and 10000
+# When the limit is 1, `git receive-pack` will call `git index-pack`.
+# When the limit is 10000, `git receive-pack` will call `git unpack-objects`.
+
+test_pack_input_limit () {
+       case "$1" in
+       index) unpack_limit=1 ;;
+       unpack) unpack_limit=10000 ;;
+       esac
+
+       test_expect_success 'prepare destination repository' '
+               rm -fr dest &&
+               git --bare init dest
+       '
+
+       test_expect_success "set unpacklimit to $unpack_limit" '
+               git --git-dir=dest config receive.unpacklimit "$unpack_limit"
+       '
+
+       test_expect_success 'setting receive.maxInputSize to 512 rejects push' '
+               git --git-dir=dest config receive.maxInputSize 512 &&
+               test_must_fail git push dest HEAD
+       '
+
+       test_expect_success 'bumping limit to 4k allows push' '
+               git --git-dir=dest config receive.maxInputSize 4k &&
+               git push dest HEAD
+       '
+
+       test_expect_success 'prepare destination repository (again)' '
+               rm -fr dest &&
+               git --bare init dest
+       '
+
+       test_expect_success 'lifting the limit allows push' '
+               git --git-dir=dest config receive.maxInputSize 0 &&
+               git push dest HEAD
+       '
+}
+
+test_expect_success "create known-size (1024 bytes) commit" '
+       test-genrandom foo 1024 >one-k &&
+       git add one-k &&
+       test_commit one-k
+'
+
+test_pack_input_limit index
+test_pack_input_limit unpack
+
+test_done
index 3484b6f0f3cf04a9cf831a5d91c31486efebcc38..dc9b87d6b41efc472eac1a2b768bf56c01caf4d1 100755 (executable)
@@ -263,15 +263,15 @@ check_language () {
                >expect
                ;;
        ?*)
-               echo "Accept-Language: $1" >expect
+               echo "=> Send header: Accept-Language: $1" >expect
                ;;
        esac &&
-       GIT_CURL_VERBOSE=1 \
+       GIT_TRACE_CURL=true \
        LANGUAGE=$2 \
        git ls-remote "$HTTPD_URL/dumb/repo.git" >output 2>&1 &&
        tr -d '\015' <output |
        sort -u |
-       sed -ne '/^Accept-Language:/ p' >actual &&
+       sed -ne '/^=> Send header: Accept-Language:/ p' >actual &&
        test_cmp expect actual
 }
 
@@ -295,8 +295,8 @@ ja;q=0.95, zh;q=0.94, sv;q=0.93, pt;q=0.92, nb;q=0.91, *;q=0.90" \
 '
 
 test_expect_success 'git client does not send an empty Accept-Language' '
-       GIT_CURL_VERBOSE=1 LANGUAGE= git ls-remote "$HTTPD_URL/dumb/repo.git" 2>stderr &&
-       ! grep "^Accept-Language:" stderr
+       GIT_TRACE_CURL=true LANGUAGE= git ls-remote "$HTTPD_URL/dumb/repo.git" 2>stderr &&
+       ! grep "^=> Send header: Accept-Language:" stderr
 '
 
 stop_httpd
index 2f375eb94d528baefad038ff5b07baf0fe08d1fc..1ec5b2747a2100d3ae043cde5a2436eed2d52aec 100755 (executable)
@@ -43,12 +43,21 @@ cat >exp <<EOF
 < Content-Type: application/x-git-upload-pack-result
 EOF
 test_expect_success 'clone http repository' '
-       GIT_CURL_VERBOSE=1 git clone --quiet $HTTPD_URL/smart/repo.git clone 2>err &&
+       GIT_TRACE_CURL=true git clone --quiet $HTTPD_URL/smart/repo.git clone 2>err &&
        test_cmp file clone/file &&
        tr '\''\015'\'' Q <err |
        sed -e "
                s/Q\$//
                /^[*] /d
+               /^== Info:/d
+               /^=> Send header, /d
+               /^=> Send header:$/d
+               /^<= Recv header, /d
+               /^<= Recv header:$/d
+               s/=> Send header: //
+               s/= Recv header://
+               /^<= Recv data/d
+               /^=> Send data/d
                /^$/d
                /^< $/d
 
@@ -261,9 +270,9 @@ test_expect_success CMDLINE_LIMIT \
 '
 
 test_expect_success 'large fetch-pack requests can be split across POSTs' '
-       GIT_CURL_VERBOSE=1 git -c http.postbuffer=65536 \
+       GIT_TRACE_CURL=true git -c http.postbuffer=65536 \
                clone --bare "$HTTPD_URL/smart/repo.git" split.git 2>err &&
-       grep "^> POST" err >posts &&
+       grep "^=> Send header: POST" err >posts &&
        test_line_count = 2 posts
 '
 
index dd8f88d18782f15e35aa3105668d9a713ba9fe3b..7a6e33e6732eaf69e298b56729ba4ead9ffaee0e 100755 (executable)
@@ -185,7 +185,9 @@ test_expect_success 'custom merge does not lock index' '
        git reset --hard anchor &&
        write_script sleep-one-second.sh <<-\EOF &&
                sleep 1 &
+               echo $! >sleep.pid
        EOF
+       test_when_finished "kill \$(cat sleep.pid)" &&
 
        test_write_lines >.gitattributes \
                "* merge=ours" "text merge=sleep-one-second" &&
index 4d17363a926c8938c6c8d78e997a53ffb81b3c6c..53cf42fac19c83f2da7de1cd5b6c4ca0cf6e5ccf 100755 (executable)
@@ -232,4 +232,25 @@ test_expect_success 'status --branch with detached HEAD' '
        test_i18ncmp expected actual
 '
 
+## Duplicate the above test and verify --porcelain=v1 arg parsing.
+test_expect_success 'status --porcelain=v1 --branch with detached HEAD' '
+       git reset --hard &&
+       git checkout master^0 &&
+       git status --branch --porcelain=v1 >actual &&
+       cat >expected <<-EOF &&
+       ## HEAD (no branch)
+       ?? .gitconfig
+       ?? actual
+       ?? expect
+       ?? expected
+       ?? mdconflict/
+       EOF
+       test_i18ncmp expected actual
+'
+
+## Verify parser error on invalid --porcelain argument.
+test_expect_success 'status --porcelain=bogus' '
+       test_must_fail git status --porcelain=bogus
+'
+
 test_done
diff --git a/t/t7064-wtstatus-pv2.sh b/t/t7064-wtstatus-pv2.sh
new file mode 100755 (executable)
index 0000000..3012a4d
--- /dev/null
@@ -0,0 +1,593 @@
+#!/bin/sh
+
+test_description='git status --porcelain=v2
+
+This test exercises porcelain V2 output for git status.'
+
+
+. ./test-lib.sh
+
+
+test_expect_success setup '
+       test_tick &&
+       git config core.autocrlf false &&
+       echo x >file_x &&
+       echo y >file_y &&
+       echo z >file_z &&
+       mkdir dir1 &&
+       echo a >dir1/file_a &&
+       echo b >dir1/file_b
+'
+
+test_expect_success 'before initial commit, nothing added, only untracked' '
+       cat >expect <<-EOF &&
+       # branch.oid (initial)
+       # branch.head master
+       ? actual
+       ? dir1/
+       ? expect
+       ? file_x
+       ? file_y
+       ? file_z
+       EOF
+
+       git status --porcelain=v2 --branch --untracked-files=normal >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'before initial commit, things added' '
+       git add file_x file_y file_z dir1 &&
+       OID_A=$(git hash-object -t blob -- dir1/file_a) &&
+       OID_B=$(git hash-object -t blob -- dir1/file_b) &&
+       OID_X=$(git hash-object -t blob -- file_x) &&
+       OID_Y=$(git hash-object -t blob -- file_y) &&
+       OID_Z=$(git hash-object -t blob -- file_z) &&
+
+       cat >expect <<-EOF &&
+       # branch.oid (initial)
+       # branch.head master
+       1 A. N... 000000 100644 100644 $_z40 $OID_A dir1/file_a
+       1 A. N... 000000 100644 100644 $_z40 $OID_B dir1/file_b
+       1 A. N... 000000 100644 100644 $_z40 $OID_X file_x
+       1 A. N... 000000 100644 100644 $_z40 $OID_Y file_y
+       1 A. N... 000000 100644 100644 $_z40 $OID_Z file_z
+       ? actual
+       ? expect
+       EOF
+
+       git status --porcelain=v2 --branch --untracked-files=all >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'before initial commit, things added (-z)' '
+       lf_to_nul >expect <<-EOF &&
+       # branch.oid (initial)
+       # branch.head master
+       1 A. N... 000000 100644 100644 $_z40 $OID_A dir1/file_a
+       1 A. N... 000000 100644 100644 $_z40 $OID_B dir1/file_b
+       1 A. N... 000000 100644 100644 $_z40 $OID_X file_x
+       1 A. N... 000000 100644 100644 $_z40 $OID_Y file_y
+       1 A. N... 000000 100644 100644 $_z40 $OID_Z file_z
+       ? actual
+       ? expect
+       EOF
+
+       git status -z --porcelain=v2 --branch --untracked-files=all >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'make first commit, comfirm HEAD oid and branch' '
+       git commit -m initial &&
+       H0=$(git rev-parse HEAD) &&
+       cat >expect <<-EOF &&
+       # branch.oid $H0
+       # branch.head master
+       ? actual
+       ? expect
+       EOF
+
+       git status --porcelain=v2 --branch --untracked-files=all >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'after first commit, create unstaged changes' '
+       echo x >>file_x &&
+       OID_X1=$(git hash-object -t blob -- file_x) &&
+       rm file_z &&
+       H0=$(git rev-parse HEAD) &&
+
+       cat >expect <<-EOF &&
+       # branch.oid $H0
+       # branch.head master
+       1 .M N... 100644 100644 100644 $OID_X $OID_X file_x
+       1 .D N... 100644 100644 000000 $OID_Z $OID_Z file_z
+       ? actual
+       ? expect
+       EOF
+
+       git status --porcelain=v2 --branch --untracked-files=all >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'after first commit but omit untracked files and branch' '
+       cat >expect <<-EOF &&
+       1 .M N... 100644 100644 100644 $OID_X $OID_X file_x
+       1 .D N... 100644 100644 000000 $OID_Z $OID_Z file_z
+       EOF
+
+       git status --porcelain=v2 --untracked-files=no >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'after first commit, stage existing changes' '
+       git add file_x &&
+       git rm file_z &&
+       H0=$(git rev-parse HEAD) &&
+
+       cat >expect <<-EOF &&
+       # branch.oid $H0
+       # branch.head master
+       1 M. N... 100644 100644 100644 $OID_X $OID_X1 file_x
+       1 D. N... 100644 000000 000000 $OID_Z $_z40 file_z
+       ? actual
+       ? expect
+       EOF
+
+       git status --porcelain=v2 --branch --untracked-files=all >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'rename causes 2 path lines' '
+       git mv file_y renamed_y &&
+       H0=$(git rev-parse HEAD) &&
+
+       q_to_tab >expect <<-EOF &&
+       # branch.oid $H0
+       # branch.head master
+       1 M. N... 100644 100644 100644 $OID_X $OID_X1 file_x
+       1 D. N... 100644 000000 000000 $OID_Z $_z40 file_z
+       2 R. N... 100644 100644 100644 $OID_Y $OID_Y R100 renamed_yQfile_y
+       ? actual
+       ? expect
+       EOF
+
+       git status --porcelain=v2 --branch --untracked-files=all >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'rename causes 2 path lines (-z)' '
+       H0=$(git rev-parse HEAD) &&
+
+       ## Lines use NUL path separator and line terminator, so double transform here.
+       q_to_nul <<-EOF | lf_to_nul >expect &&
+       # branch.oid $H0
+       # branch.head master
+       1 M. N... 100644 100644 100644 $OID_X $OID_X1 file_x
+       1 D. N... 100644 000000 000000 $OID_Z $_z40 file_z
+       2 R. N... 100644 100644 100644 $OID_Y $OID_Y R100 renamed_yQfile_y
+       ? actual
+       ? expect
+       EOF
+
+       git status --porcelain=v2 --branch --untracked-files=all -z >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'make second commit, confirm clean and new HEAD oid' '
+       git commit -m second &&
+       H1=$(git rev-parse HEAD) &&
+
+       cat >expect <<-EOF &&
+       # branch.oid $H1
+       # branch.head master
+       ? actual
+       ? expect
+       EOF
+
+       git status --porcelain=v2 --branch --untracked-files=all >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'confirm ignored files are not printed' '
+       test_when_finished "rm -f x.ign .gitignore" &&
+       echo x.ign >.gitignore &&
+       echo "ignore me" >x.ign &&
+
+       cat >expect <<-EOF &&
+       ? .gitignore
+       ? actual
+       ? expect
+       EOF
+
+       git status --porcelain=v2 --untracked-files=all >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'ignored files are printed with --ignored' '
+       test_when_finished "rm -f x.ign .gitignore" &&
+       echo x.ign >.gitignore &&
+       echo "ignore me" >x.ign &&
+
+       cat >expect <<-EOF &&
+       ? .gitignore
+       ? actual
+       ? expect
+       ! x.ign
+       EOF
+
+       git status --porcelain=v2 --ignored --untracked-files=all >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'create and commit permanent ignore file' '
+       cat >.gitignore <<-EOF &&
+       actual*
+       expect*
+       EOF
+
+       git add .gitignore &&
+       git commit -m ignore_trash &&
+       H1=$(git rev-parse HEAD) &&
+
+       cat >expect <<-EOF &&
+       # branch.oid $H1
+       # branch.head master
+       EOF
+
+       git status --porcelain=v2 --branch >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'verify --intent-to-add output' '
+       test_when_finished "git rm -f intent1.add intent2.add" &&
+       touch intent1.add &&
+       echo test >intent2.add &&
+
+       git add --intent-to-add intent1.add intent2.add &&
+
+       cat >expect <<-EOF &&
+       1 AM N... 000000 100644 100644 $_z40 $EMPTY_BLOB intent1.add
+       1 AM N... 000000 100644 100644 $_z40 $EMPTY_BLOB intent2.add
+       EOF
+
+       git status --porcelain=v2 >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'verify AA (add-add) conflict' '
+       test_when_finished "git reset --hard" &&
+
+       git branch AA_A master &&
+       git checkout AA_A &&
+       echo "Branch AA_A" >conflict.txt &&
+       OID_AA_A=$(git hash-object -t blob -- conflict.txt) &&
+       git add conflict.txt &&
+       git commit -m "branch aa_a" &&
+
+       git branch AA_B master &&
+       git checkout AA_B &&
+       echo "Branch AA_B" >conflict.txt &&
+       OID_AA_B=$(git hash-object -t blob -- conflict.txt) &&
+       git add conflict.txt &&
+       git commit -m "branch aa_b" &&
+
+       git branch AA_M AA_B &&
+       git checkout AA_M &&
+       test_must_fail git merge AA_A &&
+
+       HM=$(git rev-parse HEAD) &&
+
+       cat >expect <<-EOF &&
+       # branch.oid $HM
+       # branch.head AA_M
+       u AA N... 000000 100644 100644 100644 $_z40 $OID_AA_B $OID_AA_A conflict.txt
+       EOF
+
+       git status --porcelain=v2 --branch --untracked-files=all >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'verify UU (edit-edit) conflict' '
+       test_when_finished "git reset --hard" &&
+
+       git branch UU_ANC master &&
+       git checkout UU_ANC &&
+       echo "Ancestor" >conflict.txt &&
+       OID_UU_ANC=$(git hash-object -t blob -- conflict.txt) &&
+       git add conflict.txt &&
+       git commit -m "UU_ANC" &&
+
+       git branch UU_A UU_ANC &&
+       git checkout UU_A &&
+       echo "Branch UU_A" >conflict.txt &&
+       OID_UU_A=$(git hash-object -t blob -- conflict.txt) &&
+       git add conflict.txt &&
+       git commit -m "branch uu_a" &&
+
+       git branch UU_B UU_ANC &&
+       git checkout UU_B &&
+       echo "Branch UU_B" >conflict.txt &&
+       OID_UU_B=$(git hash-object -t blob -- conflict.txt) &&
+       git add conflict.txt &&
+       git commit -m "branch uu_b" &&
+
+       git branch UU_M UU_B &&
+       git checkout UU_M &&
+       test_must_fail git merge UU_A &&
+
+       HM=$(git rev-parse HEAD) &&
+
+       cat >expect <<-EOF &&
+       # branch.oid $HM
+       # branch.head UU_M
+       u UU N... 100644 100644 100644 100644 $OID_UU_ANC $OID_UU_B $OID_UU_A conflict.txt
+       EOF
+
+       git status --porcelain=v2 --branch --untracked-files=all >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'verify upstream fields in branch header' '
+       git checkout master &&
+       test_when_finished "rm -rf sub_repo" &&
+       git clone . sub_repo &&
+       (
+               ## Confirm local master tracks remote master.
+               cd sub_repo &&
+               HUF=$(git rev-parse HEAD) &&
+
+               cat >expect <<-EOF &&
+               # branch.oid $HUF
+               # branch.head master
+               # branch.upstream origin/master
+               # branch.ab +0 -0
+               EOF
+
+               git status --porcelain=v2 --branch --untracked-files=all >actual &&
+               test_cmp expect actual &&
+
+               ## Test ahead/behind.
+               echo xyz >file_xyz &&
+               git add file_xyz &&
+               git commit -m xyz &&
+
+               HUF=$(git rev-parse HEAD) &&
+
+               cat >expect <<-EOF &&
+               # branch.oid $HUF
+               # branch.head master
+               # branch.upstream origin/master
+               # branch.ab +1 -0
+               EOF
+
+               git status --porcelain=v2 --branch --untracked-files=all >actual &&
+               test_cmp expect actual &&
+
+               ## Repeat the above but without --branch.
+               cat >expect <<-EOF &&
+               EOF
+
+               git status --porcelain=v2 --untracked-files=all >actual &&
+               test_cmp expect actual &&
+
+               ## Test upstream-gone case. Fake this by pointing origin/master at
+               ## a non-existing commit.
+               OLD=$(git rev-parse origin/master) &&
+               NEW=$_z40 &&
+               mv .git/packed-refs .git/old-packed-refs &&
+               sed "s/$OLD/$NEW/g" <.git/old-packed-refs >.git/packed-refs &&
+
+               HUF=$(git rev-parse HEAD) &&
+
+               cat >expect <<-EOF &&
+               # branch.oid $HUF
+               # branch.head master
+               # branch.upstream origin/master
+               EOF
+
+               git status --porcelain=v2 --branch --untracked-files=all >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'create and add submodule, submodule appears clean (A. S...)' '
+       git checkout master &&
+       git clone . sub_repo &&
+       git clone . super_repo &&
+       (       cd super_repo &&
+               git submodule add ../sub_repo sub1 &&
+
+               ## Confirm stage/add of clean submodule.
+               HMOD=$(git hash-object -t blob -- .gitmodules) &&
+               HSUP=$(git rev-parse HEAD) &&
+               HSUB=$HSUP &&
+
+               cat >expect <<-EOF &&
+               # branch.oid $HSUP
+               # branch.head master
+               # branch.upstream origin/master
+               # branch.ab +0 -0
+               1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
+               1 A. S... 000000 160000 160000 $_z40 $HSUB sub1
+               EOF
+
+               git status --porcelain=v2 --branch --untracked-files=all >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'untracked changes in added submodule (AM S..U)' '
+       (       cd super_repo &&
+               ## create untracked file in the submodule.
+               (       cd sub1 &&
+                       echo "xxxx" >file_in_sub
+               ) &&
+
+               HMOD=$(git hash-object -t blob -- .gitmodules) &&
+               HSUP=$(git rev-parse HEAD) &&
+               HSUB=$HSUP &&
+
+               cat >expect <<-EOF &&
+               # branch.oid $HSUP
+               # branch.head master
+               # branch.upstream origin/master
+               # branch.ab +0 -0
+               1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
+               1 AM S..U 000000 160000 160000 $_z40 $HSUB sub1
+               EOF
+
+               git status --porcelain=v2 --branch --untracked-files=all >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'staged changes in added submodule (AM S.M.)' '
+       (       cd super_repo &&
+               ## stage the changes in the submodule.
+               (       cd sub1 &&
+                       git add file_in_sub
+               ) &&
+
+               HMOD=$(git hash-object -t blob -- .gitmodules) &&
+               HSUP=$(git rev-parse HEAD) &&
+               HSUB=$HSUP &&
+
+               cat >expect <<-EOF &&
+               # branch.oid $HSUP
+               # branch.head master
+               # branch.upstream origin/master
+               # branch.ab +0 -0
+               1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
+               1 AM S.M. 000000 160000 160000 $_z40 $HSUB sub1
+               EOF
+
+               git status --porcelain=v2 --branch --untracked-files=all >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'staged and unstaged changes in added (AM S.M.)' '
+       (       cd super_repo &&
+               (       cd sub1 &&
+                       ## make additional unstaged changes (on the same file) in the submodule.
+                       ## This does not cause us to get S.MU (because the submodule does not report
+                       ## a "?" line for the unstaged changes).
+                       echo "more changes" >>file_in_sub
+               ) &&
+
+               HMOD=$(git hash-object -t blob -- .gitmodules) &&
+               HSUP=$(git rev-parse HEAD) &&
+               HSUB=$HSUP &&
+
+               cat >expect <<-EOF &&
+               # branch.oid $HSUP
+               # branch.head master
+               # branch.upstream origin/master
+               # branch.ab +0 -0
+               1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
+               1 AM S.M. 000000 160000 160000 $_z40 $HSUB sub1
+               EOF
+
+               git status --porcelain=v2 --branch --untracked-files=all >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'staged and untracked changes in added submodule (AM S.MU)' '
+       (       cd super_repo &&
+               (       cd sub1 &&
+                       ## stage new changes in tracked file.
+                       git add file_in_sub &&
+                       ## create new untracked file.
+                       echo "yyyy" >>another_file_in_sub
+               ) &&
+
+               HMOD=$(git hash-object -t blob -- .gitmodules) &&
+               HSUP=$(git rev-parse HEAD) &&
+               HSUB=$HSUP &&
+
+               cat >expect <<-EOF &&
+               # branch.oid $HSUP
+               # branch.head master
+               # branch.upstream origin/master
+               # branch.ab +0 -0
+               1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
+               1 AM S.MU 000000 160000 160000 $_z40 $HSUB sub1
+               EOF
+
+               git status --porcelain=v2 --branch --untracked-files=all >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'commit within the submodule appears as new commit in super (AM SC..)' '
+       (       cd super_repo &&
+               (       cd sub1 &&
+                       ## Make a new commit in the submodule.
+                       git add file_in_sub &&
+                       rm -f another_file_in_sub &&
+                       git commit -m "new commit"
+               ) &&
+
+               HMOD=$(git hash-object -t blob -- .gitmodules) &&
+               HSUP=$(git rev-parse HEAD) &&
+               HSUB=$HSUP &&
+
+               cat >expect <<-EOF &&
+               # branch.oid $HSUP
+               # branch.head master
+               # branch.upstream origin/master
+               # branch.ab +0 -0
+               1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
+               1 AM SC.. 000000 160000 160000 $_z40 $HSUB sub1
+               EOF
+
+               git status --porcelain=v2 --branch --untracked-files=all >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'stage submodule in super and commit' '
+       (       cd super_repo &&
+               ## Stage the new submodule commit in the super.
+               git add sub1 &&
+               ## Commit the super so that the sub no longer appears as added.
+               git commit -m "super commit" &&
+
+               HSUP=$(git rev-parse HEAD) &&
+
+               cat >expect <<-EOF &&
+               # branch.oid $HSUP
+               # branch.head master
+               # branch.upstream origin/master
+               # branch.ab +1 -0
+               EOF
+
+               git status --porcelain=v2 --branch --untracked-files=all >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'make unstaged changes in existing submodule (.M S.M.)' '
+       (       cd super_repo &&
+               (       cd sub1 &&
+                       echo "zzzz" >>file_in_sub
+               ) &&
+
+               HSUP=$(git rev-parse HEAD) &&
+               HSUB=$(cd sub1 && git rev-parse HEAD) &&
+
+               cat >expect <<-EOF &&
+               # branch.oid $HSUP
+               # branch.head master
+               # branch.upstream origin/master
+               # branch.ab +1 -0
+               1 .M S.M. 160000 160000 160000 $HSUB $HSUB sub1
+               EOF
+
+               git status --porcelain=v2 --branch --untracked-files=all >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_done
index eaea19b8f291ef6b9f13a05342dc10317f3bfbe9..1c1e289ffd982ab74ed80fb776b3ecc4d7abf2f1 100755 (executable)
@@ -8,74 +8,121 @@ test_description='test clone --reference'
 
 base_dir=$(pwd)
 
-U=$base_dir/UPLOAD_LOG
-
-test_expect_success 'preparing first repository' \
-'test_create_repo A && cd A &&
-echo first > file1 &&
-git add file1 &&
-git commit -m A-initial'
-
-cd "$base_dir"
-
-test_expect_success 'preparing second repository' \
-'git clone A B && cd B &&
-echo second > file2 &&
-git add file2 &&
-git commit -m B-addition &&
-git repack -a -d &&
-git prune'
-
-cd "$base_dir"
-
-test_expect_success 'preparing superproject' \
-'test_create_repo super && cd super &&
-echo file > file &&
-git add file &&
-git commit -m B-super-initial'
-
-cd "$base_dir"
-
-test_expect_success 'submodule add --reference' \
-'cd super && git submodule add --reference ../B "file://$base_dir/A" sub &&
-git commit -m B-super-added'
-
-cd "$base_dir"
-
-test_expect_success 'after add: existence of info/alternates' \
-'test_line_count = 1 super/.git/modules/sub/objects/info/alternates'
-
-cd "$base_dir"
-
-test_expect_success 'that reference gets used with add' \
-'cd super/sub &&
-echo "0 objects, 0 kilobytes" > expected &&
-git count-objects > current &&
-diff expected current'
-
-cd "$base_dir"
-
-test_expect_success 'cloning superproject' \
-'git clone super super-clone'
-
-cd "$base_dir"
-
-test_expect_success 'update with reference' \
-'cd super-clone && git submodule update --init --reference ../B'
-
-cd "$base_dir"
-
-test_expect_success 'after update: existence of info/alternates' \
-'test_line_count = 1 super-clone/.git/modules/sub/objects/info/alternates'
-
-cd "$base_dir"
-
-test_expect_success 'that reference gets used with update' \
-'cd super-clone/sub &&
-echo "0 objects, 0 kilobytes" > expected &&
-git count-objects > current &&
-diff expected current'
-
-cd "$base_dir"
+test_alternate_is_used () {
+       alternates_file="$1" &&
+       working_dir="$2" &&
+       test_line_count = 1 "$alternates_file" &&
+       echo "0 objects, 0 kilobytes" >expect &&
+       git -C "$working_dir" count-objects >actual &&
+       test_cmp expect actual
+}
+
+test_expect_success 'preparing first repository' '
+       test_create_repo A &&
+       (
+               cd A &&
+               echo first >file1 &&
+               git add file1 &&
+               git commit -m A-initial
+       )
+'
+
+test_expect_success 'preparing second repository' '
+       git clone A B &&
+       (
+               cd B &&
+               echo second >file2 &&
+               git add file2 &&
+               git commit -m B-addition &&
+               git repack -a -d &&
+               git prune
+       )
+'
+
+test_expect_success 'preparing superproject' '
+       test_create_repo super &&
+       (
+               cd super &&
+               echo file >file &&
+               git add file &&
+               git commit -m B-super-initial
+       )
+'
+
+test_expect_success 'submodule add --reference uses alternates' '
+       (
+               cd super &&
+               git submodule add --reference ../B "file://$base_dir/A" sub &&
+               git commit -m B-super-added &&
+               git repack -ad
+       ) &&
+       test_alternate_is_used super/.git/modules/sub/objects/info/alternates super/sub
+'
+
+test_expect_success 'that reference gets used with add' '
+       (
+               cd super/sub &&
+               echo "0 objects, 0 kilobytes" >expected &&
+               git count-objects >current &&
+               diff expected current
+       )
+'
+
+# The tests up to this point, and repositories created by them
+# (A, B, super and super/sub), are about setting up the stage
+# for subsequent tests and meant to be kept throughout the
+# remainder of the test.
+# Tests from here on, if they create their own test repository,
+# are expected to clean after themselves.
+
+test_expect_success 'updating superproject keeps alternates' '
+       test_when_finished "rm -rf super-clone" &&
+       git clone super super-clone &&
+       git -C super-clone submodule update --init --reference ../B &&
+       test_alternate_is_used super-clone/.git/modules/sub/objects/info/alternates super-clone/sub
+'
+
+test_expect_success 'submodules use alternates when cloning a superproject' '
+       test_when_finished "rm -rf super-clone" &&
+       git clone --reference super --recursive super super-clone &&
+       (
+               cd super-clone &&
+               # test superproject has alternates setup correctly
+               test_alternate_is_used .git/objects/info/alternates . &&
+               # test submodule has correct setup
+               test_alternate_is_used .git/modules/sub/objects/info/alternates sub
+       )
+'
+
+test_expect_success 'missing submodule alternate fails clone and submodule update' '
+       test_when_finished "rm -rf super-clone" &&
+       git clone super super2 &&
+       test_must_fail git clone --recursive --reference super2 super2 super-clone &&
+       (
+               cd super-clone &&
+               # test superproject has alternates setup correctly
+               test_alternate_is_used .git/objects/info/alternates . &&
+               # update of the submodule succeeds
+               test_must_fail git submodule update --init &&
+               # and we have no alternates:
+               test_must_fail test_alternate_is_used .git/modules/sub/objects/info/alternates sub &&
+               test_must_fail test_path_is_file sub/file1
+       )
+'
+
+test_expect_success 'ignoring missing submodule alternates passes clone and submodule update' '
+       test_when_finished "rm -rf super-clone" &&
+       git clone --reference-if-able super2 --recursive super2 super-clone &&
+       (
+               cd super-clone &&
+               # test superproject has alternates setup correctly
+               test_alternate_is_used .git/objects/info/alternates . &&
+               # update of the submodule succeeds
+               git submodule update --init &&
+               # and we have no alternates:
+               test_must_fail test_alternate_is_used .git/modules/sub/objects/info/alternates sub &&
+               test_path_is_file sub/file1
+       )
+'
 
 test_done
index 0db4469c89492ae625307629cb7132178c3b9671..97c9b32c2ecfa608f1e9c37c1c6402a1772e4187 100755 (executable)
@@ -177,7 +177,7 @@ test_expect_success 'prompt - interactive rebase' '
        git checkout b1 &&
        test_when_finished "git checkout master" &&
        git rebase -i HEAD^ &&
-       test_when_finished "git rebase --abort"
+       test_when_finished "git rebase --abort" &&
        __git_ps1 >"$actual" &&
        test_cmp expected "$actual"
 '
index 4f7eadb5963e7d698f9ee6e265b1657e543cdb44..fdaeb3a96bed361f53030cb6ea5c6bdde445163f 100644 (file)
@@ -81,6 +81,10 @@ test_decode_color () {
        '
 }
 
+lf_to_nul () {
+       perl -pe 'y/\012/\000/'
+}
+
 nul_to_q () {
        perl -pe 'y/\000/Q/'
 }
index d731d66e3673f0e9d990007dd690c14d84eae783..ac56512a1c5e4fde4af33cedcbb1cab11487d29a 100644 (file)
@@ -89,6 +89,7 @@ unset VISUAL EMAIL LANGUAGE COLUMNS $("$PERL_PATH" -e '
                UNZIP
                PERF_
                CURL_VERBOSE
+               TRACE_CURL
        ));
        my @vars = grep(/^GIT_/ && !/^GIT_($ok)/o, @env);
        print join("\n", @vars);
@@ -687,9 +688,9 @@ test_done () {
                test_results_dir="$TEST_OUTPUT_DIRECTORY/test-results"
                mkdir -p "$test_results_dir"
                base=${0##*/}
-               test_results_path="$test_results_dir/${base%.sh}-$$.counts"
+               test_results_path="$test_results_dir/${base%.sh}.counts"
 
-               cat >>"$test_results_path" <<-EOF
+               cat >"$test_results_path" <<-EOF
                total $test_count
                success $test_success
                fixed $test_fixed
index cf8de6e888fc5ce577c7319fce089245d6c36be3..94d6dc3725a2bb091df66ce6fe266ddd5317ed02 100644 (file)
@@ -771,7 +771,7 @@ static void die_with_unpushed_submodules(struct string_list *needs_pushing)
        fprintf(stderr, _("The following submodule paths contain changes that can\n"
                        "not be found on any remote:\n"));
        for (i = 0; i < needs_pushing->nr; i++)
-               printf("  %s\n", needs_pushing->items[i].string);
+               fprintf(stderr, "  %s\n", needs_pushing->items[i].string);
        fprintf(stderr, _("\nPlease try\n\n"
                          "     git push --recurse-submodules=on-demand\n\n"
                          "or cd to the path and use\n\n"
diff --git a/url.c b/url.c
index 2d89ad190cfe1c57cd20194661329551ff229993..eaf4f07081eae122fbc38e05f60ee2f11a0c65a6 100644 (file)
--- a/url.c
+++ b/url.c
@@ -29,25 +29,6 @@ int is_url(const char *url)
        return (url[0] == ':' && url[1] == '/' && url[2] == '/');
 }
 
-static int url_decode_char(const char *q)
-{
-       int i;
-       unsigned char val = 0;
-       for (i = 0; i < 2; i++) {
-               unsigned char c = *q++;
-               val <<= 4;
-               if (c >= '0' && c <= '9')
-                       val += c - '0';
-               else if (c >= 'a' && c <= 'f')
-                       val += c - 'a' + 10;
-               else if (c >= 'A' && c <= 'F')
-                       val += c - 'A' + 10;
-               else
-                       return -1;
-       }
-       return val;
-}
-
 static char *url_decode_internal(const char **query, int len,
                                 const char *stop_at, struct strbuf *out,
                                 int decode_plus)
@@ -66,7 +47,7 @@ static char *url_decode_internal(const char **query, int len,
                }
 
                if (c == '%') {
-                       int val = url_decode_char(q + 1);
+                       int val = hex2chr(q + 1);
                        if (0 <= val) {
                                strbuf_addch(out, val);
                                q += 3;
diff --git a/usage.c b/usage.c
index 1dad03fb5c9b7f8f7785915d004aff43e39b0d2a..0efa3faf601231db35239161a1a7253b3975b3f8 100644 (file)
--- a/usage.c
+++ b/usage.c
@@ -148,6 +148,7 @@ void NORETURN die_errno(const char *fmt, ...)
        va_end(params);
 }
 
+#undef error_errno
 int error_errno(const char *fmt, ...)
 {
        char buf[1024];
index 6225a2d89f2c38bea6ed64295a28e7e07d19522c..539aac15a37adcce6429c4d82f401a7db17fac28 100644 (file)
@@ -139,7 +139,7 @@ void wt_status_prepare(struct wt_status *s)
        s->display_comment_prefix = 0;
 }
 
-static void wt_status_print_unmerged_header(struct wt_status *s)
+static void wt_longstatus_print_unmerged_header(struct wt_status *s)
 {
        int i;
        int del_mod_conflict = 0;
@@ -191,7 +191,7 @@ static void wt_status_print_unmerged_header(struct wt_status *s)
        status_printf_ln(s, c, "%s", "");
 }
 
-static void wt_status_print_cached_header(struct wt_status *s)
+static void wt_longstatus_print_cached_header(struct wt_status *s)
 {
        const char *c = color(WT_STATUS_HEADER, s);
 
@@ -207,9 +207,9 @@ static void wt_status_print_cached_header(struct wt_status *s)
        status_printf_ln(s, c, "%s", "");
 }
 
-static void wt_status_print_dirty_header(struct wt_status *s,
-                                        int has_deleted,
-                                        int has_dirty_submodules)
+static void wt_longstatus_print_dirty_header(struct wt_status *s,
+                                            int has_deleted,
+                                            int has_dirty_submodules)
 {
        const char *c = color(WT_STATUS_HEADER, s);
 
@@ -226,9 +226,9 @@ static void wt_status_print_dirty_header(struct wt_status *s,
        status_printf_ln(s, c, "%s", "");
 }
 
-static void wt_status_print_other_header(struct wt_status *s,
-                                        const char *what,
-                                        const char *how)
+static void wt_longstatus_print_other_header(struct wt_status *s,
+                                            const char *what,
+                                            const char *how)
 {
        const char *c = color(WT_STATUS_HEADER, s);
        status_printf_ln(s, c, "%s:", what);
@@ -238,7 +238,7 @@ static void wt_status_print_other_header(struct wt_status *s,
        status_printf_ln(s, c, "%s", "");
 }
 
-static void wt_status_print_trailer(struct wt_status *s)
+static void wt_longstatus_print_trailer(struct wt_status *s)
 {
        status_printf_ln(s, color(WT_STATUS_HEADER, s), "%s", "");
 }
@@ -304,8 +304,8 @@ static int maxwidth(const char *(*label)(int), int minval, int maxval)
        return result;
 }
 
-static void wt_status_print_unmerged_data(struct wt_status *s,
-                                         struct string_list_item *it)
+static void wt_longstatus_print_unmerged_data(struct wt_status *s,
+                                             struct string_list_item *it)
 {
        const char *c = color(WT_STATUS_UNMERGED, s);
        struct wt_status_change_data *d = it->util;
@@ -331,9 +331,9 @@ static void wt_status_print_unmerged_data(struct wt_status *s,
        strbuf_release(&onebuf);
 }
 
-static void wt_status_print_change_data(struct wt_status *s,
-                                       int change_type,
-                                       struct string_list_item *it)
+static void wt_longstatus_print_change_data(struct wt_status *s,
+                                           int change_type,
+                                           struct string_list_item *it)
 {
        struct wt_status_change_data *d = it->util;
        const char *c = color(change_type, s);
@@ -378,7 +378,7 @@ static void wt_status_print_change_data(struct wt_status *s,
                status = d->worktree_status;
                break;
        default:
-               die("BUG: unhandled change_type %d in wt_status_print_change_data",
+               die("BUG: unhandled change_type %d in wt_longstatus_print_change_data",
                    change_type);
        }
 
@@ -434,6 +434,31 @@ static void wt_status_collect_changed_cb(struct diff_queue_struct *q,
                if (S_ISGITLINK(p->two->mode))
                        d->new_submodule_commits = !!oidcmp(&p->one->oid,
                                                            &p->two->oid);
+
+               switch (p->status) {
+               case DIFF_STATUS_ADDED:
+                       die("BUG: worktree status add???");
+                       break;
+
+               case DIFF_STATUS_DELETED:
+                       d->mode_index = p->one->mode;
+                       oidcpy(&d->oid_index, &p->one->oid);
+                       /* mode_worktree is zero for a delete. */
+                       break;
+
+               case DIFF_STATUS_MODIFIED:
+               case DIFF_STATUS_TYPE_CHANGED:
+               case DIFF_STATUS_UNMERGED:
+                       d->mode_index = p->one->mode;
+                       d->mode_worktree = p->two->mode;
+                       oidcpy(&d->oid_index, &p->one->oid);
+                       break;
+
+               case DIFF_STATUS_UNKNOWN:
+                       die("BUG: worktree status unknown???");
+                       break;
+               }
+
        }
 }
 
@@ -479,12 +504,36 @@ static void wt_status_collect_updated_cb(struct diff_queue_struct *q,
                if (!d->index_status)
                        d->index_status = p->status;
                switch (p->status) {
+               case DIFF_STATUS_ADDED:
+                       /* Leave {mode,oid}_head zero for an add. */
+                       d->mode_index = p->two->mode;
+                       oidcpy(&d->oid_index, &p->two->oid);
+                       break;
+               case DIFF_STATUS_DELETED:
+                       d->mode_head = p->one->mode;
+                       oidcpy(&d->oid_head, &p->one->oid);
+                       /* Leave {mode,oid}_index zero for a delete. */
+                       break;
+
                case DIFF_STATUS_COPIED:
                case DIFF_STATUS_RENAMED:
                        d->head_path = xstrdup(p->one->path);
+                       d->score = p->score * 100 / MAX_SCORE;
+                       /* fallthru */
+               case DIFF_STATUS_MODIFIED:
+               case DIFF_STATUS_TYPE_CHANGED:
+                       d->mode_head = p->one->mode;
+                       d->mode_index = p->two->mode;
+                       oidcpy(&d->oid_head, &p->one->oid);
+                       oidcpy(&d->oid_index, &p->two->oid);
                        break;
                case DIFF_STATUS_UNMERGED:
                        d->stagemask = unmerged_mask(p->two->path);
+                       /*
+                        * Don't bother setting {mode,oid}_{head,index} since the print
+                        * code will output the stage values directly and not use the
+                        * values in these fields.
+                        */
                        break;
                }
        }
@@ -565,9 +614,17 @@ static void wt_status_collect_changes_initial(struct wt_status *s)
                if (ce_stage(ce)) {
                        d->index_status = DIFF_STATUS_UNMERGED;
                        d->stagemask |= (1 << (ce_stage(ce) - 1));
-               }
-               else
+                       /*
+                        * Don't bother setting {mode,oid}_{head,index} since the print
+                        * code will output the stage values directly and not use the
+                        * values in these fields.
+                        */
+               } else {
                        d->index_status = DIFF_STATUS_ADDED;
+                       /* Leave {mode,oid}_head zero for adds. */
+                       d->mode_index = ce->ce_mode;
+                       hashcpy(d->oid_index.hash, ce->sha1);
+               }
        }
 }
 
@@ -627,7 +684,7 @@ void wt_status_collect(struct wt_status *s)
        wt_status_collect_untracked(s);
 }
 
-static void wt_status_print_unmerged(struct wt_status *s)
+static void wt_longstatus_print_unmerged(struct wt_status *s)
 {
        int shown_header = 0;
        int i;
@@ -640,17 +697,17 @@ static void wt_status_print_unmerged(struct wt_status *s)
                if (!d->stagemask)
                        continue;
                if (!shown_header) {
-                       wt_status_print_unmerged_header(s);
+                       wt_longstatus_print_unmerged_header(s);
                        shown_header = 1;
                }
-               wt_status_print_unmerged_data(s, it);
+               wt_longstatus_print_unmerged_data(s, it);
        }
        if (shown_header)
-               wt_status_print_trailer(s);
+               wt_longstatus_print_trailer(s);
 
 }
 
-static void wt_status_print_updated(struct wt_status *s)
+static void wt_longstatus_print_updated(struct wt_status *s)
 {
        int shown_header = 0;
        int i;
@@ -664,14 +721,14 @@ static void wt_status_print_updated(struct wt_status *s)
                    d->index_status == DIFF_STATUS_UNMERGED)
                        continue;
                if (!shown_header) {
-                       wt_status_print_cached_header(s);
+                       wt_longstatus_print_cached_header(s);
                        s->commitable = 1;
                        shown_header = 1;
                }
-               wt_status_print_change_data(s, WT_STATUS_UPDATED, it);
+               wt_longstatus_print_change_data(s, WT_STATUS_UPDATED, it);
        }
        if (shown_header)
-               wt_status_print_trailer(s);
+               wt_longstatus_print_trailer(s);
 }
 
 /*
@@ -703,7 +760,7 @@ static int wt_status_check_worktree_changes(struct wt_status *s,
        return changes;
 }
 
-static void wt_status_print_changed(struct wt_status *s)
+static void wt_longstatus_print_changed(struct wt_status *s)
 {
        int i, dirty_submodules;
        int worktree_changes = wt_status_check_worktree_changes(s, &dirty_submodules);
@@ -711,7 +768,7 @@ static void wt_status_print_changed(struct wt_status *s)
        if (!worktree_changes)
                return;
 
-       wt_status_print_dirty_header(s, worktree_changes < 0, dirty_submodules);
+       wt_longstatus_print_dirty_header(s, worktree_changes < 0, dirty_submodules);
 
        for (i = 0; i < s->change.nr; i++) {
                struct wt_status_change_data *d;
@@ -721,12 +778,12 @@ static void wt_status_print_changed(struct wt_status *s)
                if (!d->worktree_status ||
                    d->worktree_status == DIFF_STATUS_UNMERGED)
                        continue;
-               wt_status_print_change_data(s, WT_STATUS_CHANGED, it);
+               wt_longstatus_print_change_data(s, WT_STATUS_CHANGED, it);
        }
-       wt_status_print_trailer(s);
+       wt_longstatus_print_trailer(s);
 }
 
-static void wt_status_print_submodule_summary(struct wt_status *s, int uncommitted)
+static void wt_longstatus_print_submodule_summary(struct wt_status *s, int uncommitted)
 {
        struct child_process sm_summary = CHILD_PROCESS_INIT;
        struct strbuf cmd_stdout = STRBUF_INIT;
@@ -772,10 +829,10 @@ static void wt_status_print_submodule_summary(struct wt_status *s, int uncommitt
        strbuf_release(&summary);
 }
 
-static void wt_status_print_other(struct wt_status *s,
-                                 struct string_list *l,
-                                 const char *what,
-                                 const char *how)
+static void wt_longstatus_print_other(struct wt_status *s,
+                                     struct string_list *l,
+                                     const char *what,
+                                     const char *how)
 {
        int i;
        struct strbuf buf = STRBUF_INIT;
@@ -785,7 +842,7 @@ static void wt_status_print_other(struct wt_status *s,
        if (!l->nr)
                return;
 
-       wt_status_print_other_header(s, what, how);
+       wt_longstatus_print_other_header(s, what, how);
 
        for (i = 0; i < l->nr; i++) {
                struct string_list_item *it;
@@ -845,7 +902,7 @@ void wt_status_add_cut_line(FILE *fp)
        strbuf_release(&buf);
 }
 
-static void wt_status_print_verbose(struct wt_status *s)
+static void wt_longstatus_print_verbose(struct wt_status *s)
 {
        struct rev_info rev;
        struct setup_revision_opt opt;
@@ -878,7 +935,7 @@ static void wt_status_print_verbose(struct wt_status *s)
        if (s->verbose > 1 && s->commitable) {
                /* print_updated() printed a header, so do we */
                if (s->fp != stdout)
-                       wt_status_print_trailer(s);
+                       wt_longstatus_print_trailer(s);
                status_printf_ln(s, c, _("Changes to be committed:"));
                rev.diffopt.a_prefix = "c/";
                rev.diffopt.b_prefix = "i/";
@@ -896,7 +953,7 @@ static void wt_status_print_verbose(struct wt_status *s)
        }
 }
 
-static void wt_status_print_tracking(struct wt_status *s)
+static void wt_longstatus_print_tracking(struct wt_status *s)
 {
        struct strbuf sb = STRBUF_INIT;
        const char *cp, *ep, *branch_name;
@@ -962,7 +1019,7 @@ static void show_merge_in_progress(struct wt_status *s,
                        status_printf_ln(s, color,
                                _("  (use \"git commit\" to conclude merge)"));
        }
-       wt_status_print_trailer(s);
+       wt_longstatus_print_trailer(s);
 }
 
 static void show_am_in_progress(struct wt_status *s,
@@ -983,7 +1040,7 @@ static void show_am_in_progress(struct wt_status *s,
                status_printf_ln(s, color,
                        _("  (use \"git am --abort\" to restore the original branch)"));
        }
-       wt_status_print_trailer(s);
+       wt_longstatus_print_trailer(s);
 }
 
 static char *read_line_from_git_path(const char *filename)
@@ -1207,7 +1264,7 @@ static void show_rebase_in_progress(struct wt_status *s,
                                _("  (use \"git rebase --continue\" once you are satisfied with your changes)"));
                }
        }
-       wt_status_print_trailer(s);
+       wt_longstatus_print_trailer(s);
 }
 
 static void show_cherry_pick_in_progress(struct wt_status *s,
@@ -1226,7 +1283,7 @@ static void show_cherry_pick_in_progress(struct wt_status *s,
                status_printf_ln(s, color,
                        _("  (use \"git cherry-pick --abort\" to cancel the cherry-pick operation)"));
        }
-       wt_status_print_trailer(s);
+       wt_longstatus_print_trailer(s);
 }
 
 static void show_revert_in_progress(struct wt_status *s,
@@ -1245,7 +1302,7 @@ static void show_revert_in_progress(struct wt_status *s,
                status_printf_ln(s, color,
                        _("  (use \"git revert --abort\" to cancel the revert operation)"));
        }
-       wt_status_print_trailer(s);
+       wt_longstatus_print_trailer(s);
 }
 
 static void show_bisect_in_progress(struct wt_status *s,
@@ -1262,7 +1319,7 @@ static void show_bisect_in_progress(struct wt_status *s,
        if (s->hints)
                status_printf_ln(s, color,
                        _("  (use \"git bisect reset\" to get back to the original branch)"));
-       wt_status_print_trailer(s);
+       wt_longstatus_print_trailer(s);
 }
 
 /*
@@ -1432,8 +1489,8 @@ void wt_status_get_state(struct wt_status_state *state,
                wt_status_get_detached_from(state);
 }
 
-static void wt_status_print_state(struct wt_status *s,
-                                 struct wt_status_state *state)
+static void wt_longstatus_print_state(struct wt_status *s,
+                                     struct wt_status_state *state)
 {
        const char *state_color = color(WT_STATUS_HEADER, s);
        if (state->merge_in_progress)
@@ -1450,7 +1507,7 @@ static void wt_status_print_state(struct wt_status *s,
                show_bisect_in_progress(s, state, state_color);
 }
 
-void wt_status_print(struct wt_status *s)
+static void wt_longstatus_print(struct wt_status *s)
 {
        const char *branch_color = color(WT_STATUS_ONBRANCH, s);
        const char *branch_status_color = color(WT_STATUS_HEADER, s);
@@ -1487,10 +1544,10 @@ void wt_status_print(struct wt_status *s)
                status_printf_more(s, branch_status_color, "%s", on_what);
                status_printf_more(s, branch_color, "%s\n", branch_name);
                if (!s->is_initial)
-                       wt_status_print_tracking(s);
+                       wt_longstatus_print_tracking(s);
        }
 
-       wt_status_print_state(s, &state);
+       wt_longstatus_print_state(s, &state);
        free(state.branch);
        free(state.onto);
        free(state.detached_from);
@@ -1501,19 +1558,19 @@ void wt_status_print(struct wt_status *s)
                status_printf_ln(s, color(WT_STATUS_HEADER, s), "%s", "");
        }
 
-       wt_status_print_updated(s);
-       wt_status_print_unmerged(s);
-       wt_status_print_changed(s);
+       wt_longstatus_print_updated(s);
+       wt_longstatus_print_unmerged(s);
+       wt_longstatus_print_changed(s);
        if (s->submodule_summary &&
            (!s->ignore_submodule_arg ||
             strcmp(s->ignore_submodule_arg, "all"))) {
-               wt_status_print_submodule_summary(s, 0);  /* staged */
-               wt_status_print_submodule_summary(s, 1);  /* unstaged */
+               wt_longstatus_print_submodule_summary(s, 0);  /* staged */
+               wt_longstatus_print_submodule_summary(s, 1);  /* unstaged */
        }
        if (s->show_untracked_files) {
-               wt_status_print_other(s, &s->untracked, _("Untracked files"), "add");
+               wt_longstatus_print_other(s, &s->untracked, _("Untracked files"), "add");
                if (s->show_ignored_files)
-                       wt_status_print_other(s, &s->ignored, _("Ignored files"), "add -f");
+                       wt_longstatus_print_other(s, &s->ignored, _("Ignored files"), "add -f");
                if (advice_status_u_option && 2000 < s->untracked_in_ms) {
                        status_printf_ln(s, GIT_COLOR_NORMAL, "%s", "");
                        status_printf_ln(s, GIT_COLOR_NORMAL,
@@ -1528,7 +1585,7 @@ void wt_status_print(struct wt_status *s)
                        ? _(" (use -u option to show untracked files)") : "");
 
        if (s->verbose)
-               wt_status_print_verbose(s);
+               wt_longstatus_print_verbose(s);
        if (!s->commitable) {
                if (s->amend)
                        status_printf_ln(s, GIT_COLOR_NORMAL, _("No changes"));
@@ -1717,7 +1774,7 @@ static void wt_shortstatus_print_tracking(struct wt_status *s)
        fputc(s->null_termination ? '\0' : '\n', s->fp);
 }
 
-void wt_shortstatus_print(struct wt_status *s)
+static void wt_shortstatus_print(struct wt_status *s)
 {
        int i;
 
@@ -1749,7 +1806,7 @@ void wt_shortstatus_print(struct wt_status *s)
        }
 }
 
-void wt_porcelain_print(struct wt_status *s)
+static void wt_porcelain_print(struct wt_status *s)
 {
        s->use_color = 0;
        s->relative_paths = 0;
@@ -1757,3 +1814,398 @@ void wt_porcelain_print(struct wt_status *s)
        s->no_gettext = 1;
        wt_shortstatus_print(s);
 }
+
+/*
+ * Print branch information for porcelain v2 output.  These lines
+ * are printed when the '--branch' parameter is given.
+ *
+ *    # branch.oid <commit><eol>
+ *    # branch.head <head><eol>
+ *   [# branch.upstream <upstream><eol>
+ *   [# branch.ab +<ahead> -<behind><eol>]]
+ *
+ *      <commit> ::= the current commit hash or the the literal
+ *                   "(initial)" to indicate an initialized repo
+ *                   with no commits.
+ *
+ *        <head> ::= <branch_name> the current branch name or
+ *                   "(detached)" literal when detached head or
+ *                   "(unknown)" when something is wrong.
+ *
+ *    <upstream> ::= the upstream branch name, when set.
+ *
+ *       <ahead> ::= integer ahead value, when upstream set
+ *                   and the commit is present (not gone).
+ *
+ *      <behind> ::= integer behind value, when upstream set
+ *                   and commit is present.
+ *
+ *
+ * The end-of-line is defined by the -z flag.
+ *
+ *                 <eol> ::= NUL when -z,
+ *                           LF when NOT -z.
+ *
+ */
+static void wt_porcelain_v2_print_tracking(struct wt_status *s)
+{
+       struct branch *branch;
+       const char *base;
+       const char *branch_name;
+       struct wt_status_state state;
+       int ab_info, nr_ahead, nr_behind;
+       char eol = s->null_termination ? '\0' : '\n';
+
+       memset(&state, 0, sizeof(state));
+       wt_status_get_state(&state, s->branch && !strcmp(s->branch, "HEAD"));
+
+       fprintf(s->fp, "# branch.oid %s%c",
+                       (s->is_initial ? "(initial)" : sha1_to_hex(s->sha1_commit)),
+                       eol);
+
+       if (!s->branch)
+               fprintf(s->fp, "# branch.head %s%c", "(unknown)", eol);
+       else {
+               if (!strcmp(s->branch, "HEAD")) {
+                       fprintf(s->fp, "# branch.head %s%c", "(detached)", eol);
+
+                       if (state.rebase_in_progress || state.rebase_interactive_in_progress)
+                               branch_name = state.onto;
+                       else if (state.detached_from)
+                               branch_name = state.detached_from;
+                       else
+                               branch_name = "";
+               } else {
+                       branch_name = NULL;
+                       skip_prefix(s->branch, "refs/heads/", &branch_name);
+
+                       fprintf(s->fp, "# branch.head %s%c", branch_name, eol);
+               }
+
+               /* Lookup stats on the upstream tracking branch, if set. */
+               branch = branch_get(branch_name);
+               base = NULL;
+               ab_info = (stat_tracking_info(branch, &nr_ahead, &nr_behind, &base) == 0);
+               if (base) {
+                       base = shorten_unambiguous_ref(base, 0);
+                       fprintf(s->fp, "# branch.upstream %s%c", base, eol);
+                       free((char *)base);
+
+                       if (ab_info)
+                               fprintf(s->fp, "# branch.ab +%d -%d%c", nr_ahead, nr_behind, eol);
+               }
+       }
+
+       free(state.branch);
+       free(state.onto);
+       free(state.detached_from);
+}
+
+/*
+ * Convert various submodule status values into a
+ * fixed-length string of characters in the buffer provided.
+ */
+static void wt_porcelain_v2_submodule_state(
+       struct wt_status_change_data *d,
+       char sub[5])
+{
+       if (S_ISGITLINK(d->mode_head) ||
+               S_ISGITLINK(d->mode_index) ||
+               S_ISGITLINK(d->mode_worktree)) {
+               sub[0] = 'S';
+               sub[1] = d->new_submodule_commits ? 'C' : '.';
+               sub[2] = (d->dirty_submodule & DIRTY_SUBMODULE_MODIFIED) ? 'M' : '.';
+               sub[3] = (d->dirty_submodule & DIRTY_SUBMODULE_UNTRACKED) ? 'U' : '.';
+       } else {
+               sub[0] = 'N';
+               sub[1] = '.';
+               sub[2] = '.';
+               sub[3] = '.';
+       }
+       sub[4] = 0;
+}
+
+/*
+ * Fix-up changed entries before we print them.
+ */
+static void wt_porcelain_v2_fix_up_changed(
+       struct string_list_item *it,
+       struct wt_status *s)
+{
+       struct wt_status_change_data *d = it->util;
+
+       if (!d->index_status) {
+               /*
+                * This entry is unchanged in the index (relative to the head).
+                * Therefore, the collect_updated_cb was never called for this
+                * entry (during the head-vs-index scan) and so the head column
+                * fields were never set.
+                *
+                * We must have data for the index column (from the
+                * index-vs-worktree scan (otherwise, this entry should not be
+                * in the list of changes)).
+                *
+                * Copy index column fields to the head column, so that our
+                * output looks complete.
+                */
+               assert(d->mode_head == 0);
+               d->mode_head = d->mode_index;
+               oidcpy(&d->oid_head, &d->oid_index);
+       }
+
+       if (!d->worktree_status) {
+               /*
+                * This entry is unchanged in the worktree (relative to the index).
+                * Therefore, the collect_changed_cb was never called for this entry
+                * (during the index-vs-worktree scan) and so the worktree column
+                * fields were never set.
+                *
+                * We must have data for the index column (from the head-vs-index
+                * scan).
+                *
+                * Copy the index column fields to the worktree column so that
+                * our output looks complete.
+                *
+                * Note that we only have a mode field in the worktree column
+                * because the scan code tries really hard to not have to compute it.
+                */
+               assert(d->mode_worktree == 0);
+               d->mode_worktree = d->mode_index;
+       }
+}
+
+/*
+ * Print porcelain v2 info for tracked entries with changes.
+ */
+static void wt_porcelain_v2_print_changed_entry(
+       struct string_list_item *it,
+       struct wt_status *s)
+{
+       struct wt_status_change_data *d = it->util;
+       struct strbuf buf_index = STRBUF_INIT;
+       struct strbuf buf_head = STRBUF_INIT;
+       const char *path_index = NULL;
+       const char *path_head = NULL;
+       char key[3];
+       char submodule_token[5];
+       char sep_char, eol_char;
+
+       wt_porcelain_v2_fix_up_changed(it, s);
+       wt_porcelain_v2_submodule_state(d, submodule_token);
+
+       key[0] = d->index_status ? d->index_status : '.';
+       key[1] = d->worktree_status ? d->worktree_status : '.';
+       key[2] = 0;
+
+       if (s->null_termination) {
+               /*
+                * In -z mode, we DO NOT C-quote pathnames.  Current path is ALWAYS first.
+                * A single NUL character separates them.
+                */
+               sep_char = '\0';
+               eol_char = '\0';
+               path_index = it->string;
+               path_head = d->head_path;
+       } else {
+               /*
+                * Path(s) are C-quoted if necessary. Current path is ALWAYS first.
+                * The source path is only present when necessary.
+                * A single TAB separates them (because paths can contain spaces
+                * which are not escaped and C-quoting does escape TAB characters).
+                */
+               sep_char = '\t';
+               eol_char = '\n';
+               path_index = quote_path(it->string, s->prefix, &buf_index);
+               if (d->head_path)
+                       path_head = quote_path(d->head_path, s->prefix, &buf_head);
+       }
+
+       if (path_head)
+               fprintf(s->fp, "2 %s %s %06o %06o %06o %s %s %c%d %s%c%s%c",
+                               key, submodule_token,
+                               d->mode_head, d->mode_index, d->mode_worktree,
+                               oid_to_hex(&d->oid_head), oid_to_hex(&d->oid_index),
+                               key[0], d->score,
+                               path_index, sep_char, path_head, eol_char);
+       else
+               fprintf(s->fp, "1 %s %s %06o %06o %06o %s %s %s%c",
+                               key, submodule_token,
+                               d->mode_head, d->mode_index, d->mode_worktree,
+                               oid_to_hex(&d->oid_head), oid_to_hex(&d->oid_index),
+                               path_index, eol_char);
+
+       strbuf_release(&buf_index);
+       strbuf_release(&buf_head);
+}
+
+/*
+ * Print porcelain v2 status info for unmerged entries.
+ */
+static void wt_porcelain_v2_print_unmerged_entry(
+       struct string_list_item *it,
+       struct wt_status *s)
+{
+       struct wt_status_change_data *d = it->util;
+       const struct cache_entry *ce;
+       struct strbuf buf_index = STRBUF_INIT;
+       const char *path_index = NULL;
+       int pos, stage, sum;
+       struct {
+               int mode;
+               struct object_id oid;
+       } stages[3];
+       char *key;
+       char submodule_token[5];
+       char unmerged_prefix = 'u';
+       char eol_char = s->null_termination ? '\0' : '\n';
+
+       wt_porcelain_v2_submodule_state(d, submodule_token);
+
+       switch (d->stagemask) {
+       case 1: key = "DD"; break; /* both deleted */
+       case 2: key = "AU"; break; /* added by us */
+       case 3: key = "UD"; break; /* deleted by them */
+       case 4: key = "UA"; break; /* added by them */
+       case 5: key = "DU"; break; /* deleted by us */
+       case 6: key = "AA"; break; /* both added */
+       case 7: key = "UU"; break; /* both modified */
+       default:
+               die("BUG: unhandled unmerged status %x", d->stagemask);
+       }
+
+       /*
+        * Disregard d.aux.porcelain_v2 data that we accumulated
+        * for the head and index columns during the scans and
+        * replace with the actual stage data.
+        *
+        * Note that this is a last-one-wins for each the individual
+        * stage [123] columns in the event of multiple cache entries
+        * for same stage.
+        */
+       memset(stages, 0, sizeof(stages));
+       sum = 0;
+       pos = cache_name_pos(it->string, strlen(it->string));
+       assert(pos < 0);
+       pos = -pos-1;
+       while (pos < active_nr) {
+               ce = active_cache[pos++];
+               stage = ce_stage(ce);
+               if (strcmp(ce->name, it->string) || !stage)
+                       break;
+               stages[stage - 1].mode = ce->ce_mode;
+               hashcpy(stages[stage - 1].oid.hash, ce->sha1);
+               sum |= (1 << (stage - 1));
+       }
+       if (sum != d->stagemask)
+               die("BUG: observed stagemask 0x%x != expected stagemask 0x%x", sum, d->stagemask);
+
+       if (s->null_termination)
+               path_index = it->string;
+       else
+               path_index = quote_path(it->string, s->prefix, &buf_index);
+
+       fprintf(s->fp, "%c %s %s %06o %06o %06o %06o %s %s %s %s%c",
+                       unmerged_prefix, key, submodule_token,
+                       stages[0].mode, /* stage 1 */
+                       stages[1].mode, /* stage 2 */
+                       stages[2].mode, /* stage 3 */
+                       d->mode_worktree,
+                       oid_to_hex(&stages[0].oid), /* stage 1 */
+                       oid_to_hex(&stages[1].oid), /* stage 2 */
+                       oid_to_hex(&stages[2].oid), /* stage 3 */
+                       path_index,
+                       eol_char);
+
+       strbuf_release(&buf_index);
+}
+
+/*
+ * Print porcelain V2 status info for untracked and ignored entries.
+ */
+static void wt_porcelain_v2_print_other(
+       struct string_list_item *it,
+       struct wt_status *s,
+       char prefix)
+{
+       struct strbuf buf = STRBUF_INIT;
+       const char *path;
+       char eol_char;
+
+       if (s->null_termination) {
+               path = it->string;
+               eol_char = '\0';
+       } else {
+               path = quote_path(it->string, s->prefix, &buf);
+               eol_char = '\n';
+       }
+
+       fprintf(s->fp, "%c %s%c", prefix, path, eol_char);
+
+       strbuf_release(&buf);
+}
+
+/*
+ * Print porcelain V2 status.
+ *
+ * [<v2_branch>]
+ * [<v2_changed_items>]*
+ * [<v2_unmerged_items>]*
+ * [<v2_untracked_items>]*
+ * [<v2_ignored_items>]*
+ *
+ */
+static void wt_porcelain_v2_print(struct wt_status *s)
+{
+       struct wt_status_change_data *d;
+       struct string_list_item *it;
+       int i;
+
+       if (s->show_branch)
+               wt_porcelain_v2_print_tracking(s);
+
+       for (i = 0; i < s->change.nr; i++) {
+               it = &(s->change.items[i]);
+               d = it->util;
+               if (!d->stagemask)
+                       wt_porcelain_v2_print_changed_entry(it, s);
+       }
+
+       for (i = 0; i < s->change.nr; i++) {
+               it = &(s->change.items[i]);
+               d = it->util;
+               if (d->stagemask)
+                       wt_porcelain_v2_print_unmerged_entry(it, s);
+       }
+
+       for (i = 0; i < s->untracked.nr; i++) {
+               it = &(s->untracked.items[i]);
+               wt_porcelain_v2_print_other(it, s, '?');
+       }
+
+       for (i = 0; i < s->ignored.nr; i++) {
+               it = &(s->ignored.items[i]);
+               wt_porcelain_v2_print_other(it, s, '!');
+       }
+}
+
+void wt_status_print(struct wt_status *s)
+{
+       switch (s->status_format) {
+       case STATUS_FORMAT_SHORT:
+               wt_shortstatus_print(s);
+               break;
+       case STATUS_FORMAT_PORCELAIN:
+               wt_porcelain_print(s);
+               break;
+       case STATUS_FORMAT_PORCELAIN_V2:
+               wt_porcelain_v2_print(s);
+               break;
+       case STATUS_FORMAT_UNSPECIFIED:
+               die("BUG: finalize_deferred_config() should have been called");
+               break;
+       case STATUS_FORMAT_NONE:
+       case STATUS_FORMAT_LONG:
+               wt_longstatus_print(s);
+               break;
+       }
+}
index 2ca93f6957f69cd5652ddc764f5afe81b598a2a9..e40183770700cb593d4e4f2bf914a5b6eff0bb09 100644 (file)
@@ -38,11 +38,24 @@ struct wt_status_change_data {
        int worktree_status;
        int index_status;
        int stagemask;
+       int score;
+       int mode_head, mode_index, mode_worktree;
+       struct object_id oid_head, oid_index;
        char *head_path;
        unsigned dirty_submodule       : 2;
        unsigned new_submodule_commits : 1;
 };
 
+enum wt_status_format {
+       STATUS_FORMAT_NONE = 0,
+       STATUS_FORMAT_LONG,
+       STATUS_FORMAT_SHORT,
+       STATUS_FORMAT_PORCELAIN,
+       STATUS_FORMAT_PORCELAIN_V2,
+
+       STATUS_FORMAT_UNSPECIFIED
+};
+
 struct wt_status {
        int is_initial;
        char *branch;
@@ -66,6 +79,9 @@ struct wt_status {
        int show_branch;
        int hints;
 
+       enum wt_status_format status_format;
+       unsigned char sha1_commit[GIT_SHA1_RAWSZ]; /* when not Initial */
+
        /* These are computed during processing of the individual sections */
        int commitable;
        int workdir_dirty;
@@ -107,9 +123,6 @@ int wt_status_check_rebase(const struct worktree *wt,
 int wt_status_check_bisect(const struct worktree *wt,
                           struct wt_status_state *state);
 
-void wt_shortstatus_print(struct wt_status *s);
-void wt_porcelain_print(struct wt_status *s);
-
 __attribute__((format (printf, 3, 4)))
 void status_printf_ln(struct wt_status *s, const char *color, const char *fmt, ...);
 __attribute__((format (printf, 3, 4)))
index 49aa16ff78d8c0f10942e0f519543cc6befabb9d..b52b4b9c1ee3ba3c6b94594af68a275e458bebaf 100644 (file)
 
 #include "xinclude.h"
 
-
-
-
-static long xdl_get_rec(xdfile_t *xdf, long ri, char const **rec);
-static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t *ecb);
-
-
-
-
 static long xdl_get_rec(xdfile_t *xdf, long ri, char const **rec) {
 
        *rec = xdf->recs[ri]->ptr;