Merge branch 'mf/format-patch-commit-list-format-doc'

Doc updates.

* mf/format-patch-commit-list-format-doc:
  format-patch: removing unconditional wrapping
  docs: fix --commit-list-format related entries
diff --git a/.editorconfig b/.editorconfig
index 6e4eaa8..82e121a 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -4,7 +4,11 @@
 
 # The settings for C (*.c and *.h) files are mirrored in .clang-format.  Keep
 # them in sync.
-[{*.{c,h,sh,bash,perl,pl,pm,txt,adoc},config.mak.*,Makefile,templates/hooks/*.sample}]
+[{*.{c,h,sh,bash,perl,pl,pm,txt,adoc},config.mak.*,Makefile}]
+indent_style = tab
+tab_width = 8
+
+[templates/hooks/*.sample]
 indent_style = tab
 tab_width = 8
 
diff --git a/Documentation/RelNotes/2.54.0.adoc b/Documentation/RelNotes/2.54.0.adoc
index cf30eaa..4ce30d9 100644
--- a/Documentation/RelNotes/2.54.0.adoc
+++ b/Documentation/RelNotes/2.54.0.adoc
@@ -81,6 +81,34 @@
    accepts charset to use from the end-user, to avoid 'y' (mistaken
    'yes' when expecting a charset like 'UTF-8') and other nonsense.
 
+ * "git status" learned to show comparison between the current branch
+   and various other branches listed on status.compareBranches
+   configuration.
+
+ * "git repo structure" command learns to report maximum values on
+   various aspects of objects it inspects.
+
+ * "git rebase" learns "--trailer" command to drive the
+   interpret-trailers machinery.
+
+ * "git fast-import" learned to optionally replace signature on
+   commits whose signatures get invalidated due to replaying by
+   signing afresh.
+
+ * "git history" learned the "split" subcommand.
+
+ * The reference-transaction hook was taught to be triggered before
+   taking locks on references in the "preparing" phase.
+
+ * "git apply" now reports the name of the input file along with the
+   line number when it encounters a corrupt patch, and correctly
+   resets the line counter when processing multiple patch files.
+
+ * The HTTP transport learned to react to "429 Too Many Requests".
+
+ * "git repo info -h" and "git repo structure -h" limit their help output
+   to the part that is specific to the subcommand.
+
 
 Performance, Internal Implementation, Development Support etc.
 --------------------------------------------------------------
@@ -94,7 +122,7 @@
 
  * Improve set-up time of a perf test.
 
- * ISO C23 redefines strchr and friends that tradiotionally took
+ * ISO C23 redefines strchr and friends that traditionally took
    a const pointer and returned a non-const pointer derived from it to
    preserve constness (i.e., if you ask for a substring in a const
    string, you get a const pointer to the substring).  Update code
@@ -180,6 +208,65 @@
 
  * Move gitlab CI from macOS 14 images that are being deprecated.
 
+ * The object source API is getting restructured to allow plugging new
+   backends.
+
+ * Reduce dependence on the global the_hash_algo and the_repository
+   variables of wt-status code path.
+
+  * The way combined list-object filter options are parsed has been
+    revamped.
+
+ * Editorconfig filename patterns were specified incorrectly, making
+   many source files inside subdirectories unaffected, which has been
+   corrected.
+
+ * The run_command() API lost its implicit dependency on the singleton
+   `the_repository` instance.
+
+ * The unit test helper function was taught to use backslash +
+   mnemonic notation for certain control characters like "\t", instead
+   of octal notation like "\011".
+
+ * Adjust test-lint to allow "sed -E" to use ERE in the patterns.
+
+ * Clar (unit testing framework) update from the upstream.
+
+ * Reduce system overhead "git upload-pack" spends on relaying "git
+   pack-objects" output to the "git fetch" running on the other end of
+   the connection.
+
+ * Add a coccinelle rule to break the build when "struct strbuf" gets
+   passed by value.
+
+ * Further work on incremental repacking using MIDX/bitmap
+
+ * The logic to count objects has been cleaned up.
+
+ * Tweak the build infrastructure by moving tools around.
+
+ * Uses of prio_queue as a LIFO stack of commits have been written
+   with commit_stack.
+
+ * The cleanup of remaining bitmaps in "ahead_behind()" has been
+   simplified.
+
+ * split-index.c has been updated to not use the global the_repository
+   and the_hash_algo variables.
+
+ * The unsigned integer that is used as an bitset to specify the kind
+   of branches interpret_branch_name() function has been changed to
+   use a dedicated enum type.
+
+ * Various updates to contrib/diff-highlight, including documentation
+   updates, test improvements, and color configuration handling.
+
+ * Code paths that loop over another array to push each element into a
+   strvec have been rewritten to use strvec_pushv() instead.
+
+ * In case homebrew breaks REG_ENHANCED again, leave a in-code comment
+   to suggest use of our replacement regex as a workaround.
+
 
 Fixes since v2.53
 -----------------
@@ -291,6 +378,73 @@
  * Fix typo-induced breakages in fsmonitor-watchman sample hook.
    (merge 41366e4677 pt/fsmonitor-watchman-sample-fix later to maint).
 
+ * "git for-each-repo" started from a secondary worktree did not work
+   as expected, which has been corrected.
+   (merge e87493b9b4 ds/for-each-repo-w-worktree later to maint).
+
+ * The construct 'test "$(command)" = expectation' loses the exit
+   status from the command, which has been fixed by breaking up the
+   statement into pieces.
+   (merge d3edca979a fp/t3310-unhide-git-failures later to maint).
+
+ * While discovering a ".git" directory, the code treats any stat()
+   failure as a sign that a filesystem entity .git does not exist
+   there, and ignores ".git" that is not a "gitdir" file or a
+   directory.  The code has been tightened to notice and report
+   filesystem corruption better.
+   (merge 1dd27bfbfd ty/setup-error-tightening later to maint).
+
+ * Plug a few leaks where mmap'ed memory regions are not unmapped.
+   (merge a8a69bbb64 jk/unleak-mmap later to maint).
+
+ * A test now uses the symbolic constant $ZERO_OID instead of 40 "0" to
+   work better with SHA-256 as well as SHA-1.
+   (merge 30310f3cc4 ss/t3200-test-zero-oid later to maint).
+
+ * Instead of hardcoded 'origin', use the configured default remote
+   when fetching from submodules.
+   (merge 3b5fb32da8 ng/submodule-default-remote later to maint).
+
+ * The code in "git help" that shows configuration items in sorted
+   order was awkwardly organized and prone to bugs.
+
+ * "imap-send" used to use functions whose use is going to be removed
+   with OpenSSL 4.0; rewrite them using public API that has been
+   available since OpenSSL 1.1 since 2016 or so.
+   (merge 6392a0b75d bb/imap-send-openssl-4.0-prep later to maint).
+
+ * Fix an example in the user-manual.
+   (merge 5514f14617 gj/user-manual-fix-grep-example later to maint).
+
+ * The final clean-up phase of the diff output could turn the result of
+   histogram diff algorithm suboptimal, which has been corrected.
+   (merge e417277ae9 yc/histogram-hunk-shift-fix later to maint).
+
+ * "git diff -U<num>" was too lenient in its command line parsing and
+   took an empty string as a valid <num>.
+   (merge 4f6a803aba ty/doc-diff-u-wo-number later to maint).
+
+ * The handling of the incomplete lines at the end by "git
+   diff-highlight" has been fixed.
+
+ * merge-file --object-id used to trigger a BUG when run in a linked
+   worktree, which has been fixed.
+   (merge 57246b7c62 mr/merge-file-object-id-worktree-fix later to maint).
+
+ * "git apply -p<n>" parses <n> more carefully now.
+   (merge d05d84c5f5 mf/apply-p-no-atoi later to maint).
+
+ * A test to run a .bat file with whitespaces in the name with arguments
+   with whitespaces in them was flaky in that sometimes it got killed
+   before it produced expected side effects, which has been rewritten to
+   make it more robust.
+   (merge 3ad4921838 jk/t0061-bat-test-update later to maint).
+
+ * "git ls-remote '+refs/tags/*:refs/tags/*' https://..." run outside a
+   repository would dereference a NULL while trying to see if the given
+   refspec is a single-object refspec, which has been corrected.
+   (merge 4e5dc601dd kj/refspec-parsing-outside-repository later to maint).
+
  * Other code cleanup, docfix, build fix, etc.
    (merge d79fff4a11 jk/remote-tracking-ref-leakfix later to maint).
    (merge 7a747f972d dd/t5403-modernise later to maint).
@@ -328,3 +482,16 @@
    (merge a56fa1ca05 lp/doc-gitprotocol-pack-fixes later to maint).
    (merge 0d6bb8b541 ss/t3700-modernize later to maint).
    (merge 63c00a677b ss/t9123-setup-inside-test-expect-success later to maint).
+   (merge beca0ca4be os/doc-git-custom-commands later to maint).
+   (merge 4c223571be ty/patch-ids-document-lazy-eval later to maint).
+   (merge 476365ac85 jc/doc-wholesale-replace-before-next later to maint).
+   (merge 35f220b639 ss/submodule--helper-use-xmalloc later to maint).
+   (merge 02cbae61df cf/constness-fixes later to maint).
+   (merge 69efd53c81 ms/t7605-test-path-is-helpers later to maint).
+   (merge d39cef3a1a ss/t0410-delete-object-cleanup later to maint).
+   (merge 2f05039717 rj/pack-refs-tests-path-is-helpers later to maint).
+   (merge 2594747ad1 jk/transport-color-leakfix later to maint).
+   (merge 48430e44ac mf/t0008-cleanup later to maint).
+   (merge fc8a4f15e7 gi/doc-boolean-config-typofix later to maint).
+   (merge 37182267a0 kh/doc-interpret-trailers-1 later to maint).
+   (merge f64c50e768 jc/rerere-modern-strbuf-handling later to maint).
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index 359f5fb..d570184 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -56,6 +56,18 @@
 series immediately after receiving a review. This helps collect broader
 input and avoids unnecessary churn from many rapid iterations.
 
+. These early update iterations are expected to be full replacements,
+  not incremental updates on top of what you posted already.  If you
+  are correcting mistakes you made in the previous iteration that a
+  reviewer noticed and pointed out in their review, you _fix_ that
+  mistake by rewriting your history (e.g., by using "git rebase -i")
+  to pretend that you never made the mistake in the first place.  In
+  other words, this is a chance to pretend to be a perfect developer,
+  and you are expected to take advantage of that.  In the larger
+  picture, nobody is interested in your earlier mistakes.  Just
+  present a logical progression made by a perfect developer who makes
+  no mistakes while working on the topic.
+
 . Polish, refine, and re-send your patches to the list and to the people
   who spent their time to improve your patch.  Go back to step (2).
 
diff --git a/Documentation/config/http.adoc b/Documentation/config/http.adoc
index 9da5c29..849c89f 100644
--- a/Documentation/config/http.adoc
+++ b/Documentation/config/http.adoc
@@ -315,6 +315,32 @@
 	unset, curl's default value is used. Can be overridden by the
 	`GIT_HTTP_KEEPALIVE_COUNT` environment variable.
 
+http.retryAfter::
+	Default wait time in seconds before retrying when a server returns
+	HTTP 429 (Too Many Requests) without a Retry-After header.
+	Defaults to 0 (retry immediately). When a Retry-After header is
+	present, its value takes precedence over this setting; however,
+	automatic use of the server-provided `Retry-After` header requires
+	libcurl 7.66.0 or later. On older versions, configure this setting
+	manually to control the retry delay. Can be overridden by the
+	`GIT_HTTP_RETRY_AFTER` environment variable.
+	See also `http.maxRetries` and `http.maxRetryTime`.
+
+http.maxRetries::
+	Maximum number of times to retry after receiving HTTP 429 (Too Many
+	Requests) responses. Set to 0 (the default) to disable retries.
+	Can be overridden by the `GIT_HTTP_MAX_RETRIES` environment variable.
+	See also `http.retryAfter` and `http.maxRetryTime`.
+
+http.maxRetryTime::
+	Maximum time in seconds to wait for a single retry attempt when
+	handling HTTP 429 (Too Many Requests) responses. If the server
+	requests a delay (via Retry-After header) or if `http.retryAfter`
+	is configured with a value that exceeds this maximum, Git will fail
+	immediately rather than waiting. Default is 300 seconds (5 minutes).
+	Can be overridden by the `GIT_HTTP_MAX_RETRY_TIME` environment
+	variable. See also `http.retryAfter` and `http.maxRetries`.
+
 http.noEPSV::
 	A boolean which disables using of EPSV ftp command by curl.
 	This can be helpful with some "poor" ftp servers which don't
diff --git a/Documentation/config/status.adoc b/Documentation/config/status.adoc
index 8caf90f..b5dd85b 100644
--- a/Documentation/config/status.adoc
+++ b/Documentation/config/status.adoc
@@ -17,6 +17,31 @@
 	`--no-ahead-behind` by default in linkgit:git-status[1] for
 	non-porcelain status formats.  Defaults to true.
 
+status.compareBranches::
+	A space-separated list of branch comparison specifiers to use in
+	linkgit:git-status[1]. Currently, only `@{upstream}` and `@{push}`
+	are supported. They are interpreted as `branch@{upstream}` and
+	`branch@{push}` for the current branch.
++
+If not set, the default behavior is equivalent to `@{upstream}`, which
+compares against the configured upstream tracking branch.
++
+The entries are shown in the order they appear in the configuration.
+Duplicate entries that resolve to the same ref are suppressed after
+their first occurrence, so `@{push} @{upstream} @{push}` shows at
+most two comparisons.  When `@{upstream}` and `@{push}` resolve to
+the same remote-tracking branch, only one comparison is shown.
++
+Example:
++
+----
+[status]
+	compareBranches = @{upstream} @{push}
+----
++
+This would show comparisons against both the configured upstream and push
+tracking branches for the current branch.
+
 status.displayCommentPrefix::
 	If set to true, linkgit:git-status[1] will insert a comment
 	prefix before each output line (starting with
diff --git a/Documentation/config/trailer.adoc b/Documentation/config/trailer.adoc
index 60bc221..1bc7019 100644
--- a/Documentation/config/trailer.adoc
+++ b/Documentation/config/trailer.adoc
@@ -1,21 +1,21 @@
-trailer.separators::
+`trailer.separators`::
 	This option tells which characters are recognized as trailer
-	separators. By default only ':' is recognized as a trailer
-	separator, except that '=' is always accepted on the command
+	separators. By default only `:` is recognized as a trailer
+	separator, except that `=` is always accepted on the command
 	line for compatibility with other git commands.
 +
 The first character given by this option will be the default character
 used when another separator is not specified in the config for this
 trailer.
 +
-For example, if the value for this option is "%=$", then only lines
-using the format '<key><sep><value>' with <sep> containing '%', '='
-or '$' and then spaces will be considered trailers. And '%' will be
+For example, if the value for this option is `%=$`, then only lines
+using the format _<key><sep><value>_ with _<sep>_ containing `%`, `=`
+or `$` and then spaces will be considered trailers. And `%` will be
 the default separator used, so by default trailers will appear like:
-'<key>% <value>' (one percent sign and one space will appear between
+`<key>% <value>` (one percent sign and one space will appear between
 the key and the value).
 
-trailer.where::
+`trailer.where`::
 	This option tells where a new trailer will be added.
 +
 This can be `end`, which is the default, `start`, `after` or `before`.
@@ -27,41 +27,41 @@
 instead of the end, of the existing trailers.
 +
 If it is `after`, then each new trailer will appear just after the
-last trailer with the same <key>.
+last trailer with the same _<key>_.
 +
 If it is `before`, then each new trailer will appear just before the
-first trailer with the same <key>.
+first trailer with the same _<key>_.
 
-trailer.ifexists::
+`trailer.ifexists`::
 	This option makes it possible to choose what action will be
 	performed when there is already at least one trailer with the
-	same <key> in the input.
+	same _<key>_ in the input.
 +
 The valid values for this option are: `addIfDifferentNeighbor` (this
 is the default), `addIfDifferent`, `add`, `replace` or `doNothing`.
 +
 With `addIfDifferentNeighbor`, a new trailer will be added only if no
-trailer with the same (<key>, <value>) pair is above or below the line
+trailer with the same (_<key>_, _<value>_) pair is above or below the line
 where the new trailer will be added.
 +
 With `addIfDifferent`, a new trailer will be added only if no trailer
-with the same (<key>, <value>) pair is already in the input.
+with the same (_<key>_, _<value>_) pair is already in the input.
 +
 With `add`, a new trailer will be added, even if some trailers with
-the same (<key>, <value>) pair are already in the input.
+the same (_<key>_, _<value>_) pair are already in the input.
 +
-With `replace`, an existing trailer with the same <key> will be
+With `replace`, an existing trailer with the same _<key>_ will be
 deleted and the new trailer will be added. The deleted trailer will be
-the closest one (with the same <key>) to the place where the new one
+the closest one (with the same _<key>_) to the place where the new one
 will be added.
 +
 With `doNothing`, nothing will be done; that is no new trailer will be
-added if there is already one with the same <key> in the input.
+added if there is already one with the same _<key>_ in the input.
 
-trailer.ifmissing::
+`trailer.ifmissing`::
 	This option makes it possible to choose what action will be
 	performed when there is not yet any trailer with the same
-	<key> in the input.
+	_<key>_ in the input.
 +
 The valid values for this option are: `add` (this is the default) and
 `doNothing`.
@@ -70,67 +70,68 @@
 +
 With `doNothing`, nothing will be done.
 
-trailer.<keyAlias>.key::
-	Defines a <keyAlias> for the <key>. The <keyAlias> must be a
-	prefix (case does not matter) of the <key>. For example, in `git
-	config trailer.ack.key "Acked-by"` the "Acked-by" is the <key> and
-	the "ack" is the <keyAlias>. This configuration allows the shorter
+`trailer.<key-alias>.key`::
+	Defines a _<key-alias>_ for the _<key>_. The _<key-alias>_ must be a
+	prefix (case does not matter) of the _<key>_. For example, in `git
+	config trailer.ack.key "Acked-by"` the `Acked-by` is the _<key>_ and
+	the `ack` is the _<key-alias>_. This configuration allows the shorter
 	`--trailer "ack:..."` invocation on the command line using the "ack"
-	<keyAlias> instead of the longer `--trailer "Acked-by:..."`.
+	`<key-alias>` instead of the longer `--trailer "Acked-by:..."`.
 +
-At the end of the <key>, a separator can appear and then some
-space characters. By default the only valid separator is ':',
+At the end of the _<key>_, a separator can appear and then some
+space characters. By default the only valid separator is `:`,
 but this can be changed using the `trailer.separators` config
 variable.
 +
 If there is a separator in the key, then it overrides the default
 separator when adding the trailer.
 
-trailer.<keyAlias>.where::
-	This option takes the same values as the 'trailer.where'
+`trailer.<key-alias>.where`::
+	This option takes the same values as the `trailer.where`
 	configuration variable and it overrides what is specified by
-	that option for trailers with the specified <keyAlias>.
+	that option for trailers with the specified _<key-alias>_.
 
-trailer.<keyAlias>.ifexists::
-	This option takes the same values as the 'trailer.ifexists'
+`trailer.<key-alias>.ifexists`::
+	This option takes the same values as the `trailer.ifexists`
 	configuration variable and it overrides what is specified by
-	that option for trailers with the specified <keyAlias>.
+	that option for trailers with the specified _<key-alias>_.
 
-trailer.<keyAlias>.ifmissing::
-	This option takes the same values as the 'trailer.ifmissing'
+`trailer.<key-alias>.ifmissing`::
+	This option takes the same values as the `trailer.ifmissing`
 	configuration variable and it overrides what is specified by
-	that option for trailers with the specified <keyAlias>.
+	that option for trailers with the specified _<key-alias>_.
 
-trailer.<keyAlias>.command::
-	Deprecated in favor of 'trailer.<keyAlias>.cmd'.
-	This option behaves in the same way as 'trailer.<keyAlias>.cmd', except
+`trailer.<key-alias>.command`::
+	Deprecated in favor of `trailer.<key-alias>.cmd`.
+	This option behaves in the same way as `trailer.<key-alias>.cmd`, except
 	that it doesn't pass anything as argument to the specified command.
-	Instead the first occurrence of substring $ARG is replaced by the
-	<value> that would be passed as argument.
+	Instead the first occurrence of substring `$ARG` is replaced by the
+	_<value>_ that would be passed as argument.
 +
-Note that $ARG in the user's command is
-only replaced once and that the original way of replacing $ARG is not safe.
+Note that `$ARG` in the user's command is
+only replaced once and that the original way of replacing `$ARG` is not safe.
 +
-When both 'trailer.<keyAlias>.cmd' and 'trailer.<keyAlias>.command' are given
-for the same <keyAlias>, 'trailer.<keyAlias>.cmd' is used and
-'trailer.<keyAlias>.command' is ignored.
+When both `trailer.<key-alias>.cmd` and `trailer.<key-alias>.command` are given
+for the same _<key-alias>_, `trailer.<key-alias>.cmd` is used and
+`trailer.<key-alias>.command` is ignored.
 
-trailer.<keyAlias>.cmd::
+`trailer.<key-alias>.cmd`::
 	This option can be used to specify a shell command that will be called
-	once to automatically add a trailer with the specified <keyAlias>, and then
-	called each time a '--trailer <keyAlias>=<value>' argument is specified to
-	modify the <value> of the trailer that this option would produce.
+	once to automatically add a trailer with the specified _<key-alias>_, and then
+	called each time a `--trailer <key-alias>=<value>` argument is specified to
+	modify the _<value>_ of the trailer that this option would produce.
 +
 When the specified command is first called to add a trailer
-with the specified <keyAlias>, the behavior is as if a special
-'--trailer <keyAlias>=<value>' argument was added at the beginning
-of the "git interpret-trailers" command, where <value>
-is taken to be the standard output of the command with any
-leading and trailing whitespace trimmed off.
+with the specified _<key-alias>_, the behavior is as if a special
+`--trailer <key-alias>=<value>` argument was added at the beginning
+of linkgit:git-interpret-trailers[1], where _<value>_ is taken to be the
+standard output of the command with any leading and trailing whitespace
+trimmed off.
 +
-If some '--trailer <keyAlias>=<value>' arguments are also passed
+If some `--trailer <key-alias>=<value>` arguments are also passed
 on the command line, the command is called again once for each
-of these arguments with the same <keyAlias>. And the <value> part
+of these arguments with the same _<key-alias>_. And the _<value>_ part
 of these arguments, if any, will be passed to the command as its
-first argument. This way the command can produce a <value> computed
-from the <value> passed in the '--trailer <keyAlias>=<value>' argument.
+first argument. This way the command can produce a _<value>_ computed
+from the _<value>_ passed in the `--trailer <key-alias>=<value>`
+argument.
diff --git a/Documentation/diff-context-options.adoc b/Documentation/diff-context-options.adoc
index e161260..b9ace2a 100644
--- a/Documentation/diff-context-options.adoc
+++ b/Documentation/diff-context-options.adoc
@@ -1,7 +1,9 @@
 `-U<n>`::
 `--unified=<n>`::
-	Generate diffs with _<n>_ lines of context. Defaults to `diff.context`
-	or 3 if the config option is unset.
+	Generate diffs with _<n>_ lines of context. The number of context
+	lines defaults to `diff.context` or 3 if the configuration variable
+	is unset. (`-U` without `<n>` is silently accepted as a synonym for
+	`-p` due to a historical accident).
 
 `--inter-hunk-context=<n>`::
 	Show the context between diff hunks, up to the specified _<number>_
diff --git a/Documentation/diff-options.adoc b/Documentation/diff-options.adoc
index fcfcdf0..8a63b5e 100644
--- a/Documentation/diff-options.adoc
+++ b/Documentation/diff-options.adoc
@@ -127,8 +127,10 @@
 
 `-U<n>`::
 `--unified=<n>`::
-	Generate diffs with _<n>_ lines of context instead of
-	the usual three.
+	Generate diffs with _<n>_ lines of context. The number of context
+	lines defaults to `diff.context` or 3 if the configuration variable
+	is unset. (`-U` without `<n>` is silently accepted as a synonym for
+	`-p` due to a historical accident).
 ifndef::git-format-patch[]
 	Implies `--patch`.
 endif::git-format-patch[]
diff --git a/Documentation/git-config.adoc b/Documentation/git-config.adoc
index 5300dd4..00545b2 100644
--- a/Documentation/git-config.adoc
+++ b/Documentation/git-config.adoc
@@ -221,7 +221,7 @@
 +
 Valid `<type>`'s include:
 +
-- 'bool': canonicalize values `true`, `yes`,`on`, and positive
+- 'bool': canonicalize values `true`, `yes`, `on`, and positive
   numbers as "true", and values `false`, `no`, `off` and `0` as
   "false".
 - 'int': canonicalize values as simple decimal numbers. An optional suffix of
diff --git a/Documentation/git-fast-import.adoc b/Documentation/git-fast-import.adoc
index 479c408..b3f42d4 100644
--- a/Documentation/git-fast-import.adoc
+++ b/Documentation/git-fast-import.adoc
@@ -86,6 +86,10 @@
 * `strip-if-invalid` will check signatures and, if they are invalid,
   will strip them and display a warning. The validation is performed
   in the same way as linkgit:git-verify-commit[1] does it.
+* `sign-if-invalid[=<keyid>]`, similar to `strip-if-invalid`, verifies
+  commit signatures and replaces invalid signatures with newly created ones.
+  Valid signatures are left unchanged. If `<keyid>` is provided, that key is
+  used for signing; otherwise the configured default signing key is used.
 
 Options for Frontends
 ~~~~~~~~~~~~~~~~~~~~~
diff --git a/Documentation/git-history.adoc b/Documentation/git-history.adoc
index cc019de..24dc907 100644
--- a/Documentation/git-history.adoc
+++ b/Documentation/git-history.adoc
@@ -9,6 +9,7 @@
 --------
 [synopsis]
 git history reword <commit> [--dry-run] [--update-refs=(branches|head)]
+git history split <commit> [--dry-run] [--update-refs=(branches|head)] [--] [<pathspec>...]
 
 DESCRIPTION
 -----------
@@ -57,6 +58,26 @@
 	details of this commit remain unchanged. This command will spawn an
 	editor with the current message of that commit.
 
+`split <commit> [--] [<pathspec>...]`::
+	Interactively split up <commit> into two commits by choosing
+	hunks introduced by it that will be moved into the new split-out
+	commit. These hunks will then be written into a new commit that
+	becomes the parent of the previous commit. The original commit
+	stays intact, except that its parent will be the newly split-out
+	commit.
++
+The commit messages of the split-up commits will be asked for by launching
+the configured editor. Authorship of the commit will be the same as for the
+original commit.
++
+If passed, _<pathspec>_ can be used to limit which changes shall be split out
+of the original commit. Files not matching any of the pathspecs will remain
+part of the original commit. For more details, see the 'pathspec' entry in
+linkgit:gitglossary[7].
++
+It is invalid to select either all or no hunks, as that would lead to
+one of the commits becoming empty.
+
 OPTIONS
 -------
 
@@ -72,6 +93,47 @@
 	descendants of the original commit will be rewritten. With `head`, only
 	the current `HEAD` reference will be rewritten. Defaults to `branches`.
 
+EXAMPLES
+--------
+
+Split a commit
+~~~~~~~~~~~~~~
+
+----------
+$ git log --stat --oneline
+3f81232 (HEAD -> main) original
+ bar | 1 +
+ foo | 1 +
+ 2 files changed, 2 insertions(+)
+
+$ git history split HEAD
+diff --git a/bar b/bar
+new file mode 100644
+index 0000000..5716ca5
+--- /dev/null
++++ b/bar
+@@ -0,0 +1 @@
++bar
+(1/1) Stage addition [y,n,q,a,d,p,?]? y
+
+diff --git a/foo b/foo
+new file mode 100644
+index 0000000..257cc56
+--- /dev/null
++++ b/foo
+@@ -0,0 +1 @@
++foo
+(1/1) Stage addition [y,n,q,a,d,p,?]? n
+
+$ git log --stat --oneline
+7cebe64 (HEAD -> main) original
+ foo | 1 +
+ 1 file changed, 1 insertion(+)
+d1582f3 split-out commit
+ bar | 1 +
+ 1 file changed, 1 insertion(+)
+----------
+
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-interpret-trailers.adoc b/Documentation/git-interpret-trailers.adoc
index fd335fe..77b4f63 100644
--- a/Documentation/git-interpret-trailers.adoc
+++ b/Documentation/git-interpret-trailers.adoc
@@ -7,14 +7,14 @@
 
 SYNOPSIS
 --------
-[verse]
-'git interpret-trailers' [--in-place] [--trim-empty]
+[synopsis]
+git interpret-trailers [--in-place] [--trim-empty]
 			[(--trailer (<key>|<key-alias>)[(=|:)<value>])...]
 			[--parse] [<file>...]
 
 DESCRIPTION
 -----------
-Add or parse 'trailer' lines that look similar to RFC 822 e-mail
+Add or parse _trailer_ lines that look similar to RFC 822 e-mail
 headers, at the end of the otherwise free-form part of a commit
 message. For example, in the following commit message
 
@@ -27,23 +27,24 @@
 Signed-off-by: Bob <bob@example.com>
 ------------------------------------------------
 
-the last two lines starting with "Signed-off-by" are trailers.
+the last two lines starting with `Signed-off-by` are trailers.
 
 This command reads commit messages from either the
-<file> arguments or the standard input if no <file> is specified.
+_<file>_ arguments or the standard input if no _<file>_ is specified.
 If `--parse` is specified, the output consists of the parsed trailers
 coming from the input, without influencing them with any command line
 options or configuration variables.
 
-Otherwise, this command applies `trailer.*` configuration variables
-(which could potentially add new trailers, as well as reposition them),
-as well as any command line arguments that can override configuration
-variables (such as `--trailer=...` which could also add new trailers),
-to each input file. The result is emitted on the standard output.
+Otherwise, this command applies `trailer.<key-alias>` configuration
+variables (which could potentially add new trailers, as well as
+reposition them), as well as any command line arguments that can
+override configuration variables (such as `--trailer=...` which could
+also add new trailers), to each input file. The result is emitted on the
+standard output.
 
 This command can also operate on the output of linkgit:git-format-patch[1],
 which is more elaborate than a plain commit message. Namely, such output
-includes a commit message (as above), a "---" divider line, and a patch part.
+includes a commit message (as above), a `---` divider line, and a patch part.
 For these inputs, the divider and patch parts are not modified by
 this command and are emitted as is on the output, unless
 `--no-divider` is specified.
@@ -53,24 +54,24 @@
 the input is changed. They also make it possible to
 automatically add some trailers.
 
-By default, a '<key>=<value>' or '<key>:<value>' argument given
+By default, a `<key>=<value>` or `<key>:<value>` argument given
 using `--trailer` will be appended after the existing trailers only if
-the last trailer has a different (<key>, <value>) pair (or if there
-is no existing trailer). The <key> and <value> parts will be trimmed
+the last trailer has a different (_<key>_, _<value>_) pair (or if there
+is no existing trailer). The _<key>_ and _<value>_ parts will be trimmed
 to remove starting and trailing whitespace, and the resulting trimmed
-<key> and <value> will appear in the output like this:
+_<key>_ and _<value>_ will appear in the output like this:
 
 ------------------------------------------------
 key: value
 ------------------------------------------------
 
-This means that the trimmed <key> and <value> will be separated by
-`': '` (one colon followed by one space).
+This means that the trimmed _<key>_ and _<value>_ will be separated by
+"`:`{nbsp}" (one colon followed by one space).
 
-For convenience, a <key-alias> can be configured to make using `--trailer`
+For convenience, a _<key-alias>_ can be configured to make using `--trailer`
 shorter to type on the command line. This can be configured using the
-'trailer.<key-alias>.key' configuration variable. The <keyAlias> must be a prefix
-of the full <key> string, although case sensitivity does not matter. For
+`trailer.<key-alias>.key` configuration variable. The _<key-alias>_ must be a prefix
+of the full _<key>_ string, although case sensitivity does not matter. For
 example, if you have
 
 ------------------------------------------------
@@ -91,13 +92,13 @@
 least 25% trailers.
 The group must be preceded by one or more empty (or whitespace-only) lines.
 The group must either be at the end of the input or be the last
-non-whitespace lines before a line that starts with '---' (followed by a
+non-whitespace lines before a line that starts with `---` (followed by a
 space or the end of the line).
 
 When reading trailers, there can be no whitespace before or inside the
-<key>, but any number of regular space and tab characters are allowed
-between the <key> and the separator. There can be whitespaces before,
-inside or after the <value>. The <value> may be split over multiple lines
+_<key>_, but any number of regular space and tab characters are allowed
+between the _<key>_ and the separator. There can be whitespaces before,
+inside or after the _<value>_. The _<value>_ may be split over multiple lines
 with each subsequent line starting with at least one whitespace, like
 the "folding" in RFC 822. Example:
 
@@ -111,77 +112,97 @@
 
 OPTIONS
 -------
---in-place::
-	Edit the files in place.
+`--in-place`::
+`--no-in-place`::
+	Edit the files in place. The default is `--no-in-place`.
 
---trim-empty::
-	If the <value> part of any trailer contains only whitespace,
+`--trim-empty`::
+`--no-trim-empty`::
+	If the _<value>_ part of any trailer contains only whitespace,
 	the whole trailer will be removed from the output.
 	This applies to existing trailers as well as new trailers.
++
+The default is `--no-trim-empty`.
 
---trailer <key>[(=|:)<value>]::
-	Specify a (<key>, <value>) pair that should be applied as a
-	trailer to the inputs. See the description of this
-	command.
+`--trailer=<key>[(=|:)<value>]`::
+`--no-trailer`::
+	Specify a (_<key>_, _<value>_) pair that should be applied as a
+	trailer to the inputs. See the description of this command. Can
+	be given multiple times.
++
+Use `--no-trailer` to reset the list.
 
---where <placement>::
---no-where::
+`--where=<placement>`::
+`--no-where`::
 	Specify where all new trailers will be added.  A setting
-	provided with '--where' overrides the `trailer.where` and any
-	applicable `trailer.<keyAlias>.where` configuration variables
-	and applies to all '--trailer' options until the next occurrence of
-	'--where' or '--no-where'. Upon encountering '--no-where', clear the
-	effect of any previous use of '--where', such that the relevant configuration
-	variables are no longer overridden. Possible placements are `after`,
+	provided with `--where` overrides the `trailer.where` and any
+	applicable `trailer.<key-alias>.where` configuration variables
+	and applies to all `--trailer` options until the next occurrence of
+	`--where` or `--no-where`. Possible placements are `after`,
 	`before`, `end` or `start`.
++
+Use `--no-where` to clear the effect of any previous use of `--where`,
+such that the relevant configuration variables are no longer overridden.
 
---if-exists <action>::
---no-if-exists::
+`--if-exists=<action>`::
+`--no-if-exists`::
 	Specify what action will be performed when there is already at
-	least one trailer with the same <key> in the input.  A setting
-	provided with '--if-exists' overrides the `trailer.ifExists` and any
-	applicable `trailer.<keyAlias>.ifExists` configuration variables
-	and applies to all '--trailer' options until the next occurrence of
-	'--if-exists' or '--no-if-exists'. Upon encountering '--no-if-exists', clear the
-	effect of any previous use of '--if-exists', such that the relevant configuration
-	variables are no longer overridden. Possible actions are `addIfDifferent`,
+	least one trailer with the same _<key>_ in the input.  A setting
+	provided with `--if-exists` overrides the `trailer.ifExists` and any
+	applicable `trailer.<key-alias>.ifExists` configuration variables
+	and applies to all `--trailer` options until the next occurrence of
+	`--if-exists` or `--no-if-exists`. Possible actions are `addIfDifferent`,
 	`addIfDifferentNeighbor`, `add`, `replace` and `doNothing`.
++
+Use `--no-if-exists` to clear the effect of any previous use of
+`--if-exists`, such that the relevant configuration variables are no
+longer overridden.
 
---if-missing <action>::
---no-if-missing::
+`--if-missing=<action>`::
+`--no-if-missing`::
 	Specify what action will be performed when there is no other
-	trailer with the same <key> in the input.  A setting
-	provided with '--if-missing' overrides the `trailer.ifMissing` and any
-	applicable `trailer.<keyAlias>.ifMissing` configuration variables
-	and applies to all '--trailer' options until the next occurrence of
-	'--if-missing' or '--no-if-missing'. Upon encountering '--no-if-missing',
-	clear the effect of any previous use of '--if-missing', such that the relevant
-	configuration variables are no longer overridden. Possible actions are `doNothing`
-	or `add`.
+	trailer with the same _<key>_ in the input.  A setting
+	provided with `--if-missing` overrides the `trailer.ifMissing` and any
+	applicable `trailer.<key-alias>.ifMissing` configuration variables
+	and applies to all `--trailer` options until the next occurrence of
+	`--if-missing` or `--no-if-missing`. Possible actions are
+	`doNothing` or `add`.
++
+Use `--no-if-missing` to clear the effect of any previous use of
+`--if-missing`, such that the relevant configuration variables are no
+longer overridden.
 
---only-trailers::
-	Output only the trailers, not any other parts of the input.
+`--only-trailers`::
+`--no-only-trailers`::
+	Output only the trailers, not any other parts of the
+	input. The default is `--no-only-trailers`.
 
---only-input::
+`--only-input`::
+`--no-only-input`::
 	Output only trailers that exist in the input; do not add any
-	from the command-line or by applying `trailer.*` configuration
-	variables.
+	from the command-line or by applying `trailer.<key-alias>` configuration
+	variables. The default is `--no-only-input`.
 
---unfold::
+`--unfold`::
+`--no-unfold`::
 	If a trailer has a value that runs over multiple lines (aka "folded"),
-	reformat the value into a single line.
+	reformat the value into a single line. The default is `--no-unfold`.
 
---parse::
+`--parse`::
 	A convenience alias for `--only-trailers --only-input
 	--unfold`. This makes it easier to only see the trailers coming from the
 	input without influencing them with any command line options or
 	configuration variables, while also making the output machine-friendly with
-	--unfold.
+	`--unfold`.
++
+There is no convenience alias to negate this alias.
 
---no-divider::
-	Do not treat `---` as the end of the commit message. Use this
-	when you know your input contains just the commit message itself
-	(and not an email or the output of `git format-patch`).
+`--divider`::
+`--no-divider`::
+	Treat `---` as the end of the commit message. This is the default.
+	Use `--no-divider` when you know your input contains just the
+	commit message itself (and not an email or the output of
+	linkgit:git-format-patch[1]).
 
 CONFIGURATION VARIABLES
 -----------------------
@@ -193,7 +214,7 @@
 EXAMPLES
 --------
 
-* Configure a 'sign' trailer with a 'Signed-off-by' key, and then
+* Configure a `sign` trailer with a `Signed-off-by` key, and then
   add two of these trailers to a commit message file:
 +
 ------------
@@ -230,8 +251,8 @@
 Acked-by: Alice <alice@example.com>
 ------------
 
-* Extract the last commit as a patch, and add a 'Cc' and a
-  'Reviewed-by' trailer to it:
+* Extract the last commit as a patch, and add a `Cc` and a
+  `Reviewed-by` trailer to it:
 +
 ------------
 $ git format-patch -1
@@ -239,9 +260,9 @@
 $ git interpret-trailers --trailer 'Cc: Alice <alice@example.com>' --trailer 'Reviewed-by: Bob <bob@example.com>' 0001-foo.patch >0001-bar.patch
 ------------
 
-* Configure a 'sign' trailer with a command to automatically add a
-  'Signed-off-by: ' with the author information only if there is no
-  'Signed-off-by: ' already, and show how it works:
+* Configure a `sign` trailer with a command to automatically add a
+  "`Signed-off-by:`{nbsp}" with the author information only if there is no
+  "`Signed-off-by:`{nbsp}" already, and show how it works:
 +
 ------------
 $ cat msg1.txt
@@ -272,7 +293,7 @@
 Signed-off-by: Alice <alice@example.com>
 ------------
 
-* Configure a 'fix' trailer with a key that contains a '#' and no
+* Configure a `fix` trailer with a key that contains a `#` and no
   space after this character, and show how it works:
 +
 ------------
@@ -284,7 +305,7 @@
 Fix #42
 ------------
 
-* Configure a 'help' trailer with a cmd use a script `glog-find-author`
+* Configure a `help` trailer with a cmd use a script `glog-find-author`
   which search specified author identity from git log in git repository
   and show how it works:
 +
@@ -308,7 +329,7 @@
 Helped-by: Christian Couder <christian.couder@gmail.com>
 ------------
 
-* Configure a 'ref' trailer with a cmd use a script `glog-grep`
+* Configure a `ref` trailer with a cmd use a script `glog-grep`
   to grep last relevant commit from git log in the git repository
   and show how it works:
 +
@@ -331,7 +352,7 @@
 Reference-to: 8bc9a0c769 (Add copyright notices., 2005-04-07)
 ------------
 
-* Configure a 'see' trailer with a command to show the subject of a
+* Configure a `see` trailer with a command to show the subject of a
   commit that is related, and show how it works:
 +
 ------------
@@ -359,8 +380,8 @@
 * Configure a commit template with some trailers with empty values
   (using sed to show and keep the trailing spaces at the end of the
   trailers), then configure a commit-msg hook that uses
-  'git interpret-trailers' to remove trailers with empty values and
-  to add a 'git-version' trailer:
+  git-interpret-trailers(1) to remove trailers with empty values and to
+  add a `git-version` trailer:
 +
 ------------
 $ cat temp.txt
diff --git a/Documentation/git-multi-pack-index.adoc b/Documentation/git-multi-pack-index.adoc
index 2f64269..6125683 100644
--- a/Documentation/git-multi-pack-index.adoc
+++ b/Documentation/git-multi-pack-index.adoc
@@ -9,7 +9,14 @@
 SYNOPSIS
 --------
 [verse]
-'git multi-pack-index' [--object-dir=<dir>] [--[no-]bitmap] <sub-command>
+'git multi-pack-index' [<options>] write [--preferred-pack=<pack>]
+		         [--[no-]bitmap] [--[no-]incremental] [--[no-]stdin-packs]
+		         [--refs-snapshot=<path>]
+'git multi-pack-index' [<options>] compact [--[no-]incremental]
+		         [--[no-]bitmap] <from> <to>
+'git multi-pack-index' [<options>] verify
+'git multi-pack-index' [<options>] expire
+'git multi-pack-index' [<options>] repack [--batch-size=<size>]
 
 DESCRIPTION
 -----------
@@ -18,6 +25,8 @@
 OPTIONS
 -------
 
+The following command-line options are applicable to all sub-commands:
+
 --object-dir=<dir>::
 	Use given directory for the location of Git objects. We check
 	`<dir>/packs/multi-pack-index` for the current MIDX file, and
@@ -73,7 +82,21 @@
 		Write an incremental MIDX file containing only objects
 		and packs not present in an existing MIDX layer.
 		Migrates non-incremental MIDXs to incremental ones when
-		necessary. Incompatible with `--bitmap`.
+		necessary.
+--
+
+compact::
+	Write a new MIDX layer containing only objects and packs present
+	in the range `<from>` to `<to>`, where both arguments are
+	checksums of existing layers in the MIDX chain.
++
+--
+	--incremental::
+		Write the result to a MIDX chain instead of writing a
+		stand-alone MIDX.
+
+	--[no-]bitmap::
+		Control whether or not a multi-pack bitmap is written.
 --
 
 verify::
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index e177808..f6c22d1 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -497,6 +497,13 @@
 +
 See also INCOMPATIBLE OPTIONS below.
 
+--trailer=<trailer>::
+	Append the given trailer to every rebased commit message, processed
+	via linkgit:git-interpret-trailers[1]. This option implies
+	`--force-rebase`.
++
+See also INCOMPATIBLE OPTIONS below.
+
 -i::
 --interactive::
 	Make a list of the commits which are about to be rebased.  Let the
@@ -653,6 +660,7 @@
  * --[no-]reapply-cherry-picks when used without --keep-base
  * --update-refs
  * --root when used without --onto
+ * --trailer
 
 In addition, the following pairs of options are incompatible:
 
diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 5e2968b..42262c1 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -64,6 +64,7 @@
 * Reachable object counts categorized by type
 * Total inflated size of reachable objects by type
 * Total disk size of reachable objects by type
+* Largest reachable objects in the repository by type
 +
 The output format can be chosen through the flag `--format`. Three formats are
 supported:
diff --git a/Documentation/git.adoc b/Documentation/git.adoc
index 2b3d1d2..8a5cdd3 100644
--- a/Documentation/git.adoc
+++ b/Documentation/git.adoc
@@ -235,7 +235,10 @@
 ------------
 
 We divide Git into high level ("porcelain") commands and low level
-("plumbing") commands.
+("plumbing") commands.  For defining command aliases, see
+linkgit:git-config[1] and look for descriptions of `alias.*`.
+For installing custom "git" subcommands, see the description for
+the 'PATH' environment variable in this manual.
 
 High-level commands (porcelain)
 -------------------------------
diff --git a/Documentation/gitformat-pack.adoc b/Documentation/gitformat-pack.adoc
index 1b4db4a..3416edc 100644
--- a/Documentation/gitformat-pack.adoc
+++ b/Documentation/gitformat-pack.adoc
@@ -374,7 +374,9 @@
 	    The signature is: {'M', 'I', 'D', 'X'}
 
 	1-byte version number:
-	    Git only writes or recognizes version 1.
+	    Git writes the version specified by the "midx.version"
+	    configuration option, which defaults to 2. It recognizes
+	    both versions 1 and 2.
 
 	1-byte Object Id Version
 	    We infer the length of object IDs (OIDs) from this value:
@@ -413,7 +415,9 @@
 	    strings. There is no extra padding between the filenames,
 	    and they are listed in lexicographic order. The chunk itself
 	    is padded at the end with between 0 and 3 NUL bytes to make the
-	    chunk size a multiple of 4 bytes.
+	    chunk size a multiple of 4 bytes. Version 1 MIDXs are required to
+	    list their packs in lexicographic order, but version 2 MIDXs may
+	    list their packs in any arbitrary order.
 
 	Bitmapped Packfiles (ID: {'B', 'T', 'M', 'P'})
 	    Stores a table of two 4-byte unsigned integers in network order.
diff --git a/Documentation/githooks.adoc b/Documentation/githooks.adoc
index 0565537..ed04594 100644
--- a/Documentation/githooks.adoc
+++ b/Documentation/githooks.adoc
@@ -484,13 +484,16 @@
 ~~~~~~~~~~~~~~~~~~~~~
 
 This hook is invoked by any Git command that performs reference
-updates. It executes whenever a reference transaction is prepared,
-committed or aborted and may thus get called multiple times. The hook
-also supports symbolic reference updates.
+updates. It executes whenever a reference transaction is preparing,
+prepared, committed or aborted and may thus get called multiple times.
+The hook also supports symbolic reference updates.
 
 The hook takes exactly one argument, which is the current state the
 given reference transaction is in:
 
+    - "preparing": All reference updates have been queued to the
+      transaction but references are not yet locked on disk.
+
     - "prepared": All reference updates have been queued to the
       transaction and references were locked on disk.
 
@@ -511,16 +514,18 @@
 the reference regardless of its current value or when the reference is
 to be created anew, `<old-value>` is the all-zeroes object name. To
 distinguish these cases, you can inspect the current value of
-`<ref-name>` via `git rev-parse`.
+`<ref-name>` via `git rev-parse`. During the "preparing" state, symbolic
+references are not resolved: `<ref-name>` will reflect the symbolic reference
+itself rather than the object it points to.
 
 For symbolic reference updates the `<old_value>` and `<new-value>`
 fields could denote references instead of objects. A reference will be
 denoted with a 'ref:' prefix, like `ref:<ref-target>`.
 
 The exit status of the hook is ignored for any state except for the
-"prepared" state. In the "prepared" state, a non-zero exit status will
-cause the transaction to be aborted. The hook will not be called with
-"aborted" state in that case.
+"preparing" and "prepared" states. In these states, a non-zero exit
+status will cause the transaction to be aborted. The hook will not be
+called with "aborted" state in that case.
 
 push-to-checkout
 ~~~~~~~~~~~~~~~~
diff --git a/Documentation/user-manual.adoc b/Documentation/user-manual.adoc
index 7696987..64009ba 100644
--- a/Documentation/user-manual.adoc
+++ b/Documentation/user-manual.adoc
@@ -4466,7 +4466,7 @@
 $ git diff v2.6.15..v2.6.16 # diff between two tagged versions
 $ git diff v2.6.15..HEAD    # diff with current head
 $ git grep "foo()"	    # search working directory for "foo()"
-$ git grep v2.6.15 "foo()"  # search old tree for "foo()"
+$ git grep "foo()" v2.6.15  # search old tree for "foo()"
 $ git show v2.6.15:a.txt    # look at old version of a.txt
 -----------------------------------------------
 
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index 44240e0..92ea811 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-DEF_VER=v2.53.GIT
+DEF_VER=v2.54.0-rc0
 
 LF='
 '
diff --git a/Makefile b/Makefile
index 15b1ded..dbf0022 100644
--- a/Makefile
+++ b/Makefile
@@ -1005,8 +1005,8 @@
 # COMPUTE_HEADER_DEPENDENCIES=no this will be unset too.
 SPATCH_USE_O_DEPENDENCIES = YesPlease
 
-# Set SPATCH_CONCAT_COCCI to concatenate the contrib/cocci/*.cocci
-# files into a single contrib/cocci/ALL.cocci before running
+# Set SPATCH_CONCAT_COCCI to concatenate the tools/coccinelle/*.cocci
+# files into a single tools/coccinelle/ALL.cocci before running
 # "coccicheck".
 #
 # Pros:
@@ -1025,7 +1025,7 @@
 #   generate a specific patch, e.g. this will always use strbuf.cocci,
 #   not ALL.cocci:
 #
-#	make contrib/coccinelle/strbuf.cocci.patch
+#	make tools/coccinelle/strbuf.cocci.patch
 SPATCH_CONCAT_COCCI = YesPlease
 
 # Rebuild 'coccicheck' if $(SPATCH), its flags etc. change
@@ -1066,11 +1066,13 @@
 		'*.sh' \
 		':!*[tp][0-9][0-9][0-9][0-9]*' \
 		':!contrib' \
+		':!tools' \
 		2>/dev/null || \
 	$(FIND) . \
 		\( -name .git -type d -prune \) \
 		-o \( -name '[tp][0-9][0-9][0-9][0-9]*' -prune \) \
 		-o \( -name contrib -type d -prune \) \
+		-o \( -name tools -type d -prune \) \
 		-o \( -name build -type d -prune \) \
 		-o \( -name .build -type d -prune \) \
 		-o \( -name 'trash*' -type d -prune \) \
@@ -1214,6 +1216,8 @@
 LIB_OBJS += object-name.o
 LIB_OBJS += object.o
 LIB_OBJS += odb.o
+LIB_OBJS += odb/source.o
+LIB_OBJS += odb/source-files.o
 LIB_OBJS += odb/streaming.o
 LIB_OBJS += oid-array.o
 LIB_OBJS += oidmap.o
@@ -1603,6 +1607,7 @@
 endif
 ifneq ($(filter leak,$(SANITIZERS)),)
 BASIC_CFLAGS += -O0
+NO_MMAP = CatchMapLeaks
 SANITIZE_LEAK = YesCompiledWithIt
 endif
 ifneq ($(filter address,$(SANITIZERS)),)
@@ -2024,6 +2029,10 @@
 	COMPAT_CFLAGS += -DNO_PREAD
 	COMPAT_OBJS += compat/pread.o
 endif
+ifdef NO_WRITEV
+	COMPAT_CFLAGS += -DNO_WRITEV
+	COMPAT_OBJS += compat/writev.o
+endif
 ifdef NO_FAST_WORKING_DIRECTORY
 	BASIC_CFLAGS += -DNO_FAST_WORKING_DIRECTORY
 endif
@@ -2690,21 +2699,21 @@
 	ln -s $< $@ 2>/dev/null || \
 	cp $< $@
 
-config-list.h: generate-configlist.sh
+config-list.h: tools/generate-configlist.sh
 	@mkdir -p .depend
-	$(QUIET_GEN)$(SHELL_PATH) ./generate-configlist.sh . $@ .depend/config-list.h.d
+	$(QUIET_GEN)$(SHELL_PATH) ./tools/generate-configlist.sh . $@ .depend/config-list.h.d
 
 -include .depend/config-list.h.d
 
-command-list.h: generate-cmdlist.sh command-list.txt
+command-list.h: tools/generate-cmdlist.sh command-list.txt
 
 command-list.h: $(wildcard Documentation/git*.adoc)
-	$(QUIET_GEN)$(SHELL_PATH) ./generate-cmdlist.sh \
+	$(QUIET_GEN)$(SHELL_PATH) ./tools/generate-cmdlist.sh \
 		$(patsubst %,--exclude-program %,$(EXCLUDED_PROGRAMS)) \
 		. $@
 
-hook-list.h: generate-hooklist.sh Documentation/githooks.adoc
-	$(QUIET_GEN)$(SHELL_PATH) ./generate-hooklist.sh . $@
+hook-list.h: tools/generate-hooklist.sh Documentation/githooks.adoc
+	$(QUIET_GEN)$(SHELL_PATH) ./tools/generate-hooklist.sh . $@
 
 SCRIPT_DEFINES = $(SHELL_PATH_SQ):$(DIFF_SQ):\
 	$(localedir_SQ):$(USE_GETTEXT_SCHEME):$(SANE_TOOL_PATH_SQ):\
@@ -2717,8 +2726,8 @@
 		echo "$$FLAGS" >$@; \
             fi
 
-$(SCRIPT_SH_GEN) $(SCRIPT_LIB) : % : %.sh generate-script.sh GIT-BUILD-OPTIONS GIT-SCRIPT-DEFINES
-	$(QUIET_GEN)./generate-script.sh "$<" "$@+" ./GIT-BUILD-OPTIONS && \
+$(SCRIPT_SH_GEN) $(SCRIPT_LIB) : % : %.sh tools/generate-script.sh GIT-BUILD-OPTIONS GIT-SCRIPT-DEFINES
+	$(QUIET_GEN)./tools/generate-script.sh "$<" "$@+" ./GIT-BUILD-OPTIONS && \
 	mv $@+ $@
 
 git.rc: git.rc.in GIT-VERSION-GEN GIT-VERSION-FILE
@@ -2758,8 +2767,8 @@
 
 PERL_DEFINES += $(gitexecdir) $(perllibdir) $(localedir)
 
-$(SCRIPT_PERL_GEN): % : %.perl generate-perl.sh GIT-PERL-DEFINES GIT-PERL-HEADER GIT-VERSION-FILE
-	$(QUIET_GEN)$(SHELL_PATH) generate-perl.sh ./GIT-BUILD-OPTIONS ./GIT-VERSION-FILE GIT-PERL-HEADER "$<" "$@+" && \
+$(SCRIPT_PERL_GEN): % : %.perl tools/generate-perl.sh GIT-PERL-DEFINES GIT-PERL-HEADER GIT-VERSION-FILE
+	$(QUIET_GEN)$(SHELL_PATH) tools/generate-perl.sh ./GIT-BUILD-OPTIONS ./GIT-VERSION-FILE GIT-PERL-HEADER "$<" "$@+" && \
 	mv $@+ $@
 
 PERL_DEFINES := $(subst $(space),:,$(PERL_DEFINES))
@@ -2787,8 +2796,8 @@
 perllibdir:
 	@echo '$(perllibdir_SQ)'
 
-git-instaweb: git-instaweb.sh generate-script.sh GIT-BUILD-OPTIONS GIT-SCRIPT-DEFINES
-	$(QUIET_GEN)./generate-script.sh "$<" "$@+" ./GIT-BUILD-OPTIONS && \
+git-instaweb: git-instaweb.sh tools/generate-script.sh GIT-BUILD-OPTIONS GIT-SCRIPT-DEFINES
+	$(QUIET_GEN)./tools/generate-script.sh "$<" "$@+" ./GIT-BUILD-OPTIONS && \
 	chmod +x $@+ && \
 	mv $@+ $@
 else # NO_PERL
@@ -2805,9 +2814,9 @@
 $(SCRIPT_PYTHON_GEN): GIT-BUILD-OPTIONS
 
 ifndef NO_PYTHON
-$(SCRIPT_PYTHON_GEN): generate-python.sh
+$(SCRIPT_PYTHON_GEN): tools/generate-python.sh
 $(SCRIPT_PYTHON_GEN): % : %.py
-	$(QUIET_GEN)$(SHELL_PATH) generate-python.sh ./GIT-BUILD-OPTIONS "$<" "$@"
+	$(QUIET_GEN)$(SHELL_PATH) tools/generate-python.sh ./GIT-BUILD-OPTIONS "$<" "$@"
 else # NO_PYTHON
 $(SCRIPT_PYTHON_GEN): % : unimplemented.sh
 	$(QUIET_GEN) \
@@ -3227,9 +3236,9 @@
 NO_PERL_CPAN_FALLBACKS_SQ = $(subst ','\'',$(NO_PERL_CPAN_FALLBACKS))
 endif
 
-perl/build/lib/%.pm: perl/%.pm generate-perl.sh GIT-BUILD-OPTIONS GIT-VERSION-FILE GIT-PERL-DEFINES
+perl/build/lib/%.pm: perl/%.pm tools/generate-perl.sh GIT-BUILD-OPTIONS GIT-VERSION-FILE GIT-PERL-DEFINES
 	$(call mkdir_p_parent_template)
-	$(QUIET_GEN)$(SHELL_PATH) generate-perl.sh ./GIT-BUILD-OPTIONS ./GIT-VERSION-FILE GIT-PERL-HEADER "$<" "$@"
+	$(QUIET_GEN)$(SHELL_PATH) tools/generate-perl.sh ./GIT-BUILD-OPTIONS ./GIT-VERSION-FILE GIT-PERL-HEADER "$<" "$@"
 
 perl/build/man/man3/Git.3pm: perl/Git.pm
 	$(call mkdir_p_parent_template)
@@ -3458,15 +3467,15 @@
 		exit 1; \
 	fi
 
-COCCI_GEN_ALL = .build/contrib/coccinelle/ALL.cocci
-COCCI_GLOB = $(wildcard contrib/coccinelle/*.cocci)
+COCCI_GEN_ALL = .build/tools/coccinelle/ALL.cocci
+COCCI_GLOB = $(wildcard tools/coccinelle/*.cocci)
 COCCI_RULES_TRACKED = $(COCCI_GLOB:%=.build/%)
 COCCI_RULES_TRACKED_NO_PENDING = $(filter-out %.pending.cocci,$(COCCI_RULES_TRACKED))
 COCCI_RULES =
 COCCI_RULES += $(COCCI_GEN_ALL)
 COCCI_RULES += $(COCCI_RULES_TRACKED)
 COCCI_NAMES =
-COCCI_NAMES += $(COCCI_RULES:.build/contrib/coccinelle/%.cocci=%)
+COCCI_NAMES += $(COCCI_RULES:.build/tools/coccinelle/%.cocci=%)
 
 COCCICHECK_PENDING = $(filter %.pending.cocci,$(COCCI_RULES))
 COCCICHECK = $(filter-out $(COCCICHECK_PENDING),$(COCCI_RULES))
@@ -3481,20 +3490,20 @@
 # on $(MAKECMDGOALS) that match these $(COCCI_RULES)
 COCCI_RULES_GLOB =
 COCCI_RULES_GLOB += cocci%
-COCCI_RULES_GLOB += .build/contrib/coccinelle/%
+COCCI_RULES_GLOB += .build/tools/coccinelle/%
 COCCI_RULES_GLOB += $(COCCICHECK_PATCHES)
 COCCI_RULES_GLOB += $(COCCICHEC_PATCHES_PENDING)
 COCCI_RULES_GLOB += $(COCCICHECK_PATCHES_INTREE)
 COCCI_RULES_GLOB += $(COCCICHECK_PATCHES_PENDING_INTREE)
 COCCI_GOALS = $(filter $(COCCI_RULES_GLOB),$(MAKECMDGOALS))
 
-COCCI_TEST_RES = $(wildcard contrib/coccinelle/tests/*.res)
+COCCI_TEST_RES = $(wildcard tools/coccinelle/tests/*.res)
 
 $(COCCI_RULES_TRACKED): .build/% : %
 	$(call mkdir_p_parent_template)
 	$(QUIET_CP)cp $< $@
 
-.build/contrib/coccinelle/FOUND_H_SOURCES: $(FOUND_H_SOURCES)
+.build/tools/coccinelle/FOUND_H_SOURCES: $(FOUND_H_SOURCES)
 	$(call mkdir_p_parent_template)
 	$(QUIET_GEN) >$@
 
@@ -3508,12 +3517,12 @@
 define cocci-rule
 
 ## Rule for .build/$(1).patch/$(2); Params:
-# $(1) = e.g. ".build/contrib/coccinelle/free.cocci"
+# $(1) = e.g. ".build/tools/coccinelle/free.cocci"
 # $(2) = e.g. "grep.c"
 # $(3) = e.g. "grep.o"
-COCCI_$(1:.build/contrib/coccinelle/%.cocci=%) += $(1).d/$(2).patch
+COCCI_$(1:.build/tools/coccinelle/%.cocci=%) += $(1).d/$(2).patch
 $(1).d/$(2).patch: GIT-SPATCH-DEFINES
-$(1).d/$(2).patch: $(if $(and $(SPATCH_USE_O_DEPENDENCIES),$(wildcard $(3))),$(3),.build/contrib/coccinelle/FOUND_H_SOURCES)
+$(1).d/$(2).patch: $(if $(and $(SPATCH_USE_O_DEPENDENCIES),$(wildcard $(3))),$(3),.build/tools/coccinelle/FOUND_H_SOURCES)
 $(1).d/$(2).patch: $(1)
 $(1).d/$(2).patch: $(1).d/%.patch : %
 	$$(call mkdir_p_parent_template)
@@ -3539,13 +3548,13 @@
 
 define spatch-rule
 
-.build/contrib/coccinelle/$(1).cocci.patch: $$(COCCI_$(1))
+.build/tools/coccinelle/$(1).cocci.patch: $$(COCCI_$(1))
 	$$(QUIET_SPATCH_CAT)cat $$^ >$$@ && \
 	if test -s $$@; \
 	then \
 		echo '    ' SPATCH result: $$@; \
 	fi
-contrib/coccinelle/$(1).cocci.patch: .build/contrib/coccinelle/$(1).cocci.patch
+tools/coccinelle/$(1).cocci.patch: .build/tools/coccinelle/$(1).cocci.patch
 	$$(QUIET_CP)cp $$< $$@
 
 endef
@@ -3559,9 +3568,9 @@
 $(COCCI_TEST_RES_GEN): .build/%.res : %.c
 $(COCCI_TEST_RES_GEN): .build/%.res : %.res
 ifdef SPATCH_CONCAT_COCCI
-$(COCCI_TEST_RES_GEN): .build/contrib/coccinelle/tests/%.res : $(COCCI_GEN_ALL)
+$(COCCI_TEST_RES_GEN): .build/tools/coccinelle/tests/%.res : $(COCCI_GEN_ALL)
 else
-$(COCCI_TEST_RES_GEN): .build/contrib/coccinelle/tests/%.res : contrib/coccinelle/%.cocci
+$(COCCI_TEST_RES_GEN): .build/tools/coccinelle/tests/%.res : tools/coccinelle/%.cocci
 endif
 	$(call mkdir_p_parent_template)
 	$(QUIET_SPATCH_TEST)$(SPATCH) $(SPATCH_TEST_FLAGS) \
@@ -3577,14 +3586,14 @@
 coccicheck: coccicheck-test
 
 ifdef SPATCH_CONCAT_COCCI
-COCCICHECK_PATCH_MUST_BE_EMPTY_FILES = contrib/coccinelle/ALL.cocci.patch
+COCCICHECK_PATCH_MUST_BE_EMPTY_FILES = tools/coccinelle/ALL.cocci.patch
 else
 COCCICHECK_PATCH_MUST_BE_EMPTY_FILES = $(COCCICHECK_PATCHES_INTREE)
 endif
 coccicheck: $(COCCICHECK_PATCH_MUST_BE_EMPTY_FILES)
 	! grep ^ $(COCCICHECK_PATCH_MUST_BE_EMPTY_FILES) /dev/null
 
-# See contrib/coccinelle/README
+# See tools/coccinelle/README
 coccicheck-pending: coccicheck-test
 coccicheck-pending: $(COCCICHECK_PATCHES_PENDING_INTREE)
 
@@ -3858,8 +3867,8 @@
 
 cocciclean:
 	$(RM) GIT-SPATCH-DEFINES
-	$(RM) -r .build/contrib/coccinelle
-	$(RM) contrib/coccinelle/*.cocci.patch
+	$(RM) -r .build/tools/coccinelle
+	$(RM) tools/coccinelle/*.cocci.patch
 
 clean: profile-clean coverage-clean cocciclean
 	$(RM) -r .build $(UNIT_TEST_BIN)
@@ -3937,7 +3946,7 @@
 ### Make sure built-ins do not have dups and listed in git.c
 #
 check-builtins::
-	./check-builtins.sh
+	./tools/check-builtins.sh
 
 ### Test suite coverage testing
 #
diff --git a/add-interactive.c b/add-interactive.c
index 1580639..3cf8a1d 100644
--- a/add-interactive.c
+++ b/add-interactive.c
@@ -3,7 +3,6 @@
 #include "git-compat-util.h"
 #include "add-interactive.h"
 #include "color.h"
-#include "config.h"
 #include "diffcore.h"
 #include "gettext.h"
 #include "hash.h"
@@ -20,120 +19,18 @@
 #include "prompt.h"
 #include "tree.h"
 
-static void init_color(struct repository *r, enum git_colorbool use_color,
-		       const char *section_and_slot, char *dst,
-		       const char *default_color)
-{
-	char *key = xstrfmt("color.%s", section_and_slot);
-	const char *value;
-
-	if (!want_color(use_color))
-		dst[0] = '\0';
-	else if (repo_config_get_value(r, key, &value) ||
-		 color_parse(value, dst))
-		strlcpy(dst, default_color, COLOR_MAXLEN);
-
-	free(key);
-}
-
-static enum git_colorbool check_color_config(struct repository *r, const char *var)
-{
-	const char *value;
-	enum git_colorbool ret;
-
-	if (repo_config_get_value(r, var, &value))
-		ret = GIT_COLOR_UNKNOWN;
-	else
-		ret = git_config_colorbool(var, value);
-
-	/*
-	 * Do not rely on want_color() to fall back to color.ui for us. It uses
-	 * the value parsed by git_color_config(), which may not have been
-	 * called by the main command.
-	 */
-	if (ret == GIT_COLOR_UNKNOWN &&
-	    !repo_config_get_value(r, "color.ui", &value))
-		ret = git_config_colorbool("color.ui", value);
-
-	return ret;
-}
-
 void init_add_i_state(struct add_i_state *s, struct repository *r,
-		      struct add_p_opt *add_p_opt)
+		      struct interactive_options *opts)
 {
 	s->r = r;
-	s->context = -1;
-	s->interhunkcontext = -1;
-	s->auto_advance = add_p_opt->auto_advance;
-
-	s->use_color_interactive = check_color_config(r, "color.interactive");
-
-	init_color(r, s->use_color_interactive, "interactive.header",
-		   s->header_color, GIT_COLOR_BOLD);
-	init_color(r, s->use_color_interactive, "interactive.help",
-		   s->help_color, GIT_COLOR_BOLD_RED);
-	init_color(r, s->use_color_interactive, "interactive.prompt",
-		   s->prompt_color, GIT_COLOR_BOLD_BLUE);
-	init_color(r, s->use_color_interactive, "interactive.error",
-		   s->error_color, GIT_COLOR_BOLD_RED);
-	strlcpy(s->reset_color_interactive,
-		want_color(s->use_color_interactive) ? GIT_COLOR_RESET : "", COLOR_MAXLEN);
-
-	s->use_color_diff = check_color_config(r, "color.diff");
-
-	init_color(r, s->use_color_diff, "diff.frag", s->fraginfo_color,
-		   diff_get_color(s->use_color_diff, DIFF_FRAGINFO));
-	init_color(r, s->use_color_diff, "diff.context", s->context_color,
-		   "fall back");
-	if (!strcmp(s->context_color, "fall back"))
-		init_color(r, s->use_color_diff, "diff.plain",
-			   s->context_color,
-			   diff_get_color(s->use_color_diff, DIFF_CONTEXT));
-	init_color(r, s->use_color_diff, "diff.old", s->file_old_color,
-		   diff_get_color(s->use_color_diff, DIFF_FILE_OLD));
-	init_color(r, s->use_color_diff, "diff.new", s->file_new_color,
-		   diff_get_color(s->use_color_diff, DIFF_FILE_NEW));
-	strlcpy(s->reset_color_diff,
-		want_color(s->use_color_diff) ? GIT_COLOR_RESET : "", COLOR_MAXLEN);
-
-	FREE_AND_NULL(s->interactive_diff_filter);
-	repo_config_get_string(r, "interactive.difffilter",
-			       &s->interactive_diff_filter);
-
-	FREE_AND_NULL(s->interactive_diff_algorithm);
-	repo_config_get_string(r, "diff.algorithm",
-			       &s->interactive_diff_algorithm);
-
-	if (!repo_config_get_int(r, "diff.context", &s->context))
-		if (s->context < 0)
-			die(_("%s cannot be negative"), "diff.context");
-	if (!repo_config_get_int(r, "diff.interHunkContext", &s->interhunkcontext))
-		if (s->interhunkcontext < 0)
-			die(_("%s cannot be negative"), "diff.interHunkContext");
-
-	repo_config_get_bool(r, "interactive.singlekey", &s->use_single_key);
-	if (s->use_single_key)
-		setbuf(stdin, NULL);
-
-	if (add_p_opt->context != -1) {
-		if (add_p_opt->context < 0)
-			die(_("%s cannot be negative"), "--unified");
-		s->context = add_p_opt->context;
-	}
-	if (add_p_opt->interhunkcontext != -1) {
-		if (add_p_opt->interhunkcontext < 0)
-			die(_("%s cannot be negative"), "--inter-hunk-context");
-		s->interhunkcontext = add_p_opt->interhunkcontext;
-	}
+	interactive_config_init(&s->cfg, r, opts);
 }
 
 void clear_add_i_state(struct add_i_state *s)
 {
-	FREE_AND_NULL(s->interactive_diff_filter);
-	FREE_AND_NULL(s->interactive_diff_algorithm);
+	interactive_config_clear(&s->cfg);
 	memset(s, 0, sizeof(*s));
-	s->use_color_interactive = GIT_COLOR_UNKNOWN;
-	s->use_color_diff = GIT_COLOR_UNKNOWN;
+	interactive_config_clear(&s->cfg);
 }
 
 /*
@@ -287,7 +184,7 @@ static void list(struct add_i_state *s, struct string_list *list, int *selected,
 		return;
 
 	if (opts->header)
-		color_fprintf_ln(stdout, s->header_color,
+		color_fprintf_ln(stdout, s->cfg.header_color,
 				 "%s", opts->header);
 
 	for (i = 0; i < list->nr; i++) {
@@ -355,7 +252,7 @@ static ssize_t list_and_choose(struct add_i_state *s,
 
 		list(s, &items->items, items->selected, &opts->list_opts);
 
-		color_fprintf(stdout, s->prompt_color, "%s", opts->prompt);
+		color_fprintf(stdout, s->cfg.prompt_color, "%s", opts->prompt);
 		fputs(singleton ? "> " : ">> ", stdout);
 		fflush(stdout);
 
@@ -433,7 +330,7 @@ static ssize_t list_and_choose(struct add_i_state *s,
 
 			if (from < 0 || from >= items->items.nr ||
 			    (singleton && from + 1 != to)) {
-				color_fprintf_ln(stderr, s->error_color,
+				color_fprintf_ln(stderr, s->cfg.error_color,
 						 _("Huh (%s)?"), p);
 				break;
 			} else if (singleton) {
@@ -993,7 +890,7 @@ static int run_patch(struct add_i_state *s, const struct pathspec *ps,
 				free(files->items.items[i].string);
 			} else if (item->index.unmerged ||
 				 item->worktree.unmerged) {
-				color_fprintf_ln(stderr, s->error_color,
+				color_fprintf_ln(stderr, s->cfg.error_color,
 						 _("ignoring unmerged: %s"),
 						 files->items.items[i].string);
 				free(item);
@@ -1015,10 +912,10 @@ static int run_patch(struct add_i_state *s, const struct pathspec *ps,
 	opts->prompt = N_("Patch update");
 	count = list_and_choose(s, files, opts);
 	if (count > 0) {
-		struct add_p_opt add_p_opt = {
-			.context = s->context,
-			.interhunkcontext = s->interhunkcontext,
-			.auto_advance = s->auto_advance
+		struct interactive_options opts = {
+			.context = s->cfg.context,
+			.interhunkcontext = s->cfg.interhunkcontext,
+			.auto_advance = s->cfg.auto_advance,
 		};
 		struct strvec args = STRVEC_INIT;
 		struct pathspec ps_selected = { 0 };
@@ -1030,7 +927,7 @@ static int run_patch(struct add_i_state *s, const struct pathspec *ps,
 		parse_pathspec(&ps_selected,
 			       PATHSPEC_ALL_MAGIC & ~PATHSPEC_LITERAL,
 			       PATHSPEC_LITERAL_PATH, "", args.v);
-		res = run_add_p(s->r, ADD_P_ADD, &add_p_opt, NULL, &ps_selected);
+		res = run_add_p(s->r, ADD_P_ADD, &opts, NULL, &ps_selected, 0);
 		strvec_clear(&args);
 		clear_pathspec(&ps_selected);
 	}
@@ -1066,10 +963,10 @@ static int run_diff(struct add_i_state *s, const struct pathspec *ps,
 		struct child_process cmd = CHILD_PROCESS_INIT;
 
 		strvec_pushl(&cmd.args, "git", "diff", "-p", "--cached", NULL);
-		if (s->context != -1)
-			strvec_pushf(&cmd.args, "--unified=%i", s->context);
-		if (s->interhunkcontext != -1)
-			strvec_pushf(&cmd.args, "--inter-hunk-context=%i", s->interhunkcontext);
+		if (s->cfg.context != -1)
+			strvec_pushf(&cmd.args, "--unified=%i", s->cfg.context);
+		if (s->cfg.interhunkcontext != -1)
+			strvec_pushf(&cmd.args, "--inter-hunk-context=%i", s->cfg.interhunkcontext);
 		strvec_pushl(&cmd.args, oid_to_hex(!is_initial ? &oid :
 			     s->r->hash_algo->empty_tree), "--", NULL);
 		for (i = 0; i < files->items.nr; i++)
@@ -1087,17 +984,17 @@ static int run_help(struct add_i_state *s, const struct pathspec *ps UNUSED,
 		    struct prefix_item_list *files UNUSED,
 		    struct list_and_choose_options *opts UNUSED)
 {
-	color_fprintf_ln(stdout, s->help_color, "status        - %s",
+	color_fprintf_ln(stdout, s->cfg.help_color, "status        - %s",
 			 _("show paths with changes"));
-	color_fprintf_ln(stdout, s->help_color, "update        - %s",
+	color_fprintf_ln(stdout, s->cfg.help_color, "update        - %s",
 			 _("add working tree state to the staged set of changes"));
-	color_fprintf_ln(stdout, s->help_color, "revert        - %s",
+	color_fprintf_ln(stdout, s->cfg.help_color, "revert        - %s",
 			 _("revert staged set of changes back to the HEAD version"));
-	color_fprintf_ln(stdout, s->help_color, "patch         - %s",
+	color_fprintf_ln(stdout, s->cfg.help_color, "patch         - %s",
 			 _("pick hunks and update selectively"));
-	color_fprintf_ln(stdout, s->help_color, "diff          - %s",
+	color_fprintf_ln(stdout, s->cfg.help_color, "diff          - %s",
 			 _("view diff between HEAD and index"));
-	color_fprintf_ln(stdout, s->help_color, "add untracked - %s",
+	color_fprintf_ln(stdout, s->cfg.help_color, "add untracked - %s",
 			 _("add contents of untracked files to the staged set of changes"));
 
 	return 0;
@@ -1105,21 +1002,21 @@ static int run_help(struct add_i_state *s, const struct pathspec *ps UNUSED,
 
 static void choose_prompt_help(struct add_i_state *s)
 {
-	color_fprintf_ln(stdout, s->help_color, "%s",
+	color_fprintf_ln(stdout, s->cfg.help_color, "%s",
 			 _("Prompt help:"));
-	color_fprintf_ln(stdout, s->help_color, "1          - %s",
+	color_fprintf_ln(stdout, s->cfg.help_color, "1          - %s",
 			 _("select a single item"));
-	color_fprintf_ln(stdout, s->help_color, "3-5        - %s",
+	color_fprintf_ln(stdout, s->cfg.help_color, "3-5        - %s",
 			 _("select a range of items"));
-	color_fprintf_ln(stdout, s->help_color, "2-3,6-9    - %s",
+	color_fprintf_ln(stdout, s->cfg.help_color, "2-3,6-9    - %s",
 			 _("select multiple ranges"));
-	color_fprintf_ln(stdout, s->help_color, "foo        - %s",
+	color_fprintf_ln(stdout, s->cfg.help_color, "foo        - %s",
 			 _("select item based on unique prefix"));
-	color_fprintf_ln(stdout, s->help_color, "-...       - %s",
+	color_fprintf_ln(stdout, s->cfg.help_color, "-...       - %s",
 			 _("unselect specified items"));
-	color_fprintf_ln(stdout, s->help_color, "*          - %s",
+	color_fprintf_ln(stdout, s->cfg.help_color, "*          - %s",
 			 _("choose all items"));
-	color_fprintf_ln(stdout, s->help_color, "           - %s",
+	color_fprintf_ln(stdout, s->cfg.help_color, "           - %s",
 			 _("(empty) finish selecting"));
 }
 
@@ -1154,7 +1051,7 @@ static void print_command_item(int i, int selected UNUSED,
 
 static void command_prompt_help(struct add_i_state *s)
 {
-	const char *help_color = s->help_color;
+	const char *help_color = s->cfg.help_color;
 	color_fprintf_ln(stdout, help_color, "%s", _("Prompt help:"));
 	color_fprintf_ln(stdout, help_color, "1          - %s",
 			 _("select a numbered item"));
@@ -1165,7 +1062,7 @@ static void command_prompt_help(struct add_i_state *s)
 }
 
 int run_add_i(struct repository *r, const struct pathspec *ps,
-	      struct add_p_opt *add_p_opt)
+	      struct interactive_options *interactive_opts)
 {
 	struct add_i_state s = { NULL };
 	struct print_command_item_data data = { "[", "]" };
@@ -1208,15 +1105,15 @@ int run_add_i(struct repository *r, const struct pathspec *ps,
 			->util = util;
 	}
 
-	init_add_i_state(&s, r, add_p_opt);
+	init_add_i_state(&s, r, interactive_opts);
 
 	/*
 	 * When color was asked for, use the prompt color for
 	 * highlighting, otherwise use square brackets.
 	 */
-	if (want_color(s.use_color_interactive)) {
-		data.color = s.prompt_color;
-		data.reset = s.reset_color_interactive;
+	if (want_color(s.cfg.use_color_interactive)) {
+		data.color = s.cfg.prompt_color;
+		data.reset = s.cfg.reset_color_interactive;
 	}
 	print_file_item_data.color = data.color;
 	print_file_item_data.reset = data.reset;
diff --git a/add-interactive.h b/add-interactive.h
index 7843397..eefa2ed 100644
--- a/add-interactive.h
+++ b/add-interactive.h
@@ -1,57 +1,21 @@
 #ifndef ADD_INTERACTIVE_H
 #define ADD_INTERACTIVE_H
 
-#include "color.h"
+#include "add-patch.h"
 
-struct add_p_opt {
-	int context;
-	int interhunkcontext;
-	int auto_advance;
-};
-
-#define ADD_P_OPT_INIT { .context = -1, .interhunkcontext = -1, .auto_advance = 1 }
+struct pathspec;
+struct repository;
 
 struct add_i_state {
 	struct repository *r;
-	enum git_colorbool use_color_interactive;
-	enum git_colorbool use_color_diff;
-	char header_color[COLOR_MAXLEN];
-	char help_color[COLOR_MAXLEN];
-	char prompt_color[COLOR_MAXLEN];
-	char error_color[COLOR_MAXLEN];
-	char reset_color_interactive[COLOR_MAXLEN];
-
-	char fraginfo_color[COLOR_MAXLEN];
-	char context_color[COLOR_MAXLEN];
-	char file_old_color[COLOR_MAXLEN];
-	char file_new_color[COLOR_MAXLEN];
-	char reset_color_diff[COLOR_MAXLEN];
-
-	int use_single_key;
-	char *interactive_diff_filter, *interactive_diff_algorithm;
-	int context, interhunkcontext;
-	int auto_advance;
+	struct interactive_config cfg;
 };
 
 void init_add_i_state(struct add_i_state *s, struct repository *r,
-		      struct add_p_opt *add_p_opt);
+		      struct interactive_options *opts);
 void clear_add_i_state(struct add_i_state *s);
 
-struct repository;
-struct pathspec;
 int run_add_i(struct repository *r, const struct pathspec *ps,
-	      struct add_p_opt *add_p_opt);
-
-enum add_p_mode {
-	ADD_P_ADD,
-	ADD_P_STASH,
-	ADD_P_RESET,
-	ADD_P_CHECKOUT,
-	ADD_P_WORKTREE,
-};
-
-int run_add_p(struct repository *r, enum add_p_mode mode,
-	      struct add_p_opt *o, const char *revision,
-	      const struct pathspec *ps);
+	      struct interactive_options *opts);
 
 #endif
diff --git a/add-patch.c b/add-patch.c
index 8c03f71..4e28e5c 100644
--- a/add-patch.c
+++ b/add-patch.c
@@ -2,11 +2,15 @@
 #define DISABLE_SIGN_COMPARE_WARNINGS
 
 #include "git-compat-util.h"
-#include "add-interactive.h"
+#include "add-patch.h"
 #include "advice.h"
+#include "commit.h"
+#include "config.h"
+#include "diff.h"
 #include "editor.h"
 #include "environment.h"
 #include "gettext.h"
+#include "hex.h"
 #include "object-name.h"
 #include "pager.h"
 #include "read-cache-ll.h"
@@ -260,7 +264,10 @@ struct hunk {
 };
 
 struct add_p_state {
-	struct add_i_state s;
+	struct repository *r;
+	struct index_state *index;
+	const char *index_file;
+	struct interactive_config cfg;
 	struct strbuf answer, buf;
 
 	/* parsed diff */
@@ -278,6 +285,123 @@ struct add_p_state {
 	const char *revision;
 };
 
+static void init_color(struct repository *r,
+		       enum git_colorbool use_color,
+		       const char *section_and_slot, char *dst,
+		       const char *default_color)
+{
+	char *key = xstrfmt("color.%s", section_and_slot);
+	const char *value;
+
+	if (!want_color(use_color))
+		dst[0] = '\0';
+	else if (repo_config_get_value(r, key, &value) ||
+		 color_parse(value, dst))
+		strlcpy(dst, default_color, COLOR_MAXLEN);
+
+	free(key);
+}
+
+static enum git_colorbool check_color_config(struct repository *r, const char *var)
+{
+	const char *value;
+	enum git_colorbool ret;
+
+	if (repo_config_get_value(r, var, &value))
+		ret = GIT_COLOR_UNKNOWN;
+	else
+		ret = git_config_colorbool(var, value);
+
+	/*
+	 * Do not rely on want_color() to fall back to color.ui for us. It uses
+	 * the value parsed by git_color_config(), which may not have been
+	 * called by the main command.
+	 */
+	if (ret == GIT_COLOR_UNKNOWN &&
+	    !repo_config_get_value(r, "color.ui", &value))
+		ret = git_config_colorbool("color.ui", value);
+
+	return ret;
+}
+
+void interactive_config_init(struct interactive_config *cfg,
+			     struct repository *r,
+			     struct interactive_options *opts)
+{
+	cfg->context = -1;
+	cfg->interhunkcontext = -1;
+	cfg->auto_advance = opts->auto_advance;
+
+	cfg->use_color_interactive = check_color_config(r, "color.interactive");
+
+	init_color(r, cfg->use_color_interactive, "interactive.header",
+		   cfg->header_color, GIT_COLOR_BOLD);
+	init_color(r, cfg->use_color_interactive, "interactive.help",
+		   cfg->help_color, GIT_COLOR_BOLD_RED);
+	init_color(r, cfg->use_color_interactive, "interactive.prompt",
+		   cfg->prompt_color, GIT_COLOR_BOLD_BLUE);
+	init_color(r, cfg->use_color_interactive, "interactive.error",
+		   cfg->error_color, GIT_COLOR_BOLD_RED);
+	strlcpy(cfg->reset_color_interactive,
+		want_color(cfg->use_color_interactive) ? GIT_COLOR_RESET : "", COLOR_MAXLEN);
+
+	cfg->use_color_diff = check_color_config(r, "color.diff");
+
+	init_color(r, cfg->use_color_diff, "diff.frag", cfg->fraginfo_color,
+		   diff_get_color(cfg->use_color_diff, DIFF_FRAGINFO));
+	init_color(r, cfg->use_color_diff, "diff.context", cfg->context_color,
+		   "fall back");
+	if (!strcmp(cfg->context_color, "fall back"))
+		init_color(r, cfg->use_color_diff, "diff.plain",
+			   cfg->context_color,
+			   diff_get_color(cfg->use_color_diff, DIFF_CONTEXT));
+	init_color(r, cfg->use_color_diff, "diff.old", cfg->file_old_color,
+		diff_get_color(cfg->use_color_diff, DIFF_FILE_OLD));
+	init_color(r, cfg->use_color_diff, "diff.new", cfg->file_new_color,
+		diff_get_color(cfg->use_color_diff, DIFF_FILE_NEW));
+	strlcpy(cfg->reset_color_diff,
+		want_color(cfg->use_color_diff) ? GIT_COLOR_RESET : "", COLOR_MAXLEN);
+
+	FREE_AND_NULL(cfg->interactive_diff_filter);
+	repo_config_get_string(r, "interactive.difffilter",
+			       &cfg->interactive_diff_filter);
+
+	FREE_AND_NULL(cfg->interactive_diff_algorithm);
+	repo_config_get_string(r, "diff.algorithm",
+			       &cfg->interactive_diff_algorithm);
+
+	if (!repo_config_get_int(r, "diff.context", &cfg->context))
+		if (cfg->context < 0)
+			die(_("%s cannot be negative"), "diff.context");
+	if (!repo_config_get_int(r, "diff.interHunkContext", &cfg->interhunkcontext))
+		if (cfg->interhunkcontext < 0)
+			die(_("%s cannot be negative"), "diff.interHunkContext");
+
+	repo_config_get_bool(r, "interactive.singlekey", &cfg->use_single_key);
+	if (cfg->use_single_key)
+		setbuf(stdin, NULL);
+
+	if (opts->context != -1) {
+		if (opts->context < 0)
+			die(_("%s cannot be negative"), "--unified");
+		cfg->context = opts->context;
+	}
+	if (opts->interhunkcontext != -1) {
+		if (opts->interhunkcontext < 0)
+			die(_("%s cannot be negative"), "--inter-hunk-context");
+		cfg->interhunkcontext = opts->interhunkcontext;
+	}
+}
+
+void interactive_config_clear(struct interactive_config *cfg)
+{
+	FREE_AND_NULL(cfg->interactive_diff_filter);
+	FREE_AND_NULL(cfg->interactive_diff_algorithm);
+	memset(cfg, 0, sizeof(*cfg));
+	cfg->use_color_interactive = GIT_COLOR_UNKNOWN;
+	cfg->use_color_diff = GIT_COLOR_UNKNOWN;
+}
+
 static void add_p_state_clear(struct add_p_state *s)
 {
 	size_t i;
@@ -289,7 +413,7 @@ static void add_p_state_clear(struct add_p_state *s)
 	for (i = 0; i < s->file_diff_nr; i++)
 		free(s->file_diff[i].hunk);
 	free(s->file_diff);
-	clear_add_i_state(&s->s);
+	interactive_config_clear(&s->cfg);
 }
 
 __attribute__((format (printf, 2, 3)))
@@ -298,9 +422,9 @@ static void err(struct add_p_state *s, const char *fmt, ...)
 	va_list args;
 
 	va_start(args, fmt);
-	fputs(s->s.error_color, stdout);
+	fputs(s->cfg.error_color, stdout);
 	vprintf(fmt, args);
-	puts(s->s.reset_color_interactive);
+	puts(s->cfg.reset_color_interactive);
 	va_end(args);
 }
 
@@ -318,7 +442,7 @@ static void setup_child_process(struct add_p_state *s,
 
 	cp->git_cmd = 1;
 	strvec_pushf(&cp->env,
-		     INDEX_ENVIRONMENT "=%s", s->s.r->index_file);
+		     INDEX_ENVIRONMENT "=%s", s->index_file);
 }
 
 static int parse_range(const char **p,
@@ -423,12 +547,12 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
 	int res;
 
 	strvec_pushv(&args, s->mode->diff_cmd);
-	if (s->s.context != -1)
-		strvec_pushf(&args, "--unified=%i", s->s.context);
-	if (s->s.interhunkcontext != -1)
-		strvec_pushf(&args, "--inter-hunk-context=%i", s->s.interhunkcontext);
-	if (s->s.interactive_diff_algorithm)
-		strvec_pushf(&args, "--diff-algorithm=%s", s->s.interactive_diff_algorithm);
+	if (s->cfg.context != -1)
+		strvec_pushf(&args, "--unified=%i", s->cfg.context);
+	if (s->cfg.interhunkcontext != -1)
+		strvec_pushf(&args, "--inter-hunk-context=%i", s->cfg.interhunkcontext);
+	if (s->cfg.interactive_diff_algorithm)
+		strvec_pushf(&args, "--diff-algorithm=%s", s->cfg.interactive_diff_algorithm);
 	if (s->revision) {
 		struct object_id oid;
 		strvec_push(&args,
@@ -457,9 +581,9 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
 	}
 	strbuf_complete_line(plain);
 
-	if (want_color_fd(1, s->s.use_color_diff)) {
+	if (want_color_fd(1, s->cfg.use_color_diff)) {
 		struct child_process colored_cp = CHILD_PROCESS_INIT;
-		const char *diff_filter = s->s.interactive_diff_filter;
+		const char *diff_filter = s->cfg.interactive_diff_filter;
 
 		setup_child_process(s, &colored_cp, NULL);
 		xsnprintf((char *)args.v[color_arg_index], 8, "--color");
@@ -692,7 +816,7 @@ static void render_hunk(struct add_p_state *s, struct hunk *hunk,
 				   hunk->colored_end - hunk->colored_start);
 			return;
 		} else {
-			strbuf_addstr(out, s->s.fraginfo_color);
+			strbuf_addstr(out, s->cfg.fraginfo_color);
 			p = s->colored.buf + header->colored_extra_start;
 			len = header->colored_extra_end
 				- header->colored_extra_start;
@@ -714,7 +838,7 @@ static void render_hunk(struct add_p_state *s, struct hunk *hunk,
 		if (len)
 			strbuf_add(out, p, len);
 		else if (colored)
-			strbuf_addf(out, "%s\n", s->s.reset_color_diff);
+			strbuf_addf(out, "%s\n", s->cfg.reset_color_diff);
 		else
 			strbuf_addch(out, '\n');
 	}
@@ -1103,12 +1227,12 @@ static void recolor_hunk(struct add_p_state *s, struct hunk *hunk)
 
 		strbuf_addstr(&s->colored,
 			      plain[current] == '-' ?
-			      s->s.file_old_color :
+			      s->cfg.file_old_color :
 			      plain[current] == '+' ?
-			      s->s.file_new_color :
-			      s->s.context_color);
+			      s->cfg.file_new_color :
+			      s->cfg.context_color);
 		strbuf_add(&s->colored, plain + current, eol - current);
-		strbuf_addstr(&s->colored, s->s.reset_color_diff);
+		strbuf_addstr(&s->colored, s->cfg.reset_color_diff);
 		if (next > eol)
 			strbuf_add(&s->colored, plain + eol, next - eol);
 		current = next;
@@ -1237,7 +1361,7 @@ static int run_apply_check(struct add_p_state *s,
 
 static int read_single_character(struct add_p_state *s)
 {
-	if (s->s.use_single_key) {
+	if (s->cfg.use_single_key) {
 		int res = read_key_without_echo(&s->answer);
 		printf("%s\n", res == EOF ? "" : s->answer.buf);
 		return res;
@@ -1251,7 +1375,7 @@ static int read_single_character(struct add_p_state *s)
 static int prompt_yesno(struct add_p_state *s, const char *prompt)
 {
 	for (;;) {
-		color_fprintf(stdout, s->s.prompt_color, "%s", _(prompt));
+		color_fprintf(stdout, s->cfg.prompt_color, "%s", _(prompt));
 		fflush(stdout);
 		if (read_single_character(s) == EOF)
 			return -1;
@@ -1439,7 +1563,7 @@ static void apply_patch(struct add_p_state *s, struct file_diff *file_diff)
 		strbuf_reset(&s->buf);
 		reassemble_patch(s, file_diff, 0, &s->buf);
 
-		discard_index(s->s.r->index);
+		discard_index(s->index);
 		if (s->mode->apply_for_checkout)
 			apply_for_checkout(s, &s->buf,
 					s->mode->is_reverse);
@@ -1450,9 +1574,11 @@ static void apply_patch(struct add_p_state *s, struct file_diff *file_diff)
 					NULL, 0, NULL, 0))
 				error(_("'git apply' failed"));
 		}
-		if (repo_read_index(s->s.r) >= 0)
-			repo_refresh_and_write_index(s->s.r, REFRESH_QUIET, 0,
-							1, NULL, NULL, NULL);
+		if (read_index_from(s->index, s->index_file, s->r->gitdir) >= 0 &&
+		    s->index == s->r->index) {
+			repo_refresh_and_write_index(s->r, REFRESH_QUIET, 0,
+						     1, NULL, NULL, NULL);
+		}
 	}
 
 }
@@ -1478,7 +1604,9 @@ static bool get_first_undecided(const struct file_diff *file_diff, size_t *idx)
 	return false;
 }
 
-static size_t patch_update_file(struct add_p_state *s, size_t idx)
+static size_t patch_update_file(struct add_p_state *s,
+				size_t idx,
+				unsigned flags)
 {
 	size_t hunk_index = 0;
 	ssize_t i, undecided_previous, undecided_next, rendered_hunk_index = -1;
@@ -1540,7 +1668,7 @@ static size_t patch_update_file(struct add_p_state *s, size_t idx)
 		/* Everything decided? */
 		if (undecided_previous < 0 && undecided_next < 0 &&
 		    hunk->use != UNDECIDED_HUNK) {
-				if (!s->s.auto_advance)
+				if (!s->cfg.auto_advance)
 					all_decided = 1;
 				else {
 					patch_update_resp++;
@@ -1589,16 +1717,17 @@ static size_t patch_update_file(struct add_p_state *s, size_t idx)
 				permitted |= ALLOW_SPLIT;
 				strbuf_addstr(&s->buf, ",s");
 			}
-			if (hunk_index + 1 > file_diff->mode_change &&
+			if (!(flags & ADD_P_DISALLOW_EDIT) &&
+			    hunk_index + 1 > file_diff->mode_change &&
 			    !file_diff->deleted) {
 				permitted |= ALLOW_EDIT;
 				strbuf_addstr(&s->buf, ",e");
 			}
-			if (!s->s.auto_advance && s->file_diff_nr > 1) {
+			if (!s->cfg.auto_advance && s->file_diff_nr > 1) {
 				permitted |= ALLOW_GOTO_NEXT_FILE;
 				strbuf_addstr(&s->buf, ",>");
 			}
-			if (!s->s.auto_advance && s->file_diff_nr > 1) {
+			if (!s->cfg.auto_advance && s->file_diff_nr > 1) {
 				permitted |= ALLOW_GOTO_PREVIOUS_FILE;
 				strbuf_addstr(&s->buf, ",<");
 			}
@@ -1613,7 +1742,7 @@ static size_t patch_update_file(struct add_p_state *s, size_t idx)
 		else
 			prompt_mode_type = PROMPT_HUNK;
 
-		printf("%s(%"PRIuMAX"/%"PRIuMAX") ", s->s.prompt_color,
+		printf("%s(%"PRIuMAX"/%"PRIuMAX") ", s->cfg.prompt_color,
 			      (uintmax_t)hunk_index + 1,
 			      (uintmax_t)(file_diff->hunk_nr
 						? file_diff->hunk_nr
@@ -1626,8 +1755,8 @@ static size_t patch_update_file(struct add_p_state *s, size_t idx)
 		}
 		printf(_(s->mode->prompt_mode[prompt_mode_type]),
 			hunk_use_decision, s->buf.buf);
-		if (*s->s.reset_color_interactive)
-			fputs(s->s.reset_color_interactive, stdout);
+		if (*s->cfg.reset_color_interactive)
+			fputs(s->cfg.reset_color_interactive, stdout);
 		fflush(stdout);
 		if (read_single_character(s) == EOF) {
 			patch_update_resp = s->file_diff_nr;
@@ -1678,7 +1807,7 @@ static size_t patch_update_file(struct add_p_state *s, size_t idx)
 		} else if (ch == 'q') {
 			patch_update_resp = s->file_diff_nr;
 			break;
-		} else if (!s->s.auto_advance && s->answer.buf[0] == '>') {
+		} else if (!s->cfg.auto_advance && s->answer.buf[0] == '>') {
 			if (permitted & ALLOW_GOTO_NEXT_FILE) {
 				if (patch_update_resp == s->file_diff_nr - 1)
 					patch_update_resp = 0;
@@ -1689,7 +1818,7 @@ static size_t patch_update_file(struct add_p_state *s, size_t idx)
 				err(s, _("No next file"));
 				continue;
 			}
-		} else if (!s->s.auto_advance && s->answer.buf[0] == '<') {
+		} else if (!s->cfg.auto_advance && s->answer.buf[0] == '<') {
 			if (permitted & ALLOW_GOTO_PREVIOUS_FILE) {
 				if (patch_update_resp == 0)
 					patch_update_resp = s->file_diff_nr - 1;
@@ -1812,7 +1941,7 @@ static size_t patch_update_file(struct add_p_state *s, size_t idx)
 				err(s, _("Sorry, cannot split this hunk"));
 			} else if (!split_hunk(s, file_diff,
 					     hunk - file_diff->hunk)) {
-				color_fprintf_ln(stdout, s->s.header_color,
+				color_fprintf_ln(stdout, s->cfg.header_color,
 						 _("Split into %d hunks."),
 						 (int)splittable_into);
 				rendered_hunk_index = -1;
@@ -1830,7 +1959,7 @@ static size_t patch_update_file(struct add_p_state *s, size_t idx)
 		} else if (s->answer.buf[0] == '?') {
 			const char *p = _(help_patch_remainder), *eol = p;
 
-			color_fprintf(stdout, s->s.help_color, "%s",
+			color_fprintf(stdout, s->cfg.help_color, "%s",
 				      _(s->mode->help_patch_text));
 
 			/*
@@ -1854,13 +1983,13 @@ static size_t patch_update_file(struct add_p_state *s, size_t idx)
 						if (file_diff->hunk[i].use == SKIP_HUNK)
 							skipped += 1;
 					}
-					color_fprintf_ln(stdout, s->s.help_color, _(p),
+					color_fprintf_ln(stdout, s->cfg.help_color, _(p),
 							 total, used, skipped);
 				}
 				if (*p != '?' && !strchr(s->buf.buf, *p))
 					continue;
 
-				color_fprintf_ln(stdout, s->s.help_color,
+				color_fprintf_ln(stdout, s->cfg.help_color,
 						 "%.*s", (int)(eol - p), p);
 			}
 		} else {
@@ -1869,23 +1998,62 @@ static size_t patch_update_file(struct add_p_state *s, size_t idx)
 		}
 	}
 
-	if (s->s.auto_advance)
+	if (s->cfg.auto_advance)
 		apply_patch(s, file_diff);
 
 	putchar('\n');
 	return patch_update_resp;
 }
 
+static int run_add_p_common(struct add_p_state *state,
+			    const struct pathspec *ps,
+			    unsigned flags)
+{
+	size_t binary_count = 0;
+	size_t i;
+
+	if (parse_diff(state, ps) < 0)
+		return -1;
+
+	for (i = 0; i < state->file_diff_nr;) {
+		if (state->file_diff[i].binary && !state->file_diff[i].hunk_nr) {
+			binary_count++;
+			i++;
+			continue;
+		}
+		if ((i = patch_update_file(state, i, flags)) == state->file_diff_nr)
+			break;
+	}
+
+	if (!state->cfg.auto_advance)
+		for (i = 0; i < state->file_diff_nr; i++)
+			apply_patch(state, state->file_diff + i);
+
+	if (state->file_diff_nr == 0)
+		err(state, _("No changes."));
+	else if (binary_count == state->file_diff_nr)
+		err(state, _("Only binary files changed."));
+
+	return 0;
+}
+
 int run_add_p(struct repository *r, enum add_p_mode mode,
-	      struct add_p_opt *o, const char *revision,
-	      const struct pathspec *ps)
+	      struct interactive_options *opts, const char *revision,
+	      const struct pathspec *ps,
+	      unsigned flags)
 {
 	struct add_p_state s = {
-		{ r }, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT
+		.r = r,
+		.index = r->index,
+		.index_file = r->index_file,
+		.answer = STRBUF_INIT,
+		.buf = STRBUF_INIT,
+		.plain = STRBUF_INIT,
+		.colored = STRBUF_INIT,
 	};
-	size_t i, binary_count = 0;
+	int ret;
 
-	init_add_i_state(&s.s, r, o);
+	interactive_config_init(&s.cfg, r, opts);
 
 	if (mode == ADD_P_STASH)
 		s.mode = &patch_mode_stash;
@@ -1916,30 +2084,91 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
 	if (repo_read_index(r) < 0 ||
 	    (!s.mode->index_only &&
 	     repo_refresh_and_write_index(r, REFRESH_QUIET, 0, 1,
-					  NULL, NULL, NULL) < 0) ||
-	    parse_diff(&s, ps) < 0) {
-		add_p_state_clear(&s);
-		return -1;
+					  NULL, NULL, NULL) < 0)) {
+		ret = -1;
+		goto out;
 	}
 
-	for (i = 0; i < s.file_diff_nr;) {
-		if (s.file_diff[i].binary && !s.file_diff[i].hunk_nr) {
-			binary_count++;
-			i++;
-			continue;
-		}
-		 if ((i = patch_update_file(&s, i)) == s.file_diff_nr)
-			break;
-    }
-	if (!s.s.auto_advance)
-		for (i = 0; i < s.file_diff_nr; i++)
-			apply_patch(&s, s.file_diff + i);
+	ret = run_add_p_common(&s, ps, flags);
+	if (ret < 0)
+		goto out;
 
-	if (s.file_diff_nr == 0)
-		err(&s, _("No changes."));
-	else if (binary_count == s.file_diff_nr)
-		err(&s, _("Only binary files changed."));
+	ret = 0;
 
+out:
 	add_p_state_clear(&s);
-	return 0;
+	return ret;
+}
+
+int run_add_p_index(struct repository *r,
+		    struct index_state *index,
+		    const char *index_file,
+		    struct interactive_options *opts,
+		    const char *revision,
+		    const struct pathspec *ps,
+		    unsigned flags)
+{
+	struct patch_mode mode = {
+		.apply_args = { "--cached", NULL },
+		.apply_check_args = { "--cached", NULL },
+		.prompt_mode = {
+			N_("Stage mode change [y,n,q,a,d%s,?]? "),
+			N_("Stage deletion [y,n,q,a,d%s,?]? "),
+			N_("Stage addition [y,n,q,a,d%s,?]? "),
+			N_("Stage this hunk [y,n,q,a,d%s,?]? ")
+		},
+		.edit_hunk_hint = N_("If the patch applies cleanly, the edited hunk "
+				     "will immediately be marked for staging."),
+		.help_patch_text =
+			N_("y - stage this hunk\n"
+			   "n - do not stage this hunk\n"
+			   "q - quit; do not stage this hunk or any of the remaining "
+				"ones\n"
+			   "a - stage this hunk and all later hunks in the file\n"
+			   "d - do not stage this hunk or any of the later hunks in "
+				"the file\n"),
+		.index_only = 1,
+	};
+	struct add_p_state s = {
+		.r = r,
+		.index = index,
+		.index_file = index_file,
+		.answer = STRBUF_INIT,
+		.buf = STRBUF_INIT,
+		.plain = STRBUF_INIT,
+		.colored = STRBUF_INIT,
+		.mode = &mode,
+		.revision = revision,
+	};
+	char parent_tree_oid[GIT_MAX_HEXSZ + 1];
+	struct commit *commit;
+	int ret;
+
+	interactive_config_init(&s.cfg, r, opts);
+
+	commit = lookup_commit_reference_by_name(revision);
+	if (!commit) {
+		err(&s, _("Revision does not refer to a commit"));
+		ret = -1;
+		goto out;
+	}
+
+	if (commit->parents)
+		oid_to_hex_r(parent_tree_oid, get_commit_tree_oid(commit->parents->item));
+	else
+		oid_to_hex_r(parent_tree_oid, r->hash_algo->empty_tree);
+
+	mode.diff_cmd[0] = "diff-tree";
+	mode.diff_cmd[1] = "-r";
+	mode.diff_cmd[2] = parent_tree_oid;
+
+	ret = run_add_p_common(&s, ps, flags);
+	if (ret < 0)
+		goto out;
+
+	ret = 0;
+
+out:
+	add_p_state_clear(&s);
+	return ret;
 }
diff --git a/add-patch.h b/add-patch.h
new file mode 100644
index 0000000..fb6d975
--- /dev/null
+++ b/add-patch.h
@@ -0,0 +1,74 @@
+#ifndef ADD_PATCH_H
+#define ADD_PATCH_H
+
+#include "color.h"
+
+struct index_state;
+struct pathspec;
+struct repository;
+
+struct interactive_options {
+	int context;
+	int interhunkcontext;
+	int auto_advance;
+};
+
+#define INTERACTIVE_OPTIONS_INIT { \
+	.context = -1, \
+	.interhunkcontext = -1, \
+	.auto_advance = 1, \
+}
+
+struct interactive_config {
+	enum git_colorbool use_color_interactive;
+	enum git_colorbool use_color_diff;
+	char header_color[COLOR_MAXLEN];
+	char help_color[COLOR_MAXLEN];
+	char prompt_color[COLOR_MAXLEN];
+	char error_color[COLOR_MAXLEN];
+	char reset_color_interactive[COLOR_MAXLEN];
+
+	char fraginfo_color[COLOR_MAXLEN];
+	char context_color[COLOR_MAXLEN];
+	char file_old_color[COLOR_MAXLEN];
+	char file_new_color[COLOR_MAXLEN];
+	char reset_color_diff[COLOR_MAXLEN];
+
+	int use_single_key;
+	char *interactive_diff_filter, *interactive_diff_algorithm;
+	int context, interhunkcontext;
+	int auto_advance;
+};
+
+void interactive_config_init(struct interactive_config *cfg,
+			     struct repository *r,
+			     struct interactive_options *opts);
+void interactive_config_clear(struct interactive_config *cfg);
+
+enum add_p_mode {
+	ADD_P_ADD,
+	ADD_P_STASH,
+	ADD_P_RESET,
+	ADD_P_CHECKOUT,
+	ADD_P_WORKTREE,
+};
+
+enum add_p_flags {
+	/* Disallow "editing" hunks. */
+	ADD_P_DISALLOW_EDIT = (1 << 0),
+};
+
+int run_add_p(struct repository *r, enum add_p_mode mode,
+	      struct interactive_options *opts, const char *revision,
+	      const struct pathspec *ps,
+	      unsigned flags);
+
+int run_add_p_index(struct repository *r,
+		    struct index_state *index,
+		    const char *index_file,
+		    struct interactive_options *opts,
+		    const char *revision,
+		    const struct pathspec *ps,
+		    unsigned flags);
+
+#endif
diff --git a/apply.c b/apply.c
index b6dd106..63d5e3c 100644
--- a/apply.c
+++ b/apply.c
@@ -42,6 +42,7 @@
 
 struct gitdiff_data {
 	struct strbuf *root;
+	const char *patch_input_file;
 	int linenr;
 	int p_value;
 };
@@ -900,7 +901,8 @@ static int parse_traditional_patch(struct apply_state *state,
 		}
 	}
 	if (!name)
-		return error(_("unable to find filename in patch at line %d"), state->linenr);
+		return error(_("unable to find filename in patch at %s:%d"),
+			     state->patch_input_file, state->linenr);
 
 	return 0;
 }
@@ -937,20 +939,35 @@ static int gitdiff_verify_name(struct gitdiff_data *state,
 
 	if (*name) {
 		char *another;
-		if (isnull)
+		if (isnull) {
+			if (state->patch_input_file)
+				return error(_("git apply: bad git-diff - expected /dev/null, got %s at %s:%d"),
+					     *name, state->patch_input_file, state->linenr);
 			return error(_("git apply: bad git-diff - expected /dev/null, got %s on line %d"),
 				     *name, state->linenr);
+		}
 		another = find_name(state->root, line, NULL, state->p_value, TERM_TAB);
 		if (!another || strcmp(another, *name)) {
 			free(another);
+			if (state->patch_input_file)
+				return error((side == DIFF_NEW_NAME) ?
+					     _("git apply: bad git-diff - inconsistent new filename at %s:%d") :
+					     _("git apply: bad git-diff - inconsistent old filename at %s:%d"),
+					     state->patch_input_file, state->linenr);
 			return error((side == DIFF_NEW_NAME) ?
-			    _("git apply: bad git-diff - inconsistent new filename on line %d") :
-			    _("git apply: bad git-diff - inconsistent old filename on line %d"), state->linenr);
+				     _("git apply: bad git-diff - inconsistent new filename on line %d") :
+				     _("git apply: bad git-diff - inconsistent old filename on line %d"),
+				     state->linenr);
 		}
 		free(another);
 	} else {
-		if (!is_dev_null(line))
-			return error(_("git apply: bad git-diff - expected /dev/null on line %d"), state->linenr);
+		if (!is_dev_null(line)) {
+			if (state->patch_input_file)
+				return error(_("git apply: bad git-diff - expected /dev/null at %s:%d"),
+					     state->patch_input_file, state->linenr);
+			return error(_("git apply: bad git-diff - expected /dev/null on line %d"),
+				     state->linenr);
+		}
 	}
 
 	return 0;
@@ -974,12 +991,19 @@ static int gitdiff_newname(struct gitdiff_data *state,
 				   DIFF_NEW_NAME);
 }
 
-static int parse_mode_line(const char *line, int linenr, unsigned int *mode)
+static int parse_mode_line(const char *line,
+			   const char *patch_input_file,
+			   int linenr,
+			   unsigned int *mode)
 {
 	char *end;
 	*mode = strtoul(line, &end, 8);
-	if (end == line || !isspace(*end))
+	if (end == line || !isspace(*end)) {
+		if (patch_input_file)
+			return error(_("invalid mode at %s:%d: %s"),
+				     patch_input_file, linenr, line);
 		return error(_("invalid mode on line %d: %s"), linenr, line);
+	}
 	*mode = canon_mode(*mode);
 	return 0;
 }
@@ -988,14 +1012,16 @@ static int gitdiff_oldmode(struct gitdiff_data *state,
 			   const char *line,
 			   struct patch *patch)
 {
-	return parse_mode_line(line, state->linenr, &patch->old_mode);
+	return parse_mode_line(line, state->patch_input_file, state->linenr,
+			       &patch->old_mode);
 }
 
 static int gitdiff_newmode(struct gitdiff_data *state,
 			   const char *line,
 			   struct patch *patch)
 {
-	return parse_mode_line(line, state->linenr, &patch->new_mode);
+	return parse_mode_line(line, state->patch_input_file, state->linenr,
+			       &patch->new_mode);
 }
 
 static int gitdiff_delete(struct gitdiff_data *state,
@@ -1314,6 +1340,7 @@ static int check_header_line(int linenr, struct patch *patch)
 }
 
 int parse_git_diff_header(struct strbuf *root,
+			  const char *patch_input_file,
 			  int *linenr,
 			  int p_value,
 			  const char *line,
@@ -1345,6 +1372,7 @@ int parse_git_diff_header(struct strbuf *root,
 	size -= len;
 	(*linenr)++;
 	parse_hdr_state.root = root;
+	parse_hdr_state.patch_input_file = patch_input_file;
 	parse_hdr_state.linenr = *linenr;
 	parse_hdr_state.p_value = p_value;
 
@@ -1382,6 +1410,7 @@ int parse_git_diff_header(struct strbuf *root,
 			int res;
 			if (len < oplen || memcmp(p->str, line, oplen))
 				continue;
+			parse_hdr_state.linenr = *linenr;
 			res = p->fn(&parse_hdr_state, line + oplen, patch);
 			if (res < 0)
 				return -1;
@@ -1396,12 +1425,20 @@ int parse_git_diff_header(struct strbuf *root,
 done:
 	if (!patch->old_name && !patch->new_name) {
 		if (!patch->def_name) {
-			error(Q_("git diff header lacks filename information when removing "
-				 "%d leading pathname component (line %d)",
-				 "git diff header lacks filename information when removing "
-				 "%d leading pathname components (line %d)",
-				 parse_hdr_state.p_value),
-			      parse_hdr_state.p_value, *linenr);
+			if (patch_input_file)
+				error(Q_("git diff header lacks filename information when removing "
+					 "%d leading pathname component at %s:%d",
+					 "git diff header lacks filename information when removing "
+					 "%d leading pathname components at %s:%d",
+					 parse_hdr_state.p_value),
+				      parse_hdr_state.p_value, patch_input_file, *linenr);
+			else
+				error(Q_("git diff header lacks filename information when removing "
+					 "%d leading pathname component (line %d)",
+					 "git diff header lacks filename information when removing "
+					 "%d leading pathname components (line %d)",
+					 parse_hdr_state.p_value),
+				      parse_hdr_state.p_value, *linenr);
 			return -128;
 		}
 		patch->old_name = xstrdup(patch->def_name);
@@ -1409,8 +1446,12 @@ int parse_git_diff_header(struct strbuf *root,
 	}
 	if ((!patch->new_name && !patch->is_delete) ||
 	    (!patch->old_name && !patch->is_new)) {
-		error(_("git diff header lacks filename information "
-			"(line %d)"), *linenr);
+		if (patch_input_file)
+			error(_("git diff header lacks filename information at %s:%d"),
+			      patch_input_file, *linenr);
+		else
+			error(_("git diff header lacks filename information (line %d)"),
+			      *linenr);
 		return -128;
 	}
 	patch->is_toplevel_relative = 1;
@@ -1577,8 +1618,9 @@ static int find_header(struct apply_state *state,
 			struct fragment dummy;
 			if (parse_fragment_header(line, len, &dummy) < 0)
 				continue;
-			error(_("patch fragment without header at line %d: %.*s"),
-				     state->linenr, (int)len-1, line);
+			error(_("patch fragment without header at %s:%d: %.*s"),
+			      state->patch_input_file, state->linenr,
+			      (int)len-1, line);
 			return -128;
 		}
 
@@ -1590,7 +1632,9 @@ static int find_header(struct apply_state *state,
 		 * or mode change, so we handle that specially
 		 */
 		if (!memcmp("diff --git ", line, 11)) {
-			int git_hdr_len = parse_git_diff_header(&state->root, &state->linenr,
+			int git_hdr_len = parse_git_diff_header(&state->root,
+								state->patch_input_file,
+								&state->linenr,
 								state->p_value, line, len,
 								size, patch);
 			if (git_hdr_len < 0)
@@ -1875,7 +1919,8 @@ static int parse_single_patch(struct apply_state *state,
 		len = parse_fragment(state, line, size, patch, fragment);
 		if (len <= 0) {
 			free(fragment);
-			return error(_("corrupt patch at line %d"), state->linenr);
+			return error(_("corrupt patch at %s:%d"),
+				     state->patch_input_file, state->linenr);
 		}
 		fragment->patch = line;
 		fragment->size = len;
@@ -2065,8 +2110,8 @@ static struct fragment *parse_binary_hunk(struct apply_state *state,
  corrupt:
 	free(data);
 	*status_p = -1;
-	error(_("corrupt binary patch at line %d: %.*s"),
-	      state->linenr-1, llen-1, buffer);
+	error(_("corrupt binary patch at %s:%d: %.*s"),
+	      state->patch_input_file, state->linenr-1, llen-1, buffer);
 	return NULL;
 }
 
@@ -2102,7 +2147,8 @@ static int parse_binary(struct apply_state *state,
 	forward = parse_binary_hunk(state, &buffer, &size, &status, &used);
 	if (!forward && !status)
 		/* there has to be one hunk (forward hunk) */
-		return error(_("unrecognized binary patch at line %d"), state->linenr-1);
+		return error(_("unrecognized binary patch at %s:%d"),
+			     state->patch_input_file, state->linenr-1);
 	if (status)
 		/* otherwise we already gave an error message */
 		return status;
@@ -2264,7 +2310,8 @@ static int parse_chunk(struct apply_state *state, char *buffer, unsigned long si
 		 */
 		if ((state->apply || state->check) &&
 		    (!patch->is_binary && !metadata_changes(patch))) {
-			error(_("patch with only garbage at line %d"), state->linenr);
+			error(_("patch with only garbage at %s:%d"),
+			      state->patch_input_file, state->linenr);
 			return -128;
 		}
 	}
@@ -4825,6 +4872,7 @@ static int apply_patch(struct apply_state *state,
 	int flush_attributes = 0;
 
 	state->patch_input_file = filename;
+	state->linenr = 1;
 	if (read_patch_file(&buf, fd) < 0)
 		return -128;
 	offset = 0;
@@ -4981,7 +5029,8 @@ static int apply_option_parse_p(const struct option *opt,
 
 	BUG_ON_OPT_NEG(unset);
 
-	state->p_value = atoi(arg);
+	if (strtol_i(arg, 10, &state->p_value) < 0 || state->p_value < 0)
+		die(_("option -p expects a non-negative integer, got '%s'"), arg);
 	state->p_value_known = 1;
 	return 0;
 }
diff --git a/apply.h b/apply.h
index 90e887e..5f2f03d 100644
--- a/apply.h
+++ b/apply.h
@@ -167,6 +167,7 @@ int check_apply_state(struct apply_state *state, int force_apply);
  * Returns -1 on failure, the length of the parsed header otherwise.
  */
 int parse_git_diff_header(struct strbuf *root,
+			  const char *patch_input_file,
 			  int *linenr,
 			  int p_value,
 			  const char *line,
diff --git a/bloom.c b/bloom.c
index 77a6fdd..a805ac0 100644
--- a/bloom.c
+++ b/bloom.c
@@ -501,7 +501,7 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r,
 		struct hashmap_iter iter;
 
 		for (i = 0; i < diff_queued_diff.nr; i++) {
-			const char *path = diff_queued_diff.queue[i]->two->path;
+			char *path = diff_queued_diff.queue[i]->two->path;
 
 			/*
 			 * Add each leading directory of the changed file, i.e. for
@@ -523,7 +523,7 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r,
 					free(e);
 
 				if (!last_slash)
-					last_slash = (char*)path;
+					last_slash = path;
 				*last_slash = '\0';
 
 			} while (*path);
diff --git a/builtin/add.c b/builtin/add.c
index 0ee2169..7737ab8 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -31,7 +31,7 @@ static const char * const builtin_add_usage[] = {
 	NULL
 };
 static int patch_interactive, add_interactive, edit_interactive;
-static struct add_p_opt add_p_opt = ADD_P_OPT_INIT;
+static struct interactive_options interactive_opts = INTERACTIVE_OPTIONS_INIT;
 static int take_worktree_changes;
 static int add_renormalize;
 static int pathspec_file_nul;
@@ -160,7 +160,7 @@ static int refresh(struct repository *repo, int verbose, const struct pathspec *
 int interactive_add(struct repository *repo,
 		    const char **argv,
 		    const char *prefix,
-		    int patch, struct add_p_opt *add_p_opt)
+		    int patch, struct interactive_options *interactive_opts)
 {
 	struct pathspec pathspec;
 	int ret;
@@ -172,9 +172,9 @@ int interactive_add(struct repository *repo,
 		       prefix, argv);
 
 	if (patch)
-		ret = !!run_add_p(repo, ADD_P_ADD, add_p_opt, NULL, &pathspec);
+		ret = !!run_add_p(repo, ADD_P_ADD, interactive_opts, NULL, &pathspec, 0);
 	else
-		ret = !!run_add_i(repo, &pathspec, add_p_opt);
+		ret = !!run_add_i(repo, &pathspec, interactive_opts);
 
 	clear_pathspec(&pathspec);
 	return ret;
@@ -256,10 +256,10 @@ static struct option builtin_add_options[] = {
 	OPT_GROUP(""),
 	OPT_BOOL('i', "interactive", &add_interactive, N_("interactive picking")),
 	OPT_BOOL('p', "patch", &patch_interactive, N_("select hunks interactively")),
-	OPT_BOOL(0, "auto-advance", &add_p_opt.auto_advance,
+	OPT_BOOL(0, "auto-advance", &interactive_opts.auto_advance,
 		 N_("auto advance to the next file when selecting hunks interactively")),
-	OPT_DIFF_UNIFIED(&add_p_opt.context),
-	OPT_DIFF_INTERHUNK_CONTEXT(&add_p_opt.interhunkcontext),
+	OPT_DIFF_UNIFIED(&interactive_opts.context),
+	OPT_DIFF_INTERHUNK_CONTEXT(&interactive_opts.interhunkcontext),
 	OPT_BOOL('e', "edit", &edit_interactive, N_("edit current diff and apply")),
 	OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files"), 0),
 	OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")),
@@ -402,9 +402,9 @@ int cmd_add(int argc,
 	prepare_repo_settings(repo);
 	repo->settings.command_requires_full_index = 0;
 
-	if (add_p_opt.context < -1)
+	if (interactive_opts.context < -1)
 		die(_("'%s' cannot be negative"), "--unified");
-	if (add_p_opt.interhunkcontext < -1)
+	if (interactive_opts.interhunkcontext < -1)
 		die(_("'%s' cannot be negative"), "--inter-hunk-context");
 
 	if (patch_interactive)
@@ -414,13 +414,13 @@ int cmd_add(int argc,
 			die(_("options '%s' and '%s' cannot be used together"), "--dry-run", "--interactive/--patch");
 		if (pathspec_from_file)
 			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--interactive/--patch");
-		exit(interactive_add(repo, argv + 1, prefix, patch_interactive, &add_p_opt));
+		exit(interactive_add(repo, argv + 1, prefix, patch_interactive, &interactive_opts));
 	} else {
-		if (add_p_opt.context != -1)
+		if (interactive_opts.context != -1)
 			die(_("the option '%s' requires '%s'"), "--unified", "--interactive/--patch");
-		if (add_p_opt.interhunkcontext != -1)
+		if (interactive_opts.interhunkcontext != -1)
 			die(_("the option '%s' requires '%s'"), "--inter-hunk-context", "--interactive/--patch");
-		if (!add_p_opt.auto_advance)
+		if (!interactive_opts.auto_advance)
 			die(_("the option '%s' requires '%s'"), "--no-auto-advance", "--interactive/--patch");
 	}
 
diff --git a/builtin/am.c b/builtin/am.c
index e0c767e..fe6e087 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -1188,7 +1188,7 @@ static void am_append_signoff(struct am_state *state)
 {
 	struct strbuf sb = STRBUF_INIT;
 
-	strbuf_attach(&sb, state->msg, state->msg_len, state->msg_len);
+	strbuf_attach(&sb, state->msg, state->msg_len, state->msg_len + 1);
 	append_signoff(&sb, 0, 0);
 	state->msg = strbuf_detach(&sb, &state->msg_len);
 }
@@ -1937,7 +1937,7 @@ static void am_run(struct am_state *state, int resume)
 	 */
 	if (!state->rebasing) {
 		am_destroy(state);
-		run_auto_maintenance(state->quiet);
+		run_auto_maintenance(the_repository, state->quiet);
 	}
 }
 
diff --git a/builtin/branch.c b/builtin/branch.c
index a1a4338..1572a4f 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -228,7 +228,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
 	int ret = 0;
 	int remote_branch = 0;
 	struct strbuf bname = STRBUF_INIT;
-	unsigned allowed_interpret;
+	enum interpret_branch_kind allowed_interpret;
 	struct string_list refs_to_delete = STRING_LIST_INIT_DUP;
 	struct string_list_item *item;
 	int branch_name_pos;
diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index da059d0..b6f12f4 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -882,7 +882,8 @@ static void batch_each_object(struct batch_options *opt,
 		struct object_info oi = { 0 };
 
 		for (source = the_repository->objects->sources; source; source = source->next) {
-			int ret = packfile_store_for_each_object(source->packfiles, &oi,
+			struct odb_source_files *files = odb_source_files_downcast(source);
+			int ret = packfile_store_for_each_object(files->packed, &oi,
 								 batch_one_object_oi, &payload, flags);
 			if (ret)
 				break;
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 1d1667f..e031e61 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -532,7 +532,7 @@ static int checkout_paths(const struct checkout_opts *opts,
 
 	if (opts->patch_mode) {
 		enum add_p_mode patch_mode;
-		struct add_p_opt add_p_opt = {
+		struct interactive_options interactive_opts = {
 			.context = opts->patch_context,
 			.interhunkcontext = opts->patch_interhunk_context,
 			.auto_advance = opts->auto_advance
@@ -562,8 +562,8 @@ static int checkout_paths(const struct checkout_opts *opts,
 		else
 			BUG("either flag must have been set, worktree=%d, index=%d",
 			    opts->checkout_worktree, opts->checkout_index);
-		return !!run_add_p(the_repository, patch_mode, &add_p_opt,
-				   rev, &opts->pathspec);
+		return !!run_add_p(the_repository, patch_mode, &interactive_opts,
+				   rev, &opts->pathspec, 0);
 	}
 
 	repo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR);
@@ -891,7 +891,8 @@ static int merge_working_tree(const struct checkout_opts *opts,
 					0, 0);
 			init_ui_merge_options(&o, the_repository);
 			o.verbosity = 0;
-			work = write_in_core_index_as_tree(the_repository);
+			work = write_in_core_index_as_tree(the_repository,
+							   the_repository->index);
 
 			ret = reset_tree(new_tree,
 					 opts, 1,
diff --git a/builtin/commit.c b/builtin/commit.c
index 844bdcc..a3e52ac 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -123,7 +123,7 @@ static const char *edit_message, *use_message;
 static char *fixup_message, *fixup_commit, *squash_message;
 static const char *fixup_prefix;
 static int all, also, interactive, patch_interactive, only, amend, signoff;
-static struct add_p_opt add_p_opt = ADD_P_OPT_INIT;
+static struct interactive_options interactive_opts = INTERACTIVE_OPTIONS_INIT;
 static int edit_flag = -1; /* unspecified */
 static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;
 static int config_commit_verbose = -1; /* unspecified */
@@ -357,9 +357,9 @@ static const char *prepare_index(const char **argv, const char *prefix,
 	const char *ret;
 	char *path = NULL;
 
-	if (add_p_opt.context < -1)
+	if (interactive_opts.context < -1)
 		die(_("'%s' cannot be negative"), "--unified");
-	if (add_p_opt.interhunkcontext < -1)
+	if (interactive_opts.interhunkcontext < -1)
 		die(_("'%s' cannot be negative"), "--inter-hunk-context");
 
 	if (is_status)
@@ -408,7 +408,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
 		old_index_env = xstrdup_or_null(getenv(INDEX_ENVIRONMENT));
 		setenv(INDEX_ENVIRONMENT, the_repository->index_file, 1);
 
-		if (interactive_add(the_repository, argv, prefix, patch_interactive, &add_p_opt) != 0)
+		if (interactive_add(the_repository, argv, prefix, patch_interactive, &interactive_opts) != 0)
 			die(_("interactive add failed"));
 
 		the_repository->index_file = old_repo_index_file;
@@ -433,9 +433,9 @@ static const char *prepare_index(const char **argv, const char *prefix,
 		ret = get_lock_file_path(&index_lock);
 		goto out;
 	} else {
-		if (add_p_opt.context != -1)
+		if (interactive_opts.context != -1)
 			die(_("the option '%s' requires '%s'"), "--unified", "--interactive/--patch");
-		if (add_p_opt.interhunkcontext != -1)
+		if (interactive_opts.interhunkcontext != -1)
 			die(_("the option '%s' requires '%s'"), "--inter-hunk-context", "--interactive/--patch");
 	}
 
@@ -1720,7 +1720,8 @@ int cmd_commit(int argc,
 		OPT_STRING(0, "fixup", &fixup_message, N_("[(amend|reword):]commit"), N_("use autosquash formatted message to fixup or amend/reword specified commit")),
 		OPT_STRING(0, "squash", &squash_message, N_("commit"), N_("use autosquash formatted message to squash specified commit")),
 		OPT_BOOL(0, "reset-author", &renew_authorship, N_("the commit is authored by me now (used with -C/-c/--amend)")),
-		OPT_PASSTHRU_ARGV(0, "trailer", &trailer_args, N_("trailer"), N_("add custom trailer(s)"), PARSE_OPT_NONEG),
+		OPT_STRVEC(0, "trailer", &trailer_args, N_("trailer"),
+			   N_("add custom trailer(s)")),
 		OPT_BOOL('s', "signoff", &signoff, N_("add a Signed-off-by trailer")),
 		OPT_FILENAME('t', "template", &template_file, N_("use specified template file")),
 		OPT_BOOL('e', "edit", &edit_flag, N_("force edit of commit")),
@@ -1743,8 +1744,8 @@ int cmd_commit(int argc,
 		OPT_BOOL('i', "include", &also, N_("add specified files to index for commit")),
 		OPT_BOOL(0, "interactive", &interactive, N_("interactively add files")),
 		OPT_BOOL('p', "patch", &patch_interactive, N_("interactively add changes")),
-		OPT_DIFF_UNIFIED(&add_p_opt.context),
-		OPT_DIFF_INTERHUNK_CONTEXT(&add_p_opt.interhunkcontext),
+		OPT_DIFF_UNIFIED(&interactive_opts.context),
+		OPT_DIFF_INTERHUNK_CONTEXT(&interactive_opts.interhunkcontext),
 		OPT_BOOL('o', "only", &only, N_("commit only specified files")),
 		OPT_BOOL('n', "no-verify", &no_verify, N_("bypass pre-commit and commit-msg hooks")),
 		OPT_BOOL(0, "dry-run", &dry_run, N_("show what would be committed")),
@@ -1820,6 +1821,9 @@ int cmd_commit(int argc,
 	argc = parse_and_validate_options(argc, argv, builtin_commit_options,
 					  builtin_commit_usage,
 					  prefix, current_head, &s);
+	if (trailer_args.nr)
+		trailer_config_init();
+
 	if (verbose == -1)
 		verbose = (config_commit_verbose < 0) ? 0 : config_commit_verbose;
 
@@ -1958,7 +1962,7 @@ int cmd_commit(int argc,
 	git_test_write_commit_graph_or_die(the_repository->objects->sources);
 
 	repo_rerere(the_repository, 0);
-	run_auto_maintenance(quiet);
+	run_auto_maintenance(the_repository, quiet);
 	run_commit_hook(use_editor, repo_get_index_file(the_repository),
 			NULL, "post-commit", NULL);
 	if (amend && !no_post_rewrite) {
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 0c5d238..13621b0 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -64,7 +64,7 @@ static int parse_opt_sign_mode(const struct option *opt,
 	if (unset)
 		return 0;
 
-	if (parse_sign_mode(arg, val))
+	if (parse_sign_mode(arg, val, NULL))
 		return error(_("unknown %s mode: %s"), opt->long_name, arg);
 
 	return 0;
@@ -825,6 +825,9 @@ static void handle_commit(struct commit *commit, struct rev_info *rev,
 		case SIGN_STRIP_IF_INVALID:
 			die(_("'strip-if-invalid' is not a valid mode for "
 			      "git fast-export with --signed-commits=<mode>"));
+		case SIGN_SIGN_IF_INVALID:
+			die(_("'sign-if-invalid' is not a valid mode for "
+			      "git fast-export with --signed-commits=<mode>"));
 		default:
 			BUG("invalid signed_commit_mode value %d", signed_commit_mode);
 		}
@@ -970,6 +973,9 @@ static void handle_tag(const char *name, struct tag *tag)
 			case SIGN_STRIP_IF_INVALID:
 				die(_("'strip-if-invalid' is not a valid mode for "
 				      "git fast-export with --signed-tags=<mode>"));
+			case SIGN_SIGN_IF_INVALID:
+				die(_("'sign-if-invalid' is not a valid mode for "
+				      "git fast-export with --signed-tags=<mode>"));
 			default:
 				BUG("invalid signed_commit_mode value %d", signed_commit_mode);
 			}
diff --git a/builtin/fast-import.c b/builtin/fast-import.c
index b8a7757..570fd04 100644
--- a/builtin/fast-import.c
+++ b/builtin/fast-import.c
@@ -190,6 +190,7 @@ static const char *global_prefix;
 
 static enum sign_mode signed_tag_mode = SIGN_VERBATIM;
 static enum sign_mode signed_commit_mode = SIGN_VERBATIM;
+static const char *signed_commit_keyid;
 
 /* Memory pools */
 static struct mem_pool fi_mem_pool = {
@@ -875,6 +876,7 @@ static void end_packfile(void)
 	running = 1;
 	clear_delta_base_cache();
 	if (object_count) {
+		struct odb_source_files *files = odb_source_files_downcast(pack_data->repo->objects->sources);
 		struct packed_git *new_p;
 		struct object_id cur_pack_oid;
 		char *idx_name;
@@ -900,8 +902,7 @@ static void end_packfile(void)
 		idx_name = keep_pack(create_index());
 
 		/* Register the packfile with core git's machinery. */
-		new_p = packfile_store_load_pack(pack_data->repo->objects->sources->packfiles,
-						 idx_name, 1);
+		new_p = packfile_store_load_pack(files->packed, idx_name, 1);
 		if (!new_p)
 			die(_("core Git rejected index %s"), idx_name);
 		all_packs[pack_id] = new_p;
@@ -982,7 +983,9 @@ static int store_object(
 	}
 
 	for (source = the_repository->objects->sources; source; source = source->next) {
-		if (!packfile_list_find_oid(packfile_store_get_packs(source->packfiles), &oid))
+		struct odb_source_files *files = odb_source_files_downcast(source);
+
+		if (!packfile_list_find_oid(packfile_store_get_packs(files->packed), &oid))
 			continue;
 		e->type = type;
 		e->pack_id = MAX_PACK_ID;
@@ -1187,7 +1190,9 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark)
 	}
 
 	for (source = the_repository->objects->sources; source; source = source->next) {
-		if (!packfile_list_find_oid(packfile_store_get_packs(source->packfiles), &oid))
+		struct odb_source_files *files = odb_source_files_downcast(source);
+
+		if (!packfile_list_find_oid(packfile_store_get_packs(files->packed), &oid))
 			continue;
 		e->type = OBJ_BLOB;
 		e->pack_id = MAX_PACK_ID;
@@ -2836,10 +2841,46 @@ static void finalize_commit_buffer(struct strbuf *new_data,
 	strbuf_addbuf(new_data, msg);
 }
 
-static void handle_strip_if_invalid(struct strbuf *new_data,
-				    struct signature_data *sig_sha1,
-				    struct signature_data *sig_sha256,
-				    struct strbuf *msg)
+static void warn_invalid_signature(struct signature_check *check,
+				   const char *msg, enum sign_mode mode)
+{
+	const char *signer = check->signer ? check->signer : _("unknown");
+	const char *subject;
+	int subject_len = find_commit_subject(msg, &subject);
+
+	switch (mode) {
+	case SIGN_STRIP_IF_INVALID:
+		if (subject_len > 100)
+			warning(_("stripping invalid signature for commit '%.100s...'\n"
+				  "  allegedly by %s"), subject, signer);
+		else if (subject_len > 0)
+			warning(_("stripping invalid signature for commit '%.*s'\n"
+				  "  allegedly by %s"), subject_len, subject, signer);
+		else
+			warning(_("stripping invalid signature for commit\n"
+				  "  allegedly by %s"), signer);
+		break;
+	case SIGN_SIGN_IF_INVALID:
+		if (subject_len > 100)
+			warning(_("replacing invalid signature for commit '%.100s...'\n"
+				  "  allegedly by %s"), subject, signer);
+		else if (subject_len > 0)
+			warning(_("replacing invalid signature for commit '%.*s'\n"
+				  "  allegedly by %s"), subject_len, subject, signer);
+		else
+			warning(_("replacing invalid signature for commit\n"
+				  "  allegedly by %s"), signer);
+		break;
+	default:
+		BUG("unsupported signing mode");
+	}
+}
+
+static void handle_signature_if_invalid(struct strbuf *new_data,
+					struct signature_data *sig_sha1,
+					struct signature_data *sig_sha256,
+					struct strbuf *msg,
+					enum sign_mode mode)
 {
 	struct strbuf tmp_buf = STRBUF_INIT;
 	struct signature_check signature_check = { 0 };
@@ -2851,20 +2892,34 @@ static void handle_strip_if_invalid(struct strbuf *new_data,
 	ret = verify_commit_buffer(tmp_buf.buf, tmp_buf.len, &signature_check);
 
 	if (ret) {
-		const char *signer = signature_check.signer ?
-			signature_check.signer : _("unknown");
-		const char *subject;
-		int subject_len = find_commit_subject(msg->buf, &subject);
+		warn_invalid_signature(&signature_check, msg->buf, mode);
 
-		if (subject_len > 100)
-			warning(_("stripping invalid signature for commit '%.100s...'\n"
-				  "  allegedly by %s"), subject, signer);
-		else if (subject_len > 0)
-			warning(_("stripping invalid signature for commit '%.*s'\n"
-				  "  allegedly by %s"), subject_len, subject, signer);
-		else
-			warning(_("stripping invalid signature for commit\n"
-				  "  allegedly by %s"), signer);
+		if (mode == SIGN_SIGN_IF_INVALID) {
+			struct strbuf signature = STRBUF_INIT;
+			struct strbuf payload = STRBUF_INIT;
+
+			/*
+			 * NEEDSWORK: To properly support interoperability mode
+			 * when signing commit signatures, the commit buffer
+			 * must be provided in both the repository and
+			 * compatibility object formats. As currently
+			 * implemented, only the repository object format is
+			 * considered meaning compatibility signatures cannot be
+			 * generated. Thus, attempting to sign commit signatures
+			 * in interoperability mode is currently unsupported.
+			 */
+			if (the_repository->compat_hash_algo)
+				die(_("signing commits in interoperability mode is unsupported"));
+
+			strbuf_addstr(&payload, signature_check.payload);
+			if (sign_buffer(&payload, &signature, signed_commit_keyid,
+					SIGN_BUFFER_USE_DEFAULT_KEY))
+				die(_("failed to sign commit object"));
+			add_header_signature(new_data, &signature, the_hash_algo);
+
+			strbuf_release(&signature);
+			strbuf_release(&payload);
+		}
 
 		finalize_commit_buffer(new_data, NULL, NULL, msg);
 	} else {
@@ -2927,6 +2982,7 @@ static void parse_new_commit(const char *arg)
 			/* fallthru */
 		case SIGN_VERBATIM:
 		case SIGN_STRIP_IF_INVALID:
+		case SIGN_SIGN_IF_INVALID:
 			import_one_signature(&sig_sha1, &sig_sha256, v);
 			break;
 
@@ -3011,9 +3067,11 @@ static void parse_new_commit(const char *arg)
 			"encoding %s\n",
 			encoding);
 
-	if (signed_commit_mode == SIGN_STRIP_IF_INVALID &&
+	if ((signed_commit_mode == SIGN_STRIP_IF_INVALID ||
+	     signed_commit_mode == SIGN_SIGN_IF_INVALID) &&
 	    (sig_sha1.hash_algo || sig_sha256.hash_algo))
-		handle_strip_if_invalid(&new_data, &sig_sha1, &sig_sha256, &msg);
+		handle_signature_if_invalid(&new_data, &sig_sha1, &sig_sha256,
+					    &msg, signed_commit_mode);
 	else
 		finalize_commit_buffer(&new_data, &sig_sha1, &sig_sha256, &msg);
 
@@ -3060,6 +3118,9 @@ static void handle_tag_signature(struct strbuf *msg, const char *name)
 	case SIGN_STRIP_IF_INVALID:
 		die(_("'strip-if-invalid' is not a valid mode for "
 		      "git fast-import with --signed-tags=<mode>"));
+	case SIGN_SIGN_IF_INVALID:
+		die(_("'sign-if-invalid' is not a valid mode for "
+		      "git fast-import with --signed-tags=<mode>"));
 	default:
 		BUG("invalid signed_tag_mode value %d from tag '%s'",
 		    signed_tag_mode, name);
@@ -3246,7 +3307,7 @@ static void cat_blob(struct object_entry *oe, struct object_id *oid)
 	cat_blob_write("\n", 1);
 	if (oe && oe->pack_id == pack_id) {
 		last_blob.offset = oe->idx.offset;
-		strbuf_attach(&last_blob.data, buf, size, size);
+		strbuf_attach(&last_blob.data, buf, size, size + 1);
 		last_blob.depth = oe->depth;
 	} else
 		free(buf);
@@ -3649,10 +3710,10 @@ static int parse_one_option(const char *option)
 	} else if (skip_prefix(option, "export-pack-edges=", &option)) {
 		option_export_pack_edges(option);
 	} else if (skip_prefix(option, "signed-commits=", &option)) {
-		if (parse_sign_mode(option, &signed_commit_mode))
+		if (parse_sign_mode(option, &signed_commit_mode, &signed_commit_keyid))
 			usagef(_("unknown --signed-commits mode '%s'"), option);
 	} else if (skip_prefix(option, "signed-tags=", &option)) {
-		if (parse_sign_mode(option, &signed_tag_mode))
+		if (parse_sign_mode(option, &signed_tag_mode, NULL))
 			usagef(_("unknown --signed-tags mode '%s'"), option);
 	} else if (!strcmp(option, "quiet")) {
 		show_stats = 0;
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 8a36cf6..4795b2a 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -2873,7 +2873,7 @@ int cmd_fetch(int argc,
 			if (opt_val != 0)
 				git_config_push_parameter("maintenance.incremental-repack.auto=-1");
 		}
-		run_auto_maintenance(verbosity < 0);
+		run_auto_maintenance(the_repository, verbosity < 0);
 	}
 
  cleanup:
diff --git a/builtin/for-each-repo.c b/builtin/for-each-repo.c
index 325a792..927d3d9 100644
--- a/builtin/for-each-repo.c
+++ b/builtin/for-each-repo.c
@@ -2,6 +2,7 @@
 
 #include "builtin.h"
 #include "config.h"
+#include "environment.h"
 #include "gettext.h"
 #include "parse-options.h"
 #include "path.h"
@@ -13,17 +14,16 @@ static const char * const for_each_repo_usage[] = {
 	NULL
 };
 
-static int run_command_on_repo(const char *path, int argc, const char ** argv)
+static int run_command_on_repo(const char *path, const char **argv)
 {
-	int i;
 	struct child_process child = CHILD_PROCESS_INIT;
 	char *abspath = interpolate_path(path, 0);
 
+	sanitize_repo_env(&child.env);
+
 	child.git_cmd = 1;
 	strvec_pushl(&child.args, "-C", abspath, NULL);
-
-	for (i = 0; i < argc; i++)
-		strvec_push(&child.args, argv[i]);
+	strvec_pushv(&child.args, argv);
 
 	free(abspath);
 
@@ -63,7 +63,7 @@ int cmd_for_each_repo(int argc,
 		return 0;
 
 	for (size_t i = 0; i < values->nr; i++) {
-		int ret = run_command_on_repo(values->items[i].string, argc, argv);
+		int ret = run_command_on_repo(values->items[i].string, argv);
 		if (ret) {
 			if (!keep_going)
 					return ret;
diff --git a/builtin/gc.c b/builtin/gc.c
index fb329c2..3a71e31 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -467,37 +467,19 @@ static int rerere_gc_condition(struct gc_config *cfg UNUSED)
 static int too_many_loose_objects(int limit)
 {
 	/*
-	 * Quickly check if a "gc" is needed, by estimating how
-	 * many loose objects there are.  Because SHA-1 is evenly
-	 * distributed, we can check only one and get a reasonable
-	 * estimate.
+	 * This is weird, but stems from legacy behaviour: the GC auto
+	 * threshold was always essentially interpreted as if it was rounded up
+	 * to the next multiple 256 of, so we retain this behaviour for now.
 	 */
-	DIR *dir;
-	struct dirent *ent;
-	int auto_threshold;
-	int num_loose = 0;
-	int needed = 0;
-	const unsigned hexsz_loose = the_hash_algo->hexsz - 2;
-	char *path;
+	int auto_threshold = DIV_ROUND_UP(limit, 256) * 256;
+	unsigned long loose_count;
 
-	path = repo_git_path(the_repository, "objects/17");
-	dir = opendir(path);
-	free(path);
-	if (!dir)
+	if (odb_source_loose_count_objects(the_repository->objects->sources,
+					   ODB_COUNT_OBJECTS_APPROXIMATE,
+					   &loose_count) < 0)
 		return 0;
 
-	auto_threshold = DIV_ROUND_UP(limit, 256);
-	while ((ent = readdir(dir)) != NULL) {
-		if (strspn(ent->d_name, "0123456789abcdef") != hexsz_loose ||
-		    ent->d_name[hexsz_loose] != '\0')
-			continue;
-		if (++num_loose > auto_threshold) {
-			needed = 1;
-			break;
-		}
-	}
-	closedir(dir);
-	return needed;
+	return loose_count > auto_threshold;
 }
 
 static struct packed_git *find_base_packs(struct string_list *packs,
@@ -592,9 +574,13 @@ static uint64_t total_ram(void)
 static uint64_t estimate_repack_memory(struct gc_config *cfg,
 				       struct packed_git *pack)
 {
-	unsigned long nr_objects = repo_approximate_object_count(the_repository);
+	unsigned long nr_objects;
 	size_t os_cache, heap;
 
+	if (odb_count_objects(the_repository->objects,
+			      ODB_COUNT_OBJECTS_APPROXIMATE, &nr_objects) < 0)
+		return 0;
+
 	if (!pack || !nr_objects)
 		return 0;
 
@@ -1030,7 +1016,7 @@ int cmd_gc(int argc,
 		struct child_process repack_cmd = CHILD_PROCESS_INIT;
 
 		repack_cmd.git_cmd = 1;
-		repack_cmd.close_object_store = 1;
+		repack_cmd.odb_to_close = the_repository->objects;
 		strvec_pushv(&repack_cmd.args, repack_args.v);
 		if (run_command(&repack_cmd))
 			die(FAILED_RUN, repack_args.v[0]);
@@ -1199,7 +1185,8 @@ static int run_write_commit_graph(struct maintenance_run_opts *opts)
 {
 	struct child_process child = CHILD_PROCESS_INIT;
 
-	child.git_cmd = child.close_object_store = 1;
+	child.git_cmd = 1;
+	child.odb_to_close = the_repository->objects;
 	strvec_pushl(&child.args, "commit-graph", "write",
 		     "--split", "--reachable", NULL);
 
@@ -1268,7 +1255,8 @@ static int maintenance_task_gc_background(struct maintenance_run_opts *opts,
 {
 	struct child_process child = CHILD_PROCESS_INIT;
 
-	child.git_cmd = child.close_object_store = 1;
+	child.git_cmd = 1;
+	child.odb_to_close = the_repository->objects;
 	strvec_push(&child.args, "gc");
 
 	if (opts->auto_flag)
@@ -1484,7 +1472,8 @@ static int multi_pack_index_expire(struct maintenance_run_opts *opts)
 {
 	struct child_process child = CHILD_PROCESS_INIT;
 
-	child.git_cmd = child.close_object_store = 1;
+	child.git_cmd = 1;
+	child.odb_to_close = the_repository->objects;
 	strvec_pushl(&child.args, "multi-pack-index", "expire", NULL);
 
 	if (opts->quiet)
@@ -1542,7 +1531,8 @@ static int multi_pack_index_repack(struct maintenance_run_opts *opts)
 {
 	struct child_process child = CHILD_PROCESS_INIT;
 
-	child.git_cmd = child.close_object_store = 1;
+	child.git_cmd = 1;
+	child.odb_to_close = the_repository->objects;
 	strvec_pushl(&child.args, "multi-pack-index", "repack", NULL);
 
 	if (opts->quiet)
diff --git a/builtin/grep.c b/builtin/grep.c
index b6cecfd..e33285e 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -1218,8 +1218,10 @@ int cmd_grep(int argc,
 			struct odb_source *source;
 
 			odb_prepare_alternates(the_repository->objects);
-			for (source = the_repository->objects->sources; source; source = source->next)
-				packfile_store_prepare(source->packfiles);
+			for (source = the_repository->objects->sources; source; source = source->next) {
+				struct odb_source_files *files = odb_source_files_downcast(source);
+				packfile_store_prepare(files->packed);
+			}
 		}
 
 		start_threads(&opt);
diff --git a/builtin/help.c b/builtin/help.c
index 86a3d03..c0aece4 100644
--- a/builtin/help.c
+++ b/builtin/help.c
@@ -114,6 +114,49 @@ struct slot_expansion {
 	int found;
 };
 
+static void set_config_vars(struct string_list *keys_uniq, struct string_list_item *var)
+{
+	struct strbuf sb = STRBUF_INIT;
+	const char *str = var->string;
+	const char *wildcard = strchr(str, '*');
+	const char *tag = strchr(str, '<');
+	const char *cut;
+
+	if (wildcard && tag)
+		cut = wildcard < tag ? wildcard : tag;
+	else if (wildcard)
+		cut = wildcard;
+	else if (tag)
+		cut = tag;
+	else {
+		string_list_append(keys_uniq, str);
+		return;
+	}
+
+	strbuf_add(&sb, str, cut - str);
+	string_list_append(keys_uniq, sb.buf);
+	strbuf_release(&sb);
+}
+
+static void set_config_sections(struct string_list *keys_uniq, struct string_list_item *var)
+{
+	struct strbuf sb = STRBUF_INIT;
+	const char *str = var->string;
+	const char *dot = strchr(str, '.');
+	const char *cut;
+
+	if (dot)
+		cut = dot;
+	else {
+		set_config_vars(keys_uniq, var);
+		return;
+	}
+
+	strbuf_add(&sb, str, cut - str);
+	string_list_append(keys_uniq, sb.buf);
+	strbuf_release(&sb);
+}
+
 static void list_config_help(enum show_config_type type)
 {
 	struct slot_expansion slot_expansions[] = {
@@ -134,13 +177,12 @@ static void list_config_help(enum show_config_type type)
 	struct string_list keys = STRING_LIST_INIT_DUP;
 	struct string_list keys_uniq = STRING_LIST_INIT_DUP;
 	struct string_list_item *item;
+	struct strbuf sb = STRBUF_INIT;
 
 	for (p = config_name_list; *p; p++) {
 		const char *var = *p;
-		struct strbuf sb = STRBUF_INIT;
 
 		for (e = slot_expansions; e->prefix; e++) {
-
 			strbuf_reset(&sb);
 			strbuf_addf(&sb, "%s.%s", e->prefix, e->placeholder);
 			if (!strcasecmp(var, sb.buf)) {
@@ -149,60 +191,39 @@ static void list_config_help(enum show_config_type type)
 				break;
 			}
 		}
-		strbuf_release(&sb);
+
 		if (!e->prefix)
 			string_list_append(&keys, var);
 	}
 
+	strbuf_release(&sb);
+
 	for (e = slot_expansions; e->prefix; e++)
 		if (!e->found)
 			BUG("slot_expansion %s.%s is not used",
 			    e->prefix, e->placeholder);
 
-	string_list_sort(&keys);
 	for (size_t i = 0; i < keys.nr; i++) {
-		const char *var = keys.items[i].string;
-		const char *wildcard, *tag, *cut;
-		const char *dot = NULL;
-		struct strbuf sb = STRBUF_INIT;
-
 		switch (type) {
 		case SHOW_CONFIG_HUMAN:
-			puts(var);
-			continue;
+			string_list_append(&keys_uniq, keys.items[i].string);
+			break;
 		case SHOW_CONFIG_SECTIONS:
-			dot = strchr(var, '.');
+			set_config_sections(&keys_uniq, &keys.items[i]);
 			break;
 		case SHOW_CONFIG_VARS:
+			set_config_vars(&keys_uniq, &keys.items[i]);
 			break;
+		default:
+			BUG("%d: unexpected type", type);
 		}
-		wildcard = strchr(var, '*');
-		tag = strchr(var, '<');
-
-		if (!dot && !wildcard && !tag) {
-			string_list_append(&keys_uniq, var);
-			continue;
-		}
-
-		if (dot)
-			cut = dot;
-		else if (wildcard && !tag)
-			cut = wildcard;
-		else if (!wildcard && tag)
-			cut = tag;
-		else
-			cut = wildcard < tag ? wildcard : tag;
-
-		strbuf_add(&sb, var, cut - var);
-		string_list_append(&keys_uniq, sb.buf);
-		strbuf_release(&sb);
-
 	}
-	string_list_clear(&keys, 0);
-	string_list_remove_duplicates(&keys_uniq, 0);
+
+	string_list_sort_u(&keys_uniq, 0);
 	for_each_string_list_item(item, &keys_uniq)
 		puts(item->string);
 	string_list_clear(&keys_uniq, 0);
+	string_list_clear(&keys, 0);
 }
 
 static enum help_format parse_help_format(const char *format)
diff --git a/builtin/history.c b/builtin/history.c
index 1cf6c66..568dc75 100644
--- a/builtin/history.c
+++ b/builtin/history.c
@@ -1,6 +1,7 @@
 #define USE_THE_REPOSITORY_VARIABLE
 
 #include "builtin.h"
+#include "cache-tree.h"
 #include "commit.h"
 #include "commit-reach.h"
 #include "config.h"
@@ -8,17 +9,24 @@
 #include "environment.h"
 #include "gettext.h"
 #include "hex.h"
+#include "lockfile.h"
+#include "oidmap.h"
 #include "parse-options.h"
+#include "path.h"
+#include "read-cache.h"
 #include "refs.h"
 #include "replay.h"
 #include "revision.h"
 #include "sequencer.h"
 #include "strvec.h"
 #include "tree.h"
+#include "unpack-trees.h"
 #include "wt-status.h"
 
 #define GIT_HISTORY_REWORD_USAGE \
 	N_("git history reword <commit> [--dry-run] [--update-refs=(branches|head)]")
+#define GIT_HISTORY_SPLIT_USAGE \
+	N_("git history split <commit> [--dry-run] [--update-refs=(branches|head)] [--] [<pathspec>...]")
 
 static void change_data_free(void *util, const char *str UNUSED)
 {
@@ -83,10 +91,13 @@ static int fill_commit_message(struct repository *repo,
 	return 0;
 }
 
-static int commit_tree_with_edited_message(struct repository *repo,
-					   const char *action,
-					   struct commit *original,
-					   struct commit **out)
+static int commit_tree_with_edited_message_ext(struct repository *repo,
+					       const char *action,
+					       struct commit *commit_with_message,
+					       const struct commit_list *parents,
+					       const struct object_id *old_tree,
+					       const struct object_id *new_tree,
+					       struct commit **out)
 {
 	const char *exclude_gpgsig[] = {
 		/* We reencode the message, so the encoding needs to be stripped. */
@@ -100,44 +111,27 @@ static int commit_tree_with_edited_message(struct repository *repo,
 	struct commit_extra_header *original_extra_headers = NULL;
 	struct strbuf commit_message = STRBUF_INIT;
 	struct object_id rewritten_commit_oid;
-	struct object_id original_tree_oid;
-	struct object_id parent_tree_oid;
 	char *original_author = NULL;
-	struct commit *parent;
 	size_t len;
 	int ret;
 
-	original_tree_oid = repo_get_commit_tree(repo, original)->object.oid;
-
-	parent = original->parents ? original->parents->item : NULL;
-	if (parent) {
-		if (repo_parse_commit(repo, parent)) {
-			ret = error(_("unable to parse parent commit %s"),
-				    oid_to_hex(&parent->object.oid));
-			goto out;
-		}
-
-		parent_tree_oid = repo_get_commit_tree(repo, parent)->object.oid;
-	} else {
-		oidcpy(&parent_tree_oid, repo->hash_algo->empty_tree);
-	}
-
 	/* We retain authorship of the original commit. */
-	original_message = repo_logmsg_reencode(repo, original, NULL, NULL);
+	original_message = repo_logmsg_reencode(repo, commit_with_message, NULL, NULL);
 	ptr = find_commit_header(original_message, "author", &len);
 	if (ptr)
 		original_author = xmemdupz(ptr, len);
 	find_commit_subject(original_message, &original_body);
 
-	ret = fill_commit_message(repo, &parent_tree_oid, &original_tree_oid,
+	ret = fill_commit_message(repo, old_tree, new_tree,
 				  original_body, action, &commit_message);
 	if (ret < 0)
 		goto out;
 
-	original_extra_headers = read_commit_extra_headers(original, exclude_gpgsig);
+	original_extra_headers = read_commit_extra_headers(commit_with_message,
+							   exclude_gpgsig);
 
-	ret = commit_tree_extended(commit_message.buf, commit_message.len, &original_tree_oid,
-				   original->parents, &rewritten_commit_oid, original_author,
+	ret = commit_tree_extended(commit_message.buf, commit_message.len, new_tree,
+				   parents, &rewritten_commit_oid, original_author,
 				   NULL, NULL, original_extra_headers);
 	if (ret < 0)
 		goto out;
@@ -151,6 +145,33 @@ static int commit_tree_with_edited_message(struct repository *repo,
 	return ret;
 }
 
+static int commit_tree_with_edited_message(struct repository *repo,
+					   const char *action,
+					   struct commit *original,
+					   struct commit **out)
+{
+	struct object_id parent_tree_oid;
+	const struct object_id *tree_oid;
+	struct commit *parent;
+
+	tree_oid = &repo_get_commit_tree(repo, original)->object.oid;
+
+	parent = original->parents ? original->parents->item : NULL;
+	if (parent) {
+		if (repo_parse_commit(repo, parent)) {
+			return error(_("unable to parse parent commit %s"),
+				     oid_to_hex(&parent->object.oid));
+		}
+
+		parent_tree_oid = repo_get_commit_tree(repo, parent)->object.oid;
+	} else {
+		oidcpy(&parent_tree_oid, repo->hash_algo->empty_tree);
+	}
+
+	return commit_tree_with_edited_message_ext(repo, action, original, original->parents,
+						   &parent_tree_oid, tree_oid, out);
+}
+
 enum ref_action {
 	REF_ACTION_DEFAULT,
 	REF_ACTION_BRANCHES,
@@ -425,7 +446,7 @@ static int cmd_history_reword(int argc,
 	};
 	struct strbuf reflog_msg = STRBUF_INIT;
 	struct commit *original, *rewritten;
-	struct rev_info revs;
+	struct rev_info revs = { 0 };
 	int ret;
 
 	argc = parse_options(argc, argv, prefix, options, usage, 0);
@@ -471,6 +492,246 @@ static int cmd_history_reword(int argc,
 	return ret;
 }
 
+static int write_ondisk_index(struct repository *repo,
+			      struct object_id *oid,
+			      const char *path)
+{
+	struct unpack_trees_options opts = { 0 };
+	struct lock_file lock = LOCK_INIT;
+	struct tree_desc tree_desc;
+	struct index_state index;
+	struct tree *tree;
+	int ret;
+
+	index_state_init(&index, repo);
+
+	opts.head_idx = -1;
+	opts.src_index = &index;
+	opts.dst_index = &index;
+
+	tree = repo_parse_tree_indirect(repo, oid);
+	init_tree_desc(&tree_desc, &tree->object.oid, tree->buffer, tree->size);
+
+	if (unpack_trees(1, &tree_desc, &opts)) {
+		ret = error(_("unable to populate index with tree"));
+		goto out;
+	}
+
+	prime_cache_tree(repo, &index, tree);
+
+	if (hold_lock_file_for_update(&lock, path, 0) < 0) {
+		ret = error_errno(_("unable to acquire index lock"));
+		goto out;
+	}
+
+	if (write_locked_index(&index, &lock, COMMIT_LOCK)) {
+		ret = error(_("unable to write new index file"));
+		goto out;
+	}
+
+	ret = 0;
+
+out:
+	rollback_lock_file(&lock);
+	release_index(&index);
+	return ret;
+}
+
+static int split_commit(struct repository *repo,
+			struct commit *original,
+			struct pathspec *pathspec,
+			struct commit **out)
+{
+	struct interactive_options interactive_opts = INTERACTIVE_OPTIONS_INIT;
+	struct strbuf index_file = STRBUF_INIT;
+	struct index_state index = INDEX_STATE_INIT(repo);
+	const struct object_id *original_commit_tree_oid;
+	const struct object_id *old_tree_oid, *new_tree_oid;
+	struct object_id parent_tree_oid;
+	char original_commit_oid[GIT_MAX_HEXSZ + 1];
+	struct commit *first_commit, *second_commit;
+	struct commit_list *parents = NULL;
+	struct tree *split_tree;
+	int ret;
+
+	if (original->parents) {
+		if (repo_parse_commit(repo, original->parents->item)) {
+			ret = error(_("unable to parse parent commit %s"),
+				    oid_to_hex(&original->parents->item->object.oid));
+			goto out;
+		}
+
+		parent_tree_oid = *get_commit_tree_oid(original->parents->item);
+	} else {
+		oidcpy(&parent_tree_oid, repo->hash_algo->empty_tree);
+	}
+	original_commit_tree_oid = get_commit_tree_oid(original);
+
+	/*
+	 * Construct the first commit. This is done by taking the original
+	 * commit parent's tree and selectively patching changes from the diff
+	 * between that parent and its child.
+	 */
+	repo_git_path_replace(repo, &index_file, "%s", "history-split.index");
+
+	ret = write_ondisk_index(repo, &parent_tree_oid, index_file.buf);
+	if (ret < 0)
+		goto out;
+
+	ret = read_index_from(&index, index_file.buf, repo->gitdir);
+	if (ret < 0) {
+		ret = error(_("failed reading temporary index"));
+		goto out;
+	}
+
+	oid_to_hex_r(original_commit_oid, &original->object.oid);
+	ret = run_add_p_index(repo, &index, index_file.buf, &interactive_opts,
+			      original_commit_oid, pathspec, ADD_P_DISALLOW_EDIT);
+	if (ret < 0)
+		goto out;
+
+	split_tree = write_in_core_index_as_tree(repo, &index);
+	if (!split_tree) {
+		ret = error(_("failed split tree"));
+		goto out;
+	}
+
+	unlink(index_file.buf);
+	strbuf_release(&index_file);
+
+	/*
+	 * We disallow the cases where either the split-out commit or the
+	 * original commit would become empty. Consequently, if we see that the
+	 * new tree ID matches either of those trees we abort.
+	 */
+	if (oideq(&split_tree->object.oid, &parent_tree_oid)) {
+		ret = error(_("split commit is empty"));
+		goto out;
+	} else if (oideq(&split_tree->object.oid, original_commit_tree_oid)) {
+		ret = error(_("split commit tree matches original commit"));
+		goto out;
+	}
+
+	/*
+	 * The first commit is constructed from the split-out tree. The base
+	 * that shall be diffed against is the parent of the original commit.
+	 */
+	ret = commit_tree_with_edited_message_ext(repo, "split-out", original,
+						  original->parents, &parent_tree_oid,
+						  &split_tree->object.oid, &first_commit);
+	if (ret < 0) {
+		ret = error(_("failed writing first commit"));
+		goto out;
+	}
+
+	/*
+	 * The second commit is constructed from the original tree. The base to
+	 * diff against and the parent in this case is the first split-out
+	 * commit.
+	 */
+	commit_list_append(first_commit, &parents);
+
+	old_tree_oid = &repo_get_commit_tree(repo, first_commit)->object.oid;
+	new_tree_oid = &repo_get_commit_tree(repo, original)->object.oid;
+
+	ret = commit_tree_with_edited_message_ext(repo, "split-out", original,
+						  parents, old_tree_oid,
+						  new_tree_oid, &second_commit);
+	if (ret < 0) {
+		ret = error(_("failed writing second commit"));
+		goto out;
+	}
+
+	*out = second_commit;
+	ret = 0;
+
+out:
+	if (index_file.len)
+		unlink(index_file.buf);
+	strbuf_release(&index_file);
+	free_commit_list(parents);
+	release_index(&index);
+	return ret;
+}
+
+static int cmd_history_split(int argc,
+			     const char **argv,
+			     const char *prefix,
+			     struct repository *repo)
+{
+	const char * const usage[] = {
+		GIT_HISTORY_SPLIT_USAGE,
+		NULL,
+	};
+	enum ref_action action = REF_ACTION_DEFAULT;
+	int dry_run = 0;
+	struct option options[] = {
+		OPT_CALLBACK_F(0, "update-refs", &action, N_("<refs>"),
+			       N_("control ref update behavior (branches|head|print)"),
+			       PARSE_OPT_NONEG, parse_ref_action),
+		OPT_BOOL('n', "dry-run", &dry_run,
+			 N_("perform a dry-run without updating any refs")),
+		OPT_END(),
+	};
+	struct commit *original, *rewritten = NULL;
+	struct strbuf reflog_msg = STRBUF_INIT;
+	struct pathspec pathspec = { 0 };
+	struct rev_info revs = { 0 };
+	int ret;
+
+	argc = parse_options(argc, argv, prefix, options, usage, 0);
+	if (argc < 1) {
+		ret = error(_("command expects a committish"));
+		goto out;
+	}
+	repo_config(repo, git_default_config, NULL);
+
+	if (action == REF_ACTION_DEFAULT)
+		action = REF_ACTION_BRANCHES;
+
+	parse_pathspec(&pathspec, 0,
+		       PATHSPEC_PREFER_FULL |
+		       PATHSPEC_SYMLINK_LEADING_PATH |
+		       PATHSPEC_PREFIX_ORIGIN,
+		       prefix, argv + 1);
+
+	original = lookup_commit_reference_by_name(argv[0]);
+	if (!original) {
+		ret = error(_("commit cannot be found: %s"), argv[0]);
+		goto out;
+	}
+
+	ret = setup_revwalk(repo, action, original, &revs);
+	if (ret < 0)
+		goto out;
+
+	if (original->parents && original->parents->next) {
+		ret = error(_("cannot split up merge commit"));
+		goto out;
+	}
+
+	ret = split_commit(repo, original, &pathspec, &rewritten);
+	if (ret < 0)
+		goto out;
+
+	strbuf_addf(&reflog_msg, "split: updating %s", argv[0]);
+
+	ret = handle_reference_updates(&revs, action, original, rewritten,
+				       reflog_msg.buf, dry_run);
+	if (ret < 0) {
+		ret = error(_("failed replaying descendants"));
+		goto out;
+	}
+
+	ret = 0;
+
+out:
+	strbuf_release(&reflog_msg);
+	clear_pathspec(&pathspec);
+	release_revisions(&revs);
+	return ret;
+}
+
 int cmd_history(int argc,
 		const char **argv,
 		const char *prefix,
@@ -478,11 +739,13 @@ int cmd_history(int argc,
 {
 	const char * const usage[] = {
 		GIT_HISTORY_REWORD_USAGE,
+		GIT_HISTORY_SPLIT_USAGE,
 		NULL,
 	};
 	parse_opt_subcommand_fn *fn = NULL;
 	struct option options[] = {
 		OPT_SUBCOMMAND("reword", &fn, cmd_history_reword),
+		OPT_SUBCOMMAND("split", &fn, cmd_history_split),
 		OPT_END(),
 	};
 
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index b67fb02..d1e4727 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -1637,9 +1637,11 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
 	rename_tmp_packfile(&final_index_name, curr_index_name, &index_name,
 			    hash, "idx", 1);
 
-	if (do_fsck_object && startup_info->have_repository)
-		packfile_store_load_pack(the_repository->objects->sources->packfiles,
-					 final_index_name, 0);
+	if (do_fsck_object && startup_info->have_repository) {
+		struct odb_source_files *files =
+			odb_source_files_downcast(the_repository->objects->sources);
+		packfile_store_load_pack(files->packed, final_index_name, 0);
+	}
 
 	if (!from_stdin) {
 		printf("%s\n", hash_to_hex(hash));
diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c
index 41b0750..e7e86e9 100644
--- a/builtin/interpret-trailers.c
+++ b/builtin/interpret-trailers.c
@@ -93,37 +93,6 @@ static int parse_opt_parse(const struct option *opt, const char *arg,
 	return 0;
 }
 
-static struct tempfile *trailers_tempfile;
-
-static FILE *create_in_place_tempfile(const char *file)
-{
-	struct stat st;
-	struct strbuf filename_template = STRBUF_INIT;
-	const char *tail;
-	FILE *outfile;
-
-	if (stat(file, &st))
-		die_errno(_("could not stat %s"), file);
-	if (!S_ISREG(st.st_mode))
-		die(_("file %s is not a regular file"), file);
-	if (!(st.st_mode & S_IWUSR))
-		die(_("file %s is not writable by user"), file);
-
-	/* Create temporary file in the same directory as the original */
-	tail = strrchr(file, '/');
-	if (tail)
-		strbuf_add(&filename_template, file, tail - file + 1);
-	strbuf_addstr(&filename_template, "git-interpret-trailers-XXXXXX");
-
-	trailers_tempfile = xmks_tempfile_m(filename_template.buf, st.st_mode);
-	strbuf_release(&filename_template);
-	outfile = fdopen_tempfile(trailers_tempfile, "w");
-	if (!outfile)
-		die_errno(_("could not open temporary file"));
-
-	return outfile;
-}
-
 static void read_input_file(struct strbuf *sb, const char *file)
 {
 	if (file) {
@@ -140,55 +109,31 @@ static void interpret_trailers(const struct process_trailer_options *opts,
 			       struct list_head *new_trailer_head,
 			       const char *file)
 {
-	LIST_HEAD(head);
-	struct strbuf sb = STRBUF_INIT;
-	struct strbuf trailer_block_sb = STRBUF_INIT;
-	struct trailer_block *trailer_block;
-	FILE *outfile = stdout;
+	struct strbuf input = STRBUF_INIT;
+	struct strbuf out = STRBUF_INIT;
+	struct tempfile *tempfile = NULL;
+	int fd = 1;
 
 	trailer_config_init();
 
-	read_input_file(&sb, file);
+	read_input_file(&input, file);
 
-	if (opts->in_place)
-		outfile = create_in_place_tempfile(file);
-
-	trailer_block = parse_trailers(opts, sb.buf, &head);
-
-	/* Print the lines before the trailer block */
-	if (!opts->only_trailers)
-		fwrite(sb.buf, 1, trailer_block_start(trailer_block), outfile);
-
-	if (!opts->only_trailers && !blank_line_before_trailer_block(trailer_block))
-		fprintf(outfile, "\n");
-
-
-	if (!opts->only_input) {
-		LIST_HEAD(config_head);
-		LIST_HEAD(arg_head);
-		parse_trailers_from_config(&config_head);
-		parse_trailers_from_command_line_args(&arg_head, new_trailer_head);
-		list_splice(&config_head, &arg_head);
-		process_trailers_lists(&head, &arg_head);
+	if (opts->in_place) {
+		tempfile = trailer_create_in_place_tempfile(file);
+		if (!tempfile)
+			die(NULL);
+		fd = tempfile->fd;
 	}
+	process_trailers(opts, new_trailer_head, &input, &out);
 
-	/* Print trailer block. */
-	format_trailers(opts, &head, &trailer_block_sb);
-	free_trailers(&head);
-	fwrite(trailer_block_sb.buf, 1, trailer_block_sb.len, outfile);
-	strbuf_release(&trailer_block_sb);
-
-	/* Print the lines after the trailer block as is. */
-	if (!opts->only_trailers)
-		fwrite(sb.buf + trailer_block_end(trailer_block), 1,
-		       sb.len - trailer_block_end(trailer_block), outfile);
-	trailer_block_release(trailer_block);
-
+	if (write_in_full(fd, out.buf, out.len) < 0)
+		die_errno(_("could not write to temporary file '%s'"), file);
 	if (opts->in_place)
-		if (rename_tempfile(&trailers_tempfile, file))
+		if (rename_tempfile(&tempfile, file))
 			die_errno(_("could not rename temporary file to %s"), file);
 
-	strbuf_release(&sb);
+	strbuf_release(&input);
+	strbuf_release(&out);
 }
 
 int cmd_interpret_trailers(int argc,
@@ -211,7 +156,7 @@ int cmd_interpret_trailers(int argc,
 			     N_("action if trailer is missing"), option_parse_if_missing),
 
 		OPT_BOOL(0, "only-trailers", &opts.only_trailers, N_("output only the trailers")),
-		OPT_BOOL(0, "only-input", &opts.only_input, N_("do not apply trailer.* configuration variables")),
+		OPT_BOOL(0, "only-input", &opts.only_input, N_("do not apply trailer.<key-alias> configuration variables")),
 		OPT_BOOL(0, "unfold", &opts.unfold, N_("reformat multiline trailer values as single-line values")),
 		OPT_CALLBACK_F(0, "parse", &opts, NULL, N_("alias for --only-trailers --only-input --unfold"),
 			PARSE_OPT_NOARG | PARSE_OPT_NONEG, parse_opt_parse),
diff --git a/builtin/merge-file.c b/builtin/merge-file.c
index 084fdfe..59a9792 100644
--- a/builtin/merge-file.c
+++ b/builtin/merge-file.c
@@ -108,7 +108,8 @@ int cmd_merge_file(int argc,
 			return error_errno("failed to redirect stderr to /dev/null");
 	}
 
-	if (object_id)
+	if (!repo && object_id)
+		/* emit the correct "not a git repo" error in this case */
 		setup_git_directory();
 
 	for (i = 0; i < 3; i++) {
diff --git a/builtin/merge.c b/builtin/merge.c
index 4e456a3..2cbce56 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -506,7 +506,7 @@ static void finish(struct commit *head_commit,
 			 * We ignore errors in 'gc --auto', since the
 			 * user should see them.
 			 */
-			run_auto_maintenance(verbosity < 0);
+			run_auto_maintenance(the_repository, verbosity < 0);
 		}
 	}
 	if (new_head && show_diffstat) {
diff --git a/builtin/mktree.c b/builtin/mktree.c
index 1277230..4084e32 100644
--- a/builtin/mktree.c
+++ b/builtin/mktree.c
@@ -3,7 +3,6 @@
  *
  * Copyright (c) Junio C Hamano, 2006, 2009
  */
-#define USE_THE_REPOSITORY_VARIABLE
 #include "builtin.h"
 #include "gettext.h"
 #include "hex.h"
@@ -46,7 +45,7 @@ static int ent_compare(const void *a_, const void *b_)
 				 b->name, b->len, b->mode);
 }
 
-static void write_tree(struct object_id *oid)
+static void write_tree(struct repository *repo, struct object_id *oid)
 {
 	struct strbuf buf;
 	size_t size;
@@ -60,10 +59,10 @@ static void write_tree(struct object_id *oid)
 	for (i = 0; i < used; i++) {
 		struct treeent *ent = entries[i];
 		strbuf_addf(&buf, "%o %s%c", ent->mode, ent->name, '\0');
-		strbuf_add(&buf, ent->oid.hash, the_hash_algo->rawsz);
+		strbuf_add(&buf, ent->oid.hash, repo->hash_algo->rawsz);
 	}
 
-	odb_write_object(the_repository->objects, buf.buf, buf.len, OBJ_TREE, oid);
+	odb_write_object(repo->objects, buf.buf, buf.len, OBJ_TREE, oid);
 	strbuf_release(&buf);
 }
 
@@ -72,7 +71,7 @@ static const char *const mktree_usage[] = {
 	NULL
 };
 
-static void mktree_line(char *buf, int nul_term_line, int allow_missing)
+static void mktree_line(struct repository *repo, char *buf, int nul_term_line, int allow_missing)
 {
 	char *ptr, *ntr;
 	const char *p;
@@ -93,7 +92,7 @@ static void mktree_line(char *buf, int nul_term_line, int allow_missing)
 		die("input format error: %s", buf);
 	ptr = ntr + 1; /* type */
 	ntr = strchr(ptr, ' ');
-	if (!ntr || parse_oid_hex(ntr + 1, &oid, &p) ||
+	if (!ntr || parse_oid_hex_algop(ntr + 1, &oid, &p, repo->hash_algo) ||
 	    *p != '\t')
 		die("input format error: %s", buf);
 
@@ -124,7 +123,7 @@ static void mktree_line(char *buf, int nul_term_line, int allow_missing)
 
 	/* Check the type of object identified by oid without fetching objects */
 	oi.typep = &obj_type;
-	if (odb_read_object_info_extended(the_repository->objects, &oid, &oi,
+	if (odb_read_object_info_extended(repo->objects, &oid, &oi,
 					  OBJECT_INFO_LOOKUP_REPLACE |
 					  OBJECT_INFO_QUICK |
 					  OBJECT_INFO_SKIP_FETCH_OBJECT) < 0)
@@ -155,7 +154,7 @@ static void mktree_line(char *buf, int nul_term_line, int allow_missing)
 int cmd_mktree(int ac,
 	       const char **av,
 	       const char *prefix,
-	       struct repository *repo UNUSED)
+	       struct repository *repo)
 {
 	struct strbuf sb = STRBUF_INIT;
 	struct object_id oid;
@@ -187,7 +186,7 @@ int cmd_mktree(int ac,
 					break;
 				die("input format error: (blank line only valid in batch mode)");
 			}
-			mktree_line(sb.buf, nul_term_line, allow_missing);
+			mktree_line(repo, sb.buf, nul_term_line, allow_missing);
 		}
 		if (is_batch_mode && got_eof && used < 1) {
 			/*
@@ -197,7 +196,7 @@ int cmd_mktree(int ac,
 			 */
 			; /* skip creating an empty tree */
 		} else {
-			write_tree(&oid);
+			write_tree(repo, &oid);
 			puts(oid_to_hex(&oid));
 			fflush(stdout);
 		}
diff --git a/builtin/multi-pack-index.c b/builtin/multi-pack-index.c
index 5f364aa..0f72d96 100644
--- a/builtin/multi-pack-index.c
+++ b/builtin/multi-pack-index.c
@@ -9,12 +9,18 @@
 #include "strbuf.h"
 #include "trace2.h"
 #include "odb.h"
+#include "odb/source.h"
 #include "replace-object.h"
 #include "repository.h"
 
 #define BUILTIN_MIDX_WRITE_USAGE \
-	N_("git multi-pack-index [<options>] write [--preferred-pack=<pack>]" \
-	   "[--refs-snapshot=<path>]")
+	N_("git multi-pack-index [<options>] write [--preferred-pack=<pack>]\n" \
+	   "  [--[no-]bitmap] [--[no-]incremental] [--[no-]stdin-packs]\n" \
+	   "  [--refs-snapshot=<path>]")
+
+#define BUILTIN_MIDX_COMPACT_USAGE \
+	N_("git multi-pack-index [<options>] compact [--[no-]incremental]\n" \
+	   "  [--[no-]bitmap] <from> <to>")
 
 #define BUILTIN_MIDX_VERIFY_USAGE \
 	N_("git multi-pack-index [<options>] verify")
@@ -29,6 +35,10 @@ static char const * const builtin_multi_pack_index_write_usage[] = {
 	BUILTIN_MIDX_WRITE_USAGE,
 	NULL
 };
+static char const * const builtin_multi_pack_index_compact_usage[] = {
+	BUILTIN_MIDX_COMPACT_USAGE,
+	NULL
+};
 static char const * const builtin_multi_pack_index_verify_usage[] = {
 	BUILTIN_MIDX_VERIFY_USAGE,
 	NULL
@@ -43,6 +53,7 @@ static char const * const builtin_multi_pack_index_repack_usage[] = {
 };
 static char const * const builtin_multi_pack_index_usage[] = {
 	BUILTIN_MIDX_WRITE_USAGE,
+	BUILTIN_MIDX_COMPACT_USAGE,
 	BUILTIN_MIDX_VERIFY_USAGE,
 	BUILTIN_MIDX_EXPIRE_USAGE,
 	BUILTIN_MIDX_REPACK_USAGE,
@@ -84,6 +95,8 @@ static struct option common_opts[] = {
 	  N_("directory"),
 	  N_("object directory containing set of packfile and pack-index pairs"),
 	  parse_object_dir),
+	OPT_BIT(0, "progress", &opts.flags, N_("force progress reporting"),
+		MIDX_PROGRESS),
 	OPT_END(),
 };
 
@@ -138,8 +151,6 @@ static int cmd_multi_pack_index_write(int argc, const char **argv,
 			   N_("pack for reuse when computing a multi-pack bitmap")),
 		OPT_BIT(0, "bitmap", &opts.flags, N_("write multi-pack bitmap"),
 			MIDX_WRITE_BITMAP | MIDX_WRITE_REV_INDEX),
-		OPT_BIT(0, "progress", &opts.flags,
-			N_("force progress reporting"), MIDX_PROGRESS),
 		OPT_BIT(0, "incremental", &opts.flags,
 			N_("write a new incremental MIDX"), MIDX_WRITE_INCREMENTAL),
 		OPT_BOOL(0, "stdin-packs", &opts.stdin_packs,
@@ -194,14 +205,78 @@ static int cmd_multi_pack_index_write(int argc, const char **argv,
 	return ret;
 }
 
+static int cmd_multi_pack_index_compact(int argc, const char **argv,
+					const char *prefix,
+					struct repository *repo)
+{
+	struct multi_pack_index *m, *cur;
+	struct multi_pack_index *from_midx = NULL;
+	struct multi_pack_index *to_midx = NULL;
+	struct odb_source *source;
+	int ret;
+
+	struct option *options;
+	static struct option builtin_multi_pack_index_compact_options[] = {
+		OPT_BIT(0, "bitmap", &opts.flags, N_("write multi-pack bitmap"),
+			MIDX_WRITE_BITMAP | MIDX_WRITE_REV_INDEX),
+		OPT_BIT(0, "incremental", &opts.flags,
+			N_("write a new incremental MIDX"), MIDX_WRITE_INCREMENTAL),
+		OPT_END(),
+	};
+
+	repo_config(repo, git_multi_pack_index_write_config, NULL);
+
+	options = add_common_options(builtin_multi_pack_index_compact_options);
+
+	trace2_cmd_mode(argv[0]);
+
+	if (isatty(2))
+		opts.flags |= MIDX_PROGRESS;
+	argc = parse_options(argc, argv, prefix,
+			     options, builtin_multi_pack_index_compact_usage,
+			     0);
+
+	if (argc != 2)
+		usage_with_options(builtin_multi_pack_index_compact_usage,
+				   options);
+	source = handle_object_dir_option(the_repository);
+
+	FREE_AND_NULL(options);
+
+	m = get_multi_pack_index(source);
+
+	for (cur = m; cur && !(from_midx && to_midx); cur = cur->base_midx) {
+		const char *midx_csum = midx_get_checksum_hex(cur);
+
+		if (!from_midx && !strcmp(midx_csum, argv[0]))
+			from_midx = cur;
+		if (!to_midx && !strcmp(midx_csum, argv[1]))
+			to_midx = cur;
+	}
+
+	if (!from_midx)
+		die(_("could not find MIDX: %s"), argv[0]);
+	if (!to_midx)
+		die(_("could not find MIDX: %s"), argv[1]);
+	if (from_midx == to_midx)
+		die(_("MIDX compaction endpoints must be unique"));
+
+	for (m = from_midx; m; m = m->base_midx) {
+		if (m == to_midx)
+			die(_("MIDX %s must be an ancestor of %s"), argv[0], argv[1]);
+	}
+
+	ret = write_midx_file_compact(source, from_midx, to_midx, opts.flags);
+
+	return ret;
+}
+
 static int cmd_multi_pack_index_verify(int argc, const char **argv,
 				       const char *prefix,
 				       struct repository *repo UNUSED)
 {
 	struct option *options;
 	static struct option builtin_multi_pack_index_verify_options[] = {
-		OPT_BIT(0, "progress", &opts.flags,
-			N_("force progress reporting"), MIDX_PROGRESS),
 		OPT_END(),
 	};
 	struct odb_source *source;
@@ -231,8 +306,6 @@ static int cmd_multi_pack_index_expire(int argc, const char **argv,
 {
 	struct option *options;
 	static struct option builtin_multi_pack_index_expire_options[] = {
-		OPT_BIT(0, "progress", &opts.flags,
-			N_("force progress reporting"), MIDX_PROGRESS),
 		OPT_END(),
 	};
 	struct odb_source *source;
@@ -264,8 +337,6 @@ static int cmd_multi_pack_index_repack(int argc, const char **argv,
 	static struct option builtin_multi_pack_index_repack_options[] = {
 		OPT_UNSIGNED(0, "batch-size", &opts.batch_size,
 		  N_("during repack, collect pack-files of smaller size into a batch that is larger than this size")),
-		OPT_BIT(0, "progress", &opts.flags,
-		  N_("force progress reporting"), MIDX_PROGRESS),
 		OPT_END(),
 	};
 	struct odb_source *source;
@@ -300,6 +371,7 @@ int cmd_multi_pack_index(int argc,
 	struct option builtin_multi_pack_index_options[] = {
 		OPT_SUBCOMMAND("repack", &fn, cmd_multi_pack_index_repack),
 		OPT_SUBCOMMAND("write", &fn, cmd_multi_pack_index_write),
+		OPT_SUBCOMMAND("compact", &fn, cmd_multi_pack_index_compact),
 		OPT_SUBCOMMAND("verify", &fn, cmd_multi_pack_index_verify),
 		OPT_SUBCOMMAND("expire", &fn, cmd_multi_pack_index_expire),
 		OPT_END(),
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 6188cf9..d6594ad 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -12,7 +12,6 @@
 #include "object-name.h"
 #include "pager.h"
 #include "parse-options.h"
-#include "prio-queue.h"
 #include "hash-lookup.h"
 #include "commit-slab.h"
 #include "commit-graph.h"
@@ -178,7 +177,7 @@ static void name_rev(struct commit *start_commit,
 		const char *tip_name, timestamp_t taggerdate,
 		int from_tag, int deref, struct mem_pool *string_pool)
 {
-	struct prio_queue queue;
+	struct commit_stack stack = COMMIT_STACK_INIT;
 	struct commit *commit;
 	struct commit_stack parents_to_queue = COMMIT_STACK_INIT;
 	struct rev_name *start_name;
@@ -197,10 +196,9 @@ static void name_rev(struct commit *start_commit,
 	else
 		start_name->tip_name = mem_pool_strdup(string_pool, tip_name);
 
-	memset(&queue, 0, sizeof(queue)); /* Use the prio_queue as LIFO */
-	prio_queue_put(&queue, start_commit);
+	commit_stack_push(&stack, start_commit);
 
-	while ((commit = prio_queue_get(&queue))) {
+	while ((commit = commit_stack_pop(&stack))) {
 		struct rev_name *name = get_commit_rev_name(commit);
 		struct commit_list *parents;
 		int parent_number = 1;
@@ -241,13 +239,13 @@ static void name_rev(struct commit *start_commit,
 			}
 		}
 
-		/* The first parent must come out first from the prio_queue */
+		/* The first parent must come out first from the stack */
 		while (parents_to_queue.nr)
-			prio_queue_put(&queue,
-				       commit_stack_pop(&parents_to_queue));
+			commit_stack_push(&stack,
+					  commit_stack_pop(&parents_to_queue));
 	}
 
-	clear_prio_queue(&queue);
+	commit_stack_clear(&stack);
 	commit_stack_clear(&parents_to_queue);
 }
 
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 983f473..da10879 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -41,6 +41,7 @@
 #include "promisor-remote.h"
 #include "pack-mtimes.h"
 #include "parse-options.h"
+#include "pkt-line.h"
 #include "blob.h"
 #include "tree.h"
 #include "path-walk.h"
@@ -1330,11 +1331,25 @@ static void write_pack_file(void)
 		unsigned char hash[GIT_MAX_RAWSZ];
 		char *pack_tmp_name = NULL;
 
-		if (pack_to_stdout)
-			f = hashfd_throughput(the_repository->hash_algo, 1,
-					      "<stdout>", progress_state);
-		else
+		if (pack_to_stdout) {
+			/*
+			 * This command is most often invoked via
+			 * git-upload-pack(1), which will typically chunk data
+			 * into pktlines. As such, we use the maximum data
+			 * length of them as buffer length.
+			 *
+			 * Note that we need to subtract one though to
+			 * accomodate for the sideband byte.
+			 */
+			struct hashfd_options opts = {
+				.progress = progress_state,
+				.buffer_len = LARGE_PACKET_DATA_MAX - 1,
+			};
+			f = hashfd_ext(the_repository->hash_algo, 1,
+				       "<stdout>", &opts);
+		} else {
 			f = create_tmp_packfile(the_repository, &pack_tmp_name);
+		}
 
 		offset = write_pack_header(f, nr_remaining);
 
@@ -1531,7 +1546,8 @@ static int want_cruft_object_mtime(struct repository *r,
 	struct odb_source *source;
 
 	for (source = r->objects->sources; source; source = source->next) {
-		struct packed_git **cache = packfile_store_get_kept_pack_cache(source->packfiles, flags);
+		struct odb_source_files *files = odb_source_files_downcast(source);
+		struct packed_git **cache = packfile_store_get_kept_pack_cache(files->packed, flags);
 
 		for (; *cache; cache++) {
 			struct packed_git *p = *cache;
@@ -1753,11 +1769,13 @@ static int want_object_in_pack_mtime(const struct object_id *oid,
 	}
 
 	for (source = the_repository->objects->sources; source; source = source->next) {
-		for (e = source->packfiles->packs.head; e; e = e->next) {
+		struct odb_source_files *files = odb_source_files_downcast(source);
+
+		for (e = files->packed->packs.head; e; e = e->next) {
 			struct packed_git *p = e->pack;
 			want = want_object_in_pack_one(p, oid, exclude, found_pack, found_offset, found_mtime);
 			if (!exclude && want > 0)
-				packfile_list_prepend(&source->packfiles->packs, p);
+				packfile_list_prepend(&files->packed->packs, p);
 			if (want != -1)
 				return want;
 		}
@@ -4347,10 +4365,12 @@ static void add_objects_in_unpacked_packs(void)
 
 	odb_prepare_alternates(to_pack.repo->objects);
 	for (source = to_pack.repo->objects->sources; source; source = source->next) {
+		struct odb_source_files *files = odb_source_files_downcast(source);
+
 		if (!source->local)
 			continue;
 
-		if (packfile_store_for_each_object(source->packfiles, &oi,
+		if (packfile_store_for_each_object(files->packed, &oi,
 						   add_object_in_unpacked_pack, NULL,
 						   ODB_FOR_EACH_OBJECT_PACK_ORDER |
 						   ODB_FOR_EACH_OBJECT_LOCAL_ONLY |
diff --git a/builtin/pull.c b/builtin/pull.c
index 6ad420c..7e67fdc 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -454,7 +454,7 @@ static int run_fetch(const char *repo, const char **refspecs)
 	} else if (*refspecs)
 		BUG("refspecs without repo?");
 	cmd.git_cmd = 1;
-	cmd.close_object_store = 1;
+	cmd.odb_to_close = the_repository->objects;
 	return run_command(&cmd);
 }
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index c487e10..fa4f5d9 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -36,6 +36,7 @@
 #include "reset.h"
 #include "trace2.h"
 #include "hook.h"
+#include "trailer.h"
 
 static char const * const builtin_rebase_usage[] = {
 	N_("git rebase [-i] [options] [--exec <cmd>] "
@@ -113,6 +114,7 @@ struct rebase_options {
 	enum action action;
 	char *reflog_action;
 	int signoff;
+	struct strvec trailer_args;
 	int allow_rerere_autoupdate;
 	int keep_empty;
 	int autosquash;
@@ -143,6 +145,7 @@ struct rebase_options {
 		.flags = REBASE_NO_QUIET, 		\
 		.git_am_opts = STRVEC_INIT,		\
 		.exec = STRING_LIST_INIT_NODUP,		\
+		.trailer_args = STRVEC_INIT,		\
 		.git_format_patch_opt = STRBUF_INIT,	\
 		.fork_point = -1,			\
 		.reapply_cherry_picks = -1,             \
@@ -166,6 +169,7 @@ static void rebase_options_release(struct rebase_options *opts)
 	free(opts->strategy);
 	string_list_clear(&opts->strategy_opts, 0);
 	strbuf_release(&opts->git_format_patch_opt);
+	strvec_clear(&opts->trailer_args);
 }
 
 static struct replay_opts get_replay_opts(const struct rebase_options *opts)
@@ -177,6 +181,9 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	sequencer_init_config(&replay);
 
 	replay.signoff = opts->signoff;
+
+	strvec_pushv(&replay.trailer_args, opts->trailer_args.v);
+
 	replay.allow_ff = !(opts->flags & REBASE_FORCE);
 	if (opts->allow_rerere_autoupdate)
 		replay.allow_rerere_auto = opts->allow_rerere_autoupdate;
@@ -562,7 +569,9 @@ static int finish_rebase(struct rebase_options *opts)
 	 * We ignore errors in 'git maintenance run --auto', since the
 	 * user should see them.
 	 */
-	run_auto_maintenance(!(opts->flags & (REBASE_NO_QUIET|REBASE_VERBOSE)));
+	run_auto_maintenance(the_repository,
+			!(opts->flags & (REBASE_NO_QUIET|REBASE_VERBOSE)));
+
 	if (opts->type == REBASE_MERGE) {
 		struct replay_opts replay = REPLAY_OPTS_INIT;
 
@@ -1132,6 +1141,8 @@ int cmd_rebase(int argc,
 			.flags = PARSE_OPT_NOARG,
 			.defval = REBASE_DIFFSTAT,
 		},
+		OPT_STRVEC(0, "trailer", &options.trailer_args, N_("trailer"),
+			   N_("add custom trailer(s)")),
 		OPT_BOOL(0, "signoff", &options.signoff,
 			 N_("add a Signed-off-by trailer to each commit")),
 		OPT_BOOL(0, "committer-date-is-author-date",
@@ -1285,6 +1296,12 @@ int cmd_rebase(int argc,
 			     builtin_rebase_options,
 			     builtin_rebase_usage, 0);
 
+	if (options.trailer_args.nr) {
+		if (validate_trailer_args(&options.trailer_args))
+			die(NULL);
+		options.flags |= REBASE_FORCE;
+	}
+
 	if (preserve_merges_selected)
 		die(_("--preserve-merges was replaced by --rebase-merges\n"
 			"Note: Your `pull.rebase` configuration may also be set to 'preserve',\n"
@@ -1542,6 +1559,9 @@ int cmd_rebase(int argc,
 	if (options.root && !options.onto_name)
 		imply_merge(&options, "--root without --onto");
 
+	if (options.trailer_args.nr)
+		imply_merge(&options, "--trailer");
+
 	if (isatty(2) && options.flags & REBASE_NO_QUIET)
 		strbuf_addstr(&options.git_format_patch_opt, " --progress");
 
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index d6225df..e34edff 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -2727,7 +2727,7 @@ int cmd_receive_pack(int argc,
 		if (auto_gc) {
 			struct child_process proc = CHILD_PROCESS_INIT;
 
-			if (prepare_auto_maintenance(1, &proc)) {
+			if (prepare_auto_maintenance(the_repository, 1, &proc)) {
 				proc.no_stdin = 1;
 				proc.stdout_to_stderr = 1;
 				proc.err = use_sideband ? -1 : 0;
diff --git a/builtin/repo.c b/builtin/repo.c
index fae1141..71a5c1c 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -1,7 +1,9 @@
 #define USE_THE_REPOSITORY_VARIABLE
 
 #include "builtin.h"
+#include "commit.h"
 #include "environment.h"
+#include "hash.h"
 #include "hex.h"
 #include "odb.h"
 #include "parse-options.h"
@@ -14,13 +16,31 @@
 #include "strbuf.h"
 #include "string-list.h"
 #include "shallow.h"
+#include "tree.h"
+#include "tree-walk.h"
 #include "utf8.h"
 
+#define REPO_INFO_USAGE \
+	"git repo info [--format=(lines|nul) | -z] [--all | <key>...]", \
+	"git repo info --keys [--format=(lines|nul) | -z]"
+
+#define REPO_STRUCTURE_USAGE \
+	"git repo structure [--format=(table|lines|nul) | -z]"
+
 static const char *const repo_usage[] = {
-	"git repo info [--format=(lines|nul) | -z] [--all | <key>...]",
-	"git repo info --keys [--format=(lines|nul) | -z]",
-	"git repo structure [--format=(table|lines|nul) | -z]",
-	NULL
+	REPO_INFO_USAGE,
+	REPO_STRUCTURE_USAGE,
+	NULL,
+};
+
+static const char *const repo_info_usage[] = {
+	REPO_INFO_USAGE,
+	NULL,
+};
+
+static const char *const repo_structure_usage[] = {
+	REPO_STRUCTURE_USAGE,
+	NULL,
 };
 
 typedef int get_value_fn(struct repository *repo, struct strbuf *buf);
@@ -210,7 +230,7 @@ static int cmd_repo_info(int argc, const char **argv, const char *prefix,
 		OPT_END()
 	};
 
-	argc = parse_options(argc, argv, prefix, options, repo_usage, 0);
+	argc = parse_options(argc, argv, prefix, options, repo_info_usage, 0);
 
 	if (show_keys && (all_keys || argc))
 		die(_("--keys cannot be used with a <key> or --all"));
@@ -230,6 +250,21 @@ static int cmd_repo_info(int argc, const char **argv, const char *prefix,
 		return print_fields(argc, argv, repo, format);
 }
 
+struct object_data {
+	struct object_id oid;
+	size_t value;
+};
+
+struct largest_objects {
+	struct object_data tag_size;
+	struct object_data commit_size;
+	struct object_data tree_size;
+	struct object_data blob_size;
+
+	struct object_data parent_count;
+	struct object_data tree_entries;
+};
+
 struct ref_stats {
 	size_t branches;
 	size_t remotes;
@@ -248,6 +283,7 @@ struct object_stats {
 	struct object_values type_counts;
 	struct object_values inflated_sizes;
 	struct object_values disk_sizes;
+	struct largest_objects largest;
 };
 
 struct repo_structure {
@@ -257,6 +293,7 @@ struct repo_structure {
 
 struct stats_table {
 	struct string_list rows;
+	struct string_list annotations;
 
 	int name_col_width;
 	int value_col_width;
@@ -269,6 +306,8 @@ struct stats_table {
 struct stats_table_entry {
 	char *value;
 	const char *unit;
+	size_t index;
+	struct object_id *oid;
 };
 
 static void stats_table_vaddf(struct stats_table *table,
@@ -291,6 +330,12 @@ static void stats_table_vaddf(struct stats_table *table,
 		table->name_col_width = name_width;
 	if (!entry)
 		return;
+	if (entry->oid) {
+		entry->index = table->annotations.nr + 1;
+		strbuf_addf(&buf, "[%" PRIuMAX "] %s", (uintmax_t)entry->index,
+			    oid_to_hex(entry->oid));
+		string_list_append_nodup(&table->annotations, strbuf_detach(&buf, NULL));
+	}
 	if (entry->value) {
 		int value_width = utf8_strwidth(entry->value);
 		if (value_width > table->value_col_width)
@@ -301,6 +346,8 @@ static void stats_table_vaddf(struct stats_table *table,
 		if (unit_width > table->unit_col_width)
 			table->unit_col_width = unit_width;
 	}
+
+	strbuf_release(&buf);
 }
 
 static void stats_table_addf(struct stats_table *table, const char *format, ...)
@@ -326,6 +373,27 @@ static void stats_table_count_addf(struct stats_table *table, size_t value,
 	va_end(ap);
 }
 
+static void stats_table_object_count_addf(struct stats_table *table,
+					  struct object_id *oid, size_t value,
+					  const char *format, ...)
+{
+	struct stats_table_entry *entry;
+	va_list ap;
+
+	CALLOC_ARRAY(entry, 1);
+	humanise_count(value, &entry->value, &entry->unit);
+
+	/*
+	 * A NULL OID should not have a table annotation.
+	 */
+	if (!is_null_oid(oid))
+		entry->oid = oid;
+
+	va_start(ap, format);
+	stats_table_vaddf(table, entry, format, ap);
+	va_end(ap);
+}
+
 static void stats_table_size_addf(struct stats_table *table, size_t value,
 				  const char *format, ...)
 {
@@ -340,6 +408,27 @@ static void stats_table_size_addf(struct stats_table *table, size_t value,
 	va_end(ap);
 }
 
+static void stats_table_object_size_addf(struct stats_table *table,
+					 struct object_id *oid, size_t value,
+					 const char *format, ...)
+{
+	struct stats_table_entry *entry;
+	va_list ap;
+
+	CALLOC_ARRAY(entry, 1);
+	humanise_bytes(value, &entry->value, &entry->unit, HUMANISE_COMPACT);
+
+	/*
+	 * A NULL OID should not have a table annotation.
+	 */
+	if (!is_null_oid(oid))
+		entry->oid = oid;
+
+	va_start(ap, format);
+	stats_table_vaddf(table, entry, format, ap);
+	va_end(ap);
+}
+
 static inline size_t get_total_reference_count(struct ref_stats *stats)
 {
 	return stats->branches + stats->remotes + stats->tags + stats->others;
@@ -404,8 +493,41 @@ static void stats_table_setup_structure(struct stats_table *table,
 			      "    * %s", _("Blobs"));
 	stats_table_size_addf(table, objects->disk_sizes.tags,
 			      "    * %s", _("Tags"));
+
+	stats_table_addf(table, "");
+	stats_table_addf(table, "* %s", _("Largest objects"));
+	stats_table_addf(table, "  * %s", _("Commits"));
+	stats_table_object_size_addf(table,
+				     &objects->largest.commit_size.oid,
+				     objects->largest.commit_size.value,
+				     "    * %s", _("Maximum size"));
+	stats_table_object_count_addf(table,
+				      &objects->largest.parent_count.oid,
+				      objects->largest.parent_count.value,
+				      "    * %s", _("Maximum parents"));
+	stats_table_addf(table, "  * %s", _("Trees"));
+	stats_table_object_size_addf(table,
+				     &objects->largest.tree_size.oid,
+				     objects->largest.tree_size.value,
+				     "    * %s", _("Maximum size"));
+	stats_table_object_count_addf(table,
+				      &objects->largest.tree_entries.oid,
+				      objects->largest.tree_entries.value,
+				      "    * %s", _("Maximum entries"));
+	stats_table_addf(table, "  * %s", _("Blobs"));
+	stats_table_object_size_addf(table,
+				     &objects->largest.blob_size.oid,
+				     objects->largest.blob_size.value,
+				     "    * %s", _("Maximum size"));
+	stats_table_addf(table, "  * %s", _("Tags"));
+	stats_table_object_size_addf(table,
+				     &objects->largest.tag_size.oid,
+				     objects->largest.tag_size.value,
+				     "    * %s", _("Maximum size"));
 }
 
+#define INDEX_WIDTH 4
+
 static void stats_table_print_structure(const struct stats_table *table)
 {
 	const char *name_col_title = _("Repository structure");
@@ -424,7 +546,8 @@ static void stats_table_print_structure(const struct stats_table *table)
 		value_col_width = title_value_width - unit_col_width;
 
 	strbuf_addstr(&buf, "| ");
-	strbuf_utf8_align(&buf, ALIGN_LEFT, name_col_width, name_col_title);
+	strbuf_utf8_align(&buf, ALIGN_LEFT, name_col_width + INDEX_WIDTH,
+			  name_col_title);
 	strbuf_addstr(&buf, " | ");
 	strbuf_utf8_align(&buf, ALIGN_LEFT,
 			  value_col_width + unit_col_width + 1, value_col_title);
@@ -432,7 +555,7 @@ static void stats_table_print_structure(const struct stats_table *table)
 	printf("%s\n", buf.buf);
 
 	printf("| ");
-	for (int i = 0; i < name_col_width; i++)
+	for (int i = 0; i < name_col_width + INDEX_WIDTH; i++)
 		putchar('-');
 	printf(" | ");
 	for (int i = 0; i < value_col_width + unit_col_width + 1; i++)
@@ -453,6 +576,13 @@ static void stats_table_print_structure(const struct stats_table *table)
 		strbuf_reset(&buf);
 		strbuf_addstr(&buf, "| ");
 		strbuf_utf8_align(&buf, ALIGN_LEFT, name_col_width, item->string);
+
+		if (entry && entry->oid)
+			strbuf_addf(&buf, " [%" PRIuMAX "]",
+				    (uintmax_t)entry->index);
+		else
+			strbuf_addchars(&buf, ' ', INDEX_WIDTH);
+
 		strbuf_addstr(&buf, " | ");
 		strbuf_utf8_align(&buf, ALIGN_RIGHT, value_col_width, value);
 		strbuf_addch(&buf, ' ');
@@ -461,6 +591,12 @@ static void stats_table_print_structure(const struct stats_table *table)
 		printf("%s\n", buf.buf);
 	}
 
+	if (table->annotations.nr) {
+		printf("\n");
+		for_each_string_list_item(item, &table->annotations)
+			printf("%s\n", item->string);
+	}
+
 	strbuf_release(&buf);
 }
 
@@ -476,46 +612,76 @@ static void stats_table_clear(struct stats_table *table)
 	}
 
 	string_list_clear(&table->rows, 1);
+	string_list_clear(&table->annotations, 1);
+}
+
+static inline void print_keyvalue(const char *key, char key_delim, size_t value,
+				  char value_delim)
+{
+	printf("%s%c%" PRIuMAX "%c", key, key_delim, (uintmax_t)value,
+	       value_delim);
+}
+
+static void print_object_data(const char *key, char key_delim,
+			      struct object_data *data, char value_delim)
+{
+	print_keyvalue(key, key_delim, data->value, value_delim);
+	printf("%s_oid%c%s%c", key, key_delim, oid_to_hex(&data->oid),
+	       value_delim);
 }
 
 static void structure_keyvalue_print(struct repo_structure *stats,
 				     char key_delim, char value_delim)
 {
-	printf("references.branches.count%c%" PRIuMAX "%c", key_delim,
-	       (uintmax_t)stats->refs.branches, value_delim);
-	printf("references.tags.count%c%" PRIuMAX "%c", key_delim,
-	       (uintmax_t)stats->refs.tags, value_delim);
-	printf("references.remotes.count%c%" PRIuMAX "%c", key_delim,
-	       (uintmax_t)stats->refs.remotes, value_delim);
-	printf("references.others.count%c%" PRIuMAX "%c", key_delim,
-	       (uintmax_t)stats->refs.others, value_delim);
+	print_keyvalue("references.branches.count", key_delim,
+		       stats->refs.branches, value_delim);
+	print_keyvalue("references.tags.count", key_delim,
+		       stats->refs.tags, value_delim);
+	print_keyvalue("references.remotes.count", key_delim,
+		       stats->refs.remotes, value_delim);
+	print_keyvalue("references.others.count", key_delim,
+		       stats->refs.others, value_delim);
 
-	printf("objects.commits.count%c%" PRIuMAX "%c", key_delim,
-	       (uintmax_t)stats->objects.type_counts.commits, value_delim);
-	printf("objects.trees.count%c%" PRIuMAX "%c", key_delim,
-	       (uintmax_t)stats->objects.type_counts.trees, value_delim);
-	printf("objects.blobs.count%c%" PRIuMAX "%c", key_delim,
-	       (uintmax_t)stats->objects.type_counts.blobs, value_delim);
-	printf("objects.tags.count%c%" PRIuMAX "%c", key_delim,
-	       (uintmax_t)stats->objects.type_counts.tags, value_delim);
+	print_keyvalue("objects.commits.count", key_delim,
+		       stats->objects.type_counts.commits, value_delim);
+	print_keyvalue("objects.trees.count", key_delim,
+		       stats->objects.type_counts.trees, value_delim);
+	print_keyvalue("objects.blobs.count", key_delim,
+		       stats->objects.type_counts.blobs, value_delim);
+	print_keyvalue("objects.tags.count", key_delim,
+		       stats->objects.type_counts.tags, value_delim);
 
-	printf("objects.commits.inflated_size%c%" PRIuMAX "%c", key_delim,
-	       (uintmax_t)stats->objects.inflated_sizes.commits, value_delim);
-	printf("objects.trees.inflated_size%c%" PRIuMAX "%c", key_delim,
-	       (uintmax_t)stats->objects.inflated_sizes.trees, value_delim);
-	printf("objects.blobs.inflated_size%c%" PRIuMAX "%c", key_delim,
-	       (uintmax_t)stats->objects.inflated_sizes.blobs, value_delim);
-	printf("objects.tags.inflated_size%c%" PRIuMAX "%c", key_delim,
-	       (uintmax_t)stats->objects.inflated_sizes.tags, value_delim);
+	print_keyvalue("objects.commits.inflated_size", key_delim,
+		       stats->objects.inflated_sizes.commits, value_delim);
+	print_keyvalue("objects.trees.inflated_size", key_delim,
+		       stats->objects.inflated_sizes.trees, value_delim);
+	print_keyvalue("objects.blobs.inflated_size", key_delim,
+		       stats->objects.inflated_sizes.blobs, value_delim);
+	print_keyvalue("objects.tags.inflated_size", key_delim,
+		       stats->objects.inflated_sizes.tags, value_delim);
 
-	printf("objects.commits.disk_size%c%" PRIuMAX "%c", key_delim,
-	       (uintmax_t)stats->objects.disk_sizes.commits, value_delim);
-	printf("objects.trees.disk_size%c%" PRIuMAX "%c", key_delim,
-	       (uintmax_t)stats->objects.disk_sizes.trees, value_delim);
-	printf("objects.blobs.disk_size%c%" PRIuMAX "%c", key_delim,
-	       (uintmax_t)stats->objects.disk_sizes.blobs, value_delim);
-	printf("objects.tags.disk_size%c%" PRIuMAX "%c", key_delim,
-	       (uintmax_t)stats->objects.disk_sizes.tags, value_delim);
+	print_keyvalue("objects.commits.disk_size", key_delim,
+		       stats->objects.disk_sizes.commits, value_delim);
+	print_keyvalue("objects.trees.disk_size", key_delim,
+		       stats->objects.disk_sizes.trees, value_delim);
+	print_keyvalue("objects.blobs.disk_size", key_delim,
+		       stats->objects.disk_sizes.blobs, value_delim);
+	print_keyvalue("objects.tags.disk_size", key_delim,
+		       stats->objects.disk_sizes.tags, value_delim);
+
+	print_object_data("objects.commits.max_size", key_delim,
+			  &stats->objects.largest.commit_size, value_delim);
+	print_object_data("objects.trees.max_size", key_delim,
+			  &stats->objects.largest.tree_size, value_delim);
+	print_object_data("objects.blobs.max_size", key_delim,
+			  &stats->objects.largest.blob_size, value_delim);
+	print_object_data("objects.tags.max_size", key_delim,
+			  &stats->objects.largest.tag_size, value_delim);
+
+	print_object_data("objects.commits.max_parents", key_delim,
+			  &stats->objects.largest.parent_count, value_delim);
+	print_object_data("objects.trees.max_entries", key_delim,
+			  &stats->objects.largest.tree_entries, value_delim);
 
 	fflush(stdout);
 }
@@ -585,55 +751,97 @@ struct count_objects_data {
 	struct progress *progress;
 };
 
+static void check_largest(struct object_data *data, struct object_id *oid,
+			  size_t value)
+{
+	if (value > data->value || is_null_oid(&data->oid)) {
+		oidcpy(&data->oid, oid);
+		data->value = value;
+	}
+}
+
+static size_t count_tree_entries(struct object *obj)
+{
+	struct tree *t = object_as_type(obj, OBJ_TREE, 0);
+	struct name_entry entry;
+	struct tree_desc desc;
+	size_t count = 0;
+
+	init_tree_desc(&desc, &t->object.oid, t->buffer, t->size);
+	while (tree_entry(&desc, &entry))
+		count++;
+
+	return count;
+}
+
 static int count_objects(const char *path UNUSED, struct oid_array *oids,
 			 enum object_type type, void *cb_data)
 {
 	struct count_objects_data *data = cb_data;
 	struct object_stats *stats = data->stats;
-	size_t inflated_total = 0;
-	size_t disk_total = 0;
 	size_t object_count;
 
 	for (size_t i = 0; i < oids->nr; i++) {
 		struct object_info oi = OBJECT_INFO_INIT;
 		unsigned long inflated;
+		struct commit *commit;
+		struct object *obj;
+		void *content;
 		off_t disk;
+		int eaten;
 
 		oi.sizep = &inflated;
 		oi.disk_sizep = &disk;
+		oi.contentp = &content;
 
 		if (odb_read_object_info_extended(data->odb, &oids->oid[i], &oi,
 						  OBJECT_INFO_SKIP_FETCH_OBJECT |
 						  OBJECT_INFO_QUICK) < 0)
 			continue;
 
-		inflated_total += inflated;
-		disk_total += disk;
-	}
+		obj = parse_object_buffer(the_repository, &oids->oid[i], type,
+					  inflated, content, &eaten);
 
-	switch (type) {
-	case OBJ_TAG:
-		stats->type_counts.tags += oids->nr;
-		stats->inflated_sizes.tags += inflated_total;
-		stats->disk_sizes.tags += disk_total;
-		break;
-	case OBJ_COMMIT:
-		stats->type_counts.commits += oids->nr;
-		stats->inflated_sizes.commits += inflated_total;
-		stats->disk_sizes.commits += disk_total;
-		break;
-	case OBJ_TREE:
-		stats->type_counts.trees += oids->nr;
-		stats->inflated_sizes.trees += inflated_total;
-		stats->disk_sizes.trees += disk_total;
-		break;
-	case OBJ_BLOB:
-		stats->type_counts.blobs += oids->nr;
-		stats->inflated_sizes.blobs += inflated_total;
-		stats->disk_sizes.blobs += disk_total;
-		break;
-	default:
-		BUG("invalid object type");
+		switch (type) {
+		case OBJ_TAG:
+			stats->type_counts.tags++;
+			stats->inflated_sizes.tags += inflated;
+			stats->disk_sizes.tags += disk;
+			check_largest(&stats->largest.tag_size, &oids->oid[i],
+				      inflated);
+			break;
+		case OBJ_COMMIT:
+			commit = object_as_type(obj, OBJ_COMMIT, 0);
+			stats->type_counts.commits++;
+			stats->inflated_sizes.commits += inflated;
+			stats->disk_sizes.commits += disk;
+			check_largest(&stats->largest.commit_size, &oids->oid[i],
+				      inflated);
+			check_largest(&stats->largest.parent_count, &oids->oid[i],
+				      commit_list_count(commit->parents));
+			break;
+		case OBJ_TREE:
+			stats->type_counts.trees++;
+			stats->inflated_sizes.trees += inflated;
+			stats->disk_sizes.trees += disk;
+			check_largest(&stats->largest.tree_size, &oids->oid[i],
+				      inflated);
+			check_largest(&stats->largest.tree_entries, &oids->oid[i],
+				      count_tree_entries(obj));
+			break;
+		case OBJ_BLOB:
+			stats->type_counts.blobs++;
+			stats->inflated_sizes.blobs += inflated;
+			stats->disk_sizes.blobs += disk;
+			check_largest(&stats->largest.blob_size, &oids->oid[i],
+				      inflated);
+			break;
+		default:
+			BUG("invalid object type");
+		}
+
+		if (!eaten)
+			free(content);
 	}
 
 	object_count = get_total_object_values(&stats->type_counts);
@@ -669,6 +877,7 @@ static int cmd_repo_structure(int argc, const char **argv, const char *prefix,
 {
 	struct stats_table table = {
 		.rows = STRING_LIST_INIT_DUP,
+		.annotations = STRING_LIST_INIT_DUP,
 	};
 	enum output_format format = FORMAT_TABLE;
 	struct repo_structure stats = { 0 };
@@ -686,7 +895,7 @@ static int cmd_repo_structure(int argc, const char **argv, const char *prefix,
 		OPT_END()
 	};
 
-	argc = parse_options(argc, argv, prefix, options, repo_usage, 0);
+	argc = parse_options(argc, argv, prefix, options, repo_structure_usage, 0);
 	if (argc)
 		usage(_("too many arguments"));
 
diff --git a/builtin/reset.c b/builtin/reset.c
index 88f95f9..3590be5 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -346,7 +346,7 @@ int cmd_reset(int argc,
 	struct object_id oid;
 	struct pathspec pathspec;
 	int intent_to_add = 0;
-	struct add_p_opt add_p_opt = ADD_P_OPT_INIT;
+	struct interactive_options interactive_opts = INTERACTIVE_OPTIONS_INIT;
 	const struct option options[] = {
 		OPT__QUIET(&quiet, N_("be quiet, only report errors")),
 		OPT_BOOL(0, "no-refresh", &no_refresh,
@@ -371,10 +371,10 @@ int cmd_reset(int argc,
 			       PARSE_OPT_OPTARG,
 			       option_parse_recurse_submodules_worktree_updater),
 		OPT_BOOL('p', "patch", &patch_mode, N_("select hunks interactively")),
-		OPT_BOOL(0, "auto-advance", &add_p_opt.auto_advance,
+		OPT_BOOL(0, "auto-advance", &interactive_opts.auto_advance,
 			 N_("auto advance to the next file when selecting hunks interactively")),
-		OPT_DIFF_UNIFIED(&add_p_opt.context),
-		OPT_DIFF_INTERHUNK_CONTEXT(&add_p_opt.interhunkcontext),
+		OPT_DIFF_UNIFIED(&interactive_opts.context),
+		OPT_DIFF_INTERHUNK_CONTEXT(&interactive_opts.interhunkcontext),
 		OPT_BOOL('N', "intent-to-add", &intent_to_add,
 				N_("record only the fact that removed paths will be added later")),
 		OPT_PATHSPEC_FROM_FILE(&pathspec_from_file),
@@ -425,9 +425,9 @@ int cmd_reset(int argc,
 		oidcpy(&oid, &tree->object.oid);
 	}
 
-	if (add_p_opt.context < -1)
+	if (interactive_opts.context < -1)
 		die(_("'%s' cannot be negative"), "--unified");
-	if (add_p_opt.interhunkcontext < -1)
+	if (interactive_opts.interhunkcontext < -1)
 		die(_("'%s' cannot be negative"), "--inter-hunk-context");
 
 	prepare_repo_settings(the_repository);
@@ -438,14 +438,14 @@ int cmd_reset(int argc,
 			die(_("options '%s' and '%s' cannot be used together"), "--patch", "--{hard,mixed,soft}");
 		trace2_cmd_mode("patch-interactive");
 		update_ref_status = !!run_add_p(the_repository, ADD_P_RESET,
-						&add_p_opt, rev, &pathspec);
+						&interactive_opts, rev, &pathspec, 0);
 		goto cleanup;
 	} else {
-		if (add_p_opt.context != -1)
+		if (interactive_opts.context != -1)
 			die(_("the option '%s' requires '%s'"), "--unified", "--patch");
-		if (add_p_opt.interhunkcontext != -1)
+		if (interactive_opts.interhunkcontext != -1)
 			die(_("the option '%s' requires '%s'"), "--inter-hunk-context", "--patch");
-		if (!add_p_opt.auto_advance)
+		if (!interactive_opts.auto_advance)
 			die(_("the option '%s' requires '%s'"), "--no-auto-advance", "--patch");
 	}
 
diff --git a/builtin/stash.c b/builtin/stash.c
index e79d612..95c5005 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -1232,7 +1232,7 @@ static int check_changes(const struct pathspec *ps, int include_untracked,
 }
 
 static int save_untracked_files(struct stash_info *info, struct strbuf *msg,
-				struct strbuf files)
+				struct strbuf *files)
 {
 	int ret = 0;
 	struct strbuf untracked_msg = STRBUF_INIT;
@@ -1246,7 +1246,7 @@ static int save_untracked_files(struct stash_info *info, struct strbuf *msg,
 			 stash_index_path.buf);
 
 	strbuf_addf(&untracked_msg, "untracked files on %s\n", msg->buf);
-	if (pipe_command(&cp_upd_index, files.buf, files.len, NULL, 0,
+	if (pipe_command(&cp_upd_index, files->buf, files->len, NULL, 0,
 			 NULL, 0)) {
 		ret = -1;
 		goto done;
@@ -1306,7 +1306,7 @@ static int stash_staged(struct stash_info *info, struct strbuf *out_patch,
 
 static int stash_patch(struct stash_info *info, const struct pathspec *ps,
 		       struct strbuf *out_patch, int quiet,
-		       struct add_p_opt *add_p_opt)
+		       struct interactive_options *interactive_opts)
 {
 	int ret = 0;
 	struct child_process cp_read_tree = CHILD_PROCESS_INIT;
@@ -1331,7 +1331,7 @@ static int stash_patch(struct stash_info *info, const struct pathspec *ps,
 	old_index_env = xstrdup_or_null(getenv(INDEX_ENVIRONMENT));
 	setenv(INDEX_ENVIRONMENT, the_repository->index_file, 1);
 
-	ret = !!run_add_p(the_repository, ADD_P_STASH, add_p_opt, NULL, ps);
+	ret = !!run_add_p(the_repository, ADD_P_STASH, interactive_opts, NULL, ps, 0);
 
 	the_repository->index_file = old_repo_index_file;
 	if (old_index_env && *old_index_env)
@@ -1427,7 +1427,8 @@ static int stash_working_tree(struct stash_info *info, const struct pathspec *ps
 }
 
 static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_buf,
-			   int include_untracked, int patch_mode, struct add_p_opt *add_p_opt,
+			   int include_untracked, int patch_mode,
+			   struct interactive_options *interactive_opts,
 			   int only_staged, struct stash_info *info, struct strbuf *patch,
 			   int quiet)
 {
@@ -1499,7 +1500,7 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b
 	parents = NULL;
 
 	if (include_untracked) {
-		if (save_untracked_files(info, &msg, untracked_files)) {
+		if (save_untracked_files(info, &msg, &untracked_files)) {
 			if (!quiet)
 				fprintf_ln(stderr, _("Cannot save "
 						     "the untracked files"));
@@ -1509,7 +1510,7 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b
 		untracked_commit_option = 1;
 	}
 	if (patch_mode) {
-		ret = stash_patch(info, ps, patch, quiet, add_p_opt);
+		ret = stash_patch(info, ps, patch, quiet, interactive_opts);
 		if (ret < 0) {
 			if (!quiet)
 				fprintf_ln(stderr, _("Cannot save the current "
@@ -1595,7 +1596,8 @@ static int create_stash(int argc, const char **argv, const char *prefix UNUSED,
 }
 
 static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int quiet,
-			 int keep_index, int patch_mode, struct add_p_opt *add_p_opt,
+			 int keep_index, int patch_mode,
+			 struct interactive_options *interactive_opts,
 			 int include_untracked, int only_staged)
 {
 	int ret = 0;
@@ -1667,7 +1669,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
 	if (stash_msg)
 		strbuf_addstr(&stash_msg_buf, stash_msg);
 	if (do_create_stash(ps, &stash_msg_buf, include_untracked, patch_mode,
-			    add_p_opt, only_staged, &info, &patch, quiet)) {
+			    interactive_opts, only_staged, &info, &patch, quiet)) {
 		ret = -1;
 		goto done;
 	}
@@ -1841,7 +1843,7 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 	const char *stash_msg = NULL;
 	char *pathspec_from_file = NULL;
 	struct pathspec ps;
-	struct add_p_opt add_p_opt = ADD_P_OPT_INIT;
+	struct interactive_options interactive_opts = INTERACTIVE_OPTIONS_INIT;
 	struct option options[] = {
 		OPT_BOOL('k', "keep-index", &keep_index,
 			 N_("keep index")),
@@ -1849,10 +1851,10 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 			 N_("stash staged changes only")),
 		OPT_BOOL('p', "patch", &patch_mode,
 			 N_("stash in patch mode")),
-		OPT_BOOL(0, "auto-advance", &add_p_opt.auto_advance,
+		OPT_BOOL(0, "auto-advance", &interactive_opts.auto_advance,
 			 N_("auto advance to the next file when selecting hunks interactively")),
-		OPT_DIFF_UNIFIED(&add_p_opt.context),
-		OPT_DIFF_INTERHUNK_CONTEXT(&add_p_opt.interhunkcontext),
+		OPT_DIFF_UNIFIED(&interactive_opts.context),
+		OPT_DIFF_INTERHUNK_CONTEXT(&interactive_opts.interhunkcontext),
 		OPT__QUIET(&quiet, N_("quiet mode")),
 		OPT_BOOL('u', "include-untracked", &include_untracked,
 			 N_("include untracked files in stash")),
@@ -1909,21 +1911,21 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 	}
 
 	if (!patch_mode) {
-		if (add_p_opt.context != -1)
+		if (interactive_opts.context != -1)
 			die(_("the option '%s' requires '%s'"), "--unified", "--patch");
-		if (add_p_opt.interhunkcontext != -1)
+		if (interactive_opts.interhunkcontext != -1)
 			die(_("the option '%s' requires '%s'"), "--inter-hunk-context", "--patch");
-		if (!add_p_opt.auto_advance)
+		if (!interactive_opts.auto_advance)
 			die(_("the option '%s' requires '%s'"), "--no-auto-advance", "--patch");
 	}
 
-	if (add_p_opt.context < -1)
+	if (interactive_opts.context < -1)
 		die(_("'%s' cannot be negative"), "--unified");
-	if (add_p_opt.interhunkcontext < -1)
+	if (interactive_opts.interhunkcontext < -1)
 		die(_("'%s' cannot be negative"), "--inter-hunk-context");
 
 	ret = do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
-			    &add_p_opt, include_untracked, only_staged);
+			    &interactive_opts, include_untracked, only_staged);
 
 	clear_pathspec(&ps);
 	free(pathspec_from_file);
@@ -1948,7 +1950,7 @@ static int save_stash(int argc, const char **argv, const char *prefix,
 	const char *stash_msg = NULL;
 	struct pathspec ps;
 	struct strbuf stash_msg_buf = STRBUF_INIT;
-	struct add_p_opt add_p_opt = ADD_P_OPT_INIT;
+	struct interactive_options interactive_opts = INTERACTIVE_OPTIONS_INIT;
 	struct option options[] = {
 		OPT_BOOL('k', "keep-index", &keep_index,
 			 N_("keep index")),
@@ -1956,10 +1958,10 @@ static int save_stash(int argc, const char **argv, const char *prefix,
 			 N_("stash staged changes only")),
 		OPT_BOOL('p', "patch", &patch_mode,
 			 N_("stash in patch mode")),
-		OPT_BOOL(0, "auto-advance", &add_p_opt.auto_advance,
+		OPT_BOOL(0, "auto-advance", &interactive_opts.auto_advance,
 			 N_("auto advance to the next file when selecting hunks interactively")),
-		OPT_DIFF_UNIFIED(&add_p_opt.context),
-		OPT_DIFF_INTERHUNK_CONTEXT(&add_p_opt.interhunkcontext),
+		OPT_DIFF_UNIFIED(&interactive_opts.context),
+		OPT_DIFF_INTERHUNK_CONTEXT(&interactive_opts.interhunkcontext),
 		OPT__QUIET(&quiet, N_("quiet mode")),
 		OPT_BOOL('u', "include-untracked", &include_untracked,
 			 N_("include untracked files in stash")),
@@ -1979,22 +1981,22 @@ static int save_stash(int argc, const char **argv, const char *prefix,
 
 	memset(&ps, 0, sizeof(ps));
 
-	if (add_p_opt.context < -1)
+	if (interactive_opts.context < -1)
 		die(_("'%s' cannot be negative"), "--unified");
-	if (add_p_opt.interhunkcontext < -1)
+	if (interactive_opts.interhunkcontext < -1)
 		die(_("'%s' cannot be negative"), "--inter-hunk-context");
 
 	if (!patch_mode) {
-		if (add_p_opt.context != -1)
+		if (interactive_opts.context != -1)
 			die(_("the option '%s' requires '%s'"), "--unified", "--patch");
-		if (add_p_opt.interhunkcontext != -1)
+		if (interactive_opts.interhunkcontext != -1)
 			die(_("the option '%s' requires '%s'"), "--inter-hunk-context", "--patch");
-		if (!add_p_opt.auto_advance)
+		if (!interactive_opts.auto_advance)
 			die(_("the option '%s' requires '%s'"), "--no-auto-advance", "--patch");
 	}
 
 	ret = do_push_stash(&ps, stash_msg, quiet, keep_index,
-			    patch_mode, &add_p_opt, include_untracked,
+			    patch_mode, &interactive_opts, include_untracked,
 			    only_staged);
 
 	strbuf_release(&stash_msg_buf);
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 143f7cb..2f589e3 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -29,6 +29,7 @@
 #include "object-file.h"
 #include "object-name.h"
 #include "odb.h"
+#include "odb/source.h"
 #include "advice.h"
 #include "branch.h"
 #include "list-objects-filter-options.h"
@@ -113,6 +114,43 @@ static int get_default_remote_submodule(const char *module_path, char **default_
 	return 0;
 }
 
+static int module_get_default_remote(int argc, const char **argv, const char *prefix,
+				     struct repository *repo UNUSED)
+{
+	const char *path;
+	char *resolved_path = NULL;
+	char *default_remote = NULL;
+	int code;
+	struct option options[] = {
+		OPT_END()
+	};
+	const char *const usage[] = {
+		N_("git submodule--helper get-default-remote <path>"),
+		NULL
+	};
+
+	argc = parse_options(argc, argv, prefix, options, usage, 0);
+	if (argc != 1)
+		usage_with_options(usage, options);
+
+	path = argv[0];
+	if (prefix && *prefix && !is_absolute_path(path)) {
+		resolved_path = xstrfmt("%s%s", prefix, path);
+		path = resolved_path;
+	}
+
+	code = get_default_remote_submodule(path, &default_remote);
+	if (code) {
+		free(resolved_path);
+		return code;
+	}
+
+	printf("%s\n", default_remote);
+	free(default_remote);
+	free(resolved_path);
+	return 0;
+}
+
 /* the result should be freed by the caller. */
 static char *get_submodule_displaypath(const char *path, const char *prefix,
 				       const char *super_prefix)
@@ -1160,7 +1198,7 @@ static void submodule_summary_callback(struct diff_queue_struct *q,
 
 		if (!S_ISGITLINK(p->one->mode) && !S_ISGITLINK(p->two->mode))
 			continue;
-		temp = (struct module_cb*)malloc(sizeof(struct module_cb));
+		temp = xmalloc(sizeof(*temp));
 		temp->mod_src = p->one->mode;
 		temp->mod_dst = p->two->mode;
 		temp->oid_src = p->one->oid;
@@ -3789,6 +3827,7 @@ int cmd_submodule__helper(int argc,
 		OPT_SUBCOMMAND("set-url", &fn, module_set_url),
 		OPT_SUBCOMMAND("set-branch", &fn, module_set_branch),
 		OPT_SUBCOMMAND("create-branch", &fn, module_create_branch),
+		OPT_SUBCOMMAND("get-default-remote", &fn, module_get_default_remote),
 		OPT_END()
 	};
 	argc = parse_options(argc, argv, prefix, options, usage, 0);
diff --git a/builtin/tag.c b/builtin/tag.c
index aeb04c4..d51c2e3 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -167,7 +167,7 @@ static int do_sign(struct strbuf *buffer, struct object_id **compat_oid,
 	char *keyid = get_signing_key();
 	int ret = -1;
 
-	if (sign_buffer(buffer, &sig, keyid))
+	if (sign_buffer(buffer, &sig, keyid, 0))
 		goto out;
 
 	if (compat) {
@@ -176,7 +176,7 @@ static int do_sign(struct strbuf *buffer, struct object_id **compat_oid,
 		if (convert_object_file(the_repository ,&compat_buf, algo, compat,
 					buffer->buf, buffer->len, OBJ_TAG, 1))
 			goto out;
-		if (sign_buffer(&compat_buf, &compat_sig, keyid))
+		if (sign_buffer(&compat_buf, &compat_sig, keyid, 0))
 			goto out;
 		add_header_signature(&compat_buf, &sig, algo);
 		strbuf_addbuf(&compat_buf, &compat_sig);
@@ -499,8 +499,8 @@ int cmd_tag(int argc,
 		OPT_CALLBACK_F('m', "message", &msg, N_("message"),
 			       N_("tag message"), PARSE_OPT_NONEG, parse_msg_arg),
 		OPT_FILENAME('F', "file", &msgfile, N_("read message from file")),
-		OPT_PASSTHRU_ARGV(0, "trailer", &trailer_args, N_("trailer"),
-				  N_("add custom trailer(s)"), PARSE_OPT_NONEG),
+		OPT_STRVEC(0, "trailer", &trailer_args, N_("trailer"),
+			   N_("add custom trailer(s)")),
 		OPT_BOOL('e', "edit", &edit_flag, N_("force edit of tag message")),
 		OPT_BOOL('s', "sign", &opt.sign, N_("annotated and GPG-signed tag")),
 		OPT_CLEANUP(&cleanup_arg),
@@ -568,6 +568,9 @@ int cmd_tag(int argc,
 	if (cmdmode == 'l')
 		setup_auto_pager("tag", 1);
 
+	if (trailer_args.nr)
+		trailer_config_init();
+
 	if (opt.sign == -1)
 		opt.sign = cmdmode ? 0 : config_sign_tag > 0;
 
diff --git a/builtin/worktree.c b/builtin/worktree.c
index bc2d0d6..4035b1c 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -539,7 +539,7 @@ static int add_worktree(const char *path, const char *refname,
 
 	strbuf_reset(&sb);
 	strbuf_addf(&sb, "%s/gitdir", sb_repo.buf);
-	write_worktree_linking_files(sb_git, sb, opts->relative_paths);
+	write_worktree_linking_files(sb_git.buf, sb.buf, opts->relative_paths);
 	strbuf_reset(&sb);
 	strbuf_addf(&sb, "%s/commondir", sb_repo.buf);
 	write_file(sb.buf, "../..");
diff --git a/cache-tree.c b/cache-tree.c
index 16c3a36..60bcc07 100644
--- a/cache-tree.c
+++ b/cache-tree.c
@@ -723,11 +723,11 @@ static int write_index_as_tree_internal(struct object_id *oid,
 	return 0;
 }
 
-struct tree* write_in_core_index_as_tree(struct repository *repo) {
+struct tree *write_in_core_index_as_tree(struct repository *repo,
+					 struct index_state *index_state) {
 	struct object_id o;
 	int was_valid, ret;
 
-	struct index_state *index_state	= repo->index;
 	was_valid = index_state->cache_tree &&
 		    cache_tree_fully_valid(index_state->cache_tree);
 
diff --git a/cache-tree.h b/cache-tree.h
index b82c496..f8bddae 100644
--- a/cache-tree.h
+++ b/cache-tree.h
@@ -47,7 +47,8 @@ int cache_tree_verify(struct repository *, struct index_state *);
 #define WRITE_TREE_UNMERGED_INDEX (-2)
 #define WRITE_TREE_PREFIX_ERROR (-3)
 
-struct tree* write_in_core_index_as_tree(struct repository *repo);
+struct tree *write_in_core_index_as_tree(struct repository *repo,
+					 struct index_state *index_state);
 int write_index_as_tree(struct object_id *oid, struct index_state *index_state, const char *index_path, int flags, const char *prefix);
 void prime_cache_tree(struct repository *, struct index_state *, struct tree *);
 
diff --git a/ci/run-static-analysis.sh b/ci/run-static-analysis.sh
index 9e9c726..ba67e80 100755
--- a/ci/run-static-analysis.sh
+++ b/ci/run-static-analysis.sh
@@ -10,7 +10,7 @@
 set +x
 
 fail=
-for cocci_patch in contrib/coccinelle/*.patch
+for cocci_patch in tools/coccinelle/*.patch
 do
 	if test -s "$cocci_patch"
 	then
diff --git a/commit-graph.c b/commit-graph.c
index d250a72..c030003 100644
--- a/commit-graph.c
+++ b/commit-graph.c
@@ -1980,9 +1980,11 @@ static void fill_oids_from_all_packs(struct write_commit_graph_context *ctx)
 			ctx->approx_nr_objects);
 
 	odb_prepare_alternates(ctx->r->objects);
-	for (source = ctx->r->objects->sources; source; source = source->next)
-		packfile_store_for_each_object(source->packfiles, &oi, add_packed_commits_oi,
+	for (source = ctx->r->objects->sources; source; source = source->next) {
+		struct odb_source_files *files = odb_source_files_downcast(source);
+		packfile_store_for_each_object(files->packed, &oi, add_packed_commits_oi,
 					       ctx, ODB_FOR_EACH_OBJECT_PACK_ORDER);
+	}
 
 	if (ctx->progress_done < ctx->approx_nr_objects)
 		display_progress(ctx->progress, ctx->approx_nr_objects);
@@ -2605,7 +2607,8 @@ int write_commit_graph(struct odb_source *source,
 			replace = ctx.opts->split_flags & COMMIT_GRAPH_SPLIT_REPLACE;
 	}
 
-	ctx.approx_nr_objects = repo_approximate_object_count(r);
+	if (odb_count_objects(r->objects, ODB_COUNT_OBJECTS_APPROXIMATE, &ctx.approx_nr_objects) < 0)
+		ctx.approx_nr_objects = 0;
 
 	if (ctx.append && g) {
 		for (i = 0; i < g->num_commits; i++) {
diff --git a/commit-reach.c b/commit-reach.c
index 9604bbd..d3a9b3e 100644
--- a/commit-reach.c
+++ b/commit-reach.c
@@ -1117,10 +1117,8 @@ void ahead_behind(struct repository *r,
 
 	/* STALE is used here, PARENT2 is used by insert_no_dup(). */
 	repo_clear_commit_marks(r, PARENT2 | STALE);
-	while (prio_queue_peek(&queue)) {
-		struct commit *c = prio_queue_get(&queue);
-		free_bit_array(c);
-	}
+	for (size_t i = 0; i < queue.nr; i++)
+		free_bit_array(queue.array[i].data);
 	clear_bit_arrays(&bit_arrays);
 	clear_prio_queue(&queue);
 }
diff --git a/commit.c b/commit.c
index 0ffdd66..80d8d07 100644
--- a/commit.c
+++ b/commit.c
@@ -1170,18 +1170,6 @@ int add_header_signature(struct strbuf *buf, struct strbuf *sig, const struct gi
 	return 0;
 }
 
-static int sign_commit_to_strbuf(struct strbuf *sig, struct strbuf *buf, const char *keyid)
-{
-	char *keyid_to_free = NULL;
-	int ret = 0;
-	if (!keyid || !*keyid)
-		keyid = keyid_to_free = get_signing_key();
-	if (sign_buffer(buf, sig, keyid))
-		ret = -1;
-	free(keyid_to_free);
-	return ret;
-}
-
 int parse_signed_commit(const struct commit *commit,
 			struct strbuf *payload, struct strbuf *signature,
 			const struct git_hash_algo *algop)
@@ -1759,7 +1747,8 @@ int commit_tree_extended(const char *msg, size_t msg_len,
 		oidcpy(&parent_buf[i++], &p->item->object.oid);
 
 	write_commit_tree(&buffer, msg, msg_len, tree, parent_buf, nparents, author, committer, extra);
-	if (sign_commit && sign_commit_to_strbuf(&sig, &buffer, sign_commit)) {
+	if (sign_commit && sign_buffer(&buffer, &sig, sign_commit,
+				       SIGN_BUFFER_USE_DEFAULT_KEY)) {
 		result = -1;
 		goto out;
 	}
@@ -1791,7 +1780,9 @@ int commit_tree_extended(const char *msg, size_t msg_len,
 		free_commit_extra_headers(compat_extra);
 		free(mapped_parents);
 
-		if (sign_commit && sign_commit_to_strbuf(&compat_sig, &compat_buffer, sign_commit)) {
+		if (sign_commit && sign_buffer(&compat_buffer, &compat_sig,
+					       sign_commit,
+					       SIGN_BUFFER_USE_DEFAULT_KEY)) {
 			result = -1;
 			goto out;
 		}
diff --git a/commit.h b/commit.h
index f2f39e1..5815004 100644
--- a/commit.h
+++ b/commit.h
@@ -287,7 +287,7 @@ int for_each_commit_graft(each_commit_graft_fn, void *);
 int interactive_add(struct repository *repo,
 		    const char **argv,
 		    const char *prefix,
-		    int patch, struct add_p_opt *add_p_opt);
+		    int patch, struct interactive_options *opts);
 
 struct commit_extra_header {
 	struct commit_extra_header *next;
@@ -400,8 +400,6 @@ LAST_ARG_MUST_BE_NULL
 int run_commit_hook(int editor_is_used, const char *index_file,
 		    int *invoked_hook, const char *name, ...);
 
-/* Sign a commit or tag buffer, storing the result in a header. */
-int sign_with_header(struct strbuf *buf, const char *keyid);
 /* Parse the signature out of a header. */
 int parse_buffer_signed_by_header(const char *buffer,
 				  unsigned long size,
diff --git a/compat/posix.h b/compat/posix.h
index 245386f..3c611d2 100644
--- a/compat/posix.h
+++ b/compat/posix.h
@@ -137,6 +137,9 @@
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 #include <sys/statvfs.h>
+#ifndef NO_WRITEV
+#include <sys/uio.h>
+#endif
 #include <termios.h>
 #ifndef NO_SYS_SELECT_H
 #include <sys/select.h>
@@ -323,6 +326,17 @@ int git_lstat(const char *, struct stat *);
 ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);
 #endif
 
+#ifdef NO_WRITEV
+#define writev git_writev
+#define iovec git_iovec
+struct git_iovec {
+	void *iov_base;
+	size_t iov_len;
+};
+
+ssize_t git_writev(int fd, const struct iovec *iov, int iovcnt);
+#endif
+
 #ifdef NO_SETENV
 #define setenv gitsetenv
 int gitsetenv(const char *, const char *, int);
diff --git a/compat/regcomp_enhanced.c b/compat/regcomp_enhanced.c
index 84193ce..29c74ee 100644
--- a/compat/regcomp_enhanced.c
+++ b/compat/regcomp_enhanced.c
@@ -3,6 +3,11 @@
 
 int git_regcomp(regex_t *preg, const char *pattern, int cflags)
 {
+	/*
+	 * If you are on macOS with clang and fail to compile this line,
+	 * https://lore.kernel.org/git/458ad3c1-96df-4575-ee42-e6eb754f25f6@gmx.de/
+	 * might be relevant.
+	 */
 	if (!(cflags & REG_EXTENDED))
 		cflags |= REG_ENHANCED;
 	return regcomp(preg, pattern, cflags);
diff --git a/compat/writev.c b/compat/writev.c
new file mode 100644
index 0000000..3a94870
--- /dev/null
+++ b/compat/writev.c
@@ -0,0 +1,44 @@
+#include "../git-compat-util.h"
+#include "../wrapper.h"
+
+ssize_t git_writev(int fd, const struct iovec *iov, int iovcnt)
+{
+	size_t total_written = 0;
+	size_t sum = 0;
+
+	/*
+	 * According to writev(3p), the syscall shall error with EINVAL in case
+	 * the sum of `iov_len` overflows `ssize_t`.
+	 */
+	 for (int i = 0; i < iovcnt; i++) {
+		if (iov[i].iov_len > maximum_signed_value_of_type(ssize_t) ||
+		    iov[i].iov_len + sum > maximum_signed_value_of_type(ssize_t)) {
+			errno = EINVAL;
+			return -1;
+		}
+
+		sum += iov[i].iov_len;
+	}
+
+	for (int i = 0; i < iovcnt; i++) {
+		const char *bytes = iov[i].iov_base;
+		size_t iovec_written = 0;
+
+		while (iovec_written < iov[i].iov_len) {
+			ssize_t bytes_written = xwrite(fd, bytes + iovec_written,
+						       iov[i].iov_len - iovec_written);
+			if (bytes_written < 0) {
+				if (total_written)
+					goto out;
+				return bytes_written;
+			}
+			if (!bytes_written)
+				goto out;
+			iovec_written += bytes_written;
+			total_written += bytes_written;
+		}
+	}
+
+out:
+	return (ssize_t) total_written;
+}
diff --git a/config.mak.dev b/config.mak.dev
index e86b6e1..c8dcf78 100644
--- a/config.mak.dev
+++ b/config.mak.dev
@@ -1,5 +1,5 @@
 ifndef COMPILER_FEATURES
-COMPILER_FEATURES := $(shell ./detect-compiler $(CC))
+COMPILER_FEATURES := $(shell ./tools/detect-compiler $(CC))
 endif
 
 ifeq ($(filter no-error,$(DEVOPTS)),)
diff --git a/config.mak.uname b/config.mak.uname
index 5feb582..ccb3f718 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -459,6 +459,7 @@
 	SANE_TOOL_PATH ?= $(msvc_bin_dir_msys)
 	HAVE_ALLOCA_H = YesPlease
 	NO_PREAD = YesPlease
+	NO_WRITEV = YesPlease
 	NEEDS_CRYPTO_WITH_SSL = YesPlease
 	NO_LIBGEN_H = YesPlease
 	NO_POLL = YesPlease
@@ -674,6 +675,7 @@
 	pathsep = ;
 	HAVE_ALLOCA_H = YesPlease
 	NO_PREAD = YesPlease
+	NO_WRITEV = YesPlease
 	NEEDS_CRYPTO_WITH_SSL = YesPlease
 	NO_LIBGEN_H = YesPlease
 	NO_POLL = YesPlease
diff --git a/connected.c b/connected.c
index 7940310..6718503 100644
--- a/connected.c
+++ b/connected.c
@@ -45,20 +45,6 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
 		return err;
 	}
 
-	if (transport && transport->smart_options &&
-	    transport->smart_options->self_contained_and_connected &&
-	    transport->pack_lockfiles.nr == 1 &&
-	    strip_suffix(transport->pack_lockfiles.items[0].string,
-			 ".keep", &base_len)) {
-		struct strbuf idx_file = STRBUF_INIT;
-		strbuf_add(&idx_file, transport->pack_lockfiles.items[0].string,
-			   base_len);
-		strbuf_addstr(&idx_file, ".idx");
-		new_pack = add_packed_git(the_repository, idx_file.buf,
-					  idx_file.len, 1);
-		strbuf_release(&idx_file);
-	}
-
 	if (repo_has_promisor_remote(the_repository)) {
 		/*
 		 * For partial clones, we don't want to have to do a regular
@@ -90,7 +76,6 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
 promisor_pack_found:
 			;
 		} while ((oid = fn(cb_data)) != NULL);
-		free(new_pack);
 		return 0;
 	}
 
@@ -127,15 +112,27 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
 	else
 		rev_list.no_stderr = opt->quiet;
 
-	if (start_command(&rev_list)) {
-		free(new_pack);
+	if (start_command(&rev_list))
 		return error(_("Could not run 'git rev-list'"));
-	}
 
 	sigchain_push(SIGPIPE, SIG_IGN);
 
 	rev_list_in = xfdopen(rev_list.in, "w");
 
+	if (transport && transport->smart_options &&
+	    transport->smart_options->self_contained_and_connected &&
+	    transport->pack_lockfiles.nr == 1 &&
+	    strip_suffix(transport->pack_lockfiles.items[0].string,
+			 ".keep", &base_len)) {
+		struct strbuf idx_file = STRBUF_INIT;
+		strbuf_add(&idx_file, transport->pack_lockfiles.items[0].string,
+			   base_len);
+		strbuf_addstr(&idx_file, ".idx");
+		new_pack = add_packed_git(the_repository, idx_file.buf,
+					  idx_file.len, 1);
+		strbuf_release(&idx_file);
+	}
+
 	do {
 		/*
 		 * If index-pack already checked that:
@@ -162,6 +159,9 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
 		err = error_errno(_("failed to close rev-list's stdin"));
 
 	sigchain_pop(SIGPIPE);
-	free(new_pack);
+	if (new_pack) {
+		close_pack(new_pack);
+		free(new_pack);
+	}
 	return finish_command(&rev_list) || err;
 }
diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt
index c6cfb87..81b4306 100644
--- a/contrib/buildsystems/CMakeLists.txt
+++ b/contrib/buildsystems/CMakeLists.txt
@@ -636,7 +636,7 @@
 if(NOT EXISTS ${CMAKE_BINARY_DIR}/command-list.h OR NOT EXCLUSION_PROGS_CACHE STREQUAL EXCLUSION_PROGS)
 	list(REMOVE_ITEM EXCLUSION_PROGS empty)
 	message("Generating command-list.h")
-	execute_process(COMMAND "${SH_EXE}" "${CMAKE_SOURCE_DIR}/generate-cmdlist.sh"
+	execute_process(COMMAND "${SH_EXE}" "${CMAKE_SOURCE_DIR}/tools/generate-cmdlist.sh"
 				${EXCLUSION_PROGS}
 				"${CMAKE_SOURCE_DIR}"
 				"${CMAKE_BINARY_DIR}/command-list.h")
@@ -644,14 +644,14 @@
 
 if(NOT EXISTS ${CMAKE_BINARY_DIR}/config-list.h)
 	message("Generating config-list.h")
-	execute_process(COMMAND "${SH_EXE}" "${CMAKE_SOURCE_DIR}/generate-configlist.sh"
+	execute_process(COMMAND "${SH_EXE}" "${CMAKE_SOURCE_DIR}/tools/generate-configlist.sh"
 				"${CMAKE_SOURCE_DIR}"
 				"${CMAKE_BINARY_DIR}/config-list.h")
 endif()
 
 if(NOT EXISTS ${CMAKE_BINARY_DIR}/hook-list.h)
 	message("Generating hook-list.h")
-	execute_process(COMMAND "${SH_EXE}" ${CMAKE_SOURCE_DIR}/generate-hooklist.sh
+	execute_process(COMMAND "${SH_EXE}" ${CMAKE_SOURCE_DIR}/tools/generate-hooklist.sh
 				"${CMAKE_SOURCE_DIR}"
 				"${CMAKE_BINARY_DIR}/hook-list.h")
 endif()
@@ -832,11 +832,11 @@
 	endif()
 
 	add_custom_command(OUTPUT "${CMAKE_BINARY_DIR}/${shell_gen_path}"
-		COMMAND "${SH_EXE}" "${CMAKE_SOURCE_DIR}/generate-script.sh"
+		COMMAND "${SH_EXE}" "${CMAKE_SOURCE_DIR}/tools/generate-script.sh"
 			"${CMAKE_SOURCE_DIR}/${script}.sh"
 			"${CMAKE_BINARY_DIR}/${shell_gen_path}"
 			"${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS"
-		DEPENDS "${CMAKE_SOURCE_DIR}/generate-script.sh"
+		DEPENDS "${CMAKE_SOURCE_DIR}/tools/generate-script.sh"
 			"${CMAKE_SOURCE_DIR}/${script}.sh"
 		VERBATIM)
 	list(APPEND shell_gen ${CMAKE_BINARY_DIR}/${shell_gen_path})
@@ -875,13 +875,13 @@
 	file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/${perl_gen_dir}")
 
 	add_custom_command(OUTPUT "${CMAKE_BINARY_DIR}/${perl_gen_path}"
-		COMMAND "${SH_EXE}" "${CMAKE_SOURCE_DIR}/generate-perl.sh"
+		COMMAND "${SH_EXE}" "${CMAKE_SOURCE_DIR}/tools/generate-perl.sh"
 			"${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS"
 			"${CMAKE_BINARY_DIR}/GIT-VERSION-FILE"
 			"${CMAKE_BINARY_DIR}/GIT-PERL-HEADER"
 			"${CMAKE_SOURCE_DIR}/${script}"
 			"${CMAKE_BINARY_DIR}/${perl_gen_path}"
-		DEPENDS "${CMAKE_SOURCE_DIR}/generate-perl.sh"
+		DEPENDS "${CMAKE_SOURCE_DIR}/tools/generate-perl.sh"
 			"${CMAKE_SOURCE_DIR}/${script}"
 			"${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS"
 			"${CMAKE_BINARY_DIR}/GIT-VERSION-FILE"
@@ -892,11 +892,11 @@
 
 # Python script
 add_custom_command(OUTPUT "${CMAKE_BINARY_DIR}/git-p4"
-	COMMAND "${SH_EXE}" "${CMAKE_SOURCE_DIR}/generate-python.sh"
+	COMMAND "${SH_EXE}" "${CMAKE_SOURCE_DIR}/tools/generate-python.sh"
 		"${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS"
 		"${CMAKE_SOURCE_DIR}/git-p4.py"
 		"${CMAKE_BINARY_DIR}/git-p4"
-	DEPENDS "${CMAKE_SOURCE_DIR}/generate-python.sh"
+	DEPENDS "${CMAKE_SOURCE_DIR}/tools/generate-python.sh"
 		"${CMAKE_SOURCE_DIR}/git-p4.py"
 		"${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS"
 	VERBATIM)
diff --git a/contrib/diff-highlight/DiffHighlight.pm b/contrib/diff-highlight/DiffHighlight.pm
index 3d061bc..abe4578 100644
--- a/contrib/diff-highlight/DiffHighlight.pm
+++ b/contrib/diff-highlight/DiffHighlight.pm
@@ -1,6 +1,6 @@
 package DiffHighlight;
 
-require v5.26;
+require v5.008;
 use warnings FATAL => 'all';
 use strict;
 
@@ -9,18 +9,11 @@
 
 my $NULL = File::Spec->devnull();
 
-# Highlight by reversing foreground and background. You could do
-# other things like bold or underline if you prefer.
-my @OLD_HIGHLIGHT = (
-	color_config('color.diff-highlight.oldnormal'),
-	color_config('color.diff-highlight.oldhighlight', "\x1b[7m"),
-	color_config('color.diff-highlight.oldreset', "\x1b[27m")
-);
-my @NEW_HIGHLIGHT = (
-	color_config('color.diff-highlight.newnormal', $OLD_HIGHLIGHT[0]),
-	color_config('color.diff-highlight.newhighlight', $OLD_HIGHLIGHT[1]),
-	color_config('color.diff-highlight.newreset', $OLD_HIGHLIGHT[2])
-);
+# The color theme is initially set to nothing here to allow outside callers
+# to set the colors for their application. If nothing is sent in we use
+# colors from git config in load_color_config().
+our @OLD_HIGHLIGHT = ();
+our @NEW_HIGHLIGHT = ();
 
 my $RESET = "\x1b[m";
 my $COLOR = qr/\x1b\[[0-9;]*m/;
@@ -138,9 +131,21 @@
 # of it being used in other settings. Let's handle our own
 # fallback, which means we will work even if git can't be run.
 sub color_config {
+	our $cached_config;
 	my ($key, $default) = @_;
-	my $s = `git config --get-color $key 2>$NULL`;
-	return length($s) ? $s : $default;
+
+	if (!defined $cached_config) {
+		$cached_config = {};
+		my $data = `git config --type=color --get-regexp '^color\.diff-highlight\.' 2>$NULL`;
+		for my $line (split /\n/, $data) {
+			my ($key, $color) = split ' ', $line, 2;
+			$key =~ s/^color\.diff-highlight\.// or next;
+			$cached_config->{$key} = $color;
+		}
+	}
+
+	my $s = $cached_config->{$key};
+	return defined($s) ? $s : $default;
 }
 
 sub show_hunk {
@@ -170,6 +175,29 @@
 	$line_cb->(@queue);
 }
 
+sub load_color_config {
+	# If the colors were NOT set from outside this module we load them on-demand
+	# from the git config. Note that only one of elements 0 and 2 in each
+	# array is used (depending on whether you are doing set/unset on an
+	# attribute, or specifying normal vs highlighted coloring). So we use
+	# element 1 as our check for whether colors were passed in; it should
+	# always be set if you want highlighting to do anything.
+	if (!defined $OLD_HIGHLIGHT[1]) {
+		@OLD_HIGHLIGHT = (
+			color_config('oldnormal'),
+			color_config('oldhighlight', "\x1b[7m"),
+			color_config('oldreset', "\x1b[27m")
+		);
+	}
+	if (!defined $NEW_HIGHLIGHT[1]) {
+		@NEW_HIGHLIGHT = (
+			color_config('newnormal', $OLD_HIGHLIGHT[0]),
+			color_config('newhighlight', $OLD_HIGHLIGHT[1]),
+			color_config('newreset', $OLD_HIGHLIGHT[2])
+		);
+	};
+}
+
 sub highlight_pair {
 	my @a = split_line(shift);
 	my @b = split_line(shift);
@@ -218,6 +246,7 @@
 	}
 
 	if (is_pair_interesting(\@a, $pa, $sa, \@b, $pb, $sb)) {
+		load_color_config();
 		return highlight_line(\@a, $pa, $sa, \@OLD_HIGHLIGHT),
 		       highlight_line(\@b, $pb, $sb, \@NEW_HIGHLIGHT);
 	}
@@ -273,6 +302,18 @@
 # or suffix (disregarding boring bits like whitespace and colorization).
 sub is_pair_interesting {
 	my ($a, $pa, $sa, $b, $pb, $sb) = @_;
+
+	# We hit this case if the prefix consumed the entire line, meaning
+	# that two lines are identical. This generally shouldn't happen,
+	# since it implies the diff isn't minimal (you could shrink the hunk by
+	# making this a context line). But you can see it when the line
+	# content is the same, but the trailing newline is dropped, like:
+	#
+	#   -foo
+	#   +foo
+	#   \No newline at end of file
+	return 0 if $pa == @$a || $pb == @$b;
+
 	my $prefix_a = join('', @$a[0..($pa-1)]);
 	my $prefix_b = join('', @$b[0..($pb-1)]);
 	my $suffix_a = join('', @$a[($sa+1)..$#$a]);
diff --git a/contrib/diff-highlight/README b/contrib/diff-highlight/README
index 1db4440..ed8d876 100644
--- a/contrib/diff-highlight/README
+++ b/contrib/diff-highlight/README
@@ -39,10 +39,21 @@
 preserved; the intent is that the output should look exactly the same as
 the input, except for the occasional highlight.
 
+Build/Install
+-------------
+
+You can build the `diff-highlight` script by running `make` from within
+the diff-highlight directory. There is no `make install` target; you can
+copy the built script to your $PATH.
+
+You can run diff-highlight's internal tests by running `make test`. Note
+that you must also build Git itself first (by running `make` from the
+top-level of the project).
+
 Use
 ---
 
-You can try out the diff-highlight program with:
+You can try out the built diff-highlight program with:
 
 ---------------------------------------------
 git log -p --color | /path/to/diff-highlight
@@ -127,6 +138,12 @@
     processing a logical chunk of input). The default function flushes
     stdout.
 
+  - @DiffHighlight::OLD_HIGHLIGHT and @DiffHighlight::NEW_HIGHLIGHT - these
+    arrays specify the normal, highlighted, and reset colors (in that order)
+    for old/new lines. If unset, values will be retrieved by calling `git
+    config` (see "Color Config" above). Note that these should be the literal
+    color bytes (starting with an ANSI escape code), not color names.
+
 The script may then feed lines, one at a time, to DiffHighlight::handle_line().
 When lines are done processing, they will be fed to $line_cb. Note that
 DiffHighlight may queue up many input lines (to analyze a whole hunk)
diff --git a/contrib/diff-highlight/t/t9400-diff-highlight.sh b/contrib/diff-highlight/t/t9400-diff-highlight.sh
index dee2967..b38fe21 100755
--- a/contrib/diff-highlight/t/t9400-diff-highlight.sh
+++ b/contrib/diff-highlight/t/t9400-diff-highlight.sh
@@ -7,9 +7,6 @@
 TEST_DIRECTORY="$CURR_DIR"/../../../t
 DIFF_HIGHLIGHT="$CURR_DIR"/../diff-highlight
 
-CW="$(printf "\033[7m")"	# white
-CR="$(printf "\033[27m")"	# reset
-
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 . "$TEST_DIRECTORY"/test-lib.sh
@@ -41,8 +38,10 @@
 		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 &&
+	"$DIFF_HIGHLIGHT" <diff.raw >diff.hi &&
+	test_strip_patch_header <diff.hi | test_decode_color >diff.act &&
+	"$DIFF_HIGHLIGHT" <commit.raw >commit.hi &&
+	test_strip_patch_header <commit.hi | test_decode_color >commit.act &&
 	test_cmp patch.exp diff.act &&
 	test_cmp patch.exp commit.act
 }
@@ -124,8 +123,8 @@
 	dh_test a b <<-EOF
 		@@ -1,3 +1,3 @@
 		 aaa
-		-${CW}b${CR}bb
-		+${CW}0${CR}bb
+		-<REVERSE>b<NOREVERSE>bb
+		+<REVERSE>0<NOREVERSE>bb
 		 ccc
 	EOF
 '
@@ -146,8 +145,8 @@
 	dh_test a b <<-EOF
 		@@ -1,3 +1,3 @@
 		 aaa
-		-bb${CW}b${CR}
-		+bb${CW}0${CR}
+		-bb<REVERSE>b<NOREVERSE>
+		+bb<REVERSE>0<NOREVERSE>
 		 ccc
 	EOF
 '
@@ -168,8 +167,8 @@
 	dh_test a b <<-EOF
 		@@ -1,3 +1,3 @@
 		 aaa
-		-b${CW}b${CR}b
-		+b${CW}0${CR}b
+		-b<REVERSE>b<NOREVERSE>b
+		+b<REVERSE>0<NOREVERSE>b
 		 ccc
 	EOF
 '
@@ -211,8 +210,8 @@
 	dh_test a b <<-EOF
 		@@ -1,3 +1,3 @@
 		 aaa
-		-b${CW}b${CR}b
-		+b${CW}0${CR}b
+		-b<REVERSE>b<NOREVERSE>b
+		+b<REVERSE>0<NOREVERSE>b
 		+ccc
 	EOF
 '
@@ -230,8 +229,8 @@
 	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
+		-unic<REVERSE>${o_accent}<NOREVERSE>de
+		+unic<REVERSE>${o_stroke}<NOREVERSE>de
 	EOF
 '
 
@@ -248,8 +247,8 @@
 	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
+		-unic<REVERSE>o${combine_accent}<NOREVERSE>de
+		+unic<REVERSE>o${combine_circum}<NOREVERSE>de
 	EOF
 '
 
@@ -331,13 +330,52 @@
 	+++ b/file
 	@@ -1,3 +1,3 @@
 	 before
-	-the ${CW}old${CR} line
-	+the ${CW}new${CR} line
+	-the <REVERSE>old<NOREVERSE> line
+	+the <REVERSE>new<NOREVERSE> line
 	 -leading dash
 	EOF
 	git log --graph -p -1 | "$DIFF_HIGHLIGHT" >actual.raw &&
-	trim_graph <actual.raw | sed -n "/^---/,\$p" >actual &&
+	trim_graph <actual.raw | sed -n "/^---/,\$p" | test_decode_color >actual &&
 	test_cmp expect actual
 '
 
+test_expect_success 'highlight diff that removes final newline' '
+	printf "content\n" >a &&
+	printf "content" >b &&
+	dh_test a b <<-\EOF
+	@@ -1 +1 @@
+	-content
+	+content
+	\ No newline at end of file
+	EOF
+'
+
+test_expect_success 'configure set/reset colors' '
+	test_config color.diff-highlight.oldhighlight bold &&
+	test_config color.diff-highlight.oldreset nobold &&
+	test_config color.diff-highlight.newhighlight italic &&
+	test_config color.diff-highlight.newreset noitalic &&
+	echo "prefix a suffix" >a &&
+	echo "prefix b suffix" >b &&
+	dh_test a b <<-\EOF
+	@@ -1 +1 @@
+	-prefix <BOLD>a<NORMAL_INTENSITY> suffix
+	+prefix <ITALIC>b<NOITALIC> suffix
+	EOF
+'
+
+test_expect_success 'configure normal/highlight colors' '
+	test_config color.diff-highlight.oldnormal red &&
+	test_config color.diff-highlight.oldhighlight magenta &&
+	test_config color.diff-highlight.newnormal green &&
+	test_config color.diff-highlight.newhighlight yellow &&
+	echo "prefix a suffix" >a &&
+	echo "prefix b suffix" >b &&
+	dh_test a b <<-\EOF
+	@@ -1 +1 @@
+	<RED>-prefix <RESET><MAGENTA>a<RESET><RED> suffix<RESET>
+	<GREEN>+prefix <RESET><YELLOW>b<RESET><GREEN> suffix<RESET>
+	EOF
+'
+
 test_done
diff --git a/contrib/meson.build b/contrib/meson.build
index a88c5df..569c23e 100644
--- a/contrib/meson.build
+++ b/contrib/meson.build
@@ -2,5 +2,4 @@
   subdir(feature)
 endforeach
 
-subdir('coccinelle')
 subdir('credential')
diff --git a/contrib/subtree/meson.build b/contrib/subtree/meson.build
index 161435a..804c315 100644
--- a/contrib/subtree/meson.build
+++ b/contrib/subtree/meson.build
@@ -3,7 +3,7 @@
   output: 'git-subtree',
   command: [
     shell,
-    meson.project_source_root() / 'generate-script.sh',
+    meson.project_source_root() / 'tools/generate-script.sh',
     '@INPUT@',
     '@OUTPUT@',
     meson.project_build_root() / 'GIT-BUILD-OPTIONS',
diff --git a/csum-file.c b/csum-file.c
index 3d3047c..9558177 100644
--- a/csum-file.c
+++ b/csum-file.c
@@ -161,17 +161,16 @@ struct hashfile *hashfd_check(const struct git_hash_algo *algop,
 	return f;
 }
 
-static struct hashfile *hashfd_internal(const struct git_hash_algo *algop,
-					int fd, const char *name,
-					struct progress *tp,
-					size_t buffer_len)
+struct hashfile *hashfd_ext(const struct git_hash_algo *algop,
+			    int fd, const char *name,
+			    const struct hashfd_options *opts)
 {
 	struct hashfile *f = xmalloc(sizeof(*f));
 	f->fd = fd;
 	f->check_fd = -1;
 	f->offset = 0;
 	f->total = 0;
-	f->tp = tp;
+	f->tp = opts->progress;
 	f->name = name;
 	f->do_crc = 0;
 	f->skip_hash = 0;
@@ -179,8 +178,8 @@ static struct hashfile *hashfd_internal(const struct git_hash_algo *algop,
 	f->algop = unsafe_hash_algo(algop);
 	f->algop->init_fn(&f->ctx);
 
-	f->buffer_len = buffer_len;
-	f->buffer = xmalloc(buffer_len);
+	f->buffer_len = opts->buffer_len ? opts->buffer_len : 128 * 1024;
+	f->buffer = xmalloc(f->buffer_len);
 	f->check_buffer = NULL;
 
 	return f;
@@ -194,19 +193,8 @@ struct hashfile *hashfd(const struct git_hash_algo *algop,
 	 * measure the rate of data passing through this hashfile,
 	 * use a larger buffer size to reduce fsync() calls.
 	 */
-	return hashfd_internal(algop, fd, name, NULL, 128 * 1024);
-}
-
-struct hashfile *hashfd_throughput(const struct git_hash_algo *algop,
-				   int fd, const char *name, struct progress *tp)
-{
-	/*
-	 * Since we are expecting to report progress of the
-	 * write into this hashfile, use a smaller buffer
-	 * size so the progress indicators arrive at a more
-	 * frequent rate.
-	 */
-	return hashfd_internal(algop, fd, name, tp, 8 * 1024);
+	struct hashfd_options opts = { 0 };
+	return hashfd_ext(algop, fd, name, &opts);
 }
 
 void hashfile_checkpoint_init(struct hashfile *f,
diff --git a/csum-file.h b/csum-file.h
index ecce9d2..a9b390d 100644
--- a/csum-file.h
+++ b/csum-file.h
@@ -45,12 +45,24 @@ int hashfile_truncate(struct hashfile *, struct hashfile_checkpoint *);
 #define CSUM_FSYNC		2
 #define CSUM_HASH_IN_STREAM	4
 
+struct hashfd_options {
+	/*
+	 * Throughput progress that counts the number of bytes that have been
+	 * hashed.
+	 */
+	struct progress *progress;
+
+	/* The length of the buffer that shall be used read read data. */
+	size_t buffer_len;
+};
+
+struct hashfile *hashfd_ext(const struct git_hash_algo *algop,
+			    int fd, const char *name,
+			    const struct hashfd_options *opts);
 struct hashfile *hashfd(const struct git_hash_algo *algop,
 			int fd, const char *name);
 struct hashfile *hashfd_check(const struct git_hash_algo *algop,
 			      const char *name);
-struct hashfile *hashfd_throughput(const struct git_hash_algo *algop,
-				   int fd, const char *name, struct progress *tp);
 
 /*
  * Free the hashfile without flushing its contents to disk. This only
diff --git a/dir.c b/dir.c
index 026d851..fcb8f6d 100644
--- a/dir.c
+++ b/dir.c
@@ -3518,15 +3518,15 @@ int get_sparse_checkout_patterns(struct pattern_list *pl)
 
 int remove_path(const char *name)
 {
-	char *slash;
+	const char *last;
 
 	if (unlink(name) && !is_missing_file_error(errno))
 		return -1;
 
-	slash = strrchr(name, '/');
-	if (slash) {
+	last = strrchr(name, '/');
+	if (last) {
 		char *dirs = xstrdup(name);
-		slash = dirs + (slash - name);
+		char *slash = dirs + (last - name);
 		do {
 			*slash = '\0';
 			if (startup_info->original_cwd &&
diff --git a/fetch-pack.c b/fetch-pack.c
index 6ecd468..a32224e 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -1024,12 +1024,8 @@ static int get_pack(struct fetch_pack_args *args,
 				     fsck_msg_types.buf);
 	}
 
-	if (index_pack_args) {
-		int i;
-
-		for (i = 0; i < cmd.args.nr; i++)
-			strvec_push(index_pack_args, cmd.args.v[i]);
-	}
+	if (index_pack_args)
+		strvec_pushv(index_pack_args, cmd.args.v);
 
 	sigchain_push(SIGPIPE, SIG_IGN);
 
diff --git a/git-compat-util.h b/git-compat-util.h
index bebcf9f..4b4ea24 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -34,10 +34,6 @@ struct strbuf;
 #  define DISABLE_WARNING(warning)
 #endif
 
-#ifdef DISABLE_SIGN_COMPARE_WARNINGS
-DISABLE_WARNING(-Wsign-compare)
-#endif
-
 #undef FLEX_ARRAY
 #define FLEX_ARRAY /* empty - weather balloon to require C99 FAM */
 
@@ -1099,3 +1095,7 @@ extern int not_supposed_to_survive;
 #endif /* CHECK_ASSERTION_SIDE_EFFECTS */
 
 #endif
+
+#ifdef DISABLE_SIGN_COMPARE_WARNINGS
+DISABLE_WARNING(-Wsign-compare)
+#endif
diff --git a/git-curl-compat.h b/git-curl-compat.h
index 659e5a3..dccdd4d 100644
--- a/git-curl-compat.h
+++ b/git-curl-compat.h
@@ -38,6 +38,14 @@
 #endif
 
 /**
+ * CURLINFO_RETRY_AFTER was added in 7.66.0, released in September 2019.
+ * It allows curl to automatically parse Retry-After headers.
+ */
+#if LIBCURL_VERSION_NUM >= 0x074200
+#define GIT_CURL_HAVE_CURLINFO_RETRY_AFTER 1
+#endif
+
+/**
  * CURLOPT_PROTOCOLS_STR and CURLOPT_REDIR_PROTOCOLS_STR were added in 7.85.0,
  * released in August 2022.
  */
diff --git a/git-gui/.gitignore b/git-gui/.gitignore
index 5130b4f..38a41eb 100644
--- a/git-gui/.gitignore
+++ b/git-gui/.gitignore
@@ -5,4 +5,5 @@
 GIT-VERSION-FILE
 git-gui
 git-gui--askpass
+git-gui--askyesno
 lib/tclIndex
diff --git a/git-gui/GIT-VERSION-GEN b/git-gui/GIT-VERSION-GEN
index c2767b4..2f729de 100755
--- a/git-gui/GIT-VERSION-GEN
+++ b/git-gui/GIT-VERSION-GEN
@@ -5,19 +5,27 @@
 LF='
 '
 
-if test "$#" -ne 2
+if test "$#" -lt 2
 then
-	echo >&2 "usage: $0 <SOURCE_DIR> <OUTPUT>"
+	echo >&2 "usage: $0 <SOURCE_DIR> <OUTPUT> [<PARENT_PROJECT_DIR>]"
 	exit 1
 fi
 
 SOURCE_DIR="$1"
 OUTPUT="$2"
+PARENT_PROJECT_DIR="$3"
 
 # Protect us from reading Git version information outside of the Git directory
 # in case it is not a repository itself, but embedded in an unrelated
-# repository.
-GIT_CEILING_DIRECTORIES="$SOURCE_DIR/.."
+# repository. The PARENT_PROJECT_DIR variable can be used to override this, for
+# example when git-gui is included as a subproject.
+if test -n "$PARENT_PROJECT_DIR"
+then
+	GIT_CEILING_DIRECTORIES="$PARENT_PROJECT_DIR/.."
+else
+	GIT_CEILING_DIRECTORIES="$SOURCE_DIR/.."
+fi
+
 export GIT_CEILING_DIRECTORIES
 
 tree_search ()
diff --git a/git-gui/Makefile b/git-gui/Makefile
index 69b0b84..ca01068 100644
--- a/git-gui/Makefile
+++ b/git-gui/Makefile
@@ -9,7 +9,7 @@
 #
 
 GIT-VERSION-FILE: FORCE
-	@$(SHELL_PATH) ./GIT-VERSION-GEN . $@
+	@$(SHELL_PATH) ./GIT-VERSION-GEN . $@ "$(PARENT_PROJECT_DIR)"
 
 uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
 uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not')
@@ -177,10 +177,13 @@
 git-gui--askpass: git-gui--askpass.sh GIT-GUI-BUILD-OPTIONS generate-script.sh
 	$(QUIET_GEN)$(SHELL_PATH) generate-script.sh $@ $< ./GIT-GUI-BUILD-OPTIONS
 
+git-gui--askyesno: git-gui--askyesno.sh GIT-GUI-BUILD-OPTIONS generate-script.sh
+	$(QUIET_GEN)$(SHELL_PATH) generate-script.sh $@ $< ./GIT-GUI-BUILD-OPTIONS
+
 ifdef GITGUI_WINDOWS_WRAPPER
 all:: git-gui
 endif
-all:: $(GITGUI_MAIN) git-gui--askpass lib/tclIndex $(ALL_MSGFILES)
+all:: $(GITGUI_MAIN) git-gui--askpass git-gui--askyesno lib/tclIndex $(ALL_MSGFILES)
 
 install: all
 	$(QUIET)$(INSTALL_D0)'$(DESTDIR_SQ)$(gitexecdir_SQ)' $(INSTALL_D1)
@@ -221,7 +224,7 @@
 	@sed 's|^GITGUI_VERSION=||' <GIT-VERSION-FILE  >$(TARDIR)/version
 
 clean::
-	$(RM_RF) $(GITGUI_MAIN) git-gui--askpass lib/tclIndex po/*.msg $(PO_TEMPLATE)
+	$(RM_RF) $(GITGUI_MAIN) git-gui--askpass git-gui--askyesno lib/tclIndex po/*.msg $(PO_TEMPLATE)
 	$(RM_RF) GIT-VERSION-FILE GIT-GUI-BUILD-OPTIONS
 ifdef GITGUI_WINDOWS_WRAPPER
 	$(RM_RF) git-gui
diff --git a/git-gui/git-gui--askyesno b/git-gui/git-gui--askyesno.sh
similarity index 100%
rename from git-gui/git-gui--askyesno
rename to git-gui/git-gui--askyesno.sh
diff --git a/git-gui/git-gui.sh b/git-gui/git-gui.sh
index d3d3aa1..23fe76e 100755
--- a/git-gui/git-gui.sh
+++ b/git-gui/git-gui.sh
@@ -3900,6 +3900,24 @@
 
 	backup_commit_buffer
 
+	# Grey out comment lines (which are stripped from the final commit message by
+	# wash_commit_message).
+	$ui_comm tag configure commit_comment -foreground gray
+	proc dim_commit_comment_lines {} {
+		global ui_comm comment_string
+		$ui_comm tag remove commit_comment 1.0 end
+		set text [$ui_comm get 1.0 end]
+		# See also cmt_rx in wash_commit_message
+		set cmt_rx [strcat {^} [regsub -all {\W} $comment_string {\\&}]]
+		set ranges [regexp -all -indices -inline -line -- $cmt_rx $text]
+		foreach pair $ranges {
+			set idx "1.0 + [lindex $pair 0] chars"
+			$ui_comm tag add commit_comment $idx "$idx lineend + 1 char"
+		}
+	}
+	dim_commit_comment_lines
+	bind $ui_comm <<Modified>> { after idle dim_commit_comment_lines }
+
 	# -- If the user has aspell available we can drive it
 	#    in pipe mode to spellcheck the commit message.
 	#
diff --git a/git-gui/lib/diff.tcl b/git-gui/lib/diff.tcl
index 442737b..8be1a61 100644
--- a/git-gui/lib/diff.tcl
+++ b/git-gui/lib/diff.tcl
@@ -385,6 +385,8 @@
 		#
 		if {[string match {@@@ *} $line]} {
 			set is_3way_diff 1
+			apply_tab_size 2
+		} elseif {[string match {@@ *} $line]} {
 			apply_tab_size 1
 		}
 
diff --git a/git-gui/meson.build b/git-gui/meson.build
index 320ba09..a8119aa 100644
--- a/git-gui/meson.build
+++ b/git-gui/meson.build
@@ -4,7 +4,7 @@
 
 fs = import('fs')
 
-shell = find_program('sh')
+shell = find_program('/bin/sh', 'sh')
 tclsh = find_program('tclsh')
 wish = find_program('wish')
 
@@ -34,6 +34,7 @@
     '@INPUT@',
     meson.current_source_dir(),
     '@OUTPUT@',
+    get_option('parent_project_dir'),
   ],
   build_always_stale: true,
 )
@@ -53,19 +54,21 @@
   )
 endif
 
-custom_target(
-  output: 'git-gui--askpass',
-  input: 'git-gui--askpass.sh',
-  command: [
-    shell,
-    meson.current_source_dir() / 'generate-script.sh',
-    '@OUTPUT@',
-    '@INPUT@',
-    meson.current_build_dir() / 'GIT-GUI-BUILD-OPTIONS',
-  ],
-  install: true,
-  install_dir: get_option('libexecdir') / 'git-core',
-)
+foreach script : [ 'git-gui--askpass', 'git-gui--askyesno' ]
+  custom_target(
+    output: script,
+    input: script + '.sh',
+    command: [
+      shell,
+      meson.current_source_dir() / 'generate-script.sh',
+      '@OUTPUT@',
+      '@INPUT@',
+      meson.current_build_dir() / 'GIT-GUI-BUILD-OPTIONS',
+    ],
+    install: true,
+    install_dir: get_option('libexecdir') / 'git-core',
+  )
+endforeach
 
 custom_target(
   input: 'git-gui.sh',
diff --git a/git-gui/meson_options.txt b/git-gui/meson_options.txt
new file mode 100644
index 0000000..7591a34
--- /dev/null
+++ b/git-gui/meson_options.txt
@@ -0,0 +1,2 @@
+option('parent_project_dir', type: 'string', value: '',
+  description: 'The directory of the parent project. This is used so that the version can be determined even in case git-gui is included as a subtree.')
diff --git a/git.c b/git.c
index 2b212e6..5a40eab 100644
--- a/git.c
+++ b/git.c
@@ -877,8 +877,7 @@ static int run_argv(struct strvec *args)
 			commit_pager_choice();
 
 			strvec_push(&cmd.args, "git");
-			for (size_t i = 0; i < args->nr; i++)
-				strvec_push(&cmd.args, args->v[i]);
+			strvec_pushv(&cmd.args, args->v);
 
 			trace_argv_printf(cmd.args.v, "trace: exec:");
 
diff --git a/gitk-git/.gitignore b/gitk-git/.gitignore
index d7ebcaf..15f96aa 100644
--- a/gitk-git/.gitignore
+++ b/gitk-git/.gitignore
@@ -1,2 +1,3 @@
 /GIT-TCLTK-VARS
 /gitk-wish
+po/gitk.pot
diff --git a/gitk-git/Makefile b/gitk-git/Makefile
index cc32dca..41116d8 100644
--- a/gitk-git/Makefile
+++ b/gitk-git/Makefile
@@ -68,9 +68,12 @@
 	$(SHELL_PATH) ./generate-tcl.sh "$(TCLTK_PATH_SQ)" "$<" "$@"
 
 $(PO_TEMPLATE): gitk
-	$(XGETTEXT) -kmc -LTcl -o $@ gitk
+	$(XGETTEXT) -kmc -LTcl --package-name=Gitk -o $@ gitk
 update-po:: $(PO_TEMPLATE)
-	$(foreach p, $(ALL_POFILES), echo Updating $p ; msgmerge -U $p $(PO_TEMPLATE) ; )
+	$(foreach p, $(ALL_POFILES), echo Updating $p ; msgmerge -U --add-location $p $(PO_TEMPLATE) ; )
+	@echo "Before committing changes, ensure that a clean-filter is installed:"; \
+	echo; \
+	echo "	git config filter.gettext-no-location.clean \"msgcat --no-location -\""
 $(ALL_MSGFILES): %.msg : %.po
 	@echo Generating catalog $@
 	$(MSGFMT) --statistics --tcl -l $(basename $(notdir $<)) -d $(dir $@) $<
diff --git a/gitk-git/gitk b/gitk-git/gitk
index cbaaee9..2730274 100755
--- a/gitk-git/gitk
+++ b/gitk-git/gitk
@@ -6831,16 +6831,18 @@
         } else {
             # draw a head or other ref
             if {[incr nheads -1] >= 0} {
-                set col $headbgcolor
+                set refoutlinecol $headoutlinecolor
+                set reffillcol $headbgcolor
                 if {$tag eq $mainhead} {
                     set font mainfontbold
                 }
             } else {
-                set col "#ddddff"
+                set refoutlinecol black
+                set reffillcol "#ddddff"
             }
             set xl [expr {$xl - $delta/2}]
             $canv create polygon $x $yt $xr $yt $xr $yb $x $yb \
-                -width 1 -outline black -fill $col -tags tag.$id
+                -width 1 -outline $refoutlinecol -fill $reffillcol -tags tag.$id
             if {[regexp {^(remotes/[^/]*/|remotes/)} $tag match remoteprefix]} {
                 set rwid [font measure mainfont $remoteprefix]
                 set xi [expr {$x + 1}]
@@ -6850,7 +6852,8 @@
                         -width 0 -fill $remotebgcolor -tags tag.$id
             }
         }
-        set t [$canv create text $xl $y1 -anchor w -text $tag -fill $headfgcolor \
+        set textfgcolor [expr {$ntags >= 0 ? $tagfgcolor : $headfgcolor}]
+        set t [$canv create text $xl $y1 -anchor w -text $tag -fill $textfgcolor \
                    -font $font -tags [list tag.$id text]]
         if {$ntags >= 0} {
             $canv bind $t <1> $tagclick
@@ -11796,7 +11799,7 @@
 
 proc prefspage_colors {notebook} {
     global bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
-    global diffbgcolors
+    global diffbgcolors linkfgcolor
     global themeloader
 
     set page [create_prefs_page $notebook.colors]
@@ -11873,6 +11876,11 @@
         -command [list choosecolor selectbgcolor {} $page [mc "background"]]
     grid x $page.selbgbut $page.selbgsep -sticky w
 
+    label $page.linkfg -padx 40 -relief sunk -background $linkfgcolor
+    ttk::button $page.linkfgbut -text [mc "Link"] \
+        -command [list choosecolor linkfgcolor {} $page [mc "link"]]
+    grid x $page.linkfgbut $page.linkfg -sticky w
+
     grid columnconfigure $page 2 -weight 1
 
     return $page
@@ -11880,7 +11888,7 @@
 
 proc prefspage_set_colorswatches {page} {
     global bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
-    global diffbgcolors
+    global diffbgcolors linkfgcolor
 
     $page.bg configure -background $bgcolor
     $page.fg configure -background $fgcolor
@@ -11891,6 +11899,7 @@
     $page.hunksep configure -background [lindex $diffcolors 2]
     $page.markbgsep configure -background $markbgcolor
     $page.selbgsep configure -background $selectbgcolor
+    $page.linkfg configure -background $linkfgcolor
 }
 
 proc prefspage_fonts {notebook} {
diff --git a/gitk-git/po/.gitattributes b/gitk-git/po/.gitattributes
new file mode 100644
index 0000000..938309e
--- /dev/null
+++ b/gitk-git/po/.gitattributes
@@ -0,0 +1 @@
+/*.po    filter=gettext-no-location
diff --git a/gitk-git/po/bg.po b/gitk-git/po/bg.po
index d1e7d92..e7e2f87 100644
--- a/gitk-git/po/bg.po
+++ b/gitk-git/po/bg.po
@@ -6,7 +6,7 @@
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: gitk master\n"
+"Project-Id-Version: Gitk master\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2025-07-22 18:34+0200\n"
 "PO-Revision-Date: 2025-07-28 13:38+0200\n"
diff --git a/gitk-git/po/ca.po b/gitk-git/po/ca.po
index 87dfc18..d588d09 100644
--- a/gitk-git/po/ca.po
+++ b/gitk-git/po/ca.po
@@ -6,7 +6,7 @@
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: gitk\n"
+"Project-Id-Version: Gitk\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2015-05-17 14:32+1000\n"
 "PO-Revision-Date: 2015-10-05 22:23-0600\n"
@@ -19,33 +19,26 @@
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 "X-Generator: Poedit 1.8.5\n"
 
-#: gitk:140
 msgid "Couldn't get list of unmerged files:"
 msgstr "No s'ha pogut obtenir la llista de fitxers no fusionats:"
 
-#: gitk:212 gitk:2381
 msgid "Color words"
 msgstr "Colora les paraules"
 
-#: gitk:217 gitk:2381 gitk:8220 gitk:8253
 msgid "Markup words"
 msgstr "Marca les paraules"
 
-#: gitk:324
 msgid "Error parsing revisions:"
 msgstr "Error en analitzar les revisions:"
 
-#: gitk:380
 msgid "Error executing --argscmd command:"
 msgstr "Error en executar l'ordre --argscmd:"
 
-#: gitk:393
 msgid "No files selected: --merge specified but no files are unmerged."
 msgstr ""
 "No hi ha fitxers seleccionats: s'ha especificat --merge però cap fitxer està "
 "sense fusionar."
 
-#: gitk:396
 msgid ""
 "No files selected: --merge specified but no unmerged files are within file "
 "limit."
@@ -53,314 +46,234 @@
 "No hi ha fitxers seleccionats: s'ha especificat --merge però cap fitxer "
 "sense fusionar està dins del límit de fitxers."
 
-#: gitk:418 gitk:566
 msgid "Error executing git log:"
 msgstr "Error en executar git log:"
 
-#: gitk:436 gitk:582
 msgid "Reading"
 msgstr "Llegint"
 
-#: gitk:496 gitk:4525
 msgid "Reading commits..."
 msgstr "Llegint les revisions..."
 
-#: gitk:499 gitk:1637 gitk:4528
 msgid "No commits selected"
 msgstr "Cap comissió seleccionada"
 
-#: gitk:1445 gitk:4045 gitk:12432
 msgid "Command line"
 msgstr "Línia d'ordres"
 
-#: gitk:1511
 msgid "Can't parse git log output:"
 msgstr "No es pot analitzar la sortida del git log:"
 
-#: gitk:1740
 msgid "No commit information available"
 msgstr "Cap informació de comissió disponible"
 
-#: gitk:1903 gitk:1932 gitk:4315 gitk:9669 gitk:11241 gitk:11521
 msgid "OK"
 msgstr "D'acord"
 
-#: gitk:1934 gitk:4317 gitk:9196 gitk:9275 gitk:9391 gitk:9440 gitk:9671
-#: gitk:11242 gitk:11522
 msgid "Cancel"
 msgstr "Cancel·la"
 
-#: gitk:2069
 msgid "&Update"
 msgstr "Actualitza"
 
-#: gitk:2070
 msgid "&Reload"
 msgstr "Recarrega"
 
-#: gitk:2071
 msgid "Reread re&ferences"
 msgstr "Rellegeix les referències"
 
-#: gitk:2072
 msgid "&List references"
 msgstr "Llista les referències"
 
-#: gitk:2074
 msgid "Start git &gui"
 msgstr "Inicia el git gui"
 
-#: gitk:2076
 msgid "&Quit"
 msgstr "Surt"
 
-#: gitk:2068
 msgid "&File"
 msgstr "Fitxer"
 
-#: gitk:2080
 msgid "&Preferences"
 msgstr "Preferències"
 
-#: gitk:2079
 msgid "&Edit"
 msgstr "Edita"
 
-#: gitk:2084
 msgid "&New view..."
 msgstr "Vista nova..."
 
-#: gitk:2085
 msgid "&Edit view..."
 msgstr "Edita la vista..."
 
-#: gitk:2086
 msgid "&Delete view"
 msgstr "Suprimeix la vista"
 
-#: gitk:2088 gitk:4043
 msgid "&All files"
 msgstr "Tots els fitxers"
 
-#: gitk:2083 gitk:4067
 msgid "&View"
 msgstr "Vista"
 
-#: gitk:2093 gitk:2103 gitk:3012
 msgid "&About gitk"
 msgstr "Quant al gitk"
 
-#: gitk:2094 gitk:2108
 msgid "&Key bindings"
 msgstr "Associacions de tecles"
 
-#: gitk:2092 gitk:2107
 msgid "&Help"
 msgstr "Ajuda"
 
-#: gitk:2185 gitk:8652
 msgid "SHA1 ID:"
 msgstr "ID SHA1:"
 
-#: gitk:2229
 msgid "Row"
 msgstr "Fila"
 
-#: gitk:2267
 msgid "Find"
 msgstr "Cerca"
 
-#: gitk:2295
 msgid "commit"
 msgstr "comissió"
 
-#: gitk:2299 gitk:2301 gitk:4687 gitk:4710 gitk:4734 gitk:6755 gitk:6827
-#: gitk:6912
 msgid "containing:"
 msgstr "que contingui:"
 
-#: gitk:2302 gitk:3526 gitk:3531 gitk:4763
 msgid "touching paths:"
 msgstr "que toqui els camins:"
 
-#: gitk:2303 gitk:4777
 msgid "adding/removing string:"
 msgstr "que afegeixi/elimini la cadena:"
 
-#: gitk:2304 gitk:4779
 msgid "changing lines matching:"
 msgstr "que tingui línies canviades coincidents amb:"
 
-#: gitk:2313 gitk:2315 gitk:4766
 msgid "Exact"
 msgstr "Exacte"
 
-#: gitk:2315 gitk:4854 gitk:6723
 msgid "IgnCase"
 msgstr "Ignora majúscula i minúscula"
 
-#: gitk:2315 gitk:4736 gitk:4852 gitk:6719
 msgid "Regexp"
 msgstr "Regexp"
 
-#: gitk:2317 gitk:2318 gitk:4874 gitk:4904 gitk:4911 gitk:6848 gitk:6916
 msgid "All fields"
 msgstr "Tots els camps"
 
-#: gitk:2318 gitk:4871 gitk:4904 gitk:6786
 msgid "Headline"
 msgstr "Titular"
 
-#: gitk:2319 gitk:4871 gitk:6786 gitk:6916 gitk:7389
 msgid "Comments"
 msgstr "Comentaris"
 
-#: gitk:2319 gitk:4871 gitk:4876 gitk:4911 gitk:6786 gitk:7324 gitk:8830
-#: gitk:8845
 msgid "Author"
 msgstr "Autor"
 
-#: gitk:2319 gitk:4871 gitk:6786 gitk:7326
 msgid "Committer"
 msgstr "Comitent"
 
-#: gitk:2350
 msgid "Search"
 msgstr "Cerca"
 
-#: gitk:2358
 msgid "Diff"
 msgstr "Diferència"
 
-#: gitk:2360
 msgid "Old version"
 msgstr "Versió antiga"
 
-#: gitk:2362
 msgid "New version"
 msgstr "Versió nova"
 
-#: gitk:2364
 msgid "Lines of context"
 msgstr "Línies de context"
 
-#: gitk:2374
 msgid "Ignore space change"
 msgstr "Ignora canvis d'espai"
 
-#: gitk:2378 gitk:2380 gitk:7959 gitk:8206
 msgid "Line diff"
 msgstr "Diferència de línies"
 
-#: gitk:2445
 msgid "Patch"
 msgstr "Pedaç"
 
-#: gitk:2447
 msgid "Tree"
 msgstr "Arbre"
 
-#: gitk:2617 gitk:2637
 msgid "Diff this -> selected"
 msgstr "Diferencia aquesta -> la seleccionada"
 
-#: gitk:2618 gitk:2638
 msgid "Diff selected -> this"
 msgstr "Diferencia la seleccionada -> aquesta"
 
-#: gitk:2619 gitk:2639
 msgid "Make patch"
 msgstr "Fes pedaç"
 
-#: gitk:2620 gitk:9254
 msgid "Create tag"
 msgstr "Crea etiqueta"
 
-#: gitk:2621 gitk:9371
 msgid "Write commit to file"
 msgstr "Escriu la comissió a un fitxer"
 
-#: gitk:2622 gitk:9428
 msgid "Create new branch"
 msgstr "Crea una branca nova"
 
-#: gitk:2623
 msgid "Cherry-pick this commit"
 msgstr "Recull aquesta comissió com a cirera"
 
-#: gitk:2624
 msgid "Reset HEAD branch to here"
 msgstr "Restableix la branca HEAD aquí"
 
-#: gitk:2625
 msgid "Mark this commit"
 msgstr "Marca aquesta comissió"
 
-#: gitk:2626
 msgid "Return to mark"
 msgstr "Torna a la marca"
 
-#: gitk:2627
 msgid "Find descendant of this and mark"
 msgstr "Troba la descendent d'aquesta i marca-la"
 
-#: gitk:2628
 msgid "Compare with marked commit"
 msgstr "Compara amb la comissió marcada"
 
-#: gitk:2629 gitk:2640
 msgid "Diff this -> marked commit"
 msgstr "Diferencia aquesta -> la comissió marcada"
 
-#: gitk:2630 gitk:2641
 msgid "Diff marked commit -> this"
 msgstr "Diferencia la comissió seleccionada -> aquesta"
 
-#: gitk:2631
 msgid "Revert this commit"
 msgstr "Reverteix aquesta comissió"
 
-#: gitk:2647
 msgid "Check out this branch"
 msgstr "Agafa aquesta branca"
 
-#: gitk:2648
 msgid "Remove this branch"
 msgstr "Elimina aquesta branca"
 
-#: gitk:2649
 msgid "Copy branch name"
 msgstr "Copia el nom de branca"
 
-#: gitk:2656
 msgid "Highlight this too"
 msgstr "Ressalta aquest també"
 
-#: gitk:2657
 msgid "Highlight this only"
 msgstr "Ressalta només aquest"
 
-#: gitk:2658
 msgid "External diff"
 msgstr "Diferència externa"
 
-#: gitk:2659
 msgid "Blame parent commit"
 msgstr "Culpabilitat de la comissió mare"
 
-#: gitk:2660
 msgid "Copy path"
 msgstr "Copia el camí"
 
-#: gitk:2667
 msgid "Show origin of this line"
 msgstr "Mostra l'origen d'aquesta línia"
 
-#: gitk:2668
 msgid "Run git gui blame on this line"
 msgstr "Executa git gui blame en aquesta línia"
 
-#: gitk:3014
 msgid ""
 "\n"
 "Gitk - a commit viewer for git\n"
@@ -376,317 +289,245 @@
 "\n"
 "Useu-lo i redistribuïu-lo sota els termes de la Llicència Pública General GNU"
 
-#: gitk:3022 gitk:3089 gitk:9857
 msgid "Close"
 msgstr "Tanca"
 
-#: gitk:3043
 msgid "Gitk key bindings"
 msgstr "Associacions de tecles del Gitk"
 
-#: gitk:3046
 msgid "Gitk key bindings:"
 msgstr "Associacions de tecles del Gitk:"
 
-#: gitk:3048
 #, tcl-format
 msgid "<%s-Q>\t\tQuit"
 msgstr "<%s-Q>\t\tSurt"
 
-#: gitk:3049
 #, tcl-format
 msgid "<%s-W>\t\tClose window"
 msgstr "<%s-W>\t\tTanca la finestra"
 
-#: gitk:3050
 msgid "<Home>\t\tMove to first commit"
 msgstr "<Inici>\t\tVés a la primera comissió"
 
-#: gitk:3051
 msgid "<End>\t\tMove to last commit"
 msgstr "<Fi>\t\tVés a l'última comissió"
 
-#: gitk:3052
 msgid "<Up>, p, k\tMove up one commit"
 msgstr "<Amunt>, p, k\tMou-te cap amunt per una comissió"
 
-#: gitk:3053
 msgid "<Down>, n, j\tMove down one commit"
 msgstr "<Avall>, n, j\tMou-te cap avall per una comissió"
 
-#: gitk:3054
 msgid "<Left>, z, h\tGo back in history list"
 msgstr "<Esquerra>, z, h\tRetrocedeix en la llista d'història"
 
-#: gitk:3055
 msgid "<Right>, x, l\tGo forward in history list"
 msgstr "<Dreta>, x, l\tAvança en la llista d'història"
 
-#: gitk:3056
 #, tcl-format
 msgid "<%s-n>\tGo to n-th parent of current commit in history list"
 msgstr ""
 "<%s-n>\tVés a l'enèsima mare de la comissió actual en la llista d'història"
 
-#: gitk:3057
 msgid "<PageUp>\tMove up one page in commit list"
 msgstr "<RePàg>\tMou-te cap amunt per una pàgina en la llista de comissions"
 
-#: gitk:3058
 msgid "<PageDown>\tMove down one page in commit list"
 msgstr "<AvPàg>\tMou-te cap avall per una pàgina en la llista de comissions"
 
-#: gitk:3059
 #, tcl-format
 msgid "<%s-Home>\tScroll to top of commit list"
 msgstr "<%s-Inici>\tDesplaça't a la part superior de la llista de comissions"
 
-#: gitk:3060
 #, tcl-format
 msgid "<%s-End>\tScroll to bottom of commit list"
 msgstr "<%s-Fi>\tDesplaça't a la part inferior de la llista de comissions"
 
-#: gitk:3061
 #, tcl-format
 msgid "<%s-Up>\tScroll commit list up one line"
 msgstr "<%s-Amunt>\tDesplaça la llista de comissions cap amunt per una línia"
 
-#: gitk:3062
 #, tcl-format
 msgid "<%s-Down>\tScroll commit list down one line"
 msgstr "<%s-Avall>\tDesplaça la llista de comissions cap avall per una línia"
 
-#: gitk:3063
 #, tcl-format
 msgid "<%s-PageUp>\tScroll commit list up one page"
 msgstr "<%s-RePàg>\tDesplaça la llista de comissions cap amunt per una pàgina"
 
-#: gitk:3064
 #, tcl-format
 msgid "<%s-PageDown>\tScroll commit list down one page"
 msgstr "<%s-AvPàg>\tDesplaça la llista de comissions cap avall per una pàgina"
 
-#: gitk:3065
 msgid "<Shift-Up>\tFind backwards (upwards, later commits)"
 msgstr "<Maj-Amunt>\tCerca cap enrere (cap amunt, les comissions més noves)"
 
-#: gitk:3066
 msgid "<Shift-Down>\tFind forwards (downwards, earlier commits)"
 msgstr "<Maj-Avall>\tCerca cap endavant (cap avall, les comissions més velles)"
 
-#: gitk:3067
 msgid "<Delete>, b\tScroll diff view up one page"
 msgstr "<Supr>, b\tDesplaça la vista de diferència cap amunt per una pàgina"
 
-#: gitk:3068
 msgid "<Backspace>\tScroll diff view up one page"
 msgstr "<Retrocés>\tDesplaça la vista de diferència cap amunt per una pàgina"
 
-#: gitk:3069
 msgid "<Space>\t\tScroll diff view down one page"
 msgstr "<Espai>\t\tDesplaça la vista de diferència cap avall per una pàgina"
 
-#: gitk:3070
 msgid "u\t\tScroll diff view up 18 lines"
 msgstr "u\t\tDesplaça la vista de diferència cap amunt per 18 línies"
 
-#: gitk:3071
 msgid "d\t\tScroll diff view down 18 lines"
 msgstr "d\t\tDesplaça la vista de diferència cap avall per 18 línies"
 
-#: gitk:3072
 #, tcl-format
 msgid "<%s-F>\t\tFind"
 msgstr "<%s-F>\t\tCerca"
 
-#: gitk:3073
 #, tcl-format
 msgid "<%s-G>\t\tMove to next find hit"
 msgstr "<%s-G>\t\tMou-te a la propera coincidència de la cerca"
 
-#: gitk:3074
 msgid "<Return>\tMove to next find hit"
 msgstr "<Retorn>\tMou-te a la propera coincidència de la cerca"
 
-#: gitk:3075
 msgid "g\t\tGo to commit"
 msgstr "g\t\tVés a l'última comissió"
 
-#: gitk:3076
 msgid "/\t\tFocus the search box"
 msgstr "/\t\tPosa el focus a la caixa de cerca"
 
-#: gitk:3077
 msgid "?\t\tMove to previous find hit"
 msgstr "?\t\tMou a la coincidència prèvia de la cerca"
 
-#: gitk:3078
 msgid "f\t\tScroll diff view to next file"
 msgstr "f\t\tDesplaça la vista de diferència al proper fitxer"
 
-#: gitk:3079
 #, tcl-format
 msgid "<%s-S>\t\tSearch for next hit in diff view"
 msgstr "<%s-S>\t\tCerca la propera coincidència en la vista de diferència"
 
-#: gitk:3080
 #, tcl-format
 msgid "<%s-R>\t\tSearch for previous hit in diff view"
 msgstr "<%s-R>\t\tCerca la coincidència prèvia en la vista de diferència"
 
-#: gitk:3081
 #, tcl-format
 msgid "<%s-KP+>\tIncrease font size"
 msgstr "<%s-KP+>\tAugmenta la mida de lletra"
 
-#: gitk:3082
 #, tcl-format
 msgid "<%s-plus>\tIncrease font size"
 msgstr "<%s-més>\tAugmenta la mida de lletra"
 
-#: gitk:3083
 #, tcl-format
 msgid "<%s-KP->\tDecrease font size"
 msgstr "<%s-KP->\tDisminueix la mida de lletra"
 
-#: gitk:3084
 #, tcl-format
 msgid "<%s-minus>\tDecrease font size"
 msgstr "<%s-menys>\tDisminueix la mida de lletra"
 
-#: gitk:3085
 msgid "<F5>\t\tUpdate"
 msgstr "<F5>\t\tActualitza"
 
-#: gitk:3550 gitk:3559
 #, tcl-format
 msgid "Error creating temporary directory %s:"
 msgstr "Error en crear el directori temporal %s:"
 
-#: gitk:3572
 #, tcl-format
 msgid "Error getting \"%s\" from %s:"
 msgstr "Error en obtenir \"%s\" de %s:"
 
-#: gitk:3635
 msgid "command failed:"
 msgstr "l'ordre ha fallat:"
 
-#: gitk:3784
 msgid "No such commit"
 msgstr "Cap comissió així"
 
-#: gitk:3798
 msgid "git gui blame: command failed:"
 msgstr "git gui blame: l'ordre ha fallat:"
 
-#: gitk:3829
 #, tcl-format
 msgid "Couldn't read merge head: %s"
 msgstr "No s'ha pogut llegir el cap de fusió: %s"
 
-#: gitk:3837
 #, tcl-format
 msgid "Error reading index: %s"
 msgstr "Error en llegir l'índex: %s"
 
-#: gitk:3862
 #, tcl-format
 msgid "Couldn't start git blame: %s"
 msgstr "No s'ha pogut iniciar el git blame: %s"
 
-#: gitk:3865 gitk:6754
 msgid "Searching"
 msgstr "Cercant"
 
-#: gitk:3897
 #, tcl-format
 msgid "Error running git blame: %s"
 msgstr "Error en executar el git blame: %s"
 
-#: gitk:3925
 #, tcl-format
 msgid "That line comes from commit %s,  which is not in this view"
 msgstr ""
 "Aquella línia ve de la comissió %s, la qual no és en aquesta visualització"
 
-#: gitk:3939
 msgid "External diff viewer failed:"
 msgstr "El visualitzador de diferència extern ha fallat:"
 
-#: gitk:4070
 msgid "Gitk view definition"
 msgstr "Definició de vista del Gitk"
 
-#: gitk:4074
 msgid "Remember this view"
 msgstr "Recorda aquesta vista"
 
-#: gitk:4075
 msgid "References (space separated list):"
 msgstr "Referències (llista separada per espais)"
 
-#: gitk:4076
 msgid "Branches & tags:"
 msgstr "Branques i etiquetes:"
 
-#: gitk:4077
 msgid "All refs"
 msgstr "Totes les referències"
 
-#: gitk:4078
 msgid "All (local) branches"
 msgstr "Totes les branques (locals)"
 
-#: gitk:4079
 msgid "All tags"
 msgstr "Totes les etiquetes"
 
-#: gitk:4080
 msgid "All remote-tracking branches"
 msgstr "Totes les branques amb seguiment remot"
 
-#: gitk:4081
 msgid "Commit Info (regular expressions):"
 msgstr "Informació de comissió (expressions regulars):"
 
-#: gitk:4082
 msgid "Author:"
 msgstr "Autor:"
 
-#: gitk:4083
 msgid "Committer:"
 msgstr "Comitent:"
 
-#: gitk:4084
 msgid "Commit Message:"
 msgstr "Missatge de comissió:"
 
-#: gitk:4085
 msgid "Matches all Commit Info criteria"
 msgstr "Coincideix amb tots els criteris d'informació de comissió"
 
-#: gitk:4086
 msgid "Matches no Commit Info criteria"
 msgstr "No coincideix amb cap criteri d'informació de comissió"
 
-#: gitk:4087
 msgid "Changes to Files:"
 msgstr "Canvis als fitxers:"
 
-#: gitk:4088
 msgid "Fixed String"
 msgstr "Cadena fixa"
 
-#: gitk:4089
 msgid "Regular Expression"
 msgstr "Expressió regular"
 
-#: gitk:4090
 msgid "Search string:"
 msgstr "Cadena de cerca:"
 
-#: gitk:4091
 msgid ""
 "Commit Dates (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 "
 "15:27:38\"):"
@@ -694,201 +535,153 @@
 "Dates de comissió (\"fa 2 setmanes\", \"2009-03-17 15:27:38\", \"17 abr 2009 "
 "15:27:38\"):"
 
-#: gitk:4092
 msgid "Since:"
 msgstr "Des de:"
 
-#: gitk:4093
 msgid "Until:"
 msgstr "Fins:"
 
-#: gitk:4094
 msgid "Limit and/or skip a number of revisions (positive integer):"
 msgstr "Limita o salta un nombre de revisions (nombre enter positiu)"
 
-#: gitk:4095
 msgid "Number to show:"
 msgstr "Nombre a mostrar:"
 
-#: gitk:4096
 msgid "Number to skip:"
 msgstr "Nombre a saltar:"
 
-#: gitk:4097
 msgid "Miscellaneous options:"
 msgstr "Opcions miscel·lànies:"
 
-#: gitk:4098
 msgid "Strictly sort by date"
 msgstr "Ordena estrictament per data"
 
-#: gitk:4099
 msgid "Mark branch sides"
 msgstr "Marca els costats de les branques"
 
-#: gitk:4100
 msgid "Limit to first parent"
 msgstr "Limita a la primera mare"
 
-#: gitk:4101
 msgid "Simple history"
 msgstr "Història senzilla"
 
-#: gitk:4102
 msgid "Additional arguments to git log:"
 msgstr "Paràmetres addicionals al git log:"
 
-#: gitk:4103
 msgid "Enter files and directories to include, one per line:"
 msgstr "Introduïu els fitxers i directoris a incloure, un per línia:"
 
-#: gitk:4104
 msgid "Command to generate more commits to include:"
 msgstr "Ordre per a generar més comissions a incloure:"
 
-#: gitk:4228
 msgid "Gitk: edit view"
 msgstr "Gitk: vista d'edició"
 
-#: gitk:4236
 msgid "-- criteria for selecting revisions"
 msgstr "-- criteris per a seleccionar les revisions"
 
-#: gitk:4241
 msgid "View Name"
 msgstr "Nom de vista"
 
-#: gitk:4316
 msgid "Apply (F5)"
 msgstr "Aplica (F5)"
 
-#: gitk:4354
 msgid "Error in commit selection arguments:"
 msgstr "Error en els paràmetres de selecció de comissions:"
 
-#: gitk:4409 gitk:4462 gitk:4924 gitk:4938 gitk:6208 gitk:12373 gitk:12374
 msgid "None"
 msgstr "Cap"
 
-#: gitk:5021 gitk:5026
 msgid "Descendant"
 msgstr "Descendent"
 
-#: gitk:5022
 msgid "Not descendant"
 msgstr "No descendent"
 
-#: gitk:5029 gitk:5034
 msgid "Ancestor"
 msgstr "Avantpassat"
 
-#: gitk:5030
 msgid "Not ancestor"
 msgstr "No avantpassat"
 
-#: gitk:5324
 msgid "Local changes checked in to index but not committed"
 msgstr "Canvis locals registrats en l'índex però no comesos"
 
-#: gitk:5360
 msgid "Local uncommitted changes, not checked in to index"
 msgstr "Canvis locals sense cometre, no registrats en l'índex"
 
-#: gitk:7134
 msgid "and many more"
 msgstr "i moltes més"
 
-#: gitk:7137
 msgid "many"
 msgstr "moltes"
 
-#: gitk:7328
 msgid "Tags:"
 msgstr "Etiquetes:"
 
-#: gitk:7345 gitk:7351 gitk:8825
 msgid "Parent"
 msgstr "Mare"
 
-#: gitk:7356
 msgid "Child"
 msgstr "Filla"
 
-#: gitk:7365
 msgid "Branch"
 msgstr "Branca"
 
-#: gitk:7368
 msgid "Follows"
 msgstr "Segueix"
 
-#: gitk:7371
 msgid "Precedes"
 msgstr "Precedeix"
 
-#: gitk:7966
 #, tcl-format
 msgid "Error getting diffs: %s"
 msgstr "Error en obtenir les diferències: %s"
 
-#: gitk:8650
 msgid "Goto:"
 msgstr "Vés a:"
 
-#: gitk:8671
 #, tcl-format
 msgid "Short SHA1 id %s is ambiguous"
 msgstr "L'id SHA1 curta %s és ambigua"
 
-#: gitk:8678
 #, tcl-format
 msgid "Revision %s is not known"
 msgstr "La revisió %s és desconeguda"
 
-#: gitk:8688
 #, tcl-format
 msgid "SHA1 id %s is not known"
 msgstr "L'id SHA1 %s és desconeguda"
 
-#: gitk:8690
 #, tcl-format
 msgid "Revision %s is not in the current view"
 msgstr "La revisió %s no és en la vista actual"
 
-#: gitk:8832 gitk:8847
 msgid "Date"
 msgstr "Data"
 
-#: gitk:8835
 msgid "Children"
 msgstr "Filles"
 
-#: gitk:8898
 #, tcl-format
 msgid "Reset %s branch to here"
 msgstr "Restableix la branca %s aquí"
 
-#: gitk:8900
 msgid "Detached head: can't reset"
 msgstr "Cap separat: no es pot restablir"
 
-#: gitk:9005 gitk:9011
 msgid "Skipping merge commit "
 msgstr "Saltant la comissió de fusió "
 
-#: gitk:9020 gitk:9025
 msgid "Error getting patch ID for "
 msgstr "Error en obtenir l'ID de pedaç de "
 
-#: gitk:9021 gitk:9026
 msgid " - stopping\n"
 msgstr " - aturant\n"
 
-#: gitk:9031 gitk:9034 gitk:9042 gitk:9056 gitk:9065
 msgid "Commit "
 msgstr "Comissió "
 
-#: gitk:9035
 msgid ""
 " is the same patch as\n"
 "       "
@@ -896,7 +689,6 @@
 " és el mateix pedaç que\n"
 "       "
 
-#: gitk:9043
 msgid ""
 " differs from\n"
 "       "
@@ -904,7 +696,6 @@
 " difereix de\n"
 "       "
 
-#: gitk:9045
 msgid ""
 "Diff of commits:\n"
 "\n"
@@ -912,131 +703,101 @@
 "Diferència entre comissions:\n"
 "\n"
 
-#: gitk:9057 gitk:9066
 #, tcl-format
 msgid " has %s children - stopping\n"
 msgstr " té %s filles - aturant\n"
 
-#: gitk:9085
 #, tcl-format
 msgid "Error writing commit to file: %s"
 msgstr "Error en escriure la comissió al fitxer: %s"
 
-#: gitk:9091
 #, tcl-format
 msgid "Error diffing commits: %s"
 msgstr "Error en diferenciar les comissions: %s"
 
-#: gitk:9137
 msgid "Top"
 msgstr "Part superior"
 
-#: gitk:9138
 msgid "From"
 msgstr "De"
 
-#: gitk:9143
 msgid "To"
 msgstr "A"
 
-#: gitk:9167
 msgid "Generate patch"
 msgstr "Genera pedaç"
 
-#: gitk:9169
 msgid "From:"
 msgstr "De:"
 
-#: gitk:9178
 msgid "To:"
 msgstr "A:"
 
-#: gitk:9187
 msgid "Reverse"
 msgstr "Inverteix"
 
-#: gitk:9189 gitk:9385
 msgid "Output file:"
 msgstr "Fitxer de sortida:"
 
-#: gitk:9195
 msgid "Generate"
 msgstr "Genera"
 
-#: gitk:9233
 msgid "Error creating patch:"
 msgstr "Error en crear el pedaç:"
 
-#: gitk:9256 gitk:9373 gitk:9430
 msgid "ID:"
 msgstr "ID:"
 
-#: gitk:9265
 msgid "Tag name:"
 msgstr "Nom d'etiqueta:"
 
-#: gitk:9268
 msgid "Tag message is optional"
 msgstr "El missatge d'etiqueta és opcional"
 
-#: gitk:9270
 msgid "Tag message:"
 msgstr "Missatge d'etiqueta:"
 
-#: gitk:9274 gitk:9439
 msgid "Create"
 msgstr "Crea"
 
-#: gitk:9292
 msgid "No tag name specified"
 msgstr "No s'ha especificat cap nom d'etiqueta"
 
-#: gitk:9296
 #, tcl-format
 msgid "Tag \"%s\" already exists"
 msgstr "L'etiqueta \"%s\" ja existeix"
 
-#: gitk:9306
 msgid "Error creating tag:"
 msgstr "Error en crear l'etiqueta:"
 
-#: gitk:9382
 msgid "Command:"
 msgstr "Ordre:"
 
-#: gitk:9390
 msgid "Write"
 msgstr "Escriu"
 
-#: gitk:9408
 msgid "Error writing commit:"
 msgstr "Error en escriure la comissió:"
 
-#: gitk:9435
 msgid "Name:"
 msgstr "Nom:"
 
-#: gitk:9458
 msgid "Please specify a name for the new branch"
 msgstr "Si us plau, especifiqueu un nom per a la branca nova"
 
-#: gitk:9463
 #, tcl-format
 msgid "Branch '%s' already exists. Overwrite?"
 msgstr "La branca '%s' ja existeix. Voleu sobreescriure?"
 
-#: gitk:9530
 #, tcl-format
 msgid "Commit %s is already included in branch %s -- really re-apply it?"
 msgstr ""
 "La comissió %s ja està inclosa en la branca %s -- realment voleu tornar a "
 "aplicar-la?"
 
-#: gitk:9535
 msgid "Cherry-picking"
 msgstr "Recollint cireres"
 
-#: gitk:9544
 #, tcl-format
 msgid ""
 "Cherry-pick failed because of local changes to file '%s'.\n"
@@ -1046,7 +807,6 @@
 "Si us plau, cometeu, restabliu o emmagatzemeu els vostres canvis i torneu a "
 "intentar."
 
-#: gitk:9550
 msgid ""
 "Cherry-pick failed because of merge conflict.\n"
 "Do you wish to run git citool to resolve it?"
@@ -1054,21 +814,17 @@
 "El recull de cireres ha fallat a causa d'un conflicte de fusió.\n"
 "Voleu executar el git citool per a resoldre'l?"
 
-#: gitk:9566 gitk:9624
 msgid "No changes committed"
 msgstr "Cap canvi comès"
 
-#: gitk:9593
 #, tcl-format
 msgid "Commit %s is not included in branch %s -- really revert it?"
 msgstr ""
 "La comissió %s no s'inclou en la branca %s -- realment voleu revertir-la?"
 
-#: gitk:9598
 msgid "Reverting"
 msgstr "Revertint"
 
-#: gitk:9606
 #, tcl-format
 msgid ""
 "Revert failed because of local changes to the following files:%s Please "
@@ -1078,7 +834,6 @@
 "plau, cometeu, restabliu o emmagatzemeu els vostres canvis i torneu-ho a "
 "intentar."
 
-#: gitk:9610
 msgid ""
 "Revert failed because of merge conflict.\n"
 " Do you wish to run git citool to resolve it?"
@@ -1086,28 +841,22 @@
 "La reversió ha fallat a causa d'un conflicte de fusió.\n"
 " Voleu executar el git citool per a resoldre'l?"
 
-#: gitk:9653
 msgid "Confirm reset"
 msgstr "Confirma el restabliment"
 
-#: gitk:9655
 #, tcl-format
 msgid "Reset branch %s to %s?"
 msgstr "Voleu restablir la branca %s a %s?"
 
-#: gitk:9657
 msgid "Reset type:"
 msgstr "Tipus de restabliment:"
 
-#: gitk:9660
 msgid "Soft: Leave working tree and index untouched"
 msgstr "Suau: Deixa l'arbre de treball i l'índex sense tocar"
 
-#: gitk:9663
 msgid "Mixed: Leave working tree untouched, reset index"
 msgstr "Mixt: Deixa l'arbre de treball sense tocar, restableix l'índex"
 
-#: gitk:9666
 msgid ""
 "Hard: Reset working tree and index\n"
 "(discard ALL local changes)"
@@ -1115,19 +864,15 @@
 "Dur: Restableix l'arbre de treball i l'índex\n"
 "(descarta TOTS els canvis locals)"
 
-#: gitk:9683
 msgid "Resetting"
 msgstr "Restablint"
 
-#: gitk:9743
 msgid "Checking out"
 msgstr "Agafant"
 
-#: gitk:9796
 msgid "Cannot delete the currently checked-out branch"
 msgstr "No es pot suprimir la branca actualment agafada"
 
-#: gitk:9802
 #, tcl-format
 msgid ""
 "The commits on branch %s aren't on any other branch.\n"
@@ -1136,16 +881,13 @@
 "Les comissions en la branca %s no són en cap altra branca.\n"
 "Realment voleu suprimir la branca %s?"
 
-#: gitk:9833
 #, tcl-format
 msgid "Tags and heads: %s"
 msgstr "Etiquetes i caps: %s"
 
-#: gitk:9850
 msgid "Filter"
 msgstr "Filtre"
 
-#: gitk:10146
 msgid ""
 "Error reading commit topology information; branch and preceding/following "
 "tag information will be incomplete."
@@ -1153,201 +895,152 @@
 "Error en llegir la informació de topologia de comissió; la informació sobre "
 "branques i etiquetes precedents/següents serà incompleta."
 
-#: gitk:11123
 msgid "Tag"
 msgstr "Etiqueta"
 
-#: gitk:11127
 msgid "Id"
 msgstr "Id"
 
-#: gitk:11210
 msgid "Gitk font chooser"
 msgstr "Selector de tipus de lletra del Gitk"
 
-#: gitk:11227
 msgid "B"
 msgstr "B"
 
-#: gitk:11230
 msgid "I"
 msgstr "I"
 
-#: gitk:11348
 msgid "Commit list display options"
 msgstr "Opcions de visualització de la llista de comissions"
 
-#: gitk:11351
 msgid "Maximum graph width (lines)"
 msgstr "Amplada màxima del gràfic (línies)"
 
-#: gitk:11355
 #, no-tcl-format
 msgid "Maximum graph width (% of pane)"
 msgstr "Amplada màxima del gràfic (% del panell)"
 
-#: gitk:11358
 msgid "Show local changes"
 msgstr "Mostra els canvis locals"
 
-#: gitk:11361
 msgid "Auto-select SHA1 (length)"
 msgstr "Selecciona automàticament l'SHA1 (longitud)"
 
-#: gitk:11365
 msgid "Hide remote refs"
 msgstr "Amaga les referències remotes"
 
-#: gitk:11369
 msgid "Diff display options"
 msgstr "Opcions de visualització de diferència"
 
-#: gitk:11371
 msgid "Tab spacing"
 msgstr "Espaiat de tabulació"
 
-#: gitk:11374
 msgid "Display nearby tags/heads"
 msgstr "Mostra etiquetes/caps propers"
 
-#: gitk:11377
 msgid "Maximum # tags/heads to show"
 msgstr "Nombre màxim d'etiquetes/caps a mostrar"
 
-#: gitk:11380
 msgid "Limit diffs to listed paths"
 msgstr "Limita les diferències als camins llistats"
 
-#: gitk:11383
 msgid "Support per-file encodings"
 msgstr "Admet codificacions específiques per a cada fitxer"
 
-#: gitk:11389 gitk:11536
 msgid "External diff tool"
 msgstr "Eina de diferència externa"
 
-#: gitk:11390
 msgid "Choose..."
 msgstr "Trieu..."
 
-#: gitk:11395
 msgid "General options"
 msgstr "Opcions generals"
 
-#: gitk:11398
 msgid "Use themed widgets"
 msgstr "Usa els ginys tematitzats"
 
-#: gitk:11400
 msgid "(change requires restart)"
 msgstr "(el canvi requereix reiniciar)"
 
-#: gitk:11402
 msgid "(currently unavailable)"
 msgstr "(actualment no disponible)"
 
-#: gitk:11413
 msgid "Colors: press to choose"
 msgstr "Colors: pressiona per a triar"
 
-#: gitk:11416
 msgid "Interface"
 msgstr "Interfície"
 
-#: gitk:11417
 msgid "interface"
 msgstr "interfície"
 
-#: gitk:11420
 msgid "Background"
 msgstr "Fons"
 
-#: gitk:11421 gitk:11451
 msgid "background"
 msgstr "fons"
 
-#: gitk:11424
 msgid "Foreground"
 msgstr "Primer pla"
 
-#: gitk:11425
 msgid "foreground"
 msgstr "primer pla"
 
-#: gitk:11428
 msgid "Diff: old lines"
 msgstr "Diferència: línies velles"
 
-#: gitk:11429
 msgid "diff old lines"
 msgstr "diferencia les línies velles"
 
-#: gitk:11433
 msgid "Diff: new lines"
 msgstr "Diferència: línies noves"
 
-#: gitk:11434
 msgid "diff new lines"
 msgstr "diferencia les línies noves"
 
-#: gitk:11438
 msgid "Diff: hunk header"
 msgstr "Diferència: capçalera de tros"
 
-#: gitk:11440
 msgid "diff hunk header"
 msgstr "diferencia la capçalera de tros"
 
-#: gitk:11444
 msgid "Marked line bg"
 msgstr "Fons de la línia marcada"
 
-#: gitk:11446
 msgid "marked line background"
 msgstr "fons de la línia marcada"
 
-#: gitk:11450
 msgid "Select bg"
 msgstr "Fons de la selecció"
 
-#: gitk:11459
 msgid "Fonts: press to choose"
 msgstr "Tipus de lletra: pressiona per a triar"
 
-#: gitk:11461
 msgid "Main font"
 msgstr "Tipus de lletra principal"
 
-#: gitk:11462
 msgid "Diff display font"
 msgstr "Tipus de lletra de visualització de diferència"
 
-#: gitk:11463
 msgid "User interface font"
 msgstr "Tipus de lletra de la interfície d'usuari"
 
-#: gitk:11485
 msgid "Gitk preferences"
 msgstr "Preferències del Gitk"
 
-#: gitk:11494
 msgid "General"
 msgstr "General"
 
-#: gitk:11495
 msgid "Colors"
 msgstr "Colors"
 
-#: gitk:11496
 msgid "Fonts"
 msgstr "Tipus de lletra"
 
-#: gitk:11546
 #, tcl-format
 msgid "Gitk: choose color for %s"
 msgstr "Gitk: tria el color per a %s"
 
-#: gitk:12059
 msgid ""
 "Sorry, gitk cannot run with this version of Tcl/Tk.\n"
 " Gitk requires at least Tcl/Tk 8.4."
@@ -1355,15 +1048,12 @@
 "Perdó, el gitk no pot executar-se amb aquesta versió de Tcl/Tk.\n"
 " El Gitk requereix com a mínim el Tcl/Tk 8.4."
 
-#: gitk:12269
 msgid "Cannot find a git repository here."
 msgstr "No es pot trobar cap dipòsit de git aquí."
 
-#: gitk:12316
 #, tcl-format
 msgid "Ambiguous argument '%s': both revision and filename"
 msgstr "Paràmetre ambigu '%s': és tant revisió com nom de fitxer"
 
-#: gitk:12328
 msgid "Bad arguments to gitk:"
 msgstr "Paràmetres dolents al gitk:"
diff --git a/gitk-git/po/de.po b/gitk-git/po/de.po
index 5db3824..fea18fa 100644
--- a/gitk-git/po/de.po
+++ b/gitk-git/po/de.po
@@ -6,7 +6,7 @@
 # Frederik Schwarzer <schwarzerf@gmail.com>, 2008.
 msgid ""
 msgstr ""
-"Project-Id-Version: git-gui\n"
+"Project-Id-Version: Gitk\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2015-05-17 14:32+1000\n"
 "PO-Revision-Date: 2015-10-20 14:20+0200\n"
@@ -17,33 +17,26 @@
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: gitk:140
 msgid "Couldn't get list of unmerged files:"
 msgstr "Liste der nicht zusammengeführten Dateien nicht gefunden:"
 
-#: gitk:212 gitk:2381
 msgid "Color words"
 msgstr "Wörter einfärben"
 
-#: gitk:217 gitk:2381 gitk:8220 gitk:8253
 msgid "Markup words"
 msgstr "Wörter kennzeichnen"
 
-#: gitk:324
 msgid "Error parsing revisions:"
 msgstr "Fehler beim Laden der Versionen:"
 
-#: gitk:380
 msgid "Error executing --argscmd command:"
 msgstr "Fehler beim Ausführen des --argscmd-Kommandos:"
 
-#: gitk:393
 msgid "No files selected: --merge specified but no files are unmerged."
 msgstr ""
 "Keine Dateien ausgewählt: Es wurde --merge angegeben, aber es existieren "
 "keine nicht zusammengeführten Dateien."
 
-#: gitk:396
 msgid ""
 "No files selected: --merge specified but no unmerged files are within file "
 "limit."
@@ -51,314 +44,234 @@
 "Keine Dateien ausgewählt: Es wurde --merge angegeben, aber es sind keine "
 "nicht zusammengeführten Dateien in der Dateiauswahl."
 
-#: gitk:418 gitk:566
 msgid "Error executing git log:"
 msgstr "Fehler beim Ausführen von »git log«:"
 
-#: gitk:436 gitk:582
 msgid "Reading"
 msgstr "Lesen"
 
-#: gitk:496 gitk:4525
 msgid "Reading commits..."
 msgstr "Versionen werden gelesen ..."
 
-#: gitk:499 gitk:1637 gitk:4528
 msgid "No commits selected"
 msgstr "Keine Versionen ausgewählt"
 
-#: gitk:1445 gitk:4045 gitk:12432
 msgid "Command line"
 msgstr "Kommandozeile"
 
-#: gitk:1511
 msgid "Can't parse git log output:"
 msgstr "Ausgabe von »git log« kann nicht erkannt werden:"
 
-#: gitk:1740
 msgid "No commit information available"
 msgstr "Keine Versionsinformation verfügbar"
 
-#: gitk:1903 gitk:1932 gitk:4315 gitk:9669 gitk:11241 gitk:11521
 msgid "OK"
 msgstr "Ok"
 
-#: gitk:1934 gitk:4317 gitk:9196 gitk:9275 gitk:9391 gitk:9440 gitk:9671
-#: gitk:11242 gitk:11522
 msgid "Cancel"
 msgstr "Abbrechen"
 
-#: gitk:2069
 msgid "&Update"
 msgstr "&Aktualisieren"
 
-#: gitk:2070
 msgid "&Reload"
 msgstr "&Neu laden"
 
-#: gitk:2071
 msgid "Reread re&ferences"
 msgstr "&Zweige neu laden"
 
-#: gitk:2072
 msgid "&List references"
 msgstr "Zweige/Markierungen auf&listen"
 
-#: gitk:2074
 msgid "Start git &gui"
 msgstr "»git &gui« starten"
 
-#: gitk:2076
 msgid "&Quit"
 msgstr "&Beenden"
 
-#: gitk:2068
 msgid "&File"
 msgstr "&Datei"
 
-#: gitk:2080
 msgid "&Preferences"
 msgstr "&Einstellungen"
 
-#: gitk:2079
 msgid "&Edit"
 msgstr "&Bearbeiten"
 
-#: gitk:2084
 msgid "&New view..."
 msgstr "&Neue Ansicht ..."
 
-#: gitk:2085
 msgid "&Edit view..."
 msgstr "Ansicht &bearbeiten ..."
 
-#: gitk:2086
 msgid "&Delete view"
 msgstr "Ansicht &entfernen"
 
-#: gitk:2088 gitk:4043
 msgid "&All files"
 msgstr "&Alle Dateien"
 
-#: gitk:2083 gitk:4067
 msgid "&View"
 msgstr "&Ansicht"
 
-#: gitk:2093 gitk:2103 gitk:3012
 msgid "&About gitk"
 msgstr "Über &gitk"
 
-#: gitk:2094 gitk:2108
 msgid "&Key bindings"
 msgstr "&Tastenkürzel"
 
-#: gitk:2092 gitk:2107
 msgid "&Help"
 msgstr "&Hilfe"
 
-#: gitk:2185 gitk:8652
 msgid "SHA1 ID:"
 msgstr "SHA1 ID:"
 
-#: gitk:2229
 msgid "Row"
 msgstr "Zeile"
 
-#: gitk:2267
 msgid "Find"
 msgstr "Suche"
 
-#: gitk:2295
 msgid "commit"
 msgstr "Version nach"
 
-#: gitk:2299 gitk:2301 gitk:4687 gitk:4710 gitk:4734 gitk:6755 gitk:6827
-#: gitk:6912
 msgid "containing:"
 msgstr "Beschreibung:"
 
-#: gitk:2302 gitk:3526 gitk:3531 gitk:4763
 msgid "touching paths:"
 msgstr "Dateien:"
 
-#: gitk:2303 gitk:4777
 msgid "adding/removing string:"
 msgstr "Änderungen:"
 
-#: gitk:2304 gitk:4779
 msgid "changing lines matching:"
 msgstr "Geänderte Zeilen entsprechen:"
 
-#: gitk:2313 gitk:2315 gitk:4766
 msgid "Exact"
 msgstr "Exakt"
 
-#: gitk:2315 gitk:4854 gitk:6723
 msgid "IgnCase"
 msgstr "Kein Groß/Klein"
 
-#: gitk:2315 gitk:4736 gitk:4852 gitk:6719
 msgid "Regexp"
 msgstr "Regexp"
 
-#: gitk:2317 gitk:2318 gitk:4874 gitk:4904 gitk:4911 gitk:6848 gitk:6916
 msgid "All fields"
 msgstr "Alle Felder"
 
-#: gitk:2318 gitk:4871 gitk:4904 gitk:6786
 msgid "Headline"
 msgstr "Überschrift"
 
-#: gitk:2319 gitk:4871 gitk:6786 gitk:6916 gitk:7389
 msgid "Comments"
 msgstr "Beschreibung"
 
-#: gitk:2319 gitk:4871 gitk:4876 gitk:4911 gitk:6786 gitk:7324 gitk:8830
-#: gitk:8845
 msgid "Author"
 msgstr "Autor"
 
-#: gitk:2319 gitk:4871 gitk:6786 gitk:7326
 msgid "Committer"
 msgstr "Eintragender"
 
-#: gitk:2350
 msgid "Search"
 msgstr "Suchen"
 
-#: gitk:2358
 msgid "Diff"
 msgstr "Vergleich"
 
-#: gitk:2360
 msgid "Old version"
 msgstr "Alte Version"
 
-#: gitk:2362
 msgid "New version"
 msgstr "Neue Version"
 
-#: gitk:2364
 msgid "Lines of context"
 msgstr "Kontextzeilen"
 
-#: gitk:2374
 msgid "Ignore space change"
 msgstr "Leerzeichenänderungen ignorieren"
 
-#: gitk:2378 gitk:2380 gitk:7959 gitk:8206
 msgid "Line diff"
 msgstr "Zeilenunterschied"
 
-#: gitk:2445
 msgid "Patch"
 msgstr "Patch"
 
-#: gitk:2447
 msgid "Tree"
 msgstr "Baum"
 
-#: gitk:2617 gitk:2637
 msgid "Diff this -> selected"
 msgstr "Vergleich: diese -> gewählte"
 
-#: gitk:2618 gitk:2638
 msgid "Diff selected -> this"
 msgstr "Vergleich: gewählte -> diese"
 
-#: gitk:2619 gitk:2639
 msgid "Make patch"
 msgstr "Patch erstellen"
 
-#: gitk:2620 gitk:9254
 msgid "Create tag"
 msgstr "Markierung erstellen"
 
-#: gitk:2621 gitk:9371
 msgid "Write commit to file"
 msgstr "Version in Datei schreiben"
 
-#: gitk:2622 gitk:9428
 msgid "Create new branch"
 msgstr "Neuen Zweig erstellen"
 
-#: gitk:2623
 msgid "Cherry-pick this commit"
 msgstr "Diese Version pflücken"
 
-#: gitk:2624
 msgid "Reset HEAD branch to here"
 msgstr "HEAD-Zweig auf diese Version zurücksetzen"
 
-#: gitk:2625
 msgid "Mark this commit"
 msgstr "Lesezeichen setzen"
 
-#: gitk:2626
 msgid "Return to mark"
 msgstr "Zum Lesezeichen"
 
-#: gitk:2627
 msgid "Find descendant of this and mark"
 msgstr "Abkömmling von Lesezeichen und dieser Version finden"
 
-#: gitk:2628
 msgid "Compare with marked commit"
 msgstr "Mit Lesezeichen vergleichen"
 
-#: gitk:2629 gitk:2640
 msgid "Diff this -> marked commit"
 msgstr "Vergleich: diese -> gewählte Version"
 
-#: gitk:2630 gitk:2641
 msgid "Diff marked commit -> this"
 msgstr "Vergleich: gewählte -> diese Version"
 
-#: gitk:2631
 msgid "Revert this commit"
 msgstr "Version umkehren"
 
-#: gitk:2647
 msgid "Check out this branch"
 msgstr "Auf diesen Zweig umstellen"
 
-#: gitk:2648
 msgid "Remove this branch"
 msgstr "Zweig löschen"
 
-#: gitk:2649
 msgid "Copy branch name"
 msgstr "Zweigname kopieren"
 
-#: gitk:2656
 msgid "Highlight this too"
 msgstr "Diesen auch hervorheben"
 
-#: gitk:2657
 msgid "Highlight this only"
 msgstr "Nur diesen hervorheben"
 
-#: gitk:2658
 msgid "External diff"
 msgstr "Externes Diff-Programm"
 
-#: gitk:2659
 msgid "Blame parent commit"
 msgstr "Annotieren der Elternversion"
 
-#: gitk:2660
 msgid "Copy path"
 msgstr "Pfad kopieren"
 
-#: gitk:2667
 msgid "Show origin of this line"
 msgstr "Herkunft dieser Zeile anzeigen"
 
-#: gitk:2668
 msgid "Run git gui blame on this line"
 msgstr "Diese Zeile annotieren (»git gui blame«)"
 
-#: gitk:3014
 msgid ""
 "\n"
 "Gitk - a commit viewer for git\n"
@@ -375,517 +288,397 @@
 "Benutzung und Weiterverbreitung gemäß den Bedingungen der GNU General Public "
 "License"
 
-#: gitk:3022 gitk:3089 gitk:9857
 msgid "Close"
 msgstr "Schließen"
 
-#: gitk:3043
 msgid "Gitk key bindings"
 msgstr "Gitk-Tastaturbelegung"
 
-#: gitk:3046
 msgid "Gitk key bindings:"
 msgstr "Gitk-Tastaturbelegung:"
 
-#: gitk:3048
 #, tcl-format
 msgid "<%s-Q>\t\tQuit"
 msgstr "<%s-Q>\t\tBeenden"
 
-#: gitk:3049
 #, tcl-format
 msgid "<%s-W>\t\tClose window"
 msgstr "<%s-F>\t\tFenster schließen"
 
-#: gitk:3050
 msgid "<Home>\t\tMove to first commit"
 msgstr "<Pos1>\t\tZur neuesten Version springen"
 
-#: gitk:3051
 msgid "<End>\t\tMove to last commit"
 msgstr "<Ende>\t\tZur ältesten Version springen"
 
-#: gitk:3052
 msgid "<Up>, p, k\tMove up one commit"
 msgstr "<Hoch>, p, k\tNächste neuere Version"
 
-#: gitk:3053
 msgid "<Down>, n, j\tMove down one commit"
 msgstr "<Runter>, n, j\tNächste ältere Version"
 
-#: gitk:3054
 msgid "<Left>, z, h\tGo back in history list"
 msgstr "<Links>, z, h\tEine Version zurückgehen"
 
-#: gitk:3055
 msgid "<Right>, x, l\tGo forward in history list"
 msgstr "<Rechts>, x, l\tEine Version weitergehen"
 
-#: gitk:3056
 #, tcl-format
 msgid "<%s-n>\tGo to n-th parent of current commit in history list"
 msgstr "<%s-n>\tZu n-ter Elternversion in Versionshistorie springen"
 
-#: gitk:3057
 msgid "<PageUp>\tMove up one page in commit list"
 msgstr "<BildHoch>\tEine Seite nach oben blättern"
 
-#: gitk:3058
 msgid "<PageDown>\tMove down one page in commit list"
 msgstr "<BildRunter>\tEine Seite nach unten blättern"
 
-#: gitk:3059
 #, tcl-format
 msgid "<%s-Home>\tScroll to top of commit list"
 msgstr "<%s-Pos1>\tZum oberen Ende der Versionsliste blättern"
 
-#: gitk:3060
 #, tcl-format
 msgid "<%s-End>\tScroll to bottom of commit list"
 msgstr "<%s-Ende>\tZum unteren Ende der Versionsliste blättern"
 
-#: gitk:3061
 #, tcl-format
 msgid "<%s-Up>\tScroll commit list up one line"
 msgstr "<%s-Hoch>\tVersionsliste eine Zeile nach oben blättern"
 
-#: gitk:3062
 #, tcl-format
 msgid "<%s-Down>\tScroll commit list down one line"
 msgstr "<%s-Runter>\tVersionsliste eine Zeile nach unten blättern"
 
-#: gitk:3063
 #, tcl-format
 msgid "<%s-PageUp>\tScroll commit list up one page"
 msgstr "<%s-BildHoch>\tVersionsliste eine Seite nach oben blättern"
 
-#: gitk:3064
 #, tcl-format
 msgid "<%s-PageDown>\tScroll commit list down one page"
 msgstr "<%s-BildRunter>\tVersionsliste eine Seite nach unten blättern"
 
-#: gitk:3065
 msgid "<Shift-Up>\tFind backwards (upwards, later commits)"
 msgstr "<Umschalt-Hoch>\tRückwärts suchen (nach oben; neuere Versionen)"
 
-#: gitk:3066
 msgid "<Shift-Down>\tFind forwards (downwards, earlier commits)"
 msgstr "<Umschalt-Runter> Suchen (nach unten; ältere Versionen)"
 
-#: gitk:3067
 msgid "<Delete>, b\tScroll diff view up one page"
 msgstr "<Entf>, b\t\tVergleich eine Seite nach oben blättern"
 
-#: gitk:3068
 msgid "<Backspace>\tScroll diff view up one page"
 msgstr "<Löschtaste>\tVergleich eine Seite nach oben blättern"
 
-#: gitk:3069
 msgid "<Space>\t\tScroll diff view down one page"
 msgstr "<Leertaste>\tVergleich eine Seite nach unten blättern"
 
-#: gitk:3070
 msgid "u\t\tScroll diff view up 18 lines"
 msgstr "u\t\tVergleich um 18 Zeilen nach oben blättern"
 
-#: gitk:3071
 msgid "d\t\tScroll diff view down 18 lines"
 msgstr "d\t\tVergleich um 18 Zeilen nach unten blättern"
 
-#: gitk:3072
 #, tcl-format
 msgid "<%s-F>\t\tFind"
 msgstr "<%s-F>\t\tSuchen"
 
-#: gitk:3073
 #, tcl-format
 msgid "<%s-G>\t\tMove to next find hit"
 msgstr "<%s-G>\t\tWeitersuchen"
 
-#: gitk:3074
 msgid "<Return>\tMove to next find hit"
 msgstr "<Eingabetaste>\tWeitersuchen"
 
-#: gitk:3075
 msgid "g\t\tGo to commit"
 msgstr "g\t\tZu Version springen"
 
-#: gitk:3076
 msgid "/\t\tFocus the search box"
 msgstr "/\t\tTastaturfokus ins Suchfeld"
 
-#: gitk:3077
 msgid "?\t\tMove to previous find hit"
 msgstr "?\t\tRückwärts weitersuchen"
 
-#: gitk:3078
 msgid "f\t\tScroll diff view to next file"
 msgstr "f\t\tVergleich zur nächsten Datei blättern"
 
-#: gitk:3079
 #, tcl-format
 msgid "<%s-S>\t\tSearch for next hit in diff view"
 msgstr "<%s-S>\t\tWeitersuchen im Vergleich"
 
-#: gitk:3080
 #, tcl-format
 msgid "<%s-R>\t\tSearch for previous hit in diff view"
 msgstr "<%s-R>\t\tRückwärts weitersuchen im Vergleich"
 
-#: gitk:3081
 #, tcl-format
 msgid "<%s-KP+>\tIncrease font size"
 msgstr "<%s-Nummerblock-Plus>\tSchrift vergrößern"
 
-#: gitk:3082
 #, tcl-format
 msgid "<%s-plus>\tIncrease font size"
 msgstr "<%s-Plus>\tSchrift vergrößern"
 
-#: gitk:3083
 #, tcl-format
 msgid "<%s-KP->\tDecrease font size"
 msgstr "<%s-Nummernblock-Minus> Schrift verkleinern"
 
-#: gitk:3084
 #, tcl-format
 msgid "<%s-minus>\tDecrease font size"
 msgstr "<%s-Minus>\tSchrift verkleinern"
 
-#: gitk:3085
 msgid "<F5>\t\tUpdate"
 msgstr "<F5>\t\tAktualisieren"
 
-#: gitk:3550 gitk:3559
 #, tcl-format
 msgid "Error creating temporary directory %s:"
 msgstr "Fehler beim Erzeugen des temporären Verzeichnisses »%s«:"
 
-#: gitk:3572
 #, tcl-format
 msgid "Error getting \"%s\" from %s:"
 msgstr "Fehler beim Holen von »%s« von »%s«:"
 
-#: gitk:3635
 msgid "command failed:"
 msgstr "Kommando fehlgeschlagen:"
 
-#: gitk:3784
 msgid "No such commit"
 msgstr "Version nicht gefunden"
 
-#: gitk:3798
 msgid "git gui blame: command failed:"
 msgstr "git gui blame: Kommando fehlgeschlagen:"
 
-#: gitk:3829
 #, tcl-format
 msgid "Couldn't read merge head: %s"
 msgstr "Zusammenführungs-Spitze konnte nicht gelesen werden: %s"
 
-#: gitk:3837
 #, tcl-format
 msgid "Error reading index: %s"
 msgstr "Fehler beim Lesen der Bereitstellung (»index«): %s"
 
-#: gitk:3862
 #, tcl-format
 msgid "Couldn't start git blame: %s"
 msgstr "»git blame« konnte nicht gestartet werden: %s"
 
-#: gitk:3865 gitk:6754
 msgid "Searching"
 msgstr "Suchen"
 
-#: gitk:3897
 #, tcl-format
 msgid "Error running git blame: %s"
 msgstr "Fehler beim Ausführen von »git blame«: %s"
 
-#: gitk:3925
 #, tcl-format
 msgid "That line comes from commit %s,  which is not in this view"
 msgstr ""
 "Diese Zeile stammt aus Version %s, die nicht in dieser Ansicht gezeigt wird"
 
-#: gitk:3939
 msgid "External diff viewer failed:"
 msgstr "Externes Diff-Programm fehlgeschlagen:"
 
-#: gitk:4070
 msgid "Gitk view definition"
 msgstr "Gitk-Ansichten"
 
-#: gitk:4074
 msgid "Remember this view"
 msgstr "Diese Ansicht speichern"
 
-#: gitk:4075
 msgid "References (space separated list):"
 msgstr "Zweige/Markierungen (durch Leerzeichen getrennte Liste):"
 
-#: gitk:4076
 msgid "Branches & tags:"
 msgstr "Zweige/Markierungen:"
 
-#: gitk:4077
 msgid "All refs"
 msgstr "Alle Markierungen und Zweige"
 
-#: gitk:4078
 msgid "All (local) branches"
 msgstr "Alle (lokalen) Zweige"
 
-#: gitk:4079
 msgid "All tags"
 msgstr "Alle Markierungen"
 
-#: gitk:4080
 msgid "All remote-tracking branches"
 msgstr "Alle Übernahmezweige"
 
-#: gitk:4081
 msgid "Commit Info (regular expressions):"
 msgstr "Versionsinformationen (reguläre Ausdrücke):"
 
-#: gitk:4082
 msgid "Author:"
 msgstr "Autor:"
 
-#: gitk:4083
 msgid "Committer:"
 msgstr "Eintragender:"
 
-#: gitk:4084
 msgid "Commit Message:"
 msgstr "Versionsbeschreibung:"
 
-#: gitk:4085
 msgid "Matches all Commit Info criteria"
 msgstr "Alle Versionsinformationen-Kriterien erfüllen"
 
-#: gitk:4086
 msgid "Matches no Commit Info criteria"
 msgstr "keine Versionsinformationen-Kriterien erfüllen"
 
-#: gitk:4087
 msgid "Changes to Files:"
 msgstr "Dateien:"
 
-#: gitk:4088
 msgid "Fixed String"
 msgstr "Zeichenkette"
 
-#: gitk:4089
 msgid "Regular Expression"
 msgstr "Regulärer Ausdruck"
 
-#: gitk:4090
 msgid "Search string:"
 msgstr "Suchausdruck:"
 
-#: gitk:4091
 msgid ""
 "Commit Dates (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 "
 "15:27:38\"):"
 msgstr ""
 "Datum (»2 weeks ago«, »2009-03-17 15:27:38«, »March 17, 2009 15:27:38«)"
 
-#: gitk:4092
 msgid "Since:"
 msgstr "Von:"
 
-#: gitk:4093
 msgid "Until:"
 msgstr "Bis:"
 
-#: gitk:4094
 msgid "Limit and/or skip a number of revisions (positive integer):"
 msgstr "Versionsanzahl begrenzen oder einige überspringen (ganzzahliger Wert):"
 
-#: gitk:4095
 msgid "Number to show:"
 msgstr "Anzeigen:"
 
-#: gitk:4096
 msgid "Number to skip:"
 msgstr "Überspringen:"
 
-#: gitk:4097
 msgid "Miscellaneous options:"
 msgstr "Sonstiges:"
 
-#: gitk:4098
 msgid "Strictly sort by date"
 msgstr "Streng nach Datum sortieren"
 
-#: gitk:4099
 msgid "Mark branch sides"
 msgstr "Zweig-Seiten markieren"
 
-#: gitk:4100
 msgid "Limit to first parent"
 msgstr "Auf erste Elternversion beschränken"
 
-#: gitk:4101
 msgid "Simple history"
 msgstr "Einfache Historie"
 
-#: gitk:4102
 msgid "Additional arguments to git log:"
 msgstr "Zusätzliche Argumente für »git log«:"
 
-#: gitk:4103
 msgid "Enter files and directories to include, one per line:"
 msgstr "Folgende Dateien und Verzeichnisse anzeigen (eine pro Zeile):"
 
-#: gitk:4104
 msgid "Command to generate more commits to include:"
 msgstr "Versionsliste durch folgendes Kommando erzeugen lassen:"
 
-#: gitk:4228
 msgid "Gitk: edit view"
 msgstr "Gitk: Ansicht bearbeiten"
 
-#: gitk:4236
 msgid "-- criteria for selecting revisions"
 msgstr "-- Auswahl der angezeigten Versionen"
 
-#: gitk:4241
 msgid "View Name"
 msgstr "Ansichtsname"
 
-#: gitk:4316
 msgid "Apply (F5)"
 msgstr "Anwenden (F5)"
 
-#: gitk:4354
 msgid "Error in commit selection arguments:"
 msgstr "Fehler in den ausgewählten Versionen:"
 
-#: gitk:4409 gitk:4462 gitk:4924 gitk:4938 gitk:6208 gitk:12373 gitk:12374
 msgid "None"
 msgstr "Keine"
 
-#: gitk:5021 gitk:5026
 msgid "Descendant"
 msgstr "Abkömmling"
 
-#: gitk:5022
 msgid "Not descendant"
 msgstr "Kein Abkömmling"
 
-#: gitk:5029 gitk:5034
 msgid "Ancestor"
 msgstr "Vorgänger"
 
-#: gitk:5030
 msgid "Not ancestor"
 msgstr "Kein Vorgänger"
 
-#: gitk:5324
 msgid "Local changes checked in to index but not committed"
 msgstr "Lokale Änderungen bereitgestellt, aber nicht eingetragen"
 
-#: gitk:5360
 msgid "Local uncommitted changes, not checked in to index"
 msgstr "Lokale Änderungen, nicht bereitgestellt"
 
-#: gitk:7134
 msgid "and many more"
 msgstr "und weitere"
 
-#: gitk:7137
 msgid "many"
 msgstr "viele"
 
-#: gitk:7328
 msgid "Tags:"
 msgstr "Markierungen:"
 
-#: gitk:7345 gitk:7351 gitk:8825
 msgid "Parent"
 msgstr "Eltern"
 
-#: gitk:7356
 msgid "Child"
 msgstr "Kind"
 
-#: gitk:7365
 msgid "Branch"
 msgstr "Zweig"
 
-#: gitk:7368
 msgid "Follows"
 msgstr "Folgt auf"
 
-#: gitk:7371
 msgid "Precedes"
 msgstr "Vorgänger von"
 
-#: gitk:7966
 #, tcl-format
 msgid "Error getting diffs: %s"
 msgstr "Fehler beim Laden des Vergleichs: %s"
 
-#: gitk:8650
 msgid "Goto:"
 msgstr "Gehe zu:"
 
-#: gitk:8671
 #, tcl-format
 msgid "Short SHA1 id %s is ambiguous"
 msgstr "Kurzer SHA1-Hashwert »%s« ist mehrdeutig"
 
-#: gitk:8678
 #, tcl-format
 msgid "Revision %s is not known"
 msgstr "Version »%s« ist unbekannt"
 
-#: gitk:8688
 #, tcl-format
 msgid "SHA1 id %s is not known"
 msgstr "SHA1-Hashwert »%s« ist unbekannt"
 
-#: gitk:8690
 #, tcl-format
 msgid "Revision %s is not in the current view"
 msgstr "Version »%s« wird in der aktuellen Ansicht nicht angezeigt"
 
-#: gitk:8832 gitk:8847
 msgid "Date"
 msgstr "Datum"
 
-#: gitk:8835
 msgid "Children"
 msgstr "Kinder"
 
-#: gitk:8898
 #, tcl-format
 msgid "Reset %s branch to here"
 msgstr "Zweig »%s« hierher zurücksetzen"
 
-#: gitk:8900
 msgid "Detached head: can't reset"
 msgstr "Zweigspitze ist abgetrennt: Zurücksetzen nicht möglich"
 
-#: gitk:9005 gitk:9011
 msgid "Skipping merge commit "
 msgstr "Überspringe Zusammenführungs-Version "
 
-#: gitk:9020 gitk:9025
 msgid "Error getting patch ID for "
 msgstr "Fehler beim Holen der Patch-ID für "
 
-#: gitk:9021 gitk:9026
 msgid " - stopping\n"
 msgstr " - Abbruch.\n"
 
-#: gitk:9031 gitk:9034 gitk:9042 gitk:9056 gitk:9065
 msgid "Commit "
 msgstr "Version "
 
-#: gitk:9035
 msgid ""
 " is the same patch as\n"
 "       "
@@ -893,7 +686,6 @@
 " ist das gleiche Patch wie\n"
 "       "
 
-#: gitk:9043
 msgid ""
 " differs from\n"
 "       "
@@ -901,7 +693,6 @@
 " ist unterschiedlich von\n"
 "       "
 
-#: gitk:9045
 msgid ""
 "Diff of commits:\n"
 "\n"
@@ -909,131 +700,101 @@
 "Vergleich der Versionen:\n"
 "\n"
 
-#: gitk:9057 gitk:9066
 #, tcl-format
 msgid " has %s children - stopping\n"
 msgstr " hat %s Kinder. Abbruch\n"
 
-#: gitk:9085
 #, tcl-format
 msgid "Error writing commit to file: %s"
 msgstr "Fehler beim Schreiben der Version in Datei: %s"
 
-#: gitk:9091
 #, tcl-format
 msgid "Error diffing commits: %s"
 msgstr "Fehler beim Vergleichen der Versionen: %s"
 
-#: gitk:9137
 msgid "Top"
 msgstr "Oben"
 
-#: gitk:9138
 msgid "From"
 msgstr "Von"
 
-#: gitk:9143
 msgid "To"
 msgstr "bis"
 
-#: gitk:9167
 msgid "Generate patch"
 msgstr "Patch erstellen"
 
-#: gitk:9169
 msgid "From:"
 msgstr "Von:"
 
-#: gitk:9178
 msgid "To:"
 msgstr "bis:"
 
-#: gitk:9187
 msgid "Reverse"
 msgstr "Umgekehrt"
 
-#: gitk:9189 gitk:9385
 msgid "Output file:"
 msgstr "Ausgabedatei:"
 
-#: gitk:9195
 msgid "Generate"
 msgstr "Erzeugen"
 
-#: gitk:9233
 msgid "Error creating patch:"
 msgstr "Fehler beim Erzeugen des Patches:"
 
-#: gitk:9256 gitk:9373 gitk:9430
 msgid "ID:"
 msgstr "ID:"
 
-#: gitk:9265
 msgid "Tag name:"
 msgstr "Markierungsname:"
 
-#: gitk:9268
 msgid "Tag message is optional"
 msgstr "Eine Markierungsbeschreibung ist optional"
 
-#: gitk:9270
 msgid "Tag message:"
 msgstr "Markierungsbeschreibung:"
 
-#: gitk:9274 gitk:9439
 msgid "Create"
 msgstr "Erstellen"
 
-#: gitk:9292
 msgid "No tag name specified"
 msgstr "Kein Markierungsname angegeben"
 
-#: gitk:9296
 #, tcl-format
 msgid "Tag \"%s\" already exists"
 msgstr "Markierung »%s« existiert bereits."
 
-#: gitk:9306
 msgid "Error creating tag:"
 msgstr "Fehler beim Erstellen der Markierung:"
 
-#: gitk:9382
 msgid "Command:"
 msgstr "Kommando:"
 
-#: gitk:9390
 msgid "Write"
 msgstr "Schreiben"
 
-#: gitk:9408
 msgid "Error writing commit:"
 msgstr "Fehler beim Schreiben der Version:"
 
-#: gitk:9435
 msgid "Name:"
 msgstr "Name:"
 
-#: gitk:9458
 msgid "Please specify a name for the new branch"
 msgstr "Bitte geben Sie einen Namen für den neuen Zweig an."
 
-#: gitk:9463
 #, tcl-format
 msgid "Branch '%s' already exists. Overwrite?"
 msgstr "Zweig »%s« existiert bereits. Soll er überschrieben werden?"
 
-#: gitk:9530
 #, tcl-format
 msgid "Commit %s is already included in branch %s -- really re-apply it?"
 msgstr ""
 "Version »%s« ist bereits im Zweig »%s« enthalten -- trotzdem erneut "
 "eintragen?"
 
-#: gitk:9535
 msgid "Cherry-picking"
 msgstr "Version pflücken"
 
-#: gitk:9544
 #, tcl-format
 msgid ""
 "Cherry-pick failed because of local changes to file '%s'.\n"
@@ -1043,7 +804,6 @@
 "vorliegen. Bitte diese Änderungen eintragen, zurücksetzen oder\n"
 "zwischenspeichern (»git stash«) und dann erneut versuchen."
 
-#: gitk:9550
 msgid ""
 "Cherry-pick failed because of merge conflict.\n"
 "Do you wish to run git citool to resolve it?"
@@ -1052,21 +812,16 @@
 "ist. Soll das Zusammenführungs-Werkzeug (»git citool«) aufgerufen\n"
 "werden, um diesen Konflikt aufzulösen?"
 
-#: gitk:9566 gitk:9624
 msgid "No changes committed"
 msgstr "Keine Änderungen eingetragen"
 
-#: gitk:9593
 #, tcl-format
 msgid "Commit %s is not included in branch %s -- really revert it?"
-msgstr ""
-"Version »%s« ist nicht im Zweig »%s« enthalten -- trotzdem umkehren?"
+msgstr "Version »%s« ist nicht im Zweig »%s« enthalten -- trotzdem umkehren?"
 
-#: gitk:9598
 msgid "Reverting"
 msgstr "Umkehren"
 
-#: gitk:9606
 #, tcl-format
 msgid ""
 "Revert failed because of local changes to the following files:%s Please "
@@ -1076,7 +831,6 @@
 "vorliegen. Bitte diese Änderungen eintragen, zurücksetzen oder\n"
 "zwischenspeichern (»git stash«) und dann erneut versuchen."
 
-#: gitk:9610
 msgid ""
 "Revert failed because of merge conflict.\n"
 " Do you wish to run git citool to resolve it?"
@@ -1085,30 +839,24 @@
 "ist. Soll das Zusammenführungs-Werkzeug (»git citool«) aufgerufen\n"
 "werden, um diesen Konflikt aufzulösen?"
 
-#: gitk:9653
 msgid "Confirm reset"
 msgstr "Zurücksetzen bestätigen"
 
-#: gitk:9655
 #, tcl-format
 msgid "Reset branch %s to %s?"
 msgstr "Zweig »%s« auf »%s« zurücksetzen?"
 
-#: gitk:9657
 msgid "Reset type:"
 msgstr "Art des Zurücksetzens:"
 
-#: gitk:9660
 msgid "Soft: Leave working tree and index untouched"
 msgstr "Harmlos: Arbeitskopie und Bereitstellung unverändert"
 
-#: gitk:9663
 msgid "Mixed: Leave working tree untouched, reset index"
 msgstr ""
 "Gemischt: Arbeitskopie unverändert,\n"
 "Bereitstellung zurückgesetzt"
 
-#: gitk:9666
 msgid ""
 "Hard: Reset working tree and index\n"
 "(discard ALL local changes)"
@@ -1116,21 +864,17 @@
 "Hart: Arbeitskopie und Bereitstellung\n"
 "(Alle lokalen Änderungen werden gelöscht)"
 
-#: gitk:9683
 msgid "Resetting"
 msgstr "Zurücksetzen"
 
-#: gitk:9743
 msgid "Checking out"
 msgstr "Umstellen"
 
-#: gitk:9796
 msgid "Cannot delete the currently checked-out branch"
 msgstr ""
 "Der Zweig, auf den die Arbeitskopie momentan umgestellt ist, kann nicht "
 "gelöscht werden."
 
-#: gitk:9802
 #, tcl-format
 msgid ""
 "The commits on branch %s aren't on any other branch.\n"
@@ -1139,16 +883,13 @@
 "Die Versionen auf Zweig »%s« existieren auf keinem anderen Zweig.\n"
 "Zweig »%s« trotzdem löschen?"
 
-#: gitk:9833
 #, tcl-format
 msgid "Tags and heads: %s"
 msgstr "Markierungen und Zweige: %s"
 
-#: gitk:9850
 msgid "Filter"
 msgstr "Filtern"
 
-#: gitk:10146
 msgid ""
 "Error reading commit topology information; branch and preceding/following "
 "tag information will be incomplete."
@@ -1156,218 +897,167 @@
 "Fehler beim Lesen der Strukturinformationen; Zweige und Informationen zu "
 "Vorgänger/Nachfolger werden unvollständig sein."
 
-#: gitk:11123
 msgid "Tag"
 msgstr "Markierung"
 
-#: gitk:11127
 msgid "Id"
 msgstr "Id"
 
-#: gitk:11210
 msgid "Gitk font chooser"
 msgstr "Gitk-Schriften wählen"
 
-#: gitk:11227
 msgid "B"
 msgstr "F"
 
-#: gitk:11230
 msgid "I"
 msgstr "K"
 
-#: gitk:11348
 msgid "Commit list display options"
 msgstr "Anzeige der Versionsliste"
 
-#: gitk:11351
 msgid "Maximum graph width (lines)"
 msgstr "Maximale Graphenbreite (Zeilen)"
 
-#: gitk:11355
 #, no-tcl-format
 msgid "Maximum graph width (% of pane)"
 msgstr "Maximale Graphenbreite (% des Fensters)"
 
-#: gitk:11358
 msgid "Show local changes"
 msgstr "Lokale Änderungen anzeigen"
 
-#: gitk:11361
 msgid "Auto-select SHA1 (length)"
 msgstr "SHA1-Hashwert (Länge) automatisch auswählen"
 
-#: gitk:11365
 msgid "Hide remote refs"
 msgstr "Entfernte Zweige/Markierungen ausblenden"
 
-#: gitk:11369
 msgid "Diff display options"
 msgstr "Anzeige des Vergleichs"
 
-#: gitk:11371
 msgid "Tab spacing"
 msgstr "Tabulatorbreite"
 
-#: gitk:11374
 msgid "Display nearby tags/heads"
 msgstr "Naheliegende Markierungen/Zweigspitzen anzeigen"
 
-#: gitk:11377
 msgid "Maximum # tags/heads to show"
 msgstr "Maximale Anzahl anzuzeigender Markierungen/Zweigspitzen"
 
-#: gitk:11380
 msgid "Limit diffs to listed paths"
 msgstr "Vergleich nur für angezeigte Pfade"
 
-#: gitk:11383
 msgid "Support per-file encodings"
 msgstr "Zeichenkodierung pro Datei ermitteln"
 
-#: gitk:11389 gitk:11536
 msgid "External diff tool"
 msgstr "Externes Diff-Programm"
 
-#: gitk:11390
 msgid "Choose..."
 msgstr "Wählen ..."
 
-#: gitk:11395
 msgid "General options"
 msgstr "Allgemeine Optionen"
 
-#: gitk:11398
 msgid "Use themed widgets"
 msgstr "Aussehen der Benutzeroberfläche durch Thema bestimmen"
 
-#: gitk:11400
 msgid "(change requires restart)"
 msgstr "(Änderungen werden erst nach Neustart wirksam)"
 
-#: gitk:11402
 msgid "(currently unavailable)"
 msgstr "(Momentan nicht verfügbar)"
 
-#: gitk:11413
 msgid "Colors: press to choose"
 msgstr "Farben: Klicken zum Wählen"
 
-#: gitk:11416
 msgid "Interface"
 msgstr "Benutzeroberfläche"
 
-#: gitk:11417
 msgid "interface"
 msgstr "Benutzeroberfläche"
 
-#: gitk:11420
 msgid "Background"
 msgstr "Hintergrund"
 
-#: gitk:11421 gitk:11451
 msgid "background"
 msgstr "Hintergrund"
 
-#: gitk:11424
 msgid "Foreground"
 msgstr "Vordergrund"
 
-#: gitk:11425
 msgid "foreground"
 msgstr "Vordergrund"
 
-#: gitk:11428
 msgid "Diff: old lines"
 msgstr "Vergleich: Alte Zeilen"
 
-#: gitk:11429
 msgid "diff old lines"
 msgstr "Vergleich - Alte Zeilen"
 
-#: gitk:11433
 msgid "Diff: new lines"
 msgstr "Vergleich: Neue Zeilen"
 
-#: gitk:11434
 msgid "diff new lines"
 msgstr "Vergleich - Neue Zeilen"
 
-#: gitk:11438
 msgid "Diff: hunk header"
 msgstr "Vergleich: Änderungstitel"
 
-#: gitk:11440
 msgid "diff hunk header"
 msgstr "Vergleich - Änderungstitel"
 
-#: gitk:11444
 msgid "Marked line bg"
 msgstr "Hintergrund für markierte Zeile"
 
-#: gitk:11446
 msgid "marked line background"
 msgstr "Hintergrund für markierte Zeile"
 
-#: gitk:11450
 msgid "Select bg"
 msgstr "Hintergrundfarbe auswählen"
 
-#: gitk:11459
 msgid "Fonts: press to choose"
 msgstr "Schriftart: Klicken zum Wählen"
 
-#: gitk:11461
 msgid "Main font"
 msgstr "Programmschriftart"
 
-#: gitk:11462
 msgid "Diff display font"
 msgstr "Schriftart für Vergleich"
 
-#: gitk:11463
 msgid "User interface font"
 msgstr "Beschriftungen"
 
-#: gitk:11485
 msgid "Gitk preferences"
 msgstr "Gitk-Einstellungen"
 
-#: gitk:11494
 msgid "General"
 msgstr "Allgemein"
 
-#: gitk:11495
 msgid "Colors"
 msgstr "Farben"
 
-#: gitk:11496
 msgid "Fonts"
 msgstr "Schriftarten"
 
-#: gitk:11546
 #, tcl-format
 msgid "Gitk: choose color for %s"
 msgstr "Gitk: Farbe wählen für %s"
 
-#: gitk:12059
 msgid ""
 "Sorry, gitk cannot run with this version of Tcl/Tk.\n"
 " Gitk requires at least Tcl/Tk 8.4."
 msgstr ""
-"Entschuldigung, gitk kann nicht mit dieser Tcl/Tk Version ausgeführt werden.\n"
+"Entschuldigung, gitk kann nicht mit dieser Tcl/Tk Version ausgeführt "
+"werden.\n"
 " Gitk erfordert mindestens Tcl/Tk 8.4."
 
-#: gitk:12269
 msgid "Cannot find a git repository here."
 msgstr "Kein Git-Projektarchiv gefunden."
 
-#: gitk:12316
 #, tcl-format
 msgid "Ambiguous argument '%s': both revision and filename"
 msgstr "Mehrdeutige Angabe »%s«: Sowohl Version als auch Dateiname existiert."
 
-#: gitk:12328
 msgid "Bad arguments to gitk:"
 msgstr "Falsche Kommandozeilen-Parameter für gitk:"
 
diff --git a/gitk-git/po/es.po b/gitk-git/po/es.po
index fef3bba..25260c6 100644
--- a/gitk-git/po/es.po
+++ b/gitk-git/po/es.po
@@ -6,7 +6,7 @@
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: gitk\n"
+"Project-Id-Version: Gitk\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2015-05-17 14:32+1000\n"
 "PO-Revision-Date: 2008-03-25 11:20+0100\n"
@@ -17,34 +17,27 @@
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: gitk:140
 msgid "Couldn't get list of unmerged files:"
 msgstr "Imposible obtener la lista de archivos pendientes de fusión:"
 
-#: gitk:212 gitk:2381
 msgid "Color words"
 msgstr ""
 
-#: gitk:217 gitk:2381 gitk:8220 gitk:8253
 msgid "Markup words"
 msgstr ""
 
-#: gitk:324
 #, fuzzy
 msgid "Error parsing revisions:"
 msgstr "Error al leer las diferencias de fusión:"
 
-#: gitk:380
 msgid "Error executing --argscmd command:"
 msgstr ""
 
-#: gitk:393
 msgid "No files selected: --merge specified but no files are unmerged."
 msgstr ""
 "No hay archivos seleccionados: se seleccionó la opción --merge pero no hay "
 "archivos pendientes de fusión."
 
-#: gitk:396
 msgid ""
 "No files selected: --merge specified but no unmerged files are within file "
 "limit."
@@ -52,319 +45,239 @@
 "No hay archivos seleccionados: se seleccionó la opción --merge pero los "
 "archivos especificados no necesitan fusión."
 
-#: gitk:418 gitk:566
 #, fuzzy
 msgid "Error executing git log:"
 msgstr "Error al crear la etiqueta:"
 
-#: gitk:436 gitk:582
 msgid "Reading"
 msgstr "Leyendo"
 
-#: gitk:496 gitk:4525
 msgid "Reading commits..."
 msgstr "Leyendo revisiones..."
 
-#: gitk:499 gitk:1637 gitk:4528
 msgid "No commits selected"
 msgstr "No se seleccionaron revisiones"
 
-#: gitk:1445 gitk:4045 gitk:12432
 msgid "Command line"
 msgstr "Línea de comandos"
 
-#: gitk:1511
 msgid "Can't parse git log output:"
 msgstr "Error analizando la salida de git log:"
 
-#: gitk:1740
 msgid "No commit information available"
 msgstr "Falta información sobre las revisiones"
 
-#: gitk:1903 gitk:1932 gitk:4315 gitk:9669 gitk:11241 gitk:11521
 msgid "OK"
 msgstr "Aceptar"
 
-#: gitk:1934 gitk:4317 gitk:9196 gitk:9275 gitk:9391 gitk:9440 gitk:9671
-#: gitk:11242 gitk:11522
 msgid "Cancel"
 msgstr "Cancelar"
 
-#: gitk:2069
 msgid "&Update"
 msgstr "Actualizar"
 
-#: gitk:2070
 msgid "&Reload"
 msgstr ""
 
-#: gitk:2071
 msgid "Reread re&ferences"
 msgstr "Releer referencias"
 
-#: gitk:2072
 msgid "&List references"
 msgstr "Lista de referencias"
 
-#: gitk:2074
 msgid "Start git &gui"
 msgstr ""
 
-#: gitk:2076
 msgid "&Quit"
 msgstr "Salir"
 
-#: gitk:2068
 msgid "&File"
 msgstr "Archivo"
 
-#: gitk:2080
 msgid "&Preferences"
 msgstr "Preferencias"
 
-#: gitk:2079
 msgid "&Edit"
 msgstr "Editar"
 
-#: gitk:2084
 msgid "&New view..."
 msgstr "Nueva vista..."
 
-#: gitk:2085
 msgid "&Edit view..."
 msgstr "Modificar vista..."
 
-#: gitk:2086
 msgid "&Delete view"
 msgstr "Eliminar vista"
 
-#: gitk:2088 gitk:4043
 msgid "&All files"
 msgstr "Todos los archivos"
 
-#: gitk:2083 gitk:4067
 msgid "&View"
 msgstr "Vista"
 
-#: gitk:2093 gitk:2103 gitk:3012
 msgid "&About gitk"
 msgstr "Acerca de gitk"
 
-#: gitk:2094 gitk:2108
 msgid "&Key bindings"
 msgstr "Combinaciones de teclas"
 
-#: gitk:2092 gitk:2107
 msgid "&Help"
 msgstr "Ayuda"
 
-#: gitk:2185 gitk:8652
 msgid "SHA1 ID:"
 msgstr "SHA1 ID:"
 
-#: gitk:2229
 msgid "Row"
 msgstr ""
 
-#: gitk:2267
 msgid "Find"
 msgstr "Buscar"
 
-#: gitk:2295
 msgid "commit"
 msgstr "revisión"
 
-#: gitk:2299 gitk:2301 gitk:4687 gitk:4710 gitk:4734 gitk:6755 gitk:6827
-#: gitk:6912
 msgid "containing:"
 msgstr "que contiene:"
 
-#: gitk:2302 gitk:3526 gitk:3531 gitk:4763
 msgid "touching paths:"
 msgstr "que modifica la ruta:"
 
-#: gitk:2303 gitk:4777
 msgid "adding/removing string:"
 msgstr "que añade/elimina cadena:"
 
-#: gitk:2304 gitk:4779
 msgid "changing lines matching:"
 msgstr ""
 
-#: gitk:2313 gitk:2315 gitk:4766
 msgid "Exact"
 msgstr "Exacto"
 
-#: gitk:2315 gitk:4854 gitk:6723
 msgid "IgnCase"
 msgstr "NoMayús"
 
-#: gitk:2315 gitk:4736 gitk:4852 gitk:6719
 msgid "Regexp"
 msgstr "Regex"
 
-#: gitk:2317 gitk:2318 gitk:4874 gitk:4904 gitk:4911 gitk:6848 gitk:6916
 msgid "All fields"
 msgstr "Todos los campos"
 
-#: gitk:2318 gitk:4871 gitk:4904 gitk:6786
 msgid "Headline"
 msgstr "Título"
 
-#: gitk:2319 gitk:4871 gitk:6786 gitk:6916 gitk:7389
 msgid "Comments"
 msgstr "Comentarios"
 
-#: gitk:2319 gitk:4871 gitk:4876 gitk:4911 gitk:6786 gitk:7324 gitk:8830
-#: gitk:8845
 msgid "Author"
 msgstr "Autor"
 
-#: gitk:2319 gitk:4871 gitk:6786 gitk:7326
 msgid "Committer"
 msgstr ""
 
-#: gitk:2350
 msgid "Search"
 msgstr "Buscar"
 
-#: gitk:2358
 msgid "Diff"
 msgstr "Diferencia"
 
-#: gitk:2360
 msgid "Old version"
 msgstr "Versión antigua"
 
-#: gitk:2362
 msgid "New version"
 msgstr "Versión nueva"
 
-#: gitk:2364
 msgid "Lines of context"
 msgstr "Líneas de contexto"
 
-#: gitk:2374
 msgid "Ignore space change"
 msgstr "Ignora cambios de espaciado"
 
-#: gitk:2378 gitk:2380 gitk:7959 gitk:8206
 msgid "Line diff"
 msgstr ""
 
-#: gitk:2445
 msgid "Patch"
 msgstr "Parche"
 
-#: gitk:2447
 msgid "Tree"
 msgstr "Árbol"
 
-#: gitk:2617 gitk:2637
 msgid "Diff this -> selected"
 msgstr "Diferencia de esta -> seleccionada"
 
-#: gitk:2618 gitk:2638
 msgid "Diff selected -> this"
 msgstr "Diferencia de seleccionada -> esta"
 
-#: gitk:2619 gitk:2639
 msgid "Make patch"
 msgstr "Crear patch"
 
-#: gitk:2620 gitk:9254
 msgid "Create tag"
 msgstr "Crear etiqueta"
 
-#: gitk:2621 gitk:9371
 msgid "Write commit to file"
 msgstr "Escribir revisiones a archivo"
 
-#: gitk:2622 gitk:9428
 msgid "Create new branch"
 msgstr "Crear nueva rama"
 
-#: gitk:2623
 msgid "Cherry-pick this commit"
 msgstr "Añadir esta revisión a la rama actual (cherry-pick)"
 
-#: gitk:2624
 msgid "Reset HEAD branch to here"
 msgstr "Traer la rama HEAD aquí"
 
-#: gitk:2625
 #, fuzzy
 msgid "Mark this commit"
 msgstr "Añadir esta revisión a la rama actual (cherry-pick)"
 
-#: gitk:2626
 msgid "Return to mark"
 msgstr ""
 
-#: gitk:2627
 msgid "Find descendant of this and mark"
 msgstr ""
 
-#: gitk:2628
 msgid "Compare with marked commit"
 msgstr ""
 
-#: gitk:2629 gitk:2640
 #, fuzzy
 msgid "Diff this -> marked commit"
 msgstr "Diferencia de esta -> seleccionada"
 
-#: gitk:2630 gitk:2641
 #, fuzzy
 msgid "Diff marked commit -> this"
 msgstr "Diferencia de seleccionada -> esta"
 
-#: gitk:2631
 #, fuzzy
 msgid "Revert this commit"
 msgstr "Añadir esta revisión a la rama actual (cherry-pick)"
 
-#: gitk:2647
 msgid "Check out this branch"
 msgstr "Cambiar a esta rama"
 
-#: gitk:2648
 msgid "Remove this branch"
 msgstr "Eliminar esta rama"
 
-#: gitk:2649
 msgid "Copy branch name"
 msgstr ""
 
-#: gitk:2656
 msgid "Highlight this too"
 msgstr "Seleccionar también"
 
-#: gitk:2657
 msgid "Highlight this only"
 msgstr "Seleccionar sólo"
 
-#: gitk:2658
 msgid "External diff"
 msgstr ""
 
-#: gitk:2659
 msgid "Blame parent commit"
 msgstr ""
 
-#: gitk:2660
 msgid "Copy path"
 msgstr ""
 
-#: gitk:2667
 msgid "Show origin of this line"
 msgstr ""
 
-#: gitk:2668
 msgid "Run git gui blame on this line"
 msgstr ""
 
-#: gitk:3014
 #, fuzzy
 msgid ""
 "\n"
@@ -382,733 +295,569 @@
 "Uso y redistribución permitidos según los términos de la Licencia Pública "
 "General de GNU (GNU GPL)"
 
-#: gitk:3022 gitk:3089 gitk:9857
 msgid "Close"
 msgstr "Cerrar"
 
-#: gitk:3043
 msgid "Gitk key bindings"
 msgstr "Combinaciones de tecla de Gitk"
 
-#: gitk:3046
 msgid "Gitk key bindings:"
 msgstr "Combinaciones de tecla de Gitk:"
 
-#: gitk:3048
 #, tcl-format
 msgid "<%s-Q>\t\tQuit"
 msgstr "<%s-Q>\t\tSalir"
 
-#: gitk:3049
 #, fuzzy, tcl-format
 msgid "<%s-W>\t\tClose window"
 msgstr "<%s-F>\t\tBuscar"
 
-#: gitk:3050
 msgid "<Home>\t\tMove to first commit"
 msgstr "<Home>\t\tIr a la primera revisión"
 
-#: gitk:3051
 msgid "<End>\t\tMove to last commit"
 msgstr "<End>\t\tIr a la última revisión"
 
-#: gitk:3052
 #, fuzzy
 msgid "<Up>, p, k\tMove up one commit"
 msgstr "<Up>, p, i\tSubir una revisión"
 
-#: gitk:3053
 #, fuzzy
 msgid "<Down>, n, j\tMove down one commit"
 msgstr "<Down>, n, k\tBajar una revisión"
 
-#: gitk:3054
 #, fuzzy
 msgid "<Left>, z, h\tGo back in history list"
 msgstr "<Left>, z, j\tRetroceder en la historia"
 
-#: gitk:3055
 msgid "<Right>, x, l\tGo forward in history list"
 msgstr "<Right>, x, l\tAvanzar en la historia"
 
-#: gitk:3056
 #, tcl-format
 msgid "<%s-n>\tGo to n-th parent of current commit in history list"
 msgstr ""
 
-#: gitk:3057
 msgid "<PageUp>\tMove up one page in commit list"
 msgstr "<PageUp>\tSubir una página en la lista de revisiones"
 
-#: gitk:3058
 msgid "<PageDown>\tMove down one page in commit list"
 msgstr "<PageDown>\tBajar una página en la lista de revisiones"
 
-#: gitk:3059
 #, tcl-format
 msgid "<%s-Home>\tScroll to top of commit list"
 msgstr "<%s-Home>\tDesplazarse al inicio de la lista de revisiones"
 
-#: gitk:3060
 #, tcl-format
 msgid "<%s-End>\tScroll to bottom of commit list"
 msgstr "<%s-End>\tDesplazarse al final de la lista de revisiones"
 
-#: gitk:3061
 #, tcl-format
 msgid "<%s-Up>\tScroll commit list up one line"
 msgstr "<%s-Up>\tDesplazar una línea hacia arriba la lista de revisiones"
 
-#: gitk:3062
 #, tcl-format
 msgid "<%s-Down>\tScroll commit list down one line"
 msgstr "<%s-Down>\tDesplazar una línea hacia abajo la lista de revisiones"
 
-#: gitk:3063
 #, tcl-format
 msgid "<%s-PageUp>\tScroll commit list up one page"
 msgstr "<%s-PageUp>\tDesplazar una página hacia arriba la lista de revisiones"
 
-#: gitk:3064
 #, tcl-format
 msgid "<%s-PageDown>\tScroll commit list down one page"
 msgstr "<%s-PageDown>\tDesplazar una página hacia abajo la lista de revisiones"
 
-#: gitk:3065
 msgid "<Shift-Up>\tFind backwards (upwards, later commits)"
 msgstr "<Shift-Up>\tBuscar hacia atrás (arriba, revisiones siguientes)"
 
-#: gitk:3066
 msgid "<Shift-Down>\tFind forwards (downwards, earlier commits)"
 msgstr "<Shift-Down>\tBuscar hacia adelante (abajo, revisiones anteriores)"
 
-#: gitk:3067
 msgid "<Delete>, b\tScroll diff view up one page"
 msgstr "<Delete>, b\tDesplaza hacia arriba una página la vista de diferencias"
 
-#: gitk:3068
 msgid "<Backspace>\tScroll diff view up one page"
 msgstr "<Backspace>\tDesplaza hacia arriba una página la vista de diferencias"
 
-#: gitk:3069
 msgid "<Space>\t\tScroll diff view down one page"
 msgstr "<Space>\t\tDesplaza hacia abajo una página la vista de diferencias"
 
-#: gitk:3070
 msgid "u\t\tScroll diff view up 18 lines"
 msgstr "u\t\tDesplaza hacia arriba 18 líneas la vista de diferencias"
 
-#: gitk:3071
 msgid "d\t\tScroll diff view down 18 lines"
 msgstr "d\t\tDesplaza hacia abajo 18 líneas la vista de diferencias"
 
-#: gitk:3072
 #, tcl-format
 msgid "<%s-F>\t\tFind"
 msgstr "<%s-F>\t\tBuscar"
 
-#: gitk:3073
 #, tcl-format
 msgid "<%s-G>\t\tMove to next find hit"
 msgstr "<%s-G>\t\tBuscar el siguiente"
 
-#: gitk:3074
 msgid "<Return>\tMove to next find hit"
 msgstr "<Return>\tBuscar el siguiente"
 
-#: gitk:3075
 #, fuzzy
 msgid "g\t\tGo to commit"
 msgstr "<End>\t\tIr a la última revisión"
 
-#: gitk:3076
 msgid "/\t\tFocus the search box"
 msgstr ""
 
-#: gitk:3077
 msgid "?\t\tMove to previous find hit"
 msgstr "?\t\tBuscar el anterior"
 
-#: gitk:3078
 msgid "f\t\tScroll diff view to next file"
 msgstr "f\t\tDesplazar la vista de diferencias al archivo siguiente"
 
-#: gitk:3079
 #, tcl-format
 msgid "<%s-S>\t\tSearch for next hit in diff view"
 msgstr "<%s-S>\t\tBuscar siguiente en la vista de diferencias"
 
-#: gitk:3080
 #, tcl-format
 msgid "<%s-R>\t\tSearch for previous hit in diff view"
 msgstr "<%s-R>\t\tBuscar anterior en la vista de diferencias"
 
-#: gitk:3081
 #, tcl-format
 msgid "<%s-KP+>\tIncrease font size"
 msgstr "<%s-KP+>\tAumentar tamaño del texto"
 
-#: gitk:3082
 #, tcl-format
 msgid "<%s-plus>\tIncrease font size"
 msgstr "<%s-plus>\tAumentar tamaño del texto"
 
-#: gitk:3083
 #, tcl-format
 msgid "<%s-KP->\tDecrease font size"
 msgstr "<%s-KP->\tDisminuir tamaño del texto"
 
-#: gitk:3084
 #, tcl-format
 msgid "<%s-minus>\tDecrease font size"
 msgstr "<%s-minus>\tDisminuir tamaño del texto"
 
-#: gitk:3085
 msgid "<F5>\t\tUpdate"
 msgstr "<F5>\t\tActualizar"
 
-#: gitk:3550 gitk:3559
 #, fuzzy, tcl-format
 msgid "Error creating temporary directory %s:"
 msgstr "Error en la creación del parche:"
 
-#: gitk:3572
 #, fuzzy, tcl-format
 msgid "Error getting \"%s\" from %s:"
 msgstr "Error al leer las diferencias de fusión:"
 
-#: gitk:3635
 #, fuzzy
 msgid "command failed:"
 msgstr "Línea de comandos"
 
-#: gitk:3784
 #, fuzzy
 msgid "No such commit"
 msgstr "No se han guardado cambios"
 
-#: gitk:3798
 msgid "git gui blame: command failed:"
 msgstr ""
 
-#: gitk:3829
 #, tcl-format
 msgid "Couldn't read merge head: %s"
 msgstr ""
 
-#: gitk:3837
 #, fuzzy, tcl-format
 msgid "Error reading index: %s"
 msgstr "Error al crear la etiqueta:"
 
-#: gitk:3862
 #, tcl-format
 msgid "Couldn't start git blame: %s"
 msgstr ""
 
-#: gitk:3865 gitk:6754
 msgid "Searching"
 msgstr "Buscando"
 
-#: gitk:3897
 #, fuzzy, tcl-format
 msgid "Error running git blame: %s"
 msgstr "Error al crear la etiqueta:"
 
-#: gitk:3925
 #, tcl-format
 msgid "That line comes from commit %s,  which is not in this view"
 msgstr ""
 
-#: gitk:3939
 #, fuzzy
 msgid "External diff viewer failed:"
 msgstr "f\t\tDesplazar la vista de diferencias al archivo siguiente"
 
-#: gitk:4070
 msgid "Gitk view definition"
 msgstr "Definición de vistas de Gitk"
 
-#: gitk:4074
 msgid "Remember this view"
 msgstr "Recordar esta vista"
 
-#: gitk:4075
 msgid "References (space separated list):"
 msgstr ""
 
-#: gitk:4076
 msgid "Branches & tags:"
 msgstr ""
 
-#: gitk:4077
 #, fuzzy
 msgid "All refs"
 msgstr "Todos los archivos"
 
-#: gitk:4078
 msgid "All (local) branches"
 msgstr ""
 
-#: gitk:4079
 msgid "All tags"
 msgstr ""
 
-#: gitk:4080
 msgid "All remote-tracking branches"
 msgstr ""
 
-#: gitk:4081
 msgid "Commit Info (regular expressions):"
 msgstr ""
 
-#: gitk:4082
 #, fuzzy
 msgid "Author:"
 msgstr "Autor"
 
-#: gitk:4083
 #, fuzzy
 msgid "Committer:"
 msgstr "revisión"
 
-#: gitk:4084
 msgid "Commit Message:"
 msgstr ""
 
-#: gitk:4085
 msgid "Matches all Commit Info criteria"
 msgstr ""
 
-#: gitk:4086
 msgid "Matches no Commit Info criteria"
 msgstr ""
 
-#: gitk:4087
 msgid "Changes to Files:"
 msgstr ""
 
-#: gitk:4088
 msgid "Fixed String"
 msgstr ""
 
-#: gitk:4089
 msgid "Regular Expression"
 msgstr ""
 
-#: gitk:4090
 #, fuzzy
 msgid "Search string:"
 msgstr "Buscando"
 
-#: gitk:4091
 msgid ""
 "Commit Dates (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 "
 "15:27:38\"):"
 msgstr ""
 
-#: gitk:4092
 msgid "Since:"
 msgstr ""
 
-#: gitk:4093
 msgid "Until:"
 msgstr ""
 
-#: gitk:4094
 msgid "Limit and/or skip a number of revisions (positive integer):"
 msgstr ""
 
-#: gitk:4095
 msgid "Number to show:"
 msgstr ""
 
-#: gitk:4096
 msgid "Number to skip:"
 msgstr ""
 
-#: gitk:4097
 msgid "Miscellaneous options:"
 msgstr ""
 
-#: gitk:4098
 msgid "Strictly sort by date"
 msgstr ""
 
-#: gitk:4099
 msgid "Mark branch sides"
 msgstr ""
 
-#: gitk:4100
 #, fuzzy
 msgid "Limit to first parent"
 msgstr "Limitar las diferencias a las rutas seleccionadas"
 
-#: gitk:4101
 msgid "Simple history"
 msgstr ""
 
-#: gitk:4102
 #, fuzzy
 msgid "Additional arguments to git log:"
 msgstr "Revisiones a incluir (argumentos a git log):"
 
-#: gitk:4103
 msgid "Enter files and directories to include, one per line:"
 msgstr "Introducir archivos y directorios a incluir, uno por línea:"
 
-#: gitk:4104
 msgid "Command to generate more commits to include:"
 msgstr "Comando que genera más revisiones a incluir:"
 
-#: gitk:4228
 msgid "Gitk: edit view"
 msgstr ""
 
-#: gitk:4236
 msgid "-- criteria for selecting revisions"
 msgstr ""
 
-#: gitk:4241
 #, fuzzy
 msgid "View Name"
 msgstr "Vista"
 
-#: gitk:4316
 msgid "Apply (F5)"
 msgstr ""
 
-#: gitk:4354
 msgid "Error in commit selection arguments:"
 msgstr "Error en los argumentos de selección de las revisiones:"
 
-#: gitk:4409 gitk:4462 gitk:4924 gitk:4938 gitk:6208 gitk:12373 gitk:12374
 msgid "None"
 msgstr "Ninguno"
 
-#: gitk:5021 gitk:5026
 msgid "Descendant"
 msgstr "Descendiente"
 
-#: gitk:5022
 msgid "Not descendant"
 msgstr "No descendiente"
 
-#: gitk:5029 gitk:5034
 msgid "Ancestor"
 msgstr "Antepasado"
 
-#: gitk:5030
 msgid "Not ancestor"
 msgstr "No antepasado"
 
-#: gitk:5324
 msgid "Local changes checked in to index but not committed"
 msgstr "Cambios locales añadidos al índice pero sin completar revisión"
 
-#: gitk:5360
 msgid "Local uncommitted changes, not checked in to index"
 msgstr "Cambios locales sin añadir al índice"
 
-#: gitk:7134
 msgid "and many more"
 msgstr ""
 
-#: gitk:7137
 msgid "many"
 msgstr ""
 
-#: gitk:7328
 msgid "Tags:"
 msgstr "Etiquetas:"
 
-#: gitk:7345 gitk:7351 gitk:8825
 msgid "Parent"
 msgstr "Padre"
 
-#: gitk:7356
 msgid "Child"
 msgstr "Hija"
 
-#: gitk:7365
 msgid "Branch"
 msgstr "Rama"
 
-#: gitk:7368
 msgid "Follows"
 msgstr "Sigue-a"
 
-#: gitk:7371
 msgid "Precedes"
 msgstr "Precede-a"
 
-#: gitk:7966
 #, fuzzy, tcl-format
 msgid "Error getting diffs: %s"
 msgstr "Error al leer las diferencias de fusión:"
 
-#: gitk:8650
 msgid "Goto:"
 msgstr "Ir a:"
 
-#: gitk:8671
 #, tcl-format
 msgid "Short SHA1 id %s is ambiguous"
 msgstr "La id SHA1 abreviada %s es ambigua"
 
-#: gitk:8678
 #, fuzzy, tcl-format
 msgid "Revision %s is not known"
 msgstr "La id SHA1 %s es desconocida"
 
-#: gitk:8688
 #, tcl-format
 msgid "SHA1 id %s is not known"
 msgstr "La id SHA1 %s es desconocida"
 
-#: gitk:8690
 #, tcl-format
 msgid "Revision %s is not in the current view"
 msgstr ""
 
-#: gitk:8832 gitk:8847
 msgid "Date"
 msgstr "Fecha"
 
-#: gitk:8835
 msgid "Children"
 msgstr "Hijas"
 
-#: gitk:8898
 #, tcl-format
 msgid "Reset %s branch to here"
 msgstr "Poner la rama %s en esta revisión"
 
-#: gitk:8900
 msgid "Detached head: can't reset"
 msgstr ""
 
-#: gitk:9005 gitk:9011
 msgid "Skipping merge commit "
 msgstr ""
 
-#: gitk:9020 gitk:9025
 #, fuzzy
 msgid "Error getting patch ID for "
 msgstr "Error en la creación del parche:"
 
-#: gitk:9021 gitk:9026
 msgid " - stopping\n"
 msgstr ""
 
-#: gitk:9031 gitk:9034 gitk:9042 gitk:9056 gitk:9065
 #, fuzzy
 msgid "Commit "
 msgstr "revisión"
 
-#: gitk:9035
 msgid ""
 " is the same patch as\n"
 "       "
 msgstr ""
 
-#: gitk:9043
 msgid ""
 " differs from\n"
 "       "
 msgstr ""
 
-#: gitk:9045
 msgid ""
 "Diff of commits:\n"
 "\n"
 msgstr ""
 
-#: gitk:9057 gitk:9066
 #, tcl-format
 msgid " has %s children - stopping\n"
 msgstr ""
 
-#: gitk:9085
 #, fuzzy, tcl-format
 msgid "Error writing commit to file: %s"
 msgstr "Error al escribir revisión:"
 
-#: gitk:9091
 #, fuzzy, tcl-format
 msgid "Error diffing commits: %s"
 msgstr "Error al escribir revisión:"
 
-#: gitk:9137
 msgid "Top"
 msgstr "Origen"
 
-#: gitk:9138
 msgid "From"
 msgstr "De"
 
-#: gitk:9143
 msgid "To"
 msgstr "A"
 
-#: gitk:9167
 msgid "Generate patch"
 msgstr "Generar parche"
 
-#: gitk:9169
 msgid "From:"
 msgstr "De:"
 
-#: gitk:9178
 msgid "To:"
 msgstr "Para:"
 
-#: gitk:9187
 msgid "Reverse"
 msgstr "Invertir"
 
-#: gitk:9189 gitk:9385
 msgid "Output file:"
 msgstr "Escribir a archivo:"
 
-#: gitk:9195
 msgid "Generate"
 msgstr "Generar"
 
-#: gitk:9233
 msgid "Error creating patch:"
 msgstr "Error en la creación del parche:"
 
-#: gitk:9256 gitk:9373 gitk:9430
 msgid "ID:"
 msgstr "ID:"
 
-#: gitk:9265
 msgid "Tag name:"
 msgstr "Nombre de etiqueta:"
 
-#: gitk:9268
 msgid "Tag message is optional"
 msgstr ""
 
-#: gitk:9270
 #, fuzzy
 msgid "Tag message:"
 msgstr "Nombre de etiqueta:"
 
-#: gitk:9274 gitk:9439
 msgid "Create"
 msgstr "Crear"
 
-#: gitk:9292
 msgid "No tag name specified"
 msgstr "No se ha especificado etiqueta"
 
-#: gitk:9296
 #, tcl-format
 msgid "Tag \"%s\" already exists"
 msgstr "La etiqueta \"%s\" ya existe"
 
-#: gitk:9306
 msgid "Error creating tag:"
 msgstr "Error al crear la etiqueta:"
 
-#: gitk:9382
 msgid "Command:"
 msgstr "Comando:"
 
-#: gitk:9390
 msgid "Write"
 msgstr "Escribir"
 
-#: gitk:9408
 msgid "Error writing commit:"
 msgstr "Error al escribir revisión:"
 
-#: gitk:9435
 msgid "Name:"
 msgstr "Nombre:"
 
-#: gitk:9458
 msgid "Please specify a name for the new branch"
 msgstr "Especifique un nombre para la nueva rama"
 
-#: gitk:9463
 #, fuzzy, tcl-format
 msgid "Branch '%s' already exists. Overwrite?"
 msgstr "La etiqueta \"%s\" ya existe"
 
-#: gitk:9530
 #, tcl-format
 msgid "Commit %s is already included in branch %s -- really re-apply it?"
 msgstr "La revisión %s ya está incluida en la rama %s -- ¿Volver a aplicarla?"
 
-#: gitk:9535
 msgid "Cherry-picking"
 msgstr "Eligiendo revisiones (cherry-picking)"
 
-#: gitk:9544
 #, tcl-format
 msgid ""
 "Cherry-pick failed because of local changes to file '%s'.\n"
 "Please commit, reset or stash your changes and try again."
 msgstr ""
 
-#: gitk:9550
 msgid ""
 "Cherry-pick failed because of merge conflict.\n"
 "Do you wish to run git citool to resolve it?"
 msgstr ""
 
-#: gitk:9566 gitk:9624
 msgid "No changes committed"
 msgstr "No se han guardado cambios"
 
-#: gitk:9593
 #, fuzzy, tcl-format
 msgid "Commit %s is not included in branch %s -- really revert it?"
 msgstr "La revisión %s ya está incluida en la rama %s -- ¿Volver a aplicarla?"
 
-#: gitk:9598
 #, fuzzy
 msgid "Reverting"
 msgstr "Reponiendo"
 
-#: gitk:9606
 #, tcl-format
 msgid ""
 "Revert failed because of local changes to the following files:%s Please "
 "commit, reset or stash  your changes and try again."
 msgstr ""
 
-#: gitk:9610
 msgid ""
 "Revert failed because of merge conflict.\n"
 " Do you wish to run git citool to resolve it?"
 msgstr ""
 
-#: gitk:9653
 msgid "Confirm reset"
 msgstr "Confirmar git reset"
 
-#: gitk:9655
 #, tcl-format
 msgid "Reset branch %s to %s?"
 msgstr "¿Reponer la rama %s a %s?"
 
-#: gitk:9657
 msgid "Reset type:"
 msgstr "Tipo de reposición:"
 
-#: gitk:9660
 msgid "Soft: Leave working tree and index untouched"
 msgstr "Suave: No altera la copia de trabajo ni el índice"
 
-#: gitk:9663
 msgid "Mixed: Leave working tree untouched, reset index"
 msgstr "Mixta: Actualiza el índice, no altera la copia de trabajo"
 
-#: gitk:9666
 msgid ""
 "Hard: Reset working tree and index\n"
 "(discard ALL local changes)"
@@ -1116,19 +865,15 @@
 "Dura: Actualiza el índice y la copia de trabajo\n"
 "(abandona TODAS las modificaciones locales)"
 
-#: gitk:9683
 msgid "Resetting"
 msgstr "Reponiendo"
 
-#: gitk:9743
 msgid "Checking out"
 msgstr "Creando copia de trabajo"
 
-#: gitk:9796
 msgid "Cannot delete the currently checked-out branch"
 msgstr "No se puede borrar la rama actual"
 
-#: gitk:9802
 #, tcl-format
 msgid ""
 "The commits on branch %s aren't on any other branch.\n"
@@ -1137,16 +882,13 @@
 "Las revisiones de la rama %s no están presentes en otras ramas.\n"
 "¿Borrar la rama %s?"
 
-#: gitk:9833
 #, tcl-format
 msgid "Tags and heads: %s"
 msgstr "Etiquetas y ramas: %s"
 
-#: gitk:9850
 msgid "Filter"
 msgstr "Filtro"
 
-#: gitk:10146
 msgid ""
 "Error reading commit topology information; branch and preceding/following "
 "tag information will be incomplete."
@@ -1154,211 +896,162 @@
 "Error al leer la topología de revisiones: la información sobre las ramas y "
 "etiquetas precedentes y siguientes será incompleta."
 
-#: gitk:11123
 msgid "Tag"
 msgstr "Etiqueta"
 
-#: gitk:11127
 msgid "Id"
 msgstr "Id"
 
-#: gitk:11210
 msgid "Gitk font chooser"
 msgstr "Selector de tipografías gitk"
 
-#: gitk:11227
 msgid "B"
 msgstr "B"
 
-#: gitk:11230
 msgid "I"
 msgstr "I"
 
-#: gitk:11348
 msgid "Commit list display options"
 msgstr "Opciones de visualización de la lista de revisiones"
 
-#: gitk:11351
 msgid "Maximum graph width (lines)"
 msgstr "Ancho máximo del gráfico (en líneas)"
 
-#: gitk:11355
 #, no-tcl-format
 msgid "Maximum graph width (% of pane)"
 msgstr "Ancho máximo del gráfico (en % del panel)"
 
-#: gitk:11358
 msgid "Show local changes"
 msgstr "Mostrar cambios locales"
 
-#: gitk:11361
 #, fuzzy
 msgid "Auto-select SHA1 (length)"
 msgstr "Seleccionar automáticamente SHA1 hash"
 
-#: gitk:11365
 msgid "Hide remote refs"
 msgstr ""
 
-#: gitk:11369
 msgid "Diff display options"
 msgstr "Opciones de visualización de diferencias"
 
-#: gitk:11371
 msgid "Tab spacing"
 msgstr "Espaciado de tabulador"
 
-#: gitk:11374
 #, fuzzy
 msgid "Display nearby tags/heads"
 msgstr "Mostrar etiquetas cercanas"
 
-#: gitk:11377
 msgid "Maximum # tags/heads to show"
 msgstr ""
 
-#: gitk:11380
 msgid "Limit diffs to listed paths"
 msgstr "Limitar las diferencias a las rutas seleccionadas"
 
-#: gitk:11383
 msgid "Support per-file encodings"
 msgstr ""
 
-#: gitk:11389 gitk:11536
 msgid "External diff tool"
 msgstr ""
 
-#: gitk:11390
 msgid "Choose..."
 msgstr ""
 
-#: gitk:11395
 #, fuzzy
 msgid "General options"
 msgstr "Generar parche"
 
-#: gitk:11398
 msgid "Use themed widgets"
 msgstr ""
 
-#: gitk:11400
 msgid "(change requires restart)"
 msgstr ""
 
-#: gitk:11402
 msgid "(currently unavailable)"
 msgstr ""
 
-#: gitk:11413
 msgid "Colors: press to choose"
 msgstr "Colores: pulse para seleccionar"
 
-#: gitk:11416
 msgid "Interface"
 msgstr ""
 
-#: gitk:11417
 #, fuzzy
 msgid "interface"
 msgstr "Tipografía para interfaz de usuario"
 
-#: gitk:11420
 msgid "Background"
 msgstr "Fondo"
 
-#: gitk:11421 gitk:11451
 #, fuzzy
 msgid "background"
 msgstr "Fondo"
 
-#: gitk:11424
 msgid "Foreground"
 msgstr "Primer plano"
 
-#: gitk:11425
 #, fuzzy
 msgid "foreground"
 msgstr "Primer plano"
 
-#: gitk:11428
 msgid "Diff: old lines"
 msgstr "Diff: líneas viejas"
 
-#: gitk:11429
 #, fuzzy
 msgid "diff old lines"
 msgstr "Diff: líneas viejas"
 
-#: gitk:11433
 msgid "Diff: new lines"
 msgstr "Diff: líneas nuevas"
 
-#: gitk:11434
 #, fuzzy
 msgid "diff new lines"
 msgstr "Diff: líneas nuevas"
 
-#: gitk:11438
 msgid "Diff: hunk header"
 msgstr "Diff: cabecera de fragmento"
 
-#: gitk:11440
 #, fuzzy
 msgid "diff hunk header"
 msgstr "Diff: cabecera de fragmento"
 
-#: gitk:11444
 msgid "Marked line bg"
 msgstr ""
 
-#: gitk:11446
 msgid "marked line background"
 msgstr ""
 
-#: gitk:11450
 msgid "Select bg"
 msgstr "Color de fondo de la selección"
 
-#: gitk:11459
 msgid "Fonts: press to choose"
 msgstr "Tipografías: pulse para elegir"
 
-#: gitk:11461
 msgid "Main font"
 msgstr "Tipografía principal"
 
-#: gitk:11462
 msgid "Diff display font"
 msgstr "Tipografía para diferencias"
 
-#: gitk:11463
 msgid "User interface font"
 msgstr "Tipografía para interfaz de usuario"
 
-#: gitk:11485
 msgid "Gitk preferences"
 msgstr "Preferencias de gitk"
 
-#: gitk:11494
 #, fuzzy
 msgid "General"
 msgstr "Generar"
 
-#: gitk:11495
 msgid "Colors"
 msgstr ""
 
-#: gitk:11496
 msgid "Fonts"
 msgstr ""
 
-#: gitk:11546
 #, tcl-format
 msgid "Gitk: choose color for %s"
 msgstr "Gitk: elegir color para %s"
 
-#: gitk:12059
 msgid ""
 "Sorry, gitk cannot run with this version of Tcl/Tk.\n"
 " Gitk requires at least Tcl/Tk 8.4."
@@ -1366,17 +1059,14 @@
 "Esta versión de Tcl/Tk es demasiado antigua.\n"
 " Gitk requiere Tcl/Tk versión 8.4 o superior."
 
-#: gitk:12269
 msgid "Cannot find a git repository here."
 msgstr "No hay un repositorio git aquí."
 
-#: gitk:12316
 #, tcl-format
 msgid "Ambiguous argument '%s': both revision and filename"
 msgstr ""
 "Argumento ambiguo: '%s' es tanto una revisión como un nombre de archivo"
 
-#: gitk:12328
 msgid "Bad arguments to gitk:"
 msgstr "Argumentos incorrectos a Gitk:"
 
diff --git a/gitk-git/po/fr.po b/gitk-git/po/fr.po
index e4fac93..f1c54b6 100644
--- a/gitk-git/po/fr.po
+++ b/gitk-git/po/fr.po
@@ -6,7 +6,7 @@
 # Jean-Noël Avila <jn.avila@free.fr>
 msgid ""
 msgstr ""
-"Project-Id-Version: gitk\n"
+"Project-Id-Version: Gitk\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2016-01-22 22:04+0100\n"
 "PO-Revision-Date: 2016-01-22 23:28+0100\n"
@@ -19,355 +19,268 @@
 "X-Poedit-Language: French\n"
 "X-Poedit-Country: FRANCE\n"
 
-#: gitk:140
 msgid "Couldn't get list of unmerged files:"
 msgstr "Impossible de récupérer la liste des fichiers non fusionnés :"
 
-#: gitk:212 gitk:2399
 msgid "Color words"
 msgstr "Colorier les mots différents"
 
-#: gitk:217 gitk:2399 gitk:8239 gitk:8272
 msgid "Markup words"
 msgstr "Marquer les mots différents"
 
-#: gitk:324
 msgid "Error parsing revisions:"
 msgstr "Erreur lors du parcours des révisions :"
 
-#: gitk:380
 msgid "Error executing --argscmd command:"
 msgstr "Erreur à l'exécution de la commande --argscmd :"
 
-#: gitk:393
 msgid "No files selected: --merge specified but no files are unmerged."
 msgstr ""
 "Aucun fichier sélectionné : --merge précisé, mais tous les fichiers sont "
 "fusionnés."
 
 # FIXME : améliorer la traduction de 'file limite'
-#: gitk:396
 msgid ""
 "No files selected: --merge specified but no unmerged files are within file "
 "limit."
-msgstr "Aucun fichier sélectionné : --merge précisé mais aucun fichier non fusionné n'est dans la limite des fichiers."
+msgstr ""
+"Aucun fichier sélectionné : --merge précisé mais aucun fichier non fusionné "
+"n'est dans la limite des fichiers."
 
-#: gitk:418 gitk:566
 msgid "Error executing git log:"
 msgstr "Erreur à l'exécution de git log :"
 
-#: gitk:436 gitk:582
 msgid "Reading"
 msgstr "Lecture en cours"
 
-#: gitk:496 gitk:4544
 msgid "Reading commits..."
 msgstr "Lecture des commits..."
 
-#: gitk:499 gitk:1637 gitk:4547
 msgid "No commits selected"
 msgstr "Aucun commit sélectionné"
 
-#: gitk:1445 gitk:4064 gitk:12469
 msgid "Command line"
 msgstr "Ligne de commande"
 
-#: gitk:1511
 msgid "Can't parse git log output:"
 msgstr "Impossible de lire la sortie de git log :"
 
-#: gitk:1740
 msgid "No commit information available"
 msgstr "Aucune information disponible sur le commit"
 
-#: gitk:1903 gitk:1932 gitk:4334 gitk:9702 gitk:11274 gitk:11554
 msgid "OK"
 msgstr "OK"
 
-#: gitk:1934 gitk:4336 gitk:9215 gitk:9294 gitk:9424 gitk:9473 gitk:9704
-#: gitk:11275 gitk:11555
 msgid "Cancel"
 msgstr "Annuler"
 
-#: gitk:2083
 msgid "&Update"
 msgstr "Mise à jour"
 
-#: gitk:2084
 msgid "&Reload"
 msgstr "&Recharger"
 
-#: gitk:2085
 msgid "Reread re&ferences"
 msgstr "Relire les ré&férences"
 
-#: gitk:2086
 msgid "&List references"
 msgstr "&Lister les références"
 
-#: gitk:2088
 msgid "Start git &gui"
 msgstr "Démarrer git &gui"
 
-#: gitk:2090
 msgid "&Quit"
 msgstr "&Quitter"
 
-#: gitk:2082
 msgid "&File"
 msgstr "&Fichier"
 
-#: gitk:2094
 msgid "&Preferences"
 msgstr "Préférences"
 
-#: gitk:2093
 msgid "&Edit"
 msgstr "&Éditer"
 
-#: gitk:2098
 msgid "&New view..."
 msgstr "&Nouvelle vue..."
 
-#: gitk:2099
 msgid "&Edit view..."
 msgstr "&Éditer la vue..."
 
-#: gitk:2100
 msgid "&Delete view"
 msgstr "Supprimer la vue"
 
-#: gitk:2102
 msgid "&All files"
 msgstr "Tous les fichiers"
 
-#: gitk:2097
 msgid "&View"
 msgstr "&Vue"
 
-#: gitk:2107 gitk:2117
 msgid "&About gitk"
 msgstr "À propos de gitk"
 
-#: gitk:2108 gitk:2122
 msgid "&Key bindings"
 msgstr "Raccourcis clavier"
 
-#: gitk:2106 gitk:2121
 msgid "&Help"
 msgstr "Aide"
 
-#: gitk:2199 gitk:8671
 msgid "SHA1 ID:"
 msgstr "Id SHA1 :"
 
-#: gitk:2243
 msgid "Row"
 msgstr "Colonne"
 
-#: gitk:2281
 msgid "Find"
 msgstr "Recherche"
 
-#: gitk:2309
 msgid "commit"
 msgstr "commit"
 
-#: gitk:2313 gitk:2315 gitk:4706 gitk:4729 gitk:4753 gitk:6774 gitk:6846
-#: gitk:6931
 msgid "containing:"
 msgstr "contient :"
 
-#: gitk:2316 gitk:3545 gitk:3550 gitk:4782
 msgid "touching paths:"
 msgstr "chemins modifiés :"
 
-#: gitk:2317 gitk:4796
 msgid "adding/removing string:"
 msgstr "ajoute/supprime la chaîne :"
 
-#: gitk:2318 gitk:4798
 msgid "changing lines matching:"
 msgstr "modifie les lignes vérifiant :"
 
-#: gitk:2327 gitk:2329 gitk:4785
 msgid "Exact"
 msgstr "Exact"
 
-#: gitk:2329 gitk:4873 gitk:6742
 msgid "IgnCase"
 msgstr "Ignorer la casse"
 
-#: gitk:2329 gitk:4755 gitk:4871 gitk:6738
 msgid "Regexp"
 msgstr "Expression régulière"
 
-#: gitk:2331 gitk:2332 gitk:4893 gitk:4923 gitk:4930 gitk:6867 gitk:6935
 msgid "All fields"
 msgstr "Tous les champs"
 
-#: gitk:2332 gitk:4890 gitk:4923 gitk:6805
 msgid "Headline"
 msgstr "Titre"
 
-#: gitk:2333 gitk:4890 gitk:6805 gitk:6935 gitk:7408
 msgid "Comments"
 msgstr "Commentaires"
 
-#: gitk:2333 gitk:4890 gitk:4895 gitk:4930 gitk:6805 gitk:7343 gitk:8849
-#: gitk:8864
 msgid "Author"
 msgstr "Auteur"
 
-#: gitk:2333 gitk:4890 gitk:6805 gitk:7345
 msgid "Committer"
 msgstr "Validateur"
 
-#: gitk:2367
 msgid "Search"
 msgstr "Rechercher"
 
-#: gitk:2375
 msgid "Diff"
 msgstr "Diff"
 
-#: gitk:2377
 msgid "Old version"
 msgstr "Ancienne version"
 
-#: gitk:2379
 msgid "New version"
 msgstr "Nouvelle version"
 
-#: gitk:2382
 msgid "Lines of context"
 msgstr "Lignes de contexte"
 
-#: gitk:2392
 msgid "Ignore space change"
 msgstr "Ignorer les modifications d'espace"
 
-#: gitk:2396 gitk:2398 gitk:7978 gitk:8225
 msgid "Line diff"
 msgstr "différence par ligne"
 
-#: gitk:2463
 msgid "Patch"
 msgstr "Patch"
 
-#: gitk:2465
 msgid "Tree"
 msgstr "Arbre"
 
-#: gitk:2635 gitk:2656
 msgid "Diff this -> selected"
 msgstr "Diff ceci -> la sélection"
 
-#: gitk:2636 gitk:2657
 msgid "Diff selected -> this"
 msgstr "Diff sélection -> ceci"
 
-#: gitk:2637 gitk:2658
 msgid "Make patch"
 msgstr "Créer patch"
 
-#: gitk:2638 gitk:9273
 msgid "Create tag"
 msgstr "Créer étiquette"
 
-#: gitk:2639
 msgid "Copy commit summary"
 msgstr "Copié le résumé du commit"
 
-#: gitk:2640 gitk:9404
 msgid "Write commit to file"
 msgstr "Écrire le commit dans un fichier"
 
-#: gitk:2641 gitk:9461
 msgid "Create new branch"
 msgstr "Créer une nouvelle branche"
 
-#: gitk:2642
 msgid "Cherry-pick this commit"
 msgstr "Cueillir (cherry-pick) ce commit"
 
-#: gitk:2643
 msgid "Reset HEAD branch to here"
 msgstr "Réinitialiser la branche HEAD vers cet état"
 
-#: gitk:2644
 msgid "Mark this commit"
 msgstr "Marquer ce commit"
 
-#: gitk:2645
 msgid "Return to mark"
 msgstr "Retourner à la marque"
 
-#: gitk:2646
 msgid "Find descendant of this and mark"
 msgstr "Chercher le descendant de ceci et le marquer"
 
-#: gitk:2647
 msgid "Compare with marked commit"
 msgstr "Comparer avec le commit marqué"
 
-#: gitk:2648 gitk:2659
 msgid "Diff this -> marked commit"
 msgstr "Diff ceci -> sélection"
 
-#: gitk:2649 gitk:2660
 msgid "Diff marked commit -> this"
 msgstr "Diff entre sélection -> ceci"
 
-#: gitk:2650
 msgid "Revert this commit"
 msgstr "Défaire ce commit"
 
-#: gitk:2666
 msgid "Check out this branch"
 msgstr "Récupérer cette branche"
 
-#: gitk:2667
 msgid "Remove this branch"
 msgstr "Supprimer cette branche"
 
-#: gitk:2668
 msgid "Copy branch name"
 msgstr "Copier la nom de la branche"
 
-#: gitk:2675
 msgid "Highlight this too"
 msgstr "Surligner également ceci"
 
-#: gitk:2676
 msgid "Highlight this only"
 msgstr "Surligner seulement ceci"
 
-#: gitk:2677
 msgid "External diff"
 msgstr "Diff externe"
 
-#: gitk:2678
 msgid "Blame parent commit"
 msgstr "Blâmer le commit parent"
 
-#: gitk:2679
 msgid "Copy path"
 msgstr "Copier le chemin"
 
-#: gitk:2686
 msgid "Show origin of this line"
 msgstr "Montrer l'origine de cette ligne"
 
-#: gitk:2687
 msgid "Run git gui blame on this line"
 msgstr "Exécuter git gui blame sur cette ligne"
 
-#: gitk:3031
 msgid "About gitk"
 msgstr "À propos de gitk"
 
-#: gitk:3033
 msgid ""
 "\n"
 "Gitk - a commit viewer for git\n"
@@ -381,327 +294,254 @@
 "\n"
 "Copyright \\u00a9 2005-2016 Paul Mackerras\n"
 "\n"
-"Utilisation et redistribution soumises aux termes de la GNU General Public License"
+"Utilisation et redistribution soumises aux termes de la GNU General Public "
+"License"
 
-#: gitk:3041 gitk:3108 gitk:9890
 msgid "Close"
 msgstr "Fermer"
 
-#: gitk:3062
 msgid "Gitk key bindings"
 msgstr "Raccourcis clavier de Gitk"
 
-#: gitk:3065
 msgid "Gitk key bindings:"
 msgstr "Raccourcis clavier de Gitk :"
 
-#: gitk:3067
 #, tcl-format
 msgid "<%s-Q>\t\tQuit"
 msgstr "<%s-Q>\t\tQuitter"
 
-#: gitk:3068
 #, tcl-format
 msgid "<%s-W>\t\tClose window"
 msgstr "<%s-W>\t\tFermer la fenêtre"
 
-#: gitk:3069
 msgid "<Home>\t\tMove to first commit"
 msgstr "<Début>\t\tAller au premier commit"
 
-#: gitk:3070
 msgid "<End>\t\tMove to last commit"
 msgstr "<Fin>\t\tAller au dernier commit"
 
-#: gitk:3071
 msgid "<Up>, p, k\tMove up one commit"
 msgstr "<Haut>, p, k\t Aller au commit précédent"
 
-#: gitk:3072
 msgid "<Down>, n, j\tMove down one commit"
 msgstr "<Bas>, n, j\t Aller au commit suivant"
 
-#: gitk:3073
 msgid "<Left>, z, h\tGo back in history list"
 msgstr "<Gauche>, z, h\tReculer dans l'historique"
 
-#: gitk:3074
 msgid "<Right>, x, l\tGo forward in history list"
 msgstr "<Droite>, x, l\tAvancer dans l'historique"
 
-#: gitk:3075
 #, tcl-format
 msgid "<%s-n>\tGo to n-th parent of current commit in history list"
 msgstr "<%s-n>\tAller sur le n-ième parent du commit dans l'historique"
 
-#: gitk:3076
 msgid "<PageUp>\tMove up one page in commit list"
 msgstr "<PageUp>\tMonter d'une page dans la liste des commits"
 
-#: gitk:3077
 msgid "<PageDown>\tMove down one page in commit list"
 msgstr "<PageDown>\tDescendre d'une page dans la liste des commits"
 
-#: gitk:3078
 #, tcl-format
 msgid "<%s-Home>\tScroll to top of commit list"
 msgstr "<%s-Début>\tAller en haut de la liste des commits"
 
-#: gitk:3079
 #, tcl-format
 msgid "<%s-End>\tScroll to bottom of commit list"
 msgstr "<%s-End>\tAller en bas de la liste des commits"
 
-#: gitk:3080
 #, tcl-format
 msgid "<%s-Up>\tScroll commit list up one line"
 msgstr "<%s-Up>\tMonter d'une ligne dans la liste des commits"
 
-#: gitk:3081
 #, tcl-format
 msgid "<%s-Down>\tScroll commit list down one line"
 msgstr "<%s-Down>\tDescendre d'une ligne dans la liste des commits"
 
-#: gitk:3082
 #, tcl-format
 msgid "<%s-PageUp>\tScroll commit list up one page"
 msgstr "<%s-PageUp>\tMonter d'une page dans la liste des commits"
 
-#: gitk:3083
 #, tcl-format
 msgid "<%s-PageDown>\tScroll commit list down one page"
 msgstr "<%s-PageDown>\tDescendre d'une page dans la liste des commits"
 
-#: gitk:3084
 msgid "<Shift-Up>\tFind backwards (upwards, later commits)"
 msgstr ""
 "<Shift-Up>\tRecherche en arrière (vers l'avant, commits les plus anciens)"
 
-#: gitk:3085
 msgid "<Shift-Down>\tFind forwards (downwards, earlier commits)"
 msgstr ""
 "<Shift-Down>\tRecherche en avant (vers l'arrière, commit les plus récents)"
 
-#: gitk:3086
 msgid "<Delete>, b\tScroll diff view up one page"
 msgstr "<Supprimer>, b\tMonter d'une page dans la vue des diff"
 
-#: gitk:3087
 msgid "<Backspace>\tScroll diff view up one page"
 msgstr "<Backspace>\tMonter d'une page dans la vue des diff"
 
-#: gitk:3088
 msgid "<Space>\t\tScroll diff view down one page"
 msgstr "<Espace>\t\tDescendre d'une page dans la vue des diff"
 
-#: gitk:3089
 msgid "u\t\tScroll diff view up 18 lines"
 msgstr "u\t\tMonter de 18 lignes dans la vue des diff"
 
-#: gitk:3090
 msgid "d\t\tScroll diff view down 18 lines"
 msgstr "d\t\tDescendre de 18 lignes dans la vue des diff"
 
-#: gitk:3091
 #, tcl-format
 msgid "<%s-F>\t\tFind"
 msgstr "<%s-F>\t\tRechercher"
 
-#: gitk:3092
 #, tcl-format
 msgid "<%s-G>\t\tMove to next find hit"
 msgstr "<%s-G>\t\tAller au résultat de recherche suivant"
 
-#: gitk:3093
 msgid "<Return>\tMove to next find hit"
 msgstr "<Return>\t\tAller au résultat de recherche suivant"
 
-#: gitk:3094
 msgid "g\t\tGo to commit"
 msgstr "g\t\tAller au commit"
 
-#: gitk:3095
 msgid "/\t\tFocus the search box"
 msgstr "/\t\tFocus sur la zone de recherche"
 
-#: gitk:3096
 msgid "?\t\tMove to previous find hit"
 msgstr "?\t\tAller au résultat de recherche précédent"
 
-#: gitk:3097
 msgid "f\t\tScroll diff view to next file"
 msgstr "f\t\tAller au prochain fichier dans la vue des diff"
 
-#: gitk:3098
 #, tcl-format
 msgid "<%s-S>\t\tSearch for next hit in diff view"
 msgstr "<%s-S>\t\tAller au résultat suivant dans la vue des diff"
 
-#: gitk:3099
 #, tcl-format
 msgid "<%s-R>\t\tSearch for previous hit in diff view"
 msgstr "<%s-R>\t\tAller au résultat précédent dans la vue des diff"
 
-#: gitk:3100
 #, tcl-format
 msgid "<%s-KP+>\tIncrease font size"
 msgstr "<%s-KP+>\tAugmenter la taille de la police"
 
-#: gitk:3101
 #, tcl-format
 msgid "<%s-plus>\tIncrease font size"
 msgstr "<%s-plus>\tAugmenter la taille de la police"
 
-#: gitk:3102
 #, tcl-format
 msgid "<%s-KP->\tDecrease font size"
 msgstr "<%s-KP->\tDiminuer la taille de la police"
 
-#: gitk:3103
 #, tcl-format
 msgid "<%s-minus>\tDecrease font size"
 msgstr "<%s-minus>\tDiminuer la taille de la police"
 
-#: gitk:3104
 msgid "<F5>\t\tUpdate"
 msgstr "<F5>\t\tMise à jour"
 
-#: gitk:3569 gitk:3578
 #, tcl-format
 msgid "Error creating temporary directory %s:"
 msgstr "Erreur lors de la création du répertoire temporaire %s :"
 
-#: gitk:3591
 #, tcl-format
 msgid "Error getting \"%s\" from %s:"
 msgstr "Erreur en obtenant \"%s\" de %s:"
 
-#: gitk:3654
 msgid "command failed:"
 msgstr "échec de la commande :"
 
-#: gitk:3803
 msgid "No such commit"
 msgstr "Commit inexistant"
 
-#: gitk:3817
 msgid "git gui blame: command failed:"
 msgstr "git gui blame : échec de la commande :"
 
-#: gitk:3848
 #, tcl-format
 msgid "Couldn't read merge head: %s"
 msgstr "Impossible de lire le head de la fusion : %s"
 
-#: gitk:3856
 #, tcl-format
 msgid "Error reading index: %s"
 msgstr "Erreur à la lecture de l'index : %s"
 
-#: gitk:3881
 #, tcl-format
 msgid "Couldn't start git blame: %s"
 msgstr "Impossible de démarrer git blame : %s"
 
-#: gitk:3884 gitk:6773
 msgid "Searching"
 msgstr "Recherche en cours"
 
-#: gitk:3916
 #, tcl-format
 msgid "Error running git blame: %s"
 msgstr "Erreur à l'exécution de git blame : %s"
 
-#: gitk:3944
 #, tcl-format
 msgid "That line comes from commit %s,  which is not in this view"
 msgstr "Cette ligne est issue du commit %s, qui n'est pas dans cette vue"
 
-#: gitk:3958
 msgid "External diff viewer failed:"
 msgstr "Échec de l'outil externe de visualisation des diff :"
 
-#: gitk:4062
 msgid "All files"
 msgstr "Tous les fichiers"
 
-#: gitk:4086
 msgid "View"
 msgstr "Vue"
 
-#: gitk:4089
 msgid "Gitk view definition"
 msgstr "Définition des vues de Gitk"
 
-#: gitk:4093
 msgid "Remember this view"
 msgstr "Se souvenir de cette vue"
 
-#: gitk:4094
 msgid "References (space separated list):"
 msgstr "Références (liste d'éléments séparés par des espaces) :"
 
-#: gitk:4095
 msgid "Branches & tags:"
 msgstr "Branches & étiquettes :"
 
-#: gitk:4096
 msgid "All refs"
 msgstr "Toutes les références"
 
-#: gitk:4097
 msgid "All (local) branches"
 msgstr "Toutes les branches (locales)"
 
-#: gitk:4098
 msgid "All tags"
 msgstr "Toutes les étiquettes"
 
-#: gitk:4099
 msgid "All remote-tracking branches"
 msgstr "Toutes les branches de suivi à distance"
 
-#: gitk:4100
 msgid "Commit Info (regular expressions):"
 msgstr "Info sur les commits (expressions régulières) :"
 
-#: gitk:4101
 msgid "Author:"
 msgstr "Auteur :"
 
-#: gitk:4102
 msgid "Committer:"
 msgstr "Validateur :"
 
-#: gitk:4103
 msgid "Commit Message:"
 msgstr "Message de commit :"
 
-#: gitk:4104
 msgid "Matches all Commit Info criteria"
 msgstr "Correspond à tous les critères d'Info sur les commits"
 
-#: gitk:4105
 msgid "Matches no Commit Info criteria"
 msgstr "Ne correspond à aucun des critères d'Info sur les commits"
 
-#: gitk:4106
 msgid "Changes to Files:"
 msgstr "Changements des fichiers :"
 
-#: gitk:4107
 msgid "Fixed String"
 msgstr "Chaîne Figée"
 
-#: gitk:4108
 msgid "Regular Expression"
 msgstr "Expression Régulière"
 
-#: gitk:4109
 msgid "Search string:"
 msgstr "Recherche de la chaîne :"
 
-#: gitk:4110
 msgid ""
 "Commit Dates (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 "
 "15:27:38\"):"
@@ -709,201 +549,153 @@
 "Dates des commits (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, "
 "2009 15:27:38\") :"
 
-#: gitk:4111
 msgid "Since:"
 msgstr "Depuis :"
 
-#: gitk:4112
 msgid "Until:"
 msgstr "Jusqu'au :"
 
-#: gitk:4113
 msgid "Limit and/or skip a number of revisions (positive integer):"
 msgstr "Limiter et/ou sauter un certain nombre (entier positif) de révisions :"
 
-#: gitk:4114
 msgid "Number to show:"
 msgstr "Nombre à afficher :"
 
-#: gitk:4115
 msgid "Number to skip:"
 msgstr "Nombre à sauter :"
 
-#: gitk:4116
 msgid "Miscellaneous options:"
 msgstr "Options diverses :"
 
-#: gitk:4117
 msgid "Strictly sort by date"
 msgstr "Trier par date"
 
-#: gitk:4118
 msgid "Mark branch sides"
 msgstr "Indiquer les côtés des branches"
 
-#: gitk:4119
 msgid "Limit to first parent"
 msgstr "Limiter au premier ancêtre"
 
-#: gitk:4120
 msgid "Simple history"
 msgstr "Historique simple"
 
-#: gitk:4121
 msgid "Additional arguments to git log:"
 msgstr "Arguments supplémentaires de git log :"
 
-#: gitk:4122
 msgid "Enter files and directories to include, one per line:"
 msgstr "Saisir les fichiers et répertoires à inclure, un par ligne :"
 
-#: gitk:4123
 msgid "Command to generate more commits to include:"
 msgstr "Commande pour générer plus de commits à inclure :"
 
-#: gitk:4247
 msgid "Gitk: edit view"
 msgstr "Gitk : éditer la vue"
 
-#: gitk:4255
 msgid "-- criteria for selecting revisions"
 msgstr "-- critère pour la sélection des révisions"
 
-#: gitk:4260
 msgid "View Name"
 msgstr "Nom de la vue"
 
-#: gitk:4335
 msgid "Apply (F5)"
 msgstr "Appliquer (F5)"
 
-#: gitk:4373
 msgid "Error in commit selection arguments:"
 msgstr "Erreur dans les arguments de sélection des commits :"
 
-#: gitk:4428 gitk:4481 gitk:4943 gitk:4957 gitk:6227 gitk:12410 gitk:12411
 msgid "None"
 msgstr "Aucun"
 
-#: gitk:5040 gitk:5045
 msgid "Descendant"
 msgstr "Descendant"
 
-#: gitk:5041
 msgid "Not descendant"
 msgstr "Pas un descendant"
 
-#: gitk:5048 gitk:5053
 msgid "Ancestor"
 msgstr "Ancêtre"
 
-#: gitk:5049
 msgid "Not ancestor"
 msgstr "Pas un ancêtre"
 
-#: gitk:5343
 msgid "Local changes checked in to index but not committed"
 msgstr "Modifications locales enregistrées dans l'index mais non validées"
 
-#: gitk:5379
 msgid "Local uncommitted changes, not checked in to index"
 msgstr "Modifications locales non enregistrées dans l'index et non validées"
 
-#: gitk:7153
 msgid "and many more"
 msgstr "et beaucoup plus"
 
-#: gitk:7156
 msgid "many"
 msgstr "nombreux"
 
-#: gitk:7347
 msgid "Tags:"
 msgstr "Étiquettes :"
 
-#: gitk:7364 gitk:7370 gitk:8844
 msgid "Parent"
 msgstr "Parent"
 
-#: gitk:7375
 msgid "Child"
 msgstr "Enfant"
 
-#: gitk:7384
 msgid "Branch"
 msgstr "Branche"
 
-#: gitk:7387
 msgid "Follows"
 msgstr "Suit"
 
-#: gitk:7390
 msgid "Precedes"
 msgstr "Précède"
 
-#: gitk:7985
 #, tcl-format
 msgid "Error getting diffs: %s"
 msgstr "Erreur lors de la récupération des diff : %s"
 
-#: gitk:8669
 msgid "Goto:"
 msgstr "Aller à :"
 
-#: gitk:8690
 #, tcl-format
 msgid "Short SHA1 id %s is ambiguous"
 msgstr "L'id SHA1 court %s est ambigu"
 
-#: gitk:8697
 #, tcl-format
 msgid "Revision %s is not known"
 msgstr "La révision %s est inconnu"
 
-#: gitk:8707
 #, tcl-format
 msgid "SHA1 id %s is not known"
 msgstr "L'id SHA1 %s est inconnu"
 
-#: gitk:8709
 #, tcl-format
 msgid "Revision %s is not in the current view"
 msgstr "La révision %s n'est pas dans la vue courante"
 
-#: gitk:8851 gitk:8866
 msgid "Date"
 msgstr "Date"
 
-#: gitk:8854
 msgid "Children"
 msgstr "Enfants"
 
-#: gitk:8917
 #, tcl-format
 msgid "Reset %s branch to here"
 msgstr "Réinitialiser la branche %s vers cet état"
 
-#: gitk:8919
 msgid "Detached head: can't reset"
 msgstr "Head détaché : impossible de réinitialiser"
 
-#: gitk:9024 gitk:9030
 msgid "Skipping merge commit "
 msgstr "Éviter le commit de la fusion "
 
-#: gitk:9039 gitk:9044
 msgid "Error getting patch ID for "
 msgstr "Erreur à l'obtention de l'ID du patch pour "
 
-#: gitk:9040 gitk:9045
 msgid " - stopping\n"
 msgstr " - arrêt en cours\n"
 
-#: gitk:9050 gitk:9053 gitk:9061 gitk:9075 gitk:9084
 msgid "Commit "
 msgstr "Commit "
 
-#: gitk:9054
 msgid ""
 " is the same patch as\n"
 "       "
@@ -911,7 +703,6 @@
 "est le même patch que \n"
 "       "
 
-#: gitk:9062
 msgid ""
 " differs from\n"
 "       "
@@ -919,146 +710,118 @@
 " diffère de\n"
 "       "
 
-#: gitk:9064
 msgid ""
 "Diff of commits:\n"
 "\n"
-msgstr "Diff des commits :\n\n"
+msgstr ""
+"Diff des commits :\n"
+"\n"
 
-#: gitk:9076 gitk:9085
 #, tcl-format
 msgid " has %s children - stopping\n"
 msgstr " a %s enfants - arrêt en cours\n"
 
-#: gitk:9104
 #, tcl-format
 msgid "Error writing commit to file: %s"
 msgstr "Erreur à l'écriture du commit dans le fichier : %s"
 
-#: gitk:9110
 #, tcl-format
 msgid "Error diffing commits: %s"
 msgstr "Erreur à la différence des commits : %s"
 
-#: gitk:9156
 msgid "Top"
 msgstr "Haut"
 
-#: gitk:9157
 msgid "From"
 msgstr "De"
 
-#: gitk:9162
 msgid "To"
 msgstr "À"
 
-#: gitk:9186
 msgid "Generate patch"
 msgstr "Générer le patch"
 
-#: gitk:9188
 msgid "From:"
 msgstr "De :"
 
-#: gitk:9197
 msgid "To:"
 msgstr "À :"
 
-#: gitk:9206
 msgid "Reverse"
 msgstr "Inverser"
 
-#: gitk:9208 gitk:9418
 msgid "Output file:"
 msgstr "Fichier de sortie :"
 
-#: gitk:9214
 msgid "Generate"
 msgstr "Générer"
 
-#: gitk:9252
 msgid "Error creating patch:"
 msgstr "Erreur à la création du patch :"
 
-#: gitk:9275 gitk:9406 gitk:9463
 msgid "ID:"
 msgstr "ID :"
 
-#: gitk:9284
 msgid "Tag name:"
 msgstr "Nom de l'étiquette :"
 
-#: gitk:9287
 msgid "Tag message is optional"
 msgstr "Le message d'étiquette est optionnel"
 
-#: gitk:9289
 msgid "Tag message:"
 msgstr "Message d'étiquette :"
 
-#: gitk:9293 gitk:9472
 msgid "Create"
 msgstr "Créer"
 
-#: gitk:9311
 msgid "No tag name specified"
 msgstr "Aucun nom d'étiquette spécifié"
 
-#: gitk:9315
 #, tcl-format
 msgid "Tag \"%s\" already exists"
 msgstr "L'étiquette \"%s\" existe déjà"
 
-#: gitk:9325
 msgid "Error creating tag:"
 msgstr "Erreur à la création de l'étiquette :"
 
-#: gitk:9415
 msgid "Command:"
 msgstr "Commande :"
 
-#: gitk:9423
 msgid "Write"
 msgstr "Écrire"
 
-#: gitk:9441
 msgid "Error writing commit:"
 msgstr "Erreur à l'ecriture du commit :"
 
-#: gitk:9468
 msgid "Name:"
 msgstr "Nom :"
 
-#: gitk:9491
 msgid "Please specify a name for the new branch"
 msgstr "Veuillez spécifier un nom pour la nouvelle branche"
 
-#: gitk:9496
 #, tcl-format
 msgid "Branch '%s' already exists. Overwrite?"
 msgstr "La branche '%s' existe déjà. Écraser?"
 
-#: gitk:9563
 #, tcl-format
 msgid "Commit %s is already included in branch %s -- really re-apply it?"
 msgstr ""
 "Le Commit %s est déjà inclus dans la branche %s -- le ré-appliquer malgré "
 "tout?"
 
-#: gitk:9568
 msgid "Cherry-picking"
 msgstr "Picorer (Cherry-picking)"
 
-#: gitk:9577
 #, tcl-format
 msgid ""
 "Cherry-pick failed because of local changes to file '%s'.\n"
 "Please commit, reset or stash your changes and try again."
 msgstr ""
-"Le picorage (cherry-pick) a échouée à cause de modifications locales du fichier '%s'.\n"
-"Veuillez commiter, réinitialiser ou stasher vos changements et essayer de nouveau."
+"Le picorage (cherry-pick) a échouée à cause de modifications locales du "
+"fichier '%s'.\n"
+"Veuillez commiter, réinitialiser ou stasher vos changements et essayer de "
+"nouveau."
 
-#: gitk:9583
 msgid ""
 "Cherry-pick failed because of merge conflict.\n"
 "Do you wish to run git citool to resolve it?"
@@ -1066,27 +829,26 @@
 "Le picorage (cherry-pick) a échouée à cause d'un conflit lors d'une fusion.\n"
 "Souhaitez-vous exécuter git citool pour le résoudre ?"
 
-#: gitk:9599 gitk:9657
 msgid "No changes committed"
 msgstr "Aucune modification validée"
 
-#: gitk:9626
 #, tcl-format
 msgid "Commit %s is not included in branch %s -- really revert it?"
-msgstr "Le Commit %s n'est pas inclus dans la branche %s -- le défaire malgré tout?"
+msgstr ""
+"Le Commit %s n'est pas inclus dans la branche %s -- le défaire malgré tout?"
 
-#: gitk:9631
 msgid "Reverting"
 msgstr "Commit défait"
 
-#: gitk:9639
 #, tcl-format
 msgid ""
 "Revert failed because of local changes to the following files:%s Please "
 "commit, reset or stash  your changes and try again."
-msgstr "Échec en tentant de défaire le commit à cause de modifications locales des fichiers : %s. Veuillez valider, réinitialiser ou remiser vos modifications et essayer de nouveau."
+msgstr ""
+"Échec en tentant de défaire le commit à cause de modifications locales des "
+"fichiers : %s. Veuillez valider, réinitialiser ou remiser vos modifications "
+"et essayer de nouveau."
 
-#: gitk:9643
 msgid ""
 "Revert failed because of merge conflict.\n"
 " Do you wish to run git citool to resolve it?"
@@ -1094,30 +856,24 @@
 "Échec en tentant de défaire à cause d'un conflit de fusion.\n"
 "Souhaitez-vous exécuter git citool pour le résoudre ?"
 
-#: gitk:9686
 msgid "Confirm reset"
 msgstr "Confirmer la réinitialisation"
 
-#: gitk:9688
 #, tcl-format
 msgid "Reset branch %s to %s?"
 msgstr "Réinitialiser la branche %s à %s?"
 
-#: gitk:9690
 msgid "Reset type:"
 msgstr "Type de réinitialisation :"
 
-#: gitk:9693
 msgid "Soft: Leave working tree and index untouched"
 msgstr "Douce : Laisse le répertoire de travail et l'index intacts"
 
-#: gitk:9696
 msgid "Mixed: Leave working tree untouched, reset index"
 msgstr ""
 "Hybride : Laisse le répertoire de travail dans son état courant, "
 "réinitialise l'index"
 
-#: gitk:9699
 msgid ""
 "Hard: Reset working tree and index\n"
 "(discard ALL local changes)"
@@ -1125,20 +881,16 @@
 "Dure : Réinitialise le répertoire de travail et l'index\n"
 "(abandonne TOUTES les modifications locale)"
 
-#: gitk:9716
 msgid "Resetting"
 msgstr "Réinitialisation"
 
 # Fixme: Récupération est-il vraiment une mauvaise traduction?
-#: gitk:9776
 msgid "Checking out"
 msgstr "Extraction"
 
-#: gitk:9829
 msgid "Cannot delete the currently checked-out branch"
 msgstr "Impossible de supprimer la branche extraite"
 
-#: gitk:9835
 #, tcl-format
 msgid ""
 "The commits on branch %s aren't on any other branch.\n"
@@ -1147,16 +899,13 @@
 "Les commits de la branche %s ne sont dans aucune autre branche.\n"
 "Voulez-vous vraiment supprimer cette branche %s ?"
 
-#: gitk:9866
 #, tcl-format
 msgid "Tags and heads: %s"
 msgstr "Étiquettes et heads : %s"
 
-#: gitk:9883
 msgid "Filter"
 msgstr "Filtrer"
 
-#: gitk:10179
 msgid ""
 "Error reading commit topology information; branch and preceding/following "
 "tag information will be incomplete."
@@ -1165,202 +914,153 @@
 "informations sur les branches et les tags précédents/suivants seront "
 "incomplètes."
 
-#: gitk:11156
 msgid "Tag"
 msgstr "Étiquette"
 
-#: gitk:11160
 msgid "Id"
 msgstr "Id"
 
-#: gitk:11243
 msgid "Gitk font chooser"
 msgstr "Sélecteur de police de Gitk"
 
-#: gitk:11260
 msgid "B"
 msgstr "B"
 
-#: gitk:11263
 msgid "I"
 msgstr "I"
 
-#: gitk:11381
 msgid "Commit list display options"
 msgstr "Options d'affichage de la liste des commits"
 
-#: gitk:11384
 msgid "Maximum graph width (lines)"
 msgstr "Longueur maximum du graphe (lignes)"
 
 # FIXME : Traduction standard de "pane"?
-#: gitk:11388
 #, no-tcl-format
 msgid "Maximum graph width (% of pane)"
 msgstr "Largeur maximum du graphe (% du panneau)"
 
-#: gitk:11391
 msgid "Show local changes"
 msgstr "Montrer les modifications locales"
 
-#: gitk:11394
 msgid "Auto-select SHA1 (length)"
 msgstr "Sélection auto. du SHA1 (longueur)"
 
-#: gitk:11398
 msgid "Hide remote refs"
 msgstr "Cacher les refs distantes"
 
-#: gitk:11402
 msgid "Diff display options"
 msgstr "Options d'affichage des diff"
 
-#: gitk:11404
 msgid "Tab spacing"
 msgstr "Taille des tabulations"
 
-#: gitk:11407
 msgid "Display nearby tags/heads"
 msgstr "Afficher les tags les plus proches"
 
-#: gitk:11410
 msgid "Maximum # tags/heads to show"
 msgstr "Nombre maximum d'étiquettes/heads à afficher"
 
-#: gitk:11413
 msgid "Limit diffs to listed paths"
 msgstr "Limiter les différences aux chemins listés"
 
-#: gitk:11416
 msgid "Support per-file encodings"
 msgstr "Support pour un encodage des caractères par fichier"
 
-#: gitk:11422 gitk:11569
 msgid "External diff tool"
 msgstr "Outil diff externe"
 
-#: gitk:11423
 msgid "Choose..."
 msgstr "Choisir..."
 
-#: gitk:11428
 msgid "General options"
 msgstr "Options générales"
 
-#: gitk:11431
 msgid "Use themed widgets"
 msgstr "Utiliser des widgets en thème"
 
-#: gitk:11433
 msgid "(change requires restart)"
 msgstr "(la modification nécessite un redémarrage)"
 
-#: gitk:11435
 msgid "(currently unavailable)"
 msgstr "(non disponible actuellement)"
 
-#: gitk:11446
 msgid "Colors: press to choose"
 msgstr "Couleurs : cliquer pour choisir"
 
-#: gitk:11449
 msgid "Interface"
 msgstr "Interface"
 
-#: gitk:11450
 msgid "interface"
 msgstr "interface"
 
-#: gitk:11453
 msgid "Background"
 msgstr "Arrière-plan"
 
-#: gitk:11454 gitk:11484
 msgid "background"
 msgstr "arrière-plan"
 
-#: gitk:11457
 msgid "Foreground"
 msgstr "Premier plan"
 
-#: gitk:11458
 msgid "foreground"
 msgstr "premier plan"
 
-#: gitk:11461
 msgid "Diff: old lines"
 msgstr "Diff : anciennes lignes"
 
-#: gitk:11462
 msgid "diff old lines"
 msgstr "diff anciennes lignes"
 
-#: gitk:11466
 msgid "Diff: new lines"
 msgstr "Diff : nouvelles lignes"
 
-#: gitk:11467
 msgid "diff new lines"
 msgstr "diff nouvelles lignes"
 
-#: gitk:11471
 msgid "Diff: hunk header"
 msgstr "Diff : entête du hunk"
 
-#: gitk:11473
 msgid "diff hunk header"
 msgstr "diff : entête du hunk"
 
-#: gitk:11477
 msgid "Marked line bg"
 msgstr "Fond de la ligne marquée"
 
-#: gitk:11479
 msgid "marked line background"
 msgstr "Fond de la ligne marquée"
 
-#: gitk:11483
 msgid "Select bg"
 msgstr "Sélectionner le fond"
 
-#: gitk:11492
 msgid "Fonts: press to choose"
 msgstr "Polices : cliquer pour choisir"
 
-#: gitk:11494
 msgid "Main font"
 msgstr "Police principale"
 
-#: gitk:11495
 msgid "Diff display font"
 msgstr "Police d'affichage des diff"
 
-#: gitk:11496
 msgid "User interface font"
 msgstr "Police de l'interface utilisateur"
 
-#: gitk:11518
 msgid "Gitk preferences"
 msgstr "Préférences de Gitk"
 
-#: gitk:11527
 msgid "General"
 msgstr "Général"
 
-#: gitk:11528
 msgid "Colors"
 msgstr "Couleurs"
 
-#: gitk:11529
 msgid "Fonts"
 msgstr "Polices"
 
-#: gitk:11579
 #, tcl-format
 msgid "Gitk: choose color for %s"
 msgstr "Gitk : choisir la couleur de %s"
 
-#: gitk:12092
 msgid ""
 "Sorry, gitk cannot run with this version of Tcl/Tk.\n"
 " Gitk requires at least Tcl/Tk 8.4."
@@ -1368,16 +1068,13 @@
 "Désolé, gitk ne peut être exécuté avec cette version de Tcl/Tk.\n"
 " Gitk requiert Tcl/Tk version 8.4 ou supérieur."
 
-#: gitk:12302
 msgid "Cannot find a git repository here."
 msgstr "Impossible de trouver un dépôt git ici."
 
-#: gitk:12349
 #, tcl-format
 msgid "Ambiguous argument '%s': both revision and filename"
 msgstr "Argument '%s' ambigu : à la fois une révision et un nom de fichier"
 
-#: gitk:12361
 msgid "Bad arguments to gitk:"
 msgstr "Arguments invalides pour gitk :"
 
diff --git a/gitk-git/po/hu.po b/gitk-git/po/hu.po
index 79ec5a5..9ab3f96 100644
--- a/gitk-git/po/hu.po
+++ b/gitk-git/po/hu.po
@@ -6,7 +6,7 @@
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: git-gui\n"
+"Project-Id-Version: Gitk\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2015-05-17 14:32+1000\n"
 "PO-Revision-Date: 2009-12-14 14:04+0100\n"
@@ -17,32 +17,25 @@
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: gitk:140
 msgid "Couldn't get list of unmerged files:"
 msgstr "Nem sikerült letölteni az unmerged fájl listát:"
 
-#: gitk:212 gitk:2381
 msgid "Color words"
 msgstr ""
 
-#: gitk:217 gitk:2381 gitk:8220 gitk:8253
 msgid "Markup words"
 msgstr ""
 
-#: gitk:324
 msgid "Error parsing revisions:"
 msgstr "Hiba történt értelmezés közben:"
 
-#: gitk:380
 msgid "Error executing --argscmd command:"
 msgstr "Hiba történt a végrehajtáskor --argscmd parancs:"
 
-#: gitk:393
 msgid "No files selected: --merge specified but no files are unmerged."
 msgstr ""
 "Nincsen fájl kiválasztva: --merge megadve, de egyetlen fájl sem unmerged."
 
-#: gitk:396
 msgid ""
 "No files selected: --merge specified but no unmerged files are within file "
 "limit."
@@ -50,317 +43,237 @@
 "Nincsen fájl kiválasztva: --merge megadva, de nincsenek unmerged fájlok a "
 "fájlon belül limit."
 
-#: gitk:418 gitk:566
 msgid "Error executing git log:"
 msgstr "Hiba történt a git log végrehajtása közben:"
 
-#: gitk:436 gitk:582
 msgid "Reading"
 msgstr "Olvasás"
 
-#: gitk:496 gitk:4525
 msgid "Reading commits..."
 msgstr "Commitok olvasása ..."
 
-#: gitk:499 gitk:1637 gitk:4528
 msgid "No commits selected"
 msgstr "Nincsen commit kiválasztva"
 
-#: gitk:1445 gitk:4045 gitk:12432
 msgid "Command line"
 msgstr "Parancs sor"
 
-#: gitk:1511
 msgid "Can't parse git log output:"
 msgstr "Nem lehet értelmezni a git log kimenetét:"
 
-#: gitk:1740
 msgid "No commit information available"
 msgstr "Nincsen elérhető commit információ"
 
-#: gitk:1903 gitk:1932 gitk:4315 gitk:9669 gitk:11241 gitk:11521
 msgid "OK"
 msgstr "OK"
 
-#: gitk:1934 gitk:4317 gitk:9196 gitk:9275 gitk:9391 gitk:9440 gitk:9671
-#: gitk:11242 gitk:11522
 msgid "Cancel"
 msgstr "Visszavonás"
 
-#: gitk:2069
 msgid "&Update"
 msgstr "Frissités"
 
-#: gitk:2070
 msgid "&Reload"
 msgstr "Újratöltés"
 
-#: gitk:2071
 msgid "Reread re&ferences"
 msgstr "Referenciák újraolvasása"
 
-#: gitk:2072
 msgid "&List references"
 msgstr "Referenciák listázása"
 
-#: gitk:2074
 msgid "Start git &gui"
 msgstr "Git gui indítása"
 
-#: gitk:2076
 msgid "&Quit"
 msgstr "Kilépés"
 
-#: gitk:2068
 msgid "&File"
 msgstr "Fájl"
 
-#: gitk:2080
 msgid "&Preferences"
 msgstr "Beállítások"
 
-#: gitk:2079
 msgid "&Edit"
 msgstr "Szerkesztés"
 
-#: gitk:2084
 msgid "&New view..."
 msgstr "Új nézet ..."
 
-#: gitk:2085
 msgid "&Edit view..."
 msgstr "Nézet szerkesztése ..."
 
-#: gitk:2086
 msgid "&Delete view"
 msgstr "Nézet törlése"
 
-#: gitk:2088 gitk:4043
 msgid "&All files"
 msgstr "Minden fájl"
 
-#: gitk:2083 gitk:4067
 msgid "&View"
 msgstr "Nézet"
 
-#: gitk:2093 gitk:2103 gitk:3012
 msgid "&About gitk"
 msgstr "Gitk névjegy"
 
-#: gitk:2094 gitk:2108
 msgid "&Key bindings"
 msgstr "Billentyűkombináció"
 
-#: gitk:2092 gitk:2107
 msgid "&Help"
 msgstr "Segítség"
 
-#: gitk:2185 gitk:8652
 msgid "SHA1 ID:"
 msgstr "SHA1 ID:"
 
-#: gitk:2229
 msgid "Row"
 msgstr "Sor"
 
-#: gitk:2267
 msgid "Find"
 msgstr "Keresés"
 
-#: gitk:2295
 msgid "commit"
 msgstr "commit"
 
-#: gitk:2299 gitk:2301 gitk:4687 gitk:4710 gitk:4734 gitk:6755 gitk:6827
-#: gitk:6912
 msgid "containing:"
 msgstr "tartalmazás:"
 
-#: gitk:2302 gitk:3526 gitk:3531 gitk:4763
 msgid "touching paths:"
 msgstr "érintendő útvonalak:"
 
-#: gitk:2303 gitk:4777
 msgid "adding/removing string:"
 msgstr "string hozzáadása/törlése:"
 
-#: gitk:2304 gitk:4779
 msgid "changing lines matching:"
 msgstr ""
 
-#: gitk:2313 gitk:2315 gitk:4766
 msgid "Exact"
 msgstr "Pontos"
 
-#: gitk:2315 gitk:4854 gitk:6723
 msgid "IgnCase"
 msgstr "Kis/nagy betű nem számít"
 
-#: gitk:2315 gitk:4736 gitk:4852 gitk:6719
 msgid "Regexp"
 msgstr "Regexp"
 
-#: gitk:2317 gitk:2318 gitk:4874 gitk:4904 gitk:4911 gitk:6848 gitk:6916
 msgid "All fields"
 msgstr "Minden mező"
 
-#: gitk:2318 gitk:4871 gitk:4904 gitk:6786
 msgid "Headline"
 msgstr "Főcím"
 
-#: gitk:2319 gitk:4871 gitk:6786 gitk:6916 gitk:7389
 msgid "Comments"
 msgstr "Megjegyzések"
 
-#: gitk:2319 gitk:4871 gitk:4876 gitk:4911 gitk:6786 gitk:7324 gitk:8830
-#: gitk:8845
 msgid "Author"
 msgstr "Szerző"
 
-#: gitk:2319 gitk:4871 gitk:6786 gitk:7326
 msgid "Committer"
 msgstr "Commitoló"
 
-#: gitk:2350
 msgid "Search"
 msgstr "Keresés"
 
-#: gitk:2358
 msgid "Diff"
 msgstr "Diff"
 
-#: gitk:2360
 msgid "Old version"
 msgstr "Régi verzió"
 
-#: gitk:2362
 msgid "New version"
 msgstr "Új verzió"
 
-#: gitk:2364
 msgid "Lines of context"
 msgstr "Tartalmi sorok"
 
-#: gitk:2374
 msgid "Ignore space change"
 msgstr "Space váltás mellőzése"
 
-#: gitk:2378 gitk:2380 gitk:7959 gitk:8206
 msgid "Line diff"
 msgstr ""
 
-#: gitk:2445
 msgid "Patch"
 msgstr "Patch"
 
-#: gitk:2447
 msgid "Tree"
 msgstr "Tree"
 
-#: gitk:2617 gitk:2637
 msgid "Diff this -> selected"
 msgstr "Diff ezeket -> kiválasztott"
 
-#: gitk:2618 gitk:2638
 msgid "Diff selected -> this"
 msgstr "Diff kiválasztottakat -> ezt"
 
-#: gitk:2619 gitk:2639
 msgid "Make patch"
 msgstr "Patch készítése"
 
-#: gitk:2620 gitk:9254
 msgid "Create tag"
 msgstr "Tag készítése"
 
-#: gitk:2621 gitk:9371
 msgid "Write commit to file"
 msgstr "Commit fáljba írása"
 
-#: gitk:2622 gitk:9428
 msgid "Create new branch"
 msgstr "Új branch készítése"
 
-#: gitk:2623
 msgid "Cherry-pick this commit"
 msgstr "Cherry-pick erre a commitra"
 
-#: gitk:2624
 msgid "Reset HEAD branch to here"
 msgstr "HEAD branch újraindítása ide"
 
-#: gitk:2625
 msgid "Mark this commit"
 msgstr "Ezen commit megjelölése"
 
-#: gitk:2626
 msgid "Return to mark"
 msgstr "Visszatérés a megjelöléshez"
 
-#: gitk:2627
 msgid "Find descendant of this and mark"
 msgstr "Találd meg ezen utódokat és jelöld meg"
 
-#: gitk:2628
 msgid "Compare with marked commit"
 msgstr "Összehasonlítás a megjelölt commit-tal"
 
-#: gitk:2629 gitk:2640
 #, fuzzy
 msgid "Diff this -> marked commit"
 msgstr "Diff ezeket -> kiválasztott"
 
-#: gitk:2630 gitk:2641
 #, fuzzy
 msgid "Diff marked commit -> this"
 msgstr "Diff kiválasztottakat -> ezt"
 
-#: gitk:2631
 #, fuzzy
 msgid "Revert this commit"
 msgstr "Ezen commit megjelölése"
 
-#: gitk:2647
 msgid "Check out this branch"
 msgstr "Check out ezt a branchot"
 
-#: gitk:2648
 msgid "Remove this branch"
 msgstr "Töröld ezt a branch-ot"
 
-#: gitk:2649
 msgid "Copy branch name"
 msgstr ""
 
-#: gitk:2656
 msgid "Highlight this too"
 msgstr "Emeld ki ezt is"
 
-#: gitk:2657
 msgid "Highlight this only"
 msgstr "Csak ezt emeld ki"
 
-#: gitk:2658
 msgid "External diff"
 msgstr "Külső diff"
 
-#: gitk:2659
 msgid "Blame parent commit"
 msgstr "Blame szülő kommitra"
 
-#: gitk:2660
 msgid "Copy path"
 msgstr ""
 
-#: gitk:2667
 msgid "Show origin of this line"
 msgstr "Mutasd meg ennek a sornak az eredetét"
 
-#: gitk:2668
 msgid "Run git gui blame on this line"
 msgstr "Futtasd a git gui blame-t ezen a soron"
 
-#: gitk:3014
 #, fuzzy
 msgid ""
 "\n"
@@ -377,321 +290,249 @@
 "\n"
 "Használd és terjeszd a GNU General Public License feltételei mellett"
 
-#: gitk:3022 gitk:3089 gitk:9857
 msgid "Close"
 msgstr "Bezárás"
 
-#: gitk:3043
 msgid "Gitk key bindings"
 msgstr "Gitk-billentyű hozzárendelés"
 
-#: gitk:3046
 msgid "Gitk key bindings:"
 msgstr "Gitk-billentyű hozzaárendelés:"
 
-#: gitk:3048
 #, tcl-format
 msgid "<%s-Q>\t\tQuit"
 msgstr "<%s-Q>\t\tKilépés"
 
-#: gitk:3049
 #, fuzzy, tcl-format
 msgid "<%s-W>\t\tClose window"
 msgstr "<%s-F>\t\tKeresés"
 
-#: gitk:3050
 msgid "<Home>\t\tMove to first commit"
 msgstr "<Pos1>\t\tElső commithoz"
 
-#: gitk:3051
 msgid "<End>\t\tMove to last commit"
 msgstr "<Ende>\t\tUtolsó commithoz"
 
-#: gitk:3052
 #, fuzzy
 msgid "<Up>, p, k\tMove up one commit"
 msgstr "<Hoch>, p, i\tEgy committal feljebb"
 
-#: gitk:3053
 #, fuzzy
 msgid "<Down>, n, j\tMove down one commit"
 msgstr "<Runter>, n, k\tEgy committal lejjebb"
 
-#: gitk:3054
 #, fuzzy
 msgid "<Left>, z, h\tGo back in history list"
 msgstr "<Links>, z, j\tVissza a history listába"
 
-#: gitk:3055
 msgid "<Right>, x, l\tGo forward in history list"
 msgstr "<Rechts>, x, l\tElőre a history listába"
 
-#: gitk:3056
 #, tcl-format
 msgid "<%s-n>\tGo to n-th parent of current commit in history list"
 msgstr ""
 
-#: gitk:3057
 msgid "<PageUp>\tMove up one page in commit list"
 msgstr "<BildHoch>\tEgy lappal feljebb a commit listába"
 
-#: gitk:3058
 msgid "<PageDown>\tMove down one page in commit list"
 msgstr "<BildRunter>\tEgy lappal lejjebb a commit listába"
 
-#: gitk:3059
 #, tcl-format
 msgid "<%s-Home>\tScroll to top of commit list"
 msgstr "<%s-Pos1>\tGörgetés a commit lista tetejéhez"
 
-#: gitk:3060
 #, tcl-format
 msgid "<%s-End>\tScroll to bottom of commit list"
 msgstr "<%s-Ende>\tGörgetés a commit lista aljához"
 
-#: gitk:3061
 #, tcl-format
 msgid "<%s-Up>\tScroll commit list up one line"
 msgstr "<%s-Hoch>\tEgy sorral feljebb görgetés a commit listában"
 
-#: gitk:3062
 #, tcl-format
 msgid "<%s-Down>\tScroll commit list down one line"
 msgstr "<%s-Runter>\tEgy sorral lejjebb görgetés a commit listában"
 
-#: gitk:3063
 #, tcl-format
 msgid "<%s-PageUp>\tScroll commit list up one page"
 msgstr "<%s-BildHoch>\tEgy lappal feljebb görgetés a commit listában"
 
-#: gitk:3064
 #, tcl-format
 msgid "<%s-PageDown>\tScroll commit list down one page"
 msgstr "<%s-BildRunter>\tEgy sorral lejjebb görgetés a commit listában"
 
-#: gitk:3065
 msgid "<Shift-Up>\tFind backwards (upwards, later commits)"
 msgstr "<Umschalt-Hoch>\tKeresés visszafele (felfele, utolsó commitok)"
 
-#: gitk:3066
 msgid "<Shift-Down>\tFind forwards (downwards, earlier commits)"
 msgstr "<Umschalt-Runter>\tKeresés előre (lefelé; korábbi commitok)"
 
-#: gitk:3067
 msgid "<Delete>, b\tScroll diff view up one page"
 msgstr "<Entf>, b\t\tEgy lappal feljebb görgetés a diff nézetben"
 
-#: gitk:3068
 msgid "<Backspace>\tScroll diff view up one page"
 msgstr "<Löschtaste>\tEgy lappal feljebb görgetés a diff nézetben"
 
-#: gitk:3069
 msgid "<Space>\t\tScroll diff view down one page"
 msgstr "<Leertaste>\tEgy lappal lejjebb görgetés a diff nézetben"
 
-#: gitk:3070
 msgid "u\t\tScroll diff view up 18 lines"
 msgstr "u\t\t18 sorral felfelé görgetés diff nézetben"
 
-#: gitk:3071
 msgid "d\t\tScroll diff view down 18 lines"
 msgstr "d\t\t18 sorral lejjebb görgetés a diff nézetben"
 
-#: gitk:3072
 #, tcl-format
 msgid "<%s-F>\t\tFind"
 msgstr "<%s-F>\t\tKeresés"
 
-#: gitk:3073
 #, tcl-format
 msgid "<%s-G>\t\tMove to next find hit"
 msgstr "<%s-G>\t\tKövetkező találathoz"
 
-#: gitk:3074
 msgid "<Return>\tMove to next find hit"
 msgstr "<Eingabetaste>\tKövetkező találathoz"
 
-#: gitk:3075
 #, fuzzy
 msgid "g\t\tGo to commit"
 msgstr "<Ende>\t\tUtolsó commithoz"
 
-#: gitk:3076
 msgid "/\t\tFocus the search box"
 msgstr "/\t\tLépj a keresési mezőre"
 
-#: gitk:3077
 msgid "?\t\tMove to previous find hit"
 msgstr "?\t\tElőző találathoz"
 
-#: gitk:3078
 msgid "f\t\tScroll diff view to next file"
 msgstr "f\t\tKövetkező fájlra görgetés diff nézetben"
 
-#: gitk:3079
 #, tcl-format
 msgid "<%s-S>\t\tSearch for next hit in diff view"
 msgstr "<%s-S>\t\tKövetkező találatra keresés diff nézetben"
 
-#: gitk:3080
 #, tcl-format
 msgid "<%s-R>\t\tSearch for previous hit in diff view"
 msgstr "<%s-R>\t\tElőző találatra keresés diff nézetben"
 
-#: gitk:3081
 #, tcl-format
 msgid "<%s-KP+>\tIncrease font size"
 msgstr "<%s-Nummerblock-Plus>\tBetűméret növelése"
 
-#: gitk:3082
 #, tcl-format
 msgid "<%s-plus>\tIncrease font size"
 msgstr "<%s-Plus>\tBetűméret növelése"
 
-#: gitk:3083
 #, tcl-format
 msgid "<%s-KP->\tDecrease font size"
 msgstr "<%s-Nummernblock-Minus> Betűméret csökkentése"
 
-#: gitk:3084
 #, tcl-format
 msgid "<%s-minus>\tDecrease font size"
 msgstr "<%s-Minus>\tBetűméret csökkentése"
 
-#: gitk:3085
 msgid "<F5>\t\tUpdate"
 msgstr "<F5>\t\tFrissítés"
 
-#: gitk:3550 gitk:3559
 #, tcl-format
 msgid "Error creating temporary directory %s:"
 msgstr "Hiba történt az ideiglenes könyvtár létrehozása közben %s:"
 
-#: gitk:3572
 #, tcl-format
 msgid "Error getting \"%s\" from %s:"
 msgstr "Hiba történt \"%s\" letöltése közben %s-ről:"
 
-#: gitk:3635
 msgid "command failed:"
 msgstr "parancs hiba:"
 
-#: gitk:3784
 msgid "No such commit"
 msgstr "Nincs ilyen commit"
 
-#: gitk:3798
 msgid "git gui blame: command failed:"
 msgstr "git gui blame: parancs hiba:"
 
-#: gitk:3829
 #, tcl-format
 msgid "Couldn't read merge head: %s"
 msgstr "Nem sikerült a Merge head olvasása: %s"
 
-#: gitk:3837
 #, tcl-format
 msgid "Error reading index: %s"
 msgstr "Hiba történt az index olvasása közben: %s"
 
-#: gitk:3862
 #, tcl-format
 msgid "Couldn't start git blame: %s"
 msgstr "Nem sikerült a git blame indítása: %s"
 
-#: gitk:3865 gitk:6754
 msgid "Searching"
 msgstr "Keresés"
 
-#: gitk:3897
 #, tcl-format
 msgid "Error running git blame: %s"
 msgstr "Hiba történt a git blame futtatása közben: %s"
 
-#: gitk:3925
 #, tcl-format
 msgid "That line comes from commit %s,  which is not in this view"
 msgstr ""
 "A %s commitból származik az a sor, amelyik nem található ebben a nézetben"
 
-#: gitk:3939
 msgid "External diff viewer failed:"
 msgstr "Külső diff nézegető hiba:"
 
-#: gitk:4070
 msgid "Gitk view definition"
 msgstr "Gitk nézet meghatározása"
 
-#: gitk:4074
 msgid "Remember this view"
 msgstr "Maradj ennél a nézetnél"
 
-#: gitk:4075
 msgid "References (space separated list):"
 msgstr "Referenciák (szóközzel tagolt lista"
 
-#: gitk:4076
 msgid "Branches & tags:"
 msgstr "Branch-ek & tagek:"
 
-#: gitk:4077
 msgid "All refs"
 msgstr "Minden ref"
 
-#: gitk:4078
 msgid "All (local) branches"
 msgstr "Minden (helyi) branch"
 
-#: gitk:4079
 msgid "All tags"
 msgstr "Minden tag"
 
-#: gitk:4080
 msgid "All remote-tracking branches"
 msgstr "Minden távoli követő branch"
 
-#: gitk:4081
 msgid "Commit Info (regular expressions):"
 msgstr "Commit Infó (reguláris kifejezés):"
 
-#: gitk:4082
 msgid "Author:"
 msgstr "Szerző:"
 
-#: gitk:4083
 msgid "Committer:"
 msgstr "Commitoló:"
 
-#: gitk:4084
 msgid "Commit Message:"
 msgstr "Commit üzenet:"
 
-#: gitk:4085
 msgid "Matches all Commit Info criteria"
 msgstr "Egyezik minen Commit Infó feltétellel"
 
-#: gitk:4086
 #, fuzzy
 msgid "Matches no Commit Info criteria"
 msgstr "Egyezik minen Commit Infó feltétellel"
 
-#: gitk:4087
 msgid "Changes to Files:"
 msgstr "Fájl változások:"
 
-#: gitk:4088
 msgid "Fixed String"
 msgstr "Fix String"
 
-#: gitk:4089
 msgid "Regular Expression"
 msgstr "Reguláris kifejezés"
 
-#: gitk:4090
 msgid "Search string:"
 msgstr "Keresés szöveg:"
 
-#: gitk:4091
 msgid ""
 "Commit Dates (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 "
 "15:27:38\"):"
@@ -699,203 +540,155 @@
 "Commit Dátumok (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 "
 "15:27:38\"):"
 
-#: gitk:4092
 msgid "Since:"
 msgstr "Ettől:"
 
-#: gitk:4093
 msgid "Until:"
 msgstr "Eddig:"
 
-#: gitk:4094
 msgid "Limit and/or skip a number of revisions (positive integer):"
 msgstr "Limitálva és/vagy kihagyva egy adott számú revíziót (pozitív egész):"
 
-#: gitk:4095
 msgid "Number to show:"
 msgstr "Mutatandó szám:"
 
-#: gitk:4096
 msgid "Number to skip:"
 msgstr "Kihagyandó szám:"
 
-#: gitk:4097
 msgid "Miscellaneous options:"
 msgstr "Különféle opciók:"
 
-#: gitk:4098
 msgid "Strictly sort by date"
 msgstr "Szigorú rendezás dátum alapján"
 
-#: gitk:4099
 msgid "Mark branch sides"
 msgstr "Jelölje meg az ágakat"
 
-#: gitk:4100
 msgid "Limit to first parent"
 msgstr "Korlátozás az első szülőre"
 
-#: gitk:4101
 msgid "Simple history"
 msgstr "Egyszerű history"
 
-#: gitk:4102
 msgid "Additional arguments to git log:"
 msgstr "További argumentok a git log-hoz:"
 
-#: gitk:4103
 msgid "Enter files and directories to include, one per line:"
 msgstr "Fájlok és könyvtárak bejegyzése amiket tartalmaz, soronként:"
 
-#: gitk:4104
 msgid "Command to generate more commits to include:"
 msgstr "Parancs több tartalmazó commit generálására:"
 
-#: gitk:4228
 msgid "Gitk: edit view"
 msgstr "Gitk: szerkesztés nézet"
 
-#: gitk:4236
 msgid "-- criteria for selecting revisions"
 msgstr "-- kritériumok a revíziók kiválasztásához"
 
-#: gitk:4241
 msgid "View Name"
 msgstr "Nézet neve"
 
-#: gitk:4316
 msgid "Apply (F5)"
 msgstr "Alkalmaz (F5)"
 
-#: gitk:4354
 msgid "Error in commit selection arguments:"
 msgstr "Hiba történt a commit argumentumok kiválasztása közben:"
 
-#: gitk:4409 gitk:4462 gitk:4924 gitk:4938 gitk:6208 gitk:12373 gitk:12374
 msgid "None"
 msgstr "Keine"
 
-#: gitk:5021 gitk:5026
 msgid "Descendant"
 msgstr "Leszármazott"
 
-#: gitk:5022
 msgid "Not descendant"
 msgstr "Nem leszármazott"
 
-#: gitk:5029 gitk:5034
 msgid "Ancestor"
 msgstr "Előd"
 
-#: gitk:5030
 msgid "Not ancestor"
 msgstr "Nem előd"
 
-#: gitk:5324
 msgid "Local changes checked in to index but not committed"
 msgstr ""
 "Lokális változtatások, melyek be vannak téve az indexbe, de még nincsenek "
 "commitolva"
 
-#: gitk:5360
 msgid "Local uncommitted changes, not checked in to index"
 msgstr "Lokális nem commitolt változások, nincsenek betéve az indexbe"
 
-#: gitk:7134
 msgid "and many more"
 msgstr ""
 
-#: gitk:7137
 msgid "many"
 msgstr "sok"
 
-#: gitk:7328
 msgid "Tags:"
 msgstr "Tagek:"
 
-#: gitk:7345 gitk:7351 gitk:8825
 msgid "Parent"
 msgstr "Eltern"
 
-#: gitk:7356
 msgid "Child"
 msgstr "Gyerek"
 
-#: gitk:7365
 msgid "Branch"
 msgstr "Ág"
 
-#: gitk:7368
 msgid "Follows"
 msgstr "Következők"
 
-#: gitk:7371
 msgid "Precedes"
 msgstr "Megelőzők"
 
-#: gitk:7966
 #, tcl-format
 msgid "Error getting diffs: %s"
 msgstr "Hiba történt a diff-ek letöltése közben: %s"
 
-#: gitk:8650
 msgid "Goto:"
 msgstr "Menj:"
 
-#: gitk:8671
 #, tcl-format
 msgid "Short SHA1 id %s is ambiguous"
 msgstr "Rövid SHA1 id %s félreérthető"
 
-#: gitk:8678
 #, tcl-format
 msgid "Revision %s is not known"
 msgstr "A(z) %s revízió nem ismert"
 
-#: gitk:8688
 #, tcl-format
 msgid "SHA1 id %s is not known"
 msgstr "SHA1 id %s nem ismert"
 
-#: gitk:8690
 #, tcl-format
 msgid "Revision %s is not in the current view"
 msgstr "A(z) %s revízió nincs a jelenlegi nézetben"
 
-#: gitk:8832 gitk:8847
 msgid "Date"
 msgstr "Dátum"
 
-#: gitk:8835
 msgid "Children"
 msgstr "Gyerekek"
 
-#: gitk:8898
 #, tcl-format
 msgid "Reset %s branch to here"
 msgstr "Állítsd vissza a %s branch-ot ide"
 
-#: gitk:8900
 msgid "Detached head: can't reset"
 msgstr "Elkülönített head: nem lehet visszaállítani"
 
-#: gitk:9005 gitk:9011
 msgid "Skipping merge commit "
 msgstr "Merge commit kihagyása "
 
-#: gitk:9020 gitk:9025
 msgid "Error getting patch ID for "
 msgstr "Hiba történt a patch ID megszerzése közben a következőnél "
 
-#: gitk:9021 gitk:9026
 msgid " - stopping\n"
 msgstr " - abbahagyás\n"
 
-#: gitk:9031 gitk:9034 gitk:9042 gitk:9056 gitk:9065
 msgid "Commit "
 msgstr "Commit "
 
-#: gitk:9035
 msgid ""
 " is the same patch as\n"
 "       "
@@ -903,7 +696,6 @@
 " Ugyanaz a patch mint\n"
 "       "
 
-#: gitk:9043
 msgid ""
 " differs from\n"
 "       "
@@ -911,7 +703,6 @@
 " különbözik innentől\n"
 "       "
 
-#: gitk:9045
 msgid ""
 "Diff of commits:\n"
 "\n"
@@ -919,132 +710,102 @@
 "A commitok diffje:\n"
 "\n"
 
-#: gitk:9057 gitk:9066
 #, tcl-format
 msgid " has %s children - stopping\n"
 msgstr " %s gyereke van. abbahagyás\n"
 
-#: gitk:9085
 #, tcl-format
 msgid "Error writing commit to file: %s"
 msgstr "Hiba történt a commit fájlba írása közben: %s"
 
-#: gitk:9091
 #, tcl-format
 msgid "Error diffing commits: %s"
 msgstr "Hiba történt a commitok diffelése közben: %s"
 
-#: gitk:9137
 msgid "Top"
 msgstr "Teteje"
 
-#: gitk:9138
 msgid "From"
 msgstr "Innen"
 
-#: gitk:9143
 msgid "To"
 msgstr "Ide"
 
-#: gitk:9167
 msgid "Generate patch"
 msgstr "Patch generálása"
 
-#: gitk:9169
 msgid "From:"
 msgstr "Innen:"
 
-#: gitk:9178
 msgid "To:"
 msgstr "Ide:"
 
-#: gitk:9187
 msgid "Reverse"
 msgstr "Visszafele"
 
-#: gitk:9189 gitk:9385
 msgid "Output file:"
 msgstr "Kimeneti fájl:"
 
-#: gitk:9195
 msgid "Generate"
 msgstr "Generálás"
 
-#: gitk:9233
 msgid "Error creating patch:"
 msgstr "Hiba törtét a patch készítése közben:"
 
-#: gitk:9256 gitk:9373 gitk:9430
 msgid "ID:"
 msgstr "ID:"
 
-#: gitk:9265
 msgid "Tag name:"
 msgstr "Tag név:"
 
-#: gitk:9268
 msgid "Tag message is optional"
 msgstr ""
 
-#: gitk:9270
 #, fuzzy
 msgid "Tag message:"
 msgstr "Tag név:"
 
-#: gitk:9274 gitk:9439
 msgid "Create"
 msgstr "Létrehozás"
 
-#: gitk:9292
 msgid "No tag name specified"
 msgstr "A tag neve nincsen megadva"
 
-#: gitk:9296
 #, tcl-format
 msgid "Tag \"%s\" already exists"
 msgstr "%s Tag már létezik"
 
-#: gitk:9306
 msgid "Error creating tag:"
 msgstr "Hiba történt a tag létrehozása közben:"
 
-#: gitk:9382
 msgid "Command:"
 msgstr "Parancs:"
 
-#: gitk:9390
 msgid "Write"
 msgstr "Írás"
 
-#: gitk:9408
 msgid "Error writing commit:"
 msgstr "Hiba történt a commit írása közben:"
 
-#: gitk:9435
 msgid "Name:"
 msgstr "Név:"
 
-#: gitk:9458
 msgid "Please specify a name for the new branch"
 msgstr "Kérem adja meg a nevét az új branchhoz"
 
-#: gitk:9463
 #, tcl-format
 msgid "Branch '%s' already exists. Overwrite?"
 msgstr "%s branch már létezik. Felülírja?"
 
-#: gitk:9530
 #, tcl-format
 msgid "Commit %s is already included in branch %s -- really re-apply it?"
 msgstr ""
 "%s commit már benne van a %s branchban -- biztos hogy újra csinálja ?"
 "eintragen?"
 
-#: gitk:9535
 msgid "Cherry-picking"
 msgstr "Cherry-picking"
 
-#: gitk:9544
 #, tcl-format
 msgid ""
 "Cherry-pick failed because of local changes to file '%s'.\n"
@@ -1054,7 +815,6 @@
 "Kérem commitolja, indítsa újra vagy rejtse el a változtatásait és próbálja "
 "újra."
 
-#: gitk:9550
 msgid ""
 "Cherry-pick failed because of merge conflict.\n"
 "Do you wish to run git citool to resolve it?"
@@ -1062,23 +822,19 @@
 "Cherry-pick hiba történt merge konfliktus miatt.\n"
 "Kívánja futtatni a git citool-t a probléma megoldásához?"
 
-#: gitk:9566 gitk:9624
 msgid "No changes committed"
 msgstr "Nincsen változás commitolva"
 
-#: gitk:9593
 #, fuzzy, tcl-format
 msgid "Commit %s is not included in branch %s -- really revert it?"
 msgstr ""
 "%s commit már benne van a %s branchban -- biztos hogy újra csinálja ?"
 "eintragen?"
 
-#: gitk:9598
 #, fuzzy
 msgid "Reverting"
 msgstr "Újraindítás"
 
-#: gitk:9606
 #, fuzzy, tcl-format
 msgid ""
 "Revert failed because of local changes to the following files:%s Please "
@@ -1088,7 +844,6 @@
 "Kérem commitolja, indítsa újra vagy rejtse el a változtatásait és próbálja "
 "újra."
 
-#: gitk:9610
 #, fuzzy
 msgid ""
 "Revert failed because of merge conflict.\n"
@@ -1097,28 +852,22 @@
 "Cherry-pick hiba történt merge konfliktus miatt.\n"
 "Kívánja futtatni a git citool-t a probléma megoldásához?"
 
-#: gitk:9653
 msgid "Confirm reset"
 msgstr "Újraindítás megerősítése"
 
-#: gitk:9655
 #, tcl-format
 msgid "Reset branch %s to %s?"
 msgstr "Újraindítja a %s branchot %s-ig?"
 
-#: gitk:9657
 msgid "Reset type:"
 msgstr "Újraindítás típusa:"
 
-#: gitk:9660
 msgid "Soft: Leave working tree and index untouched"
 msgstr "Soft: Hagyd a working tree-t és az indexet érintetlenül"
 
-#: gitk:9663
 msgid "Mixed: Leave working tree untouched, reset index"
 msgstr "Kevert: Hagyd a working tree-t érintetlenül, töröld az indexet"
 
-#: gitk:9666
 msgid ""
 "Hard: Reset working tree and index\n"
 "(discard ALL local changes)"
@@ -1126,19 +875,15 @@
 "Hard: Indítsd újra a working tree-t és az indexet\n"
 "(MINDEN lokális változás eldobása)"
 
-#: gitk:9683
 msgid "Resetting"
 msgstr "Újraindítás"
 
-#: gitk:9743
 msgid "Checking out"
 msgstr "Kivesz"
 
-#: gitk:9796
 msgid "Cannot delete the currently checked-out branch"
 msgstr "Nem lehet a jelenleg kivett branch-ot törölni"
 
-#: gitk:9802
 #, tcl-format
 msgid ""
 "The commits on branch %s aren't on any other branch.\n"
@@ -1147,16 +892,13 @@
 "A %s branchon található commit nem található meg semelyik másik branchon.\n"
 "Tényleg törli a %s branchot?"
 
-#: gitk:9833
 #, tcl-format
 msgid "Tags and heads: %s"
 msgstr "Tagek és headek: %s"
 
-#: gitk:9850
 msgid "Filter"
 msgstr "Szűrő"
 
-#: gitk:10146
 msgid ""
 "Error reading commit topology information; branch and preceding/following "
 "tag information will be incomplete."
@@ -1164,204 +906,155 @@
 "Hiba történt a commit topológiai információ olvasása közben; branch ésa "
 "megelőző/következő információ nem lesz teljes."
 
-#: gitk:11123
 msgid "Tag"
 msgstr "Tag"
 
-#: gitk:11127
 msgid "Id"
 msgstr "Id"
 
-#: gitk:11210
 msgid "Gitk font chooser"
 msgstr "Gitk-betű kiválasztó"
 
-#: gitk:11227
 msgid "B"
 msgstr "F"
 
-#: gitk:11230
 msgid "I"
 msgstr "K"
 
-#: gitk:11348
 msgid "Commit list display options"
 msgstr "Commit lista kijelzési opciók"
 
-#: gitk:11351
 msgid "Maximum graph width (lines)"
 msgstr "Maximális grafikon szélesség (sorok)"
 
-#: gitk:11355
 #, no-tcl-format
 msgid "Maximum graph width (% of pane)"
 msgstr "Maximális grafikon szélesség (táble %-je)"
 
-#: gitk:11358
 msgid "Show local changes"
 msgstr "Mutasd a lokális változtatásokat"
 
-#: gitk:11361
 #, fuzzy
 msgid "Auto-select SHA1 (length)"
 msgstr "SHA1 Automatikus kiválasztása"
 
-#: gitk:11365
 msgid "Hide remote refs"
 msgstr "A távoli refek elrejtése"
 
-#: gitk:11369
 msgid "Diff display options"
 msgstr "Diff kijelző opciók"
 
-#: gitk:11371
 msgid "Tab spacing"
 msgstr "Tab sorköz"
 
-#: gitk:11374
 #, fuzzy
 msgid "Display nearby tags/heads"
 msgstr "Szomszédos tagek kijelzése"
 
-#: gitk:11377
 msgid "Maximum # tags/heads to show"
 msgstr ""
 
-#: gitk:11380
 msgid "Limit diffs to listed paths"
 msgstr "Korlátozott diffek a kilistázott útvonalakhoz"
 
-#: gitk:11383
 msgid "Support per-file encodings"
 msgstr "Fájlonkénti kódolás támgatása"
 
-#: gitk:11389 gitk:11536
 msgid "External diff tool"
 msgstr "Külső diff alkalmazás"
 
-#: gitk:11390
 msgid "Choose..."
 msgstr "Válaszd ..."
 
-#: gitk:11395
 msgid "General options"
 msgstr "Általános opciók"
 
-#: gitk:11398
 msgid "Use themed widgets"
 msgstr "Témázott vezérlők használata"
 
-#: gitk:11400
 msgid "(change requires restart)"
 msgstr "(a változás újraindítást igényel)"
 
-#: gitk:11402
 msgid "(currently unavailable)"
 msgstr "(jelenleg nem elérhető)"
 
-#: gitk:11413
 msgid "Colors: press to choose"
 msgstr "Színek: nyomja meg a kiválasztáshoz"
 
-#: gitk:11416
 msgid "Interface"
 msgstr "Interfész"
 
-#: gitk:11417
 msgid "interface"
 msgstr "interfész"
 
-#: gitk:11420
 msgid "Background"
 msgstr "Háttér"
 
-#: gitk:11421 gitk:11451
 msgid "background"
 msgstr "háttér"
 
-#: gitk:11424
 msgid "Foreground"
 msgstr "Előtér"
 
-#: gitk:11425
 msgid "foreground"
 msgstr "előtér"
 
-#: gitk:11428
 msgid "Diff: old lines"
 msgstr "Diff: régi sorok"
 
-#: gitk:11429
 msgid "diff old lines"
 msgstr "diff régi sorok"
 
-#: gitk:11433
 msgid "Diff: new lines"
 msgstr "Diff: új sorok"
 
-#: gitk:11434
 msgid "diff new lines"
 msgstr "diff - új sorok"
 
-#: gitk:11438
 msgid "Diff: hunk header"
 msgstr "Diff: nagy headerök"
 
-#: gitk:11440
 msgid "diff hunk header"
 msgstr "diff - nagy headerök"
 
-#: gitk:11444
 msgid "Marked line bg"
 msgstr "Megjelölt sor háttér"
 
-#: gitk:11446
 msgid "marked line background"
 msgstr "megjelölt sor háttér"
 
-#: gitk:11450
 msgid "Select bg"
 msgstr "Válasszon hátteret"
 
-#: gitk:11459
 msgid "Fonts: press to choose"
 msgstr "Betű: nyomja meg a kiválasztáshoz"
 
-#: gitk:11461
 msgid "Main font"
 msgstr "Fő betű"
 
-#: gitk:11462
 msgid "Diff display font"
 msgstr "Diff kijelző betű"
 
-#: gitk:11463
 msgid "User interface font"
 msgstr "Felhasználói interfész betű"
 
-#: gitk:11485
 msgid "Gitk preferences"
 msgstr "Gitk beállítások"
 
-#: gitk:11494
 #, fuzzy
 msgid "General"
 msgstr "Generálás"
 
-#: gitk:11495
 msgid "Colors"
 msgstr ""
 
-#: gitk:11496
 msgid "Fonts"
 msgstr ""
 
-#: gitk:11546
 #, tcl-format
 msgid "Gitk: choose color for %s"
 msgstr "Gitk: válasszon színt a %s-ra"
 
-#: gitk:12059
 msgid ""
 "Sorry, gitk cannot run with this version of Tcl/Tk.\n"
 " Gitk requires at least Tcl/Tk 8.4."
@@ -1369,16 +1062,13 @@
 "Sajnáljuk, de a gitk nem futtatható ezzel a Tcl/Tk verzióval.\n"
 "Gitk futtatásához legalább Tcl/Tk 8.4 szükséges."
 
-#: gitk:12269
 msgid "Cannot find a git repository here."
 msgstr "Nem találhatü git repository itt."
 
-#: gitk:12316
 #, tcl-format
 msgid "Ambiguous argument '%s': both revision and filename"
 msgstr "Félreérthető argumentum '%s': revízió és fájlnév is"
 
-#: gitk:12328
 msgid "Bad arguments to gitk:"
 msgstr "Rossz gitk argumentumok:"
 
diff --git a/gitk-git/po/it.po b/gitk-git/po/it.po
index b58d23e..aa34a34 100644
--- a/gitk-git/po/it.po
+++ b/gitk-git/po/it.po
@@ -6,7 +6,7 @@
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: gitk\n"
+"Project-Id-Version: Gitk\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2015-05-17 14:32+1000\n"
 "PO-Revision-Date: 2010-01-28 18:41+0100\n"
@@ -17,33 +17,26 @@
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: gitk:140
 msgid "Couldn't get list of unmerged files:"
 msgstr "Impossibile ottenere l'elenco dei file in attesa di fusione:"
 
-#: gitk:212 gitk:2381
 msgid "Color words"
 msgstr ""
 
-#: gitk:217 gitk:2381 gitk:8220 gitk:8253
 msgid "Markup words"
 msgstr ""
 
-#: gitk:324
 msgid "Error parsing revisions:"
 msgstr "Errore nella lettura delle revisioni:"
 
-#: gitk:380
 msgid "Error executing --argscmd command:"
 msgstr "Errore nell'esecuzione del comando specificato con --argscmd:"
 
-#: gitk:393
 msgid "No files selected: --merge specified but no files are unmerged."
 msgstr ""
 "Nessun file selezionato: è stata specificata l'opzione --merge ma non ci "
 "sono file in attesa di fusione."
 
-#: gitk:396
 msgid ""
 "No files selected: --merge specified but no unmerged files are within file "
 "limit."
@@ -51,317 +44,237 @@
 "Nessun file selezionato: è stata specificata l'opzione --merge ma i file "
 "specificati non sono in attesa di fusione."
 
-#: gitk:418 gitk:566
 msgid "Error executing git log:"
 msgstr "Errore nell'esecuzione di git log:"
 
-#: gitk:436 gitk:582
 msgid "Reading"
 msgstr "Lettura in corso"
 
-#: gitk:496 gitk:4525
 msgid "Reading commits..."
 msgstr "Lettura delle revisioni in corso..."
 
-#: gitk:499 gitk:1637 gitk:4528
 msgid "No commits selected"
 msgstr "Nessuna revisione selezionata"
 
-#: gitk:1445 gitk:4045 gitk:12432
 msgid "Command line"
 msgstr "Linea di comando"
 
-#: gitk:1511
 msgid "Can't parse git log output:"
 msgstr "Impossibile elaborare i dati di git log:"
 
-#: gitk:1740
 msgid "No commit information available"
 msgstr "Nessuna informazione disponibile sulle revisioni"
 
-#: gitk:1903 gitk:1932 gitk:4315 gitk:9669 gitk:11241 gitk:11521
 msgid "OK"
 msgstr "OK"
 
-#: gitk:1934 gitk:4317 gitk:9196 gitk:9275 gitk:9391 gitk:9440 gitk:9671
-#: gitk:11242 gitk:11522
 msgid "Cancel"
 msgstr "Annulla"
 
-#: gitk:2069
 msgid "&Update"
 msgstr "Aggiorna"
 
-#: gitk:2070
 msgid "&Reload"
 msgstr "Ricarica"
 
-#: gitk:2071
 msgid "Reread re&ferences"
 msgstr "Rileggi riferimenti"
 
-#: gitk:2072
 msgid "&List references"
 msgstr "Elenca riferimenti"
 
-#: gitk:2074
 msgid "Start git &gui"
 msgstr "Avvia git gui"
 
-#: gitk:2076
 msgid "&Quit"
 msgstr "Esci"
 
-#: gitk:2068
 msgid "&File"
 msgstr "&File"
 
-#: gitk:2080
 msgid "&Preferences"
 msgstr "Preferenze"
 
-#: gitk:2079
 msgid "&Edit"
 msgstr "Modifica"
 
-#: gitk:2084
 msgid "&New view..."
 msgstr "Nuova vista..."
 
-#: gitk:2085
 msgid "&Edit view..."
 msgstr "Modifica vista..."
 
-#: gitk:2086
 msgid "&Delete view"
 msgstr "Elimina vista"
 
-#: gitk:2088 gitk:4043
 msgid "&All files"
 msgstr "Tutti i file"
 
-#: gitk:2083 gitk:4067
 msgid "&View"
 msgstr "Vista"
 
-#: gitk:2093 gitk:2103 gitk:3012
 msgid "&About gitk"
 msgstr "Informazioni su gitk"
 
-#: gitk:2094 gitk:2108
 msgid "&Key bindings"
 msgstr "Scorciatoie da tastiera"
 
-#: gitk:2092 gitk:2107
 msgid "&Help"
 msgstr "Aiuto"
 
-#: gitk:2185 gitk:8652
 msgid "SHA1 ID:"
 msgstr "SHA1 ID:"
 
-#: gitk:2229
 msgid "Row"
 msgstr "Riga"
 
-#: gitk:2267
 msgid "Find"
 msgstr "Trova"
 
-#: gitk:2295
 msgid "commit"
 msgstr "revisione"
 
-#: gitk:2299 gitk:2301 gitk:4687 gitk:4710 gitk:4734 gitk:6755 gitk:6827
-#: gitk:6912
 msgid "containing:"
 msgstr "contenente:"
 
-#: gitk:2302 gitk:3526 gitk:3531 gitk:4763
 msgid "touching paths:"
 msgstr "che riguarda i percorsi:"
 
-#: gitk:2303 gitk:4777
 msgid "adding/removing string:"
 msgstr "che aggiunge/rimuove la stringa:"
 
-#: gitk:2304 gitk:4779
 msgid "changing lines matching:"
 msgstr ""
 
-#: gitk:2313 gitk:2315 gitk:4766
 msgid "Exact"
 msgstr "Esatto"
 
-#: gitk:2315 gitk:4854 gitk:6723
 msgid "IgnCase"
 msgstr ""
 
-#: gitk:2315 gitk:4736 gitk:4852 gitk:6719
 msgid "Regexp"
 msgstr ""
 
-#: gitk:2317 gitk:2318 gitk:4874 gitk:4904 gitk:4911 gitk:6848 gitk:6916
 msgid "All fields"
 msgstr "Tutti i campi"
 
-#: gitk:2318 gitk:4871 gitk:4904 gitk:6786
 msgid "Headline"
 msgstr "Titolo"
 
-#: gitk:2319 gitk:4871 gitk:6786 gitk:6916 gitk:7389
 msgid "Comments"
 msgstr "Commenti"
 
-#: gitk:2319 gitk:4871 gitk:4876 gitk:4911 gitk:6786 gitk:7324 gitk:8830
-#: gitk:8845
 msgid "Author"
 msgstr "Autore"
 
-#: gitk:2319 gitk:4871 gitk:6786 gitk:7326
 msgid "Committer"
 msgstr "Revisione creata da"
 
-#: gitk:2350
 msgid "Search"
 msgstr "Cerca"
 
-#: gitk:2358
 msgid "Diff"
 msgstr ""
 
-#: gitk:2360
 msgid "Old version"
 msgstr "Vecchia versione"
 
-#: gitk:2362
 msgid "New version"
 msgstr "Nuova versione"
 
-#: gitk:2364
 msgid "Lines of context"
 msgstr "Linee di contesto"
 
-#: gitk:2374
 msgid "Ignore space change"
 msgstr "Ignora modifiche agli spazi"
 
-#: gitk:2378 gitk:2380 gitk:7959 gitk:8206
 msgid "Line diff"
 msgstr ""
 
-#: gitk:2445
 msgid "Patch"
 msgstr "Modifiche"
 
-#: gitk:2447
 msgid "Tree"
 msgstr "Directory"
 
-#: gitk:2617 gitk:2637
 msgid "Diff this -> selected"
 msgstr "Diff questo -> selezionato"
 
-#: gitk:2618 gitk:2638
 msgid "Diff selected -> this"
 msgstr "Diff selezionato -> questo"
 
-#: gitk:2619 gitk:2639
 msgid "Make patch"
 msgstr "Crea patch"
 
-#: gitk:2620 gitk:9254
 msgid "Create tag"
 msgstr "Crea etichetta"
 
-#: gitk:2621 gitk:9371
 msgid "Write commit to file"
 msgstr "Scrivi revisione in un file"
 
-#: gitk:2622 gitk:9428
 msgid "Create new branch"
 msgstr "Crea un nuovo ramo"
 
-#: gitk:2623
 msgid "Cherry-pick this commit"
 msgstr "Porta questa revisione in cima al ramo attuale"
 
-#: gitk:2624
 msgid "Reset HEAD branch to here"
 msgstr "Aggiorna il ramo HEAD a questa revisione"
 
-#: gitk:2625
 msgid "Mark this commit"
 msgstr "Segna questa revisione"
 
-#: gitk:2626
 msgid "Return to mark"
 msgstr "Torna alla revisione segnata"
 
-#: gitk:2627
 msgid "Find descendant of this and mark"
 msgstr "Trova il discendente di questa revisione e di quella segnata"
 
-#: gitk:2628
 msgid "Compare with marked commit"
 msgstr "Confronta con la revisione segnata"
 
-#: gitk:2629 gitk:2640
 #, fuzzy
 msgid "Diff this -> marked commit"
 msgstr "Diff questo -> selezionato"
 
-#: gitk:2630 gitk:2641
 #, fuzzy
 msgid "Diff marked commit -> this"
 msgstr "Diff selezionato -> questo"
 
-#: gitk:2631
 #, fuzzy
 msgid "Revert this commit"
 msgstr "Segna questa revisione"
 
-#: gitk:2647
 msgid "Check out this branch"
 msgstr "Attiva questo ramo"
 
-#: gitk:2648
 msgid "Remove this branch"
 msgstr "Elimina questo ramo"
 
-#: gitk:2649
 msgid "Copy branch name"
 msgstr ""
 
-#: gitk:2656
 msgid "Highlight this too"
 msgstr "Evidenzia anche questo"
 
-#: gitk:2657
 msgid "Highlight this only"
 msgstr "Evidenzia solo questo"
 
-#: gitk:2658
 msgid "External diff"
 msgstr "Visualizza differenze in un altro programma"
 
-#: gitk:2659
 msgid "Blame parent commit"
 msgstr "Annota la revisione precedente"
 
-#: gitk:2660
 msgid "Copy path"
 msgstr ""
 
-#: gitk:2667
 msgid "Show origin of this line"
 msgstr "Mostra la provenienza di questa riga"
 
-#: gitk:2668
 msgid "Run git gui blame on this line"
 msgstr "Esegui git gui blame su questa riga"
 
-#: gitk:3014
 #, fuzzy
 msgid ""
 "\n"
@@ -379,321 +292,249 @@
 "Utilizzo e redistribuzione permessi sotto i termini della GNU General Public "
 "License"
 
-#: gitk:3022 gitk:3089 gitk:9857
 msgid "Close"
 msgstr "Chiudi"
 
-#: gitk:3043
 msgid "Gitk key bindings"
 msgstr "Scorciatoie da tastiera di Gitk"
 
-#: gitk:3046
 msgid "Gitk key bindings:"
 msgstr "Scorciatoie da tastiera di Gitk:"
 
-#: gitk:3048
 #, tcl-format
 msgid "<%s-Q>\t\tQuit"
 msgstr "<%s-Q>\t\tEsci"
 
-#: gitk:3049
 #, fuzzy, tcl-format
 msgid "<%s-W>\t\tClose window"
 msgstr "<%s-F>\t\tTrova"
 
-#: gitk:3050
 msgid "<Home>\t\tMove to first commit"
 msgstr "<Home>\t\tVai alla prima revisione"
 
-#: gitk:3051
 msgid "<End>\t\tMove to last commit"
 msgstr "<End>\t\tVai all'ultima revisione"
 
-#: gitk:3052
 #, fuzzy
 msgid "<Up>, p, k\tMove up one commit"
 msgstr "<Su>, p, i\tVai più in alto di una revisione"
 
-#: gitk:3053
 #, fuzzy
 msgid "<Down>, n, j\tMove down one commit"
 msgstr "<Giù>, n, k\tVai più in basso di una revisione"
 
-#: gitk:3054
 #, fuzzy
 msgid "<Left>, z, h\tGo back in history list"
 msgstr "<Sinistra>, z, j\tTorna indietro nella cronologia"
 
-#: gitk:3055
 msgid "<Right>, x, l\tGo forward in history list"
 msgstr "<Destra>, x, l\tVai avanti nella cronologia"
 
-#: gitk:3056
 #, tcl-format
 msgid "<%s-n>\tGo to n-th parent of current commit in history list"
 msgstr ""
 
-#: gitk:3057
 msgid "<PageUp>\tMove up one page in commit list"
 msgstr "<PaginaSu>\tVai più in alto di una pagina nella lista delle revisioni"
 
-#: gitk:3058
 msgid "<PageDown>\tMove down one page in commit list"
 msgstr ""
 "<PaginaGiù>\tVai più in basso di una pagina nella lista delle revisioni"
 
-#: gitk:3059
 #, tcl-format
 msgid "<%s-Home>\tScroll to top of commit list"
 msgstr "<%s-Home>\tScorri alla cima della lista delle revisioni"
 
-#: gitk:3060
 #, tcl-format
 msgid "<%s-End>\tScroll to bottom of commit list"
 msgstr "<%s-End>\tScorri alla fine della lista delle revisioni"
 
-#: gitk:3061
 #, tcl-format
 msgid "<%s-Up>\tScroll commit list up one line"
 msgstr "<%s-Su>\tScorri la lista delle revisioni in alto di una riga"
 
-#: gitk:3062
 #, tcl-format
 msgid "<%s-Down>\tScroll commit list down one line"
 msgstr "<%s-Giù>\tScorri la lista delle revisioni in basso di una riga"
 
-#: gitk:3063
 #, tcl-format
 msgid "<%s-PageUp>\tScroll commit list up one page"
 msgstr "<%s-PaginaSu>\tScorri la lista delle revisioni in alto di una pagina"
 
-#: gitk:3064
 #, tcl-format
 msgid "<%s-PageDown>\tScroll commit list down one page"
 msgstr "<%s-PaginaGiù>\tScorri la lista delle revisioni in basso di una pagina"
 
-#: gitk:3065
 msgid "<Shift-Up>\tFind backwards (upwards, later commits)"
 msgstr "<Shift-Su>\tTrova all'indietro (verso l'alto, revisioni successive)"
 
-#: gitk:3066
 msgid "<Shift-Down>\tFind forwards (downwards, earlier commits)"
 msgstr "<Shift-Giù>\tTrova in avanti (verso il basso, revisioni precedenti)"
 
-#: gitk:3067
 msgid "<Delete>, b\tScroll diff view up one page"
 msgstr "<Delete>, b\tScorri la vista delle differenze in alto di una pagina"
 
-#: gitk:3068
 msgid "<Backspace>\tScroll diff view up one page"
 msgstr "<Backspace>\tScorri la vista delle differenze in alto di una pagina"
 
-#: gitk:3069
 msgid "<Space>\t\tScroll diff view down one page"
 msgstr "<Spazio>\t\tScorri la vista delle differenze in basso di una pagina"
 
-#: gitk:3070
 msgid "u\t\tScroll diff view up 18 lines"
 msgstr "u\t\tScorri la vista delle differenze in alto di 18 linee"
 
-#: gitk:3071
 msgid "d\t\tScroll diff view down 18 lines"
 msgstr "d\t\tScorri la vista delle differenze in basso di 18 linee"
 
-#: gitk:3072
 #, tcl-format
 msgid "<%s-F>\t\tFind"
 msgstr "<%s-F>\t\tTrova"
 
-#: gitk:3073
 #, tcl-format
 msgid "<%s-G>\t\tMove to next find hit"
 msgstr "<%s-G>\t\tTrova in avanti"
 
-#: gitk:3074
 msgid "<Return>\tMove to next find hit"
 msgstr "<Invio>\tTrova in avanti"
 
-#: gitk:3075
 #, fuzzy
 msgid "g\t\tGo to commit"
 msgstr "<End>\t\tVai all'ultima revisione"
 
-#: gitk:3076
 msgid "/\t\tFocus the search box"
 msgstr "/\t\tCursore nel box di ricerca"
 
-#: gitk:3077
 msgid "?\t\tMove to previous find hit"
 msgstr "?\t\tTrova all'indietro"
 
-#: gitk:3078
 msgid "f\t\tScroll diff view to next file"
 msgstr "f\t\tScorri la vista delle differenze al file successivo"
 
-#: gitk:3079
 #, tcl-format
 msgid "<%s-S>\t\tSearch for next hit in diff view"
 msgstr "<%s-S>\t\tCerca in avanti nella vista delle differenze"
 
-#: gitk:3080
 #, tcl-format
 msgid "<%s-R>\t\tSearch for previous hit in diff view"
 msgstr "<%s-R>\t\tCerca all'indietro nella vista delle differenze"
 
-#: gitk:3081
 #, tcl-format
 msgid "<%s-KP+>\tIncrease font size"
 msgstr "<%s-KP+>\tAumenta dimensione carattere"
 
-#: gitk:3082
 #, tcl-format
 msgid "<%s-plus>\tIncrease font size"
 msgstr "<%s-più>\tAumenta dimensione carattere"
 
-#: gitk:3083
 #, tcl-format
 msgid "<%s-KP->\tDecrease font size"
 msgstr "<%s-KP->\tDiminuisci dimensione carattere"
 
-#: gitk:3084
 #, tcl-format
 msgid "<%s-minus>\tDecrease font size"
 msgstr "<%s-meno>\tDiminuisci dimensione carattere"
 
-#: gitk:3085
 msgid "<F5>\t\tUpdate"
 msgstr "<F5>\t\tAggiorna"
 
-#: gitk:3550 gitk:3559
 #, tcl-format
 msgid "Error creating temporary directory %s:"
 msgstr "Errore durante la creazione della directory temporanea %s:"
 
-#: gitk:3572
 #, tcl-format
 msgid "Error getting \"%s\" from %s:"
 msgstr "Errore nella lettura di \"%s\" da %s:"
 
-#: gitk:3635
 msgid "command failed:"
 msgstr "impossibile eseguire il comando:"
 
-#: gitk:3784
 msgid "No such commit"
 msgstr "Revisione inesistente"
 
-#: gitk:3798
 msgid "git gui blame: command failed:"
 msgstr "git gui blame: impossibile eseguire il comando:"
 
-#: gitk:3829
 #, tcl-format
 msgid "Couldn't read merge head: %s"
 msgstr "Impossibile leggere merge head: %s"
 
-#: gitk:3837
 #, tcl-format
 msgid "Error reading index: %s"
 msgstr "Errore nella lettura dell'indice: %s"
 
-#: gitk:3862
 #, tcl-format
 msgid "Couldn't start git blame: %s"
 msgstr "Impossibile eseguire git blame: %s"
 
-#: gitk:3865 gitk:6754
 msgid "Searching"
 msgstr "Ricerca in corso"
 
-#: gitk:3897
 #, tcl-format
 msgid "Error running git blame: %s"
 msgstr "Errore nell'esecuzione di git blame: %s"
 
-#: gitk:3925
 #, tcl-format
 msgid "That line comes from commit %s,  which is not in this view"
 msgstr "Quella riga proviene dalla revisione %s, non presente in questa vista"
 
-#: gitk:3939
 msgid "External diff viewer failed:"
 msgstr "Impossibile eseguire il visualizzatore di differenze:"
 
-#: gitk:4070
 msgid "Gitk view definition"
 msgstr "Scelta vista Gitk"
 
-#: gitk:4074
 msgid "Remember this view"
 msgstr "Ricorda questa vista"
 
-#: gitk:4075
 msgid "References (space separated list):"
 msgstr "Riferimenti (lista di elementi separati da spazi)"
 
-#: gitk:4076
 msgid "Branches & tags:"
 msgstr "Rami ed etichette"
 
-#: gitk:4077
 msgid "All refs"
 msgstr "Tutti i riferimenti"
 
-#: gitk:4078
 msgid "All (local) branches"
 msgstr "Tutti i rami (locali)"
 
-#: gitk:4079
 msgid "All tags"
 msgstr "Tutte le etichette"
 
-#: gitk:4080
 msgid "All remote-tracking branches"
 msgstr "Tutti i rami remoti"
 
-#: gitk:4081
 msgid "Commit Info (regular expressions):"
 msgstr "Informazioni sulla revisione (espressioni regolari):"
 
-#: gitk:4082
 msgid "Author:"
 msgstr "Autore:"
 
-#: gitk:4083
 msgid "Committer:"
 msgstr "Revisione creata da:"
 
-#: gitk:4084
 msgid "Commit Message:"
 msgstr "Messaggio di revisione:"
 
-#: gitk:4085
 msgid "Matches all Commit Info criteria"
 msgstr "Risponde a tutti i criteri di ricerca sulle revisioni"
 
-#: gitk:4086
 #, fuzzy
 msgid "Matches no Commit Info criteria"
 msgstr "Risponde a tutti i criteri di ricerca sulle revisioni"
 
-#: gitk:4087
 msgid "Changes to Files:"
 msgstr "Modifiche ai file:"
 
-#: gitk:4088
 msgid "Fixed String"
 msgstr "Stringa fissa"
 
-#: gitk:4089
 msgid "Regular Expression"
 msgstr "Espressione regolare"
 
-#: gitk:4090
 msgid "Search string:"
 msgstr "Cerca stringa:"
 
-#: gitk:4091
 msgid ""
 "Commit Dates (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 "
 "15:27:38\"):"
@@ -701,201 +542,153 @@
 "Date di revisione (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, "
 "2009 15:27:38\"):"
 
-#: gitk:4092
 msgid "Since:"
 msgstr "Da:"
 
-#: gitk:4093
 msgid "Until:"
 msgstr "A:"
 
-#: gitk:4094
 msgid "Limit and/or skip a number of revisions (positive integer):"
 msgstr "Limita e/o salta N revisioni (intero positivo):"
 
-#: gitk:4095
 msgid "Number to show:"
 msgstr "Numero di revisioni da mostrare:"
 
-#: gitk:4096
 msgid "Number to skip:"
 msgstr "Numero di revisioni da saltare:"
 
-#: gitk:4097
 msgid "Miscellaneous options:"
 msgstr "Altre opzioni:"
 
-#: gitk:4098
 msgid "Strictly sort by date"
 msgstr "Ordina solo per data"
 
-#: gitk:4099
 msgid "Mark branch sides"
 msgstr "Segna i lati del ramo"
 
-#: gitk:4100
 msgid "Limit to first parent"
 msgstr "Limita al primo genitore"
 
-#: gitk:4101
 msgid "Simple history"
 msgstr "Cronologia semplificata"
 
-#: gitk:4102
 msgid "Additional arguments to git log:"
 msgstr "Ulteriori argomenti da passare a git log:"
 
-#: gitk:4103
 msgid "Enter files and directories to include, one per line:"
 msgstr "Inserire file e directory da includere, uno per riga:"
 
-#: gitk:4104
 msgid "Command to generate more commits to include:"
 msgstr "Comando che genera altre revisioni da visualizzare:"
 
-#: gitk:4228
 msgid "Gitk: edit view"
 msgstr "Gitk: modifica vista"
 
-#: gitk:4236
 msgid "-- criteria for selecting revisions"
 msgstr "-- criteri per la scelta delle revisioni"
 
-#: gitk:4241
 msgid "View Name"
 msgstr "Nome vista"
 
-#: gitk:4316
 msgid "Apply (F5)"
 msgstr "Applica (F5)"
 
-#: gitk:4354
 msgid "Error in commit selection arguments:"
 msgstr "Errore negli argomenti di selezione delle revisioni:"
 
-#: gitk:4409 gitk:4462 gitk:4924 gitk:4938 gitk:6208 gitk:12373 gitk:12374
 msgid "None"
 msgstr "Nessuno"
 
-#: gitk:5021 gitk:5026
 msgid "Descendant"
 msgstr "Discendente"
 
-#: gitk:5022
 msgid "Not descendant"
 msgstr "Non discendente"
 
-#: gitk:5029 gitk:5034
 msgid "Ancestor"
 msgstr "Ascendente"
 
-#: gitk:5030
 msgid "Not ancestor"
 msgstr "Non ascendente"
 
-#: gitk:5324
 msgid "Local changes checked in to index but not committed"
 msgstr "Modifiche locali presenti nell'indice ma non nell'archivio"
 
-#: gitk:5360
 msgid "Local uncommitted changes, not checked in to index"
 msgstr "Modifiche locali non presenti né nell'archivio né nell'indice"
 
-#: gitk:7134
 msgid "and many more"
 msgstr ""
 
-#: gitk:7137
 msgid "many"
 msgstr "molti"
 
-#: gitk:7328
 msgid "Tags:"
 msgstr "Etichette:"
 
-#: gitk:7345 gitk:7351 gitk:8825
 msgid "Parent"
 msgstr "Genitore"
 
-#: gitk:7356
 msgid "Child"
 msgstr "Figlio"
 
-#: gitk:7365
 msgid "Branch"
 msgstr "Ramo"
 
-#: gitk:7368
 msgid "Follows"
 msgstr "Segue"
 
-#: gitk:7371
 msgid "Precedes"
 msgstr "Precede"
 
-#: gitk:7966
 #, tcl-format
 msgid "Error getting diffs: %s"
 msgstr "Errore nella lettura delle differenze:"
 
-#: gitk:8650
 msgid "Goto:"
 msgstr "Vai a:"
 
-#: gitk:8671
 #, tcl-format
 msgid "Short SHA1 id %s is ambiguous"
 msgstr "La SHA1 id abbreviata %s è ambigua"
 
-#: gitk:8678
 #, tcl-format
 msgid "Revision %s is not known"
 msgstr "La revisione %s è sconosciuta"
 
-#: gitk:8688
 #, tcl-format
 msgid "SHA1 id %s is not known"
 msgstr "La SHA1 id %s è sconosciuta"
 
-#: gitk:8690
 #, tcl-format
 msgid "Revision %s is not in the current view"
 msgstr "La revisione %s non è presente nella vista attuale"
 
-#: gitk:8832 gitk:8847
 msgid "Date"
 msgstr "Data"
 
-#: gitk:8835
 msgid "Children"
 msgstr "Figli"
 
-#: gitk:8898
 #, tcl-format
 msgid "Reset %s branch to here"
 msgstr "Aggiorna il ramo %s a questa revisione"
 
-#: gitk:8900
 msgid "Detached head: can't reset"
 msgstr "Nessun ramo attivo: reset impossibile"
 
-#: gitk:9005 gitk:9011
 msgid "Skipping merge commit "
 msgstr "Salto la revisione di fusione "
 
-#: gitk:9020 gitk:9025
 msgid "Error getting patch ID for "
 msgstr "Errore nella identificazione della patch per "
 
-#: gitk:9021 gitk:9026
 msgid " - stopping\n"
 msgstr " - fine\n"
 
-#: gitk:9031 gitk:9034 gitk:9042 gitk:9056 gitk:9065
 msgid "Commit "
 msgstr "La revisione "
 
-#: gitk:9035
 msgid ""
 " is the same patch as\n"
 "       "
@@ -903,7 +696,6 @@
 " ha le stesse differenze di\n"
 "       "
 
-#: gitk:9043
 msgid ""
 " differs from\n"
 "       "
@@ -911,7 +703,6 @@
 " è diversa da\n"
 "       "
 
-#: gitk:9045
 msgid ""
 "Diff of commits:\n"
 "\n"
@@ -919,129 +710,99 @@
 "Differenze tra le revisioni:\n"
 "\n"
 
-#: gitk:9057 gitk:9066
 #, tcl-format
 msgid " has %s children - stopping\n"
 msgstr " ha %s figli - fine\n"
 
-#: gitk:9085
 #, tcl-format
 msgid "Error writing commit to file: %s"
 msgstr "Errore nella scrittura della revisione nel file: %s"
 
-#: gitk:9091
 #, tcl-format
 msgid "Error diffing commits: %s"
 msgstr "Errore nelle differenze tra le revisioni: %s"
 
-#: gitk:9137
 msgid "Top"
 msgstr "Inizio"
 
-#: gitk:9138
 msgid "From"
 msgstr "Da"
 
-#: gitk:9143
 msgid "To"
 msgstr "A"
 
-#: gitk:9167
 msgid "Generate patch"
 msgstr "Genera patch"
 
-#: gitk:9169
 msgid "From:"
 msgstr "Da:"
 
-#: gitk:9178
 msgid "To:"
 msgstr "A:"
 
-#: gitk:9187
 msgid "Reverse"
 msgstr "Inverti"
 
-#: gitk:9189 gitk:9385
 msgid "Output file:"
 msgstr "Scrivi sul file:"
 
-#: gitk:9195
 msgid "Generate"
 msgstr "Genera"
 
-#: gitk:9233
 msgid "Error creating patch:"
 msgstr "Errore nella creazione della patch:"
 
-#: gitk:9256 gitk:9373 gitk:9430
 msgid "ID:"
 msgstr "ID:"
 
-#: gitk:9265
 msgid "Tag name:"
 msgstr "Nome etichetta:"
 
-#: gitk:9268
 msgid "Tag message is optional"
 msgstr "Il messaggio dell'etichetta è opzionale"
 
-#: gitk:9270
 msgid "Tag message:"
 msgstr "Messaggio dell'etichetta:"
 
-#: gitk:9274 gitk:9439
 msgid "Create"
 msgstr "Crea"
 
-#: gitk:9292
 msgid "No tag name specified"
 msgstr "Nessuna etichetta specificata"
 
-#: gitk:9296
 #, tcl-format
 msgid "Tag \"%s\" already exists"
 msgstr "L'etichetta \"%s\" esiste già"
 
-#: gitk:9306
 msgid "Error creating tag:"
 msgstr "Errore nella creazione dell'etichetta:"
 
-#: gitk:9382
 msgid "Command:"
 msgstr "Comando:"
 
-#: gitk:9390
 msgid "Write"
 msgstr "Scrivi"
 
-#: gitk:9408
 msgid "Error writing commit:"
 msgstr "Errore nella scrittura della revisione:"
 
-#: gitk:9435
 msgid "Name:"
 msgstr "Nome:"
 
-#: gitk:9458
 msgid "Please specify a name for the new branch"
 msgstr "Specificare un nome per il nuovo ramo"
 
-#: gitk:9463
 #, tcl-format
 msgid "Branch '%s' already exists. Overwrite?"
 msgstr "Il ramo '%s' esiste già. Sovrascrivere?"
 
-#: gitk:9530
 #, tcl-format
 msgid "Commit %s is already included in branch %s -- really re-apply it?"
 msgstr "La revisione %s è già inclusa nel ramo %s -- applicarla di nuovo?"
 
-#: gitk:9535
 msgid "Cherry-picking"
 msgstr ""
 
-#: gitk:9544
 #, tcl-format
 msgid ""
 "Cherry-pick failed because of local changes to file '%s'.\n"
@@ -1052,7 +813,6 @@
 "Prima di riprovare, bisogna creare una nuova revisione, annullare le "
 "modifiche o usare 'git stash'."
 
-#: gitk:9550
 msgid ""
 "Cherry-pick failed because of merge conflict.\n"
 "Do you wish to run git citool to resolve it?"
@@ -1060,21 +820,17 @@
 "Impossibile eseguire cherry-pick a causa di un conflitto nella fusione.\n"
 "Vuoi avviare git citool per risolverlo?"
 
-#: gitk:9566 gitk:9624
 msgid "No changes committed"
 msgstr "Nessuna modifica archiviata"
 
-#: gitk:9593
 #, fuzzy, tcl-format
 msgid "Commit %s is not included in branch %s -- really revert it?"
 msgstr "La revisione %s è già inclusa nel ramo %s -- applicarla di nuovo?"
 
-#: gitk:9598
 #, fuzzy
 msgid "Reverting"
 msgstr "git reset in corso"
 
-#: gitk:9606
 #, fuzzy, tcl-format
 msgid ""
 "Revert failed because of local changes to the following files:%s Please "
@@ -1085,7 +841,6 @@
 "Prima di riprovare, bisogna creare una nuova revisione, annullare le "
 "modifiche o usare 'git stash'."
 
-#: gitk:9610
 #, fuzzy
 msgid ""
 "Revert failed because of merge conflict.\n"
@@ -1094,28 +849,22 @@
 "Impossibile eseguire cherry-pick a causa di un conflitto nella fusione.\n"
 "Vuoi avviare git citool per risolverlo?"
 
-#: gitk:9653
 msgid "Confirm reset"
 msgstr "Conferma git reset"
 
-#: gitk:9655
 #, tcl-format
 msgid "Reset branch %s to %s?"
 msgstr "Aggiornare il ramo %s a %s?"
 
-#: gitk:9657
 msgid "Reset type:"
 msgstr "Tipo di aggiornamento:"
 
-#: gitk:9660
 msgid "Soft: Leave working tree and index untouched"
 msgstr "Soft: Lascia la direcory di lavoro e l'indice come sono"
 
-#: gitk:9663
 msgid "Mixed: Leave working tree untouched, reset index"
 msgstr "Mixed: Lascia la directory di lavoro come è, aggiorna l'indice"
 
-#: gitk:9666
 msgid ""
 "Hard: Reset working tree and index\n"
 "(discard ALL local changes)"
@@ -1123,19 +872,15 @@
 "Hard: Aggiorna la directory di lavoro e l'indice\n"
 "(abbandona TUTTE le modifiche locali)"
 
-#: gitk:9683
 msgid "Resetting"
 msgstr "git reset in corso"
 
-#: gitk:9743
 msgid "Checking out"
 msgstr "Attivazione in corso"
 
-#: gitk:9796
 msgid "Cannot delete the currently checked-out branch"
 msgstr "Impossibile cancellare il ramo attualmente attivo"
 
-#: gitk:9802
 #, tcl-format
 msgid ""
 "The commits on branch %s aren't on any other branch.\n"
@@ -1144,16 +889,13 @@
 "Le revisioni nel ramo %s non sono presenti su altri rami.\n"
 "Cancellare il ramo %s?"
 
-#: gitk:9833
 #, tcl-format
 msgid "Tags and heads: %s"
 msgstr "Etichette e rami: %s"
 
-#: gitk:9850
 msgid "Filter"
 msgstr "Filtro"
 
-#: gitk:10146
 msgid ""
 "Error reading commit topology information; branch and preceding/following "
 "tag information will be incomplete."
@@ -1161,219 +903,167 @@
 "Errore nella lettura della topologia delle revisioni: le informazioni sul "
 "ramo e le etichette precedenti e seguenti saranno incomplete."
 
-#: gitk:11123
 msgid "Tag"
 msgstr "Etichetta"
 
-#: gitk:11127
 msgid "Id"
 msgstr "Id"
 
-#: gitk:11210
 msgid "Gitk font chooser"
 msgstr "Scelta caratteri gitk"
 
-#: gitk:11227
 msgid "B"
 msgstr "B"
 
-#: gitk:11230
 msgid "I"
 msgstr "I"
 
-#: gitk:11348
 msgid "Commit list display options"
 msgstr "Opzioni visualizzazione dell'elenco revisioni"
 
-#: gitk:11351
 msgid "Maximum graph width (lines)"
 msgstr "Larghezza massima del grafico (in linee)"
 
-#: gitk:11355
 #, no-tcl-format
 msgid "Maximum graph width (% of pane)"
 msgstr "Larghezza massima del grafico (% del pannello)"
 
-#: gitk:11358
 msgid "Show local changes"
 msgstr "Mostra modifiche locali"
 
-#: gitk:11361
 #, fuzzy
 msgid "Auto-select SHA1 (length)"
 msgstr "Seleziona automaticamente SHA1 hash"
 
-#: gitk:11365
 msgid "Hide remote refs"
 msgstr "Nascondi i riferimenti remoti"
 
-#: gitk:11369
 msgid "Diff display options"
 msgstr "Opzioni di visualizzazione delle differenze"
 
-#: gitk:11371
 msgid "Tab spacing"
 msgstr "Spaziatura tabulazioni"
 
-#: gitk:11374
 #, fuzzy
 msgid "Display nearby tags/heads"
 msgstr "Mostra etichette vicine"
 
-#: gitk:11377
 msgid "Maximum # tags/heads to show"
 msgstr ""
 
-#: gitk:11380
 msgid "Limit diffs to listed paths"
 msgstr "Limita le differenze ai percorsi elencati"
 
-#: gitk:11383
 msgid "Support per-file encodings"
 msgstr "Attiva codifica file per file"
 
-#: gitk:11389 gitk:11536
 msgid "External diff tool"
 msgstr "Visualizzatore di differenze"
 
-#: gitk:11390
 msgid "Choose..."
 msgstr "Scegli..."
 
-#: gitk:11395
 msgid "General options"
 msgstr "Opzioni generali"
 
-#: gitk:11398
 msgid "Use themed widgets"
 msgstr "Utilizza interfaccia a tema"
 
-#: gitk:11400
 msgid "(change requires restart)"
 msgstr "(una modifica richiede il riavvio)"
 
-#: gitk:11402
 msgid "(currently unavailable)"
 msgstr "(momentaneamente non disponibile)"
 
-#: gitk:11413
 msgid "Colors: press to choose"
 msgstr "Colori: premere per scegliere"
 
-#: gitk:11416
 msgid "Interface"
 msgstr "Interfaccia"
 
-#: gitk:11417
 msgid "interface"
 msgstr "interfaccia"
 
-#: gitk:11420
 msgid "Background"
 msgstr "Sfondo"
 
-#: gitk:11421 gitk:11451
 msgid "background"
 msgstr "sfondo"
 
-#: gitk:11424
 msgid "Foreground"
 msgstr "Primo piano"
 
-#: gitk:11425
 msgid "foreground"
 msgstr "primo piano"
 
-#: gitk:11428
 msgid "Diff: old lines"
 msgstr "Diff: vecchie linee"
 
-#: gitk:11429
 msgid "diff old lines"
 msgstr "vecchie linee"
 
-#: gitk:11433
 msgid "Diff: new lines"
 msgstr "Diff: nuove linee"
 
-#: gitk:11434
 msgid "diff new lines"
 msgstr "nuove linee"
 
-#: gitk:11438
 msgid "Diff: hunk header"
 msgstr "Diff: intestazione della sezione"
 
-#: gitk:11440
 msgid "diff hunk header"
 msgstr "intestazione della sezione"
 
-#: gitk:11444
 msgid "Marked line bg"
 msgstr "Sfondo riga selezionata"
 
-#: gitk:11446
 msgid "marked line background"
 msgstr "sfondo riga selezionata"
 
-#: gitk:11450
 msgid "Select bg"
 msgstr "Sfondo"
 
-#: gitk:11459
 msgid "Fonts: press to choose"
 msgstr "Carattere: premere per scegliere"
 
-#: gitk:11461
 msgid "Main font"
 msgstr "Carattere principale"
 
-#: gitk:11462
 msgid "Diff display font"
 msgstr "Carattere per differenze"
 
-#: gitk:11463
 msgid "User interface font"
 msgstr "Carattere per interfaccia utente"
 
-#: gitk:11485
 msgid "Gitk preferences"
 msgstr "Preferenze gitk"
 
-#: gitk:11494
 #, fuzzy
 msgid "General"
 msgstr "Genera"
 
-#: gitk:11495
 msgid "Colors"
 msgstr ""
 
-#: gitk:11496
 msgid "Fonts"
 msgstr ""
 
-#: gitk:11546
 #, tcl-format
 msgid "Gitk: choose color for %s"
 msgstr "Gitk: scegliere un colore per %s"
 
-#: gitk:12059
 msgid ""
 "Sorry, gitk cannot run with this version of Tcl/Tk.\n"
 " Gitk requires at least Tcl/Tk 8.4."
 msgstr ""
 
-#: gitk:12269
 msgid "Cannot find a git repository here."
 msgstr "Archivio git non trovato."
 
-#: gitk:12316
 #, tcl-format
 msgid "Ambiguous argument '%s': both revision and filename"
 msgstr "Argomento ambiguo: '%s' è sia revisione che nome di file"
 
-#: gitk:12328
 msgid "Bad arguments to gitk:"
 msgstr "Gitk: argomenti errati:"
 
diff --git a/gitk-git/po/ja.po b/gitk-git/po/ja.po
index ca3c29b..2c40b76 100644
--- a/gitk-git/po/ja.po
+++ b/gitk-git/po/ja.po
@@ -8,7 +8,7 @@
 # Satoshi Yasushima <s.yasushima@gmail.com>, 2016.
 msgid ""
 msgstr ""
-"Project-Id-Version: gitk\n"
+"Project-Id-Version: Gitk\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2015-05-17 14:32+1000\n"
 "PO-Revision-Date: 2015-11-12 13:00+0900\n"
@@ -20,33 +20,26 @@
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
 
-#: gitk:140
 msgid "Couldn't get list of unmerged files:"
 msgstr "マージされていないファイルのリストを取得できません:"
 
-#: gitk:212 gitk:2381
 msgid "Color words"
 msgstr "変更を着色"
 
-#: gitk:217 gitk:2381 gitk:8221 gitk:8254
 msgid "Markup words"
 msgstr "変更をマークアップ"
 
-#: gitk:324
 msgid "Error parsing revisions:"
 msgstr "リビジョン解析エラー:"
 
-#: gitk:380
 msgid "Error executing --argscmd command:"
 msgstr "--argscmd コマンド実行エラー:"
 
-#: gitk:393
 msgid "No files selected: --merge specified but no files are unmerged."
 msgstr ""
 "ファイル未選択: --merge が指定されましたが、マージされていないファイルはあり"
 "ません。"
 
-#: gitk:396
 msgid ""
 "No files selected: --merge specified but no unmerged files are within file "
 "limit."
@@ -54,322 +47,240 @@
 "ファイル未選択: --merge が指定されましたが、ファイル制限内にマージされていな"
 "いファイルはありません。"
 
-#: gitk:418 gitk:566
 msgid "Error executing git log:"
 msgstr "git log 実行エラー:"
 
-#: gitk:436 gitk:582
 msgid "Reading"
 msgstr "読み込み中"
 
-#: gitk:496 gitk:4526
 msgid "Reading commits..."
 msgstr "コミット読み込み中..."
 
-#: gitk:499 gitk:1637 gitk:4529
 msgid "No commits selected"
 msgstr "コミットが選択されていません"
 
-#: gitk:1445 gitk:4046 gitk:12447
 msgid "Command line"
 msgstr "コマンド行"
 
-#: gitk:1511
 msgid "Can't parse git log output:"
 msgstr "git log の出力を解析できません:"
 
-#: gitk:1740
 msgid "No commit information available"
 msgstr "有効なコミットの情報がありません"
 
-#: gitk:1903 gitk:1932 gitk:4316 gitk:9684 gitk:11256 gitk:11536
 msgid "OK"
 msgstr "OK"
 
-#: gitk:1934 gitk:4318 gitk:9197 gitk:9276 gitk:9406 gitk:9455 gitk:9686
-#: gitk:11257 gitk:11537
 msgid "Cancel"
 msgstr "キャンセル"
 
-#: gitk:2069
 msgid "&Update"
 msgstr "更新(&U)"
 
-#: gitk:2070
 msgid "&Reload"
 msgstr "リロード(&R)"
 
-#: gitk:2071
 msgid "Reread re&ferences"
 msgstr "リファレンスを再読み込み(&F)"
 
-#: gitk:2072
 msgid "&List references"
 msgstr "リファレンスリストを表示(&L)"
 
-#: gitk:2074
 msgid "Start git &gui"
 msgstr "git gui の開始(&G)"
 
-#: gitk:2076
 msgid "&Quit"
 msgstr "終了(&Q)"
 
-#: gitk:2068
 msgid "&File"
 msgstr "ファイル(&F)"
 
-#: gitk:2080
 msgid "&Preferences"
 msgstr "設定(&P)"
 
-#: gitk:2079
 msgid "&Edit"
 msgstr "編集(&E)"
 
-#: gitk:2084
 msgid "&New view..."
 msgstr "新規ビュー(&N)..."
 
-#: gitk:2085
 msgid "&Edit view..."
 msgstr "ビュー編集(&E)..."
 
-#: gitk:2086
 msgid "&Delete view"
 msgstr "ビュー削除(&D)"
 
-#: gitk:2088
 msgid "&All files"
 msgstr "全てのファイル(&A)"
 
-#: gitk:2083
 msgid "&View"
 msgstr "ビュー(&V)"
 
-#: gitk:2093 gitk:2103
 msgid "&About gitk"
 msgstr "gitk について(&A)"
 
-#: gitk:2094 gitk:2108
 msgid "&Key bindings"
 msgstr "キーバインディング(&K)"
 
-#: gitk:2092 gitk:2107
 msgid "&Help"
 msgstr "ヘルプ(&H)"
 
-#: gitk:2185 gitk:8653
 msgid "SHA1 ID:"
 msgstr "SHA1 ID:"
 
-#: gitk:2229
 msgid "Row"
 msgstr "行"
 
-#: gitk:2267
 msgid "Find"
 msgstr "検索"
 
-#: gitk:2295
 msgid "commit"
 msgstr "コミット"
 
-#: gitk:2299 gitk:2301 gitk:4688 gitk:4711 gitk:4735 gitk:6756 gitk:6828
-#: gitk:6913
 msgid "containing:"
 msgstr "含む:"
 
-#: gitk:2302 gitk:3527 gitk:3532 gitk:4764
 msgid "touching paths:"
 msgstr "パスの一部:"
 
-#: gitk:2303 gitk:4778
 msgid "adding/removing string:"
 msgstr "追加/除去される文字列:"
 
-#: gitk:2304 gitk:4780
 msgid "changing lines matching:"
 msgstr "変更される文字列"
 
-#: gitk:2313 gitk:2315 gitk:4767
 msgid "Exact"
 msgstr "英字の大小を区別する"
 
-#: gitk:2315 gitk:4855 gitk:6724
 msgid "IgnCase"
 msgstr "英字の大小を区別しない"
 
-#: gitk:2315 gitk:4737 gitk:4853 gitk:6720
 msgid "Regexp"
 msgstr "正規表現"
 
-#: gitk:2317 gitk:2318 gitk:4875 gitk:4905 gitk:4912 gitk:6849 gitk:6917
 msgid "All fields"
 msgstr "全ての項目"
 
-#: gitk:2318 gitk:4872 gitk:4905 gitk:6787
 msgid "Headline"
 msgstr "ヘッドライン"
 
-#: gitk:2319 gitk:4872 gitk:6787 gitk:6917 gitk:7390
 msgid "Comments"
 msgstr "コメント"
 
-#: gitk:2319 gitk:4872 gitk:4877 gitk:4912 gitk:6787 gitk:7325 gitk:8831
-#: gitk:8846
 msgid "Author"
 msgstr "作者"
 
-#: gitk:2319 gitk:4872 gitk:6787 gitk:7327
 msgid "Committer"
 msgstr "コミット者"
 
-#: gitk:2350
 msgid "Search"
 msgstr "検索"
 
-#: gitk:2358
 msgid "Diff"
 msgstr "Diff"
 
-#: gitk:2360
 msgid "Old version"
 msgstr "旧バージョン"
 
-#: gitk:2362
 msgid "New version"
 msgstr "新バージョン"
 
-#: gitk:2364
 msgid "Lines of context"
 msgstr "文脈行数"
 
-#: gitk:2374
 msgid "Ignore space change"
 msgstr "空白の違いを無視"
 
-#: gitk:2378 gitk:2380 gitk:7960 gitk:8207
 msgid "Line diff"
 msgstr "行毎のdiff"
 
-#: gitk:2445
 msgid "Patch"
 msgstr "パッチ"
 
-#: gitk:2447
 msgid "Tree"
 msgstr "ツリー"
 
-#: gitk:2617 gitk:2638
 msgid "Diff this -> selected"
 msgstr "これと選択したコミットのdiffを見る"
 
-#: gitk:2618 gitk:2639
 msgid "Diff selected -> this"
 msgstr "選択したコミットとこれのdiffを見る"
 
-#: gitk:2619 gitk:2640
 msgid "Make patch"
 msgstr "パッチ作成"
 
-#: gitk:2620 gitk:9255
 msgid "Create tag"
 msgstr "タグ生成"
 
-#: gitk:2621
 msgid "Copy commit summary"
 msgstr "コミットの要約をコピーする"
 
-#: gitk:2622 gitk:9386
 msgid "Write commit to file"
 msgstr "コミットをファイルに書き出す"
 
-#: gitk:2623 gitk:9443
 msgid "Create new branch"
 msgstr "新規ブランチ生成"
 
-#: gitk:2624
 msgid "Cherry-pick this commit"
 msgstr "このコミットをチェリーピックする"
 
-#: gitk:2625
 msgid "Reset HEAD branch to here"
 msgstr "ブランチのHEADをここにリセットする"
 
-#: gitk:2626
 msgid "Mark this commit"
 msgstr "このコミットにマークをつける"
 
-#: gitk:2627
 msgid "Return to mark"
 msgstr "マークを付けた所に戻る"
 
-#: gitk:2628
 msgid "Find descendant of this and mark"
 msgstr "これとマークをつけた所との子孫を見つける"
 
-#: gitk:2629
 msgid "Compare with marked commit"
 msgstr "マークを付けたコミットと比較する"
 
-#: gitk:2630 gitk:2641
 msgid "Diff this -> marked commit"
 msgstr "これとマークを付けたコミットのdiffを見る"
 
-#: gitk:2631 gitk:2642
 msgid "Diff marked commit -> this"
 msgstr "マークを付けたコミットとこれのdiffを見る"
 
-#: gitk:2632
 msgid "Revert this commit"
 msgstr "このコミットを撤回する"
 
-#: gitk:2648
 msgid "Check out this branch"
 msgstr "このブランチをチェックアウトする"
 
-#: gitk:2649
 msgid "Remove this branch"
 msgstr "このブランチを除去する"
 
-#: gitk:2650
 msgid "Copy branch name"
 msgstr "ブランチ名をコピーする"
 
-#: gitk:2657
 msgid "Highlight this too"
 msgstr "これもハイライトさせる"
 
-#: gitk:2658
 msgid "Highlight this only"
 msgstr "これだけをハイライトさせる"
 
-#: gitk:2659
 msgid "External diff"
 msgstr "外部diffツール"
 
-#: gitk:2660
 msgid "Blame parent commit"
 msgstr "親コミットから blame をかける"
 
-#: gitk:2661
 msgid "Copy path"
 msgstr "パス名をコピーする"
 
-#: gitk:2668
 msgid "Show origin of this line"
 msgstr "この行の出自を表示する"
 
-#: gitk:2669
 msgid "Run git gui blame on this line"
 msgstr "この行に git gui で blame をかける"
 
-#: gitk:3013
 msgid "About gitk"
 msgstr "gitk について"
 
-#: gitk:3015
 msgid ""
 "\n"
 "Gitk - a commit viewer for git\n"
@@ -385,323 +296,251 @@
 "\n"
 "使用および再配布は GNU General Public License に従ってください"
 
-#: gitk:3023 gitk:3090 gitk:9872
 msgid "Close"
 msgstr "閉じる"
 
-#: gitk:3044
 msgid "Gitk key bindings"
 msgstr "Gitk キーバインディング"
 
-#: gitk:3047
 msgid "Gitk key bindings:"
 msgstr "Gitk キーバインディング:"
 
-#: gitk:3049
 #, tcl-format
 msgid "<%s-Q>\t\tQuit"
 msgstr "<%s-Q>\t\t終了"
 
-#: gitk:3050
 #, tcl-format
 msgid "<%s-W>\t\tClose window"
 msgstr "<%s-W>\t\tウィンドウを閉じる"
 
-#: gitk:3051
 msgid "<Home>\t\tMove to first commit"
 msgstr "<Home>\t\t最初のコミットに移動"
 
-#: gitk:3052
 msgid "<End>\t\tMove to last commit"
 msgstr "<End>\t\t最後のコミットに移動"
 
-#: gitk:3053
 msgid "<Up>, p, k\tMove up one commit"
 msgstr "<Up>, p, k\t一つ上のコミットに移動"
 
-#: gitk:3054
 msgid "<Down>, n, j\tMove down one commit"
 msgstr "<Down>, n, j\t一つ下のコミットに移動"
 
-#: gitk:3055
 msgid "<Left>, z, h\tGo back in history list"
 msgstr "<Left>, z, h\t履歴の前に戻る"
 
-#: gitk:3056
 msgid "<Right>, x, l\tGo forward in history list"
 msgstr "<Right>, x, l\t履歴の次へ進む"
 
-#: gitk:3057
 #, tcl-format
 msgid "<%s-n>\tGo to n-th parent of current commit in history list"
-msgstr "<%s-n(数字)>\t履歴上で現在のコミットの親コミットの内のn(数字)番目のコミットへ移動"
+msgstr ""
+"<%s-n(数字)>\t履歴上で現在のコミットの親コミットの内のn(数字)番目のコミットへ"
+"移動"
 
-#: gitk:3058
 msgid "<PageUp>\tMove up one page in commit list"
 msgstr "<PageUp>\tコミットリストの一つ上のページに移動"
 
-#: gitk:3059
 msgid "<PageDown>\tMove down one page in commit list"
 msgstr "<PageDown>\tコミットリストの一つ下のページに移動"
 
-#: gitk:3060
 #, tcl-format
 msgid "<%s-Home>\tScroll to top of commit list"
 msgstr "<%s-Home>\tコミットリストの一番上にスクロールする"
 
-#: gitk:3061
 #, tcl-format
 msgid "<%s-End>\tScroll to bottom of commit list"
 msgstr "<%s-End>\tコミットリストの一番下にスクロールする"
 
-#: gitk:3062
 #, tcl-format
 msgid "<%s-Up>\tScroll commit list up one line"
 msgstr "<%s-Up>\tコミットリストの一つ下の行にスクロールする"
 
-#: gitk:3063
 #, tcl-format
 msgid "<%s-Down>\tScroll commit list down one line"
 msgstr "<%s-Down>\tコミットリストの一つ下の行にスクロールする"
 
-#: gitk:3064
 #, tcl-format
 msgid "<%s-PageUp>\tScroll commit list up one page"
 msgstr "<%s-PageUp>\tコミットリストの上のページにスクロールする"
 
-#: gitk:3065
 #, tcl-format
 msgid "<%s-PageDown>\tScroll commit list down one page"
 msgstr "<%s-PageDown>\tコミットリストの下のページにスクロールする"
 
-#: gitk:3066
 msgid "<Shift-Up>\tFind backwards (upwards, later commits)"
 msgstr "<Shift-Up>\t後方を検索 (上方の・新しいコミット)"
 
-#: gitk:3067
 msgid "<Shift-Down>\tFind forwards (downwards, earlier commits)"
 msgstr "<Shift-Down>\t前方を検索(下方の・古いコミット)"
 
-#: gitk:3068
 msgid "<Delete>, b\tScroll diff view up one page"
 msgstr "<Delete>, b\tdiff画面を上のページにスクロールする"
 
-#: gitk:3069
 msgid "<Backspace>\tScroll diff view up one page"
 msgstr "<Backspace>\tdiff画面を上のページにスクロールする"
 
-#: gitk:3070
 msgid "<Space>\t\tScroll diff view down one page"
 msgstr "<Space>\t\tdiff画面を下のページにスクロールする"
 
-#: gitk:3071
 msgid "u\t\tScroll diff view up 18 lines"
 msgstr "u\t\tdiff画面を上に18行スクロールする"
 
-#: gitk:3072
 msgid "d\t\tScroll diff view down 18 lines"
 msgstr "d\t\tdiff画面を下に18行スクロールする"
 
-#: gitk:3073
 #, tcl-format
 msgid "<%s-F>\t\tFind"
 msgstr "<%s-F>\t\t検索"
 
-#: gitk:3074
 #, tcl-format
 msgid "<%s-G>\t\tMove to next find hit"
 msgstr "<%s-G>\t\t次を検索して移動"
 
-#: gitk:3075
 msgid "<Return>\tMove to next find hit"
 msgstr "<Return>\t次を検索して移動"
 
-#: gitk:3076
 msgid "g\t\tGo to commit"
 msgstr "g\t\t指定してコミットに移動"
 
-#: gitk:3077
 msgid "/\t\tFocus the search box"
 msgstr "/\t\t検索ボックスにフォーカス"
 
-#: gitk:3078
 msgid "?\t\tMove to previous find hit"
 msgstr "?\t\t前を検索して移動"
 
-#: gitk:3079
 msgid "f\t\tScroll diff view to next file"
 msgstr "f\t\t次のファイルにdiff画面をスクロールする"
 
-#: gitk:3080
 #, tcl-format
 msgid "<%s-S>\t\tSearch for next hit in diff view"
 msgstr "<%s-S>\t\tdiff画面の次を検索"
 
-#: gitk:3081
 #, tcl-format
 msgid "<%s-R>\t\tSearch for previous hit in diff view"
 msgstr "<%s-R>\t\tdiff画面の前を検索"
 
-#: gitk:3082
 #, tcl-format
 msgid "<%s-KP+>\tIncrease font size"
 msgstr "<%s-KP+>\t文字サイズを拡大"
 
-#: gitk:3083
 #, tcl-format
 msgid "<%s-plus>\tIncrease font size"
 msgstr "<%s-plus>\t文字サイズを拡大"
 
-#: gitk:3084
 #, tcl-format
 msgid "<%s-KP->\tDecrease font size"
 msgstr "<%s-KP->\t文字サイズを縮小"
 
-#: gitk:3085
 #, tcl-format
 msgid "<%s-minus>\tDecrease font size"
 msgstr "<%s-minus>\t文字サイズを縮小"
 
-#: gitk:3086
 msgid "<F5>\t\tUpdate"
 msgstr "<F5>\t\t更新"
 
-#: gitk:3551 gitk:3560
 #, tcl-format
 msgid "Error creating temporary directory %s:"
 msgstr "一時ディレクトリ %s 生成時エラー:"
 
-#: gitk:3573
 #, tcl-format
 msgid "Error getting \"%s\" from %s:"
 msgstr "\"%s\" のエラーが %s に発生:"
 
-#: gitk:3636
 msgid "command failed:"
 msgstr "コマンド失敗:"
 
-#: gitk:3785
 msgid "No such commit"
 msgstr "そのようなコミットはありません"
 
-#: gitk:3799
 msgid "git gui blame: command failed:"
 msgstr "git gui blame: コマンド失敗:"
 
-#: gitk:3830
 #, tcl-format
 msgid "Couldn't read merge head: %s"
 msgstr "マージする HEAD を読み込めません: %s"
 
-#: gitk:3838
 #, tcl-format
 msgid "Error reading index: %s"
 msgstr "インデックス読み込みエラー: %s"
 
-#: gitk:3863
 #, tcl-format
 msgid "Couldn't start git blame: %s"
 msgstr "git blame を始められません: %s"
 
-#: gitk:3866 gitk:6755
 msgid "Searching"
 msgstr "検索中"
 
-#: gitk:3898
 #, tcl-format
 msgid "Error running git blame: %s"
 msgstr "git blame 実行エラー: %s"
 
-#: gitk:3926
 #, tcl-format
 msgid "That line comes from commit %s,  which is not in this view"
 msgstr "コミット %s に由来するその行は、このビューに表示されていません"
 
-#: gitk:3940
 msgid "External diff viewer failed:"
 msgstr "外部diffビューアが失敗:"
 
-#: gitk:4044
 msgid "All files"
 msgstr "全てのファイル"
 
-#: gitk:4068
 msgid "View"
 msgstr "ビュー"
 
-#: gitk:4071
 msgid "Gitk view definition"
 msgstr "Gitk ビュー定義"
 
-#: gitk:4075
 msgid "Remember this view"
 msgstr "このビューを記憶する"
 
-#: gitk:4076
 msgid "References (space separated list):"
 msgstr "リファレンス(スペース区切りのリスト):"
 
-#: gitk:4077
 msgid "Branches & tags:"
 msgstr "ブランチ&タグ:"
 
-#: gitk:4078
 msgid "All refs"
 msgstr "全てのリファレンス"
 
-#: gitk:4079
 msgid "All (local) branches"
 msgstr "全ての(ローカルな)ブランチ"
 
-#: gitk:4080
 msgid "All tags"
 msgstr "全てのタグ"
 
-#: gitk:4081
 msgid "All remote-tracking branches"
 msgstr "全てのリモート追跡ブランチ"
 
-#: gitk:4082
 msgid "Commit Info (regular expressions):"
 msgstr "コミット情報(正規表現):"
 
-#: gitk:4083
 msgid "Author:"
 msgstr "作者:"
 
-#: gitk:4084
 msgid "Committer:"
 msgstr "コミット者:"
 
-#: gitk:4085
 msgid "Commit Message:"
 msgstr "コミットメッセージ:"
 
-#: gitk:4086
 msgid "Matches all Commit Info criteria"
 msgstr "コミット情報の全ての条件に一致"
 
-#: gitk:4087
 msgid "Matches no Commit Info criteria"
 msgstr "コミット情報の全ての条件に不一致"
 
-#: gitk:4088
 msgid "Changes to Files:"
 msgstr "変更したファイル:"
 
-#: gitk:4089
 msgid "Fixed String"
 msgstr "固定文字列"
 
-#: gitk:4090
 msgid "Regular Expression"
 msgstr "正規表現"
 
-#: gitk:4091
 msgid "Search string:"
 msgstr "検索文字列:"
 
-#: gitk:4092
 msgid ""
 "Commit Dates (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 "
 "15:27:38\"):"
@@ -709,201 +548,153 @@
 "コミット日時 (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 "
 "15:27:38\"):"
 
-#: gitk:4093
 msgid "Since:"
 msgstr "期間の始め:"
 
-#: gitk:4094
 msgid "Until:"
 msgstr "期間の終わり:"
 
-#: gitk:4095
 msgid "Limit and/or skip a number of revisions (positive integer):"
 msgstr "制限・省略するリビジョンの数(正の整数):"
 
-#: gitk:4096
 msgid "Number to show:"
 msgstr "表示する数:"
 
-#: gitk:4097
 msgid "Number to skip:"
 msgstr "省略する数:"
 
-#: gitk:4098
 msgid "Miscellaneous options:"
 msgstr "その他のオプション:"
 
-#: gitk:4099
 msgid "Strictly sort by date"
 msgstr "厳密に日付順で並び替え"
 
-#: gitk:4100
 msgid "Mark branch sides"
 msgstr "側枝マーク"
 
-#: gitk:4101
 msgid "Limit to first parent"
 msgstr "最初の親に制限"
 
-#: gitk:4102
 msgid "Simple history"
 msgstr "簡易な履歴"
 
-#: gitk:4103
 msgid "Additional arguments to git log:"
 msgstr "git log への追加の引数:"
 
-#: gitk:4104
 msgid "Enter files and directories to include, one per line:"
 msgstr "含まれるファイル・ディレクトリを一行ごとに入力:"
 
-#: gitk:4105
 msgid "Command to generate more commits to include:"
 msgstr "コミット追加コマンド:"
 
-#: gitk:4229
 msgid "Gitk: edit view"
 msgstr "Gitk: ビュー編集"
 
-#: gitk:4237
 msgid "-- criteria for selecting revisions"
 msgstr "― リビジョンの選択条件"
 
-#: gitk:4242
 msgid "View Name"
 msgstr "ビュー名:"
 
-#: gitk:4317
 msgid "Apply (F5)"
 msgstr "適用 (F5)"
 
-#: gitk:4355
 msgid "Error in commit selection arguments:"
 msgstr "コミット選択引数のエラー:"
 
-#: gitk:4410 gitk:4463 gitk:4925 gitk:4939 gitk:6209 gitk:12388 gitk:12389
 msgid "None"
 msgstr "無し"
 
-#: gitk:5022 gitk:5027
 msgid "Descendant"
 msgstr "子孫"
 
-#: gitk:5023
 msgid "Not descendant"
 msgstr "非子孫"
 
-#: gitk:5030 gitk:5035
 msgid "Ancestor"
 msgstr "祖先"
 
-#: gitk:5031
 msgid "Not ancestor"
 msgstr "非祖先"
 
-#: gitk:5325
 msgid "Local changes checked in to index but not committed"
 msgstr "ステージされた、コミット前のローカルな変更"
 
-#: gitk:5361
 msgid "Local uncommitted changes, not checked in to index"
 msgstr "ステージされていない、コミット前のローカルな変更"
 
-#: gitk:7135
 msgid "and many more"
 msgstr "他多数"
 
-#: gitk:7138
 msgid "many"
 msgstr "多数"
 
-#: gitk:7329
 msgid "Tags:"
 msgstr "タグ:"
 
-#: gitk:7346 gitk:7352 gitk:8826
 msgid "Parent"
 msgstr "親"
 
-#: gitk:7357
 msgid "Child"
 msgstr "子"
 
-#: gitk:7366
 msgid "Branch"
 msgstr "ブランチ"
 
-#: gitk:7369
 msgid "Follows"
 msgstr "下位"
 
-#: gitk:7372
 msgid "Precedes"
 msgstr "上位"
 
-#: gitk:7967
 #, tcl-format
 msgid "Error getting diffs: %s"
 msgstr "diff取得エラー: %s"
 
-#: gitk:8651
 msgid "Goto:"
 msgstr "Goto:"
 
-#: gitk:8672
 #, tcl-format
 msgid "Short SHA1 id %s is ambiguous"
 msgstr "%s を含む SHA1 ID は複数存在します"
 
-#: gitk:8679
 #, tcl-format
 msgid "Revision %s is not known"
 msgstr "リビジョン %s は不明です"
 
-#: gitk:8689
 #, tcl-format
 msgid "SHA1 id %s is not known"
 msgstr "SHA1 id %s は不明です"
 
-#: gitk:8691
 #, tcl-format
 msgid "Revision %s is not in the current view"
 msgstr "リビジョン %s は現在のビューにはありません"
 
-#: gitk:8833 gitk:8848
 msgid "Date"
 msgstr "日付"
 
-#: gitk:8836
 msgid "Children"
 msgstr "子"
 
-#: gitk:8899
 #, tcl-format
 msgid "Reset %s branch to here"
 msgstr "%s ブランチをここにリセットする"
 
-#: gitk:8901
 msgid "Detached head: can't reset"
 msgstr "切り離されたHEAD: リセットできません"
 
-#: gitk:9006 gitk:9012
 msgid "Skipping merge commit "
 msgstr "コミットマージをスキップ: "
 
-#: gitk:9021 gitk:9026
 msgid "Error getting patch ID for "
 msgstr "パッチ取得エラー: ID "
 
-#: gitk:9022 gitk:9027
 msgid " - stopping\n"
 msgstr " - 停止\n"
 
-#: gitk:9032 gitk:9035 gitk:9043 gitk:9057 gitk:9066
 msgid "Commit "
 msgstr "コミット "
 
-#: gitk:9036
 msgid ""
 " is the same patch as\n"
 "       "
@@ -911,7 +702,6 @@
 " は下記のパッチと同等\n"
 "       "
 
-#: gitk:9044
 msgid ""
 " differs from\n"
 "       "
@@ -919,7 +709,6 @@
 " 下記からのdiff\n"
 "       "
 
-#: gitk:9046
 msgid ""
 "Diff of commits:\n"
 "\n"
@@ -927,130 +716,100 @@
 "コミットのdiff:\n"
 "\n"
 
-#: gitk:9058 gitk:9067
 #, tcl-format
 msgid " has %s children - stopping\n"
 msgstr " には %s の子があります - 停止\n"
 
-#: gitk:9086
 #, tcl-format
 msgid "Error writing commit to file: %s"
 msgstr "ファイルへのコミット書き出しエラー: %s"
 
-#: gitk:9092
 #, tcl-format
 msgid "Error diffing commits: %s"
 msgstr "コミットのdiff実行エラー: %s"
 
-#: gitk:9138
 msgid "Top"
 msgstr "Top"
 
-#: gitk:9139
 msgid "From"
 msgstr "From"
 
-#: gitk:9144
 msgid "To"
 msgstr "To"
 
-#: gitk:9168
 msgid "Generate patch"
 msgstr "パッチ生成"
 
-#: gitk:9170
 msgid "From:"
 msgstr "From:"
 
-#: gitk:9179
 msgid "To:"
 msgstr "To:"
 
-#: gitk:9188
 msgid "Reverse"
 msgstr "逆"
 
-#: gitk:9190 gitk:9400
 msgid "Output file:"
 msgstr "出力ファイル:"
 
-#: gitk:9196
 msgid "Generate"
 msgstr "生成"
 
-#: gitk:9234
 msgid "Error creating patch:"
 msgstr "パッチ生成エラー:"
 
-#: gitk:9257 gitk:9388 gitk:9445
 msgid "ID:"
 msgstr "ID:"
 
-#: gitk:9266
 msgid "Tag name:"
 msgstr "タグ名:"
 
-#: gitk:9269
 msgid "Tag message is optional"
 msgstr "タグメッセージを付ける事も出来ます"
 
-#: gitk:9271
 msgid "Tag message:"
 msgstr "タグメッセージ:"
 
-#: gitk:9275 gitk:9454
 msgid "Create"
 msgstr "生成"
 
-#: gitk:9293
 msgid "No tag name specified"
 msgstr "タグの名称が指定されていません"
 
-#: gitk:9297
 #, tcl-format
 msgid "Tag \"%s\" already exists"
 msgstr "タグ \"%s\" は既に存在します"
 
-#: gitk:9307
 msgid "Error creating tag:"
 msgstr "タグ生成エラー:"
 
-#: gitk:9397
 msgid "Command:"
 msgstr "コマンド:"
 
-#: gitk:9405
 msgid "Write"
 msgstr "書き出し"
 
-#: gitk:9423
 msgid "Error writing commit:"
 msgstr "コミット書き出しエラー:"
 
-#: gitk:9450
 msgid "Name:"
 msgstr "名前:"
 
-#: gitk:9473
 msgid "Please specify a name for the new branch"
 msgstr "新しいブランチの名前を指定してください"
 
-#: gitk:9478
 #, tcl-format
 msgid "Branch '%s' already exists. Overwrite?"
 msgstr "ブランチ '%s' は既に存在します。上書きしますか?"
 
-#: gitk:9545
 #, tcl-format
 msgid "Commit %s is already included in branch %s -- really re-apply it?"
 msgstr ""
 "コミット %s は既にブランチ %s に含まれています ― 本当にこれを再適用しますか?"
 
-#: gitk:9550
 msgid "Cherry-picking"
 msgstr "チェリーピック中"
 
-#: gitk:9559
 #, tcl-format
 msgid ""
 "Cherry-pick failed because of local changes to file '%s'.\n"
@@ -1060,7 +819,6 @@
 "あなたの変更に commit, reset, stash のいずれかを行ってからやり直してくださ"
 "い。"
 
-#: gitk:9565
 msgid ""
 "Cherry-pick failed because of merge conflict.\n"
 "Do you wish to run git citool to resolve it?"
@@ -1068,27 +826,25 @@
 "マージの衝突によってチェリーピックは失敗しました。\n"
 "この解決のために git citool を実行したいですか?"
 
-#: gitk:9581 gitk:9639
 msgid "No changes committed"
 msgstr "何の変更もコミットされていません"
 
-#: gitk:9608
 #, tcl-format
 msgid "Commit %s is not included in branch %s -- really revert it?"
-msgstr "コミット %s は既にブランチ %s に含まれています ― 本当にこれを撤回しますか?"
+msgstr ""
+"コミット %s は既にブランチ %s に含まれています ― 本当にこれを撤回しますか?"
 
-#: gitk:9613
 msgid "Reverting"
 msgstr "撤回中"
 
-#: gitk:9621
 #, tcl-format
 msgid ""
 "Revert failed because of local changes to the following files:%s Please "
 "commit, reset or stash  your changes and try again."
-msgstr "ファイル '%s' のローカルな変更のために撤回は失敗しました。 あなたの変更に commit, reset, stash のいずれかを行ってからやり直してください。"
+msgstr ""
+"ファイル '%s' のローカルな変更のために撤回は失敗しました。 あなたの変更に "
+"commit, reset, stash のいずれかを行ってからやり直してください。"
 
-#: gitk:9625
 msgid ""
 "Revert failed because of merge conflict.\n"
 " Do you wish to run git citool to resolve it?"
@@ -1096,28 +852,22 @@
 "マージの衝突によって撤回は失敗しました。\n"
 "この解決のために git citool を実行したいですか?"
 
-#: gitk:9668
 msgid "Confirm reset"
 msgstr "確認を取り消す"
 
-#: gitk:9670
 #, tcl-format
 msgid "Reset branch %s to %s?"
 msgstr "ブランチ %s を %s にリセットしますか?"
 
-#: gitk:9672
 msgid "Reset type:"
 msgstr "Reset タイプ:"
 
-#: gitk:9675
 msgid "Soft: Leave working tree and index untouched"
 msgstr "Soft: 作業ツリーもインデックスもそのままにする"
 
-#: gitk:9678
 msgid "Mixed: Leave working tree untouched, reset index"
 msgstr "Mixed: 作業ツリーをそのままにして、インデックスをリセット"
 
-#: gitk:9681
 msgid ""
 "Hard: Reset working tree and index\n"
 "(discard ALL local changes)"
@@ -1125,19 +875,15 @@
 "Hard: 作業ツリーやインデックスをリセット\n"
 "(「全ての」ローカルな変更を破棄)"
 
-#: gitk:9698
 msgid "Resetting"
 msgstr "リセット中"
 
-#: gitk:9758
 msgid "Checking out"
 msgstr "チェックアウト"
 
-#: gitk:9811
 msgid "Cannot delete the currently checked-out branch"
 msgstr "現在チェックアウトされているブランチを削除することはできません"
 
-#: gitk:9817
 #, tcl-format
 msgid ""
 "The commits on branch %s aren't on any other branch.\n"
@@ -1146,16 +892,13 @@
 "ブランチ %s には他のブランチに存在しないコミットがあります。\n"
 "本当にブランチ %s を削除しますか?"
 
-#: gitk:9848
 #, tcl-format
 msgid "Tags and heads: %s"
 msgstr "タグとHEAD: %s"
 
-#: gitk:9865
 msgid "Filter"
 msgstr "フィルター"
 
-#: gitk:10161
 msgid ""
 "Error reading commit topology information; branch and preceding/following "
 "tag information will be incomplete."
@@ -1163,201 +906,152 @@
 "コミット構造情報読み込みエラー; ブランチ及び上位/下位のタグ情報が不完全である"
 "ようです。"
 
-#: gitk:11138
 msgid "Tag"
 msgstr "タグ"
 
-#: gitk:11142
 msgid "Id"
 msgstr "ID"
 
-#: gitk:11225
 msgid "Gitk font chooser"
 msgstr "Gitk フォント選択"
 
-#: gitk:11242
 msgid "B"
 msgstr "B"
 
-#: gitk:11245
 msgid "I"
 msgstr "I"
 
-#: gitk:11363
 msgid "Commit list display options"
 msgstr "コミットリスト表示オプション"
 
-#: gitk:11366
 msgid "Maximum graph width (lines)"
 msgstr "最大グラフ幅(線の本数)"
 
-#: gitk:11370
 #, no-tcl-format
 msgid "Maximum graph width (% of pane)"
 msgstr "最大グラフ幅(ペインに対する%)"
 
-#: gitk:11373
 msgid "Show local changes"
 msgstr "ローカルな変更を表示"
 
-#: gitk:11376
 msgid "Auto-select SHA1 (length)"
 msgstr "SHA1 の自動選択 (選択文字数指定)"
 
-#: gitk:11380
 msgid "Hide remote refs"
 msgstr "リモートリファレンスを隠す"
 
-#: gitk:11384
 msgid "Diff display options"
 msgstr "diff表示オプション"
 
-#: gitk:11386
 msgid "Tab spacing"
 msgstr "タブ空白幅"
 
-#: gitk:11389
 msgid "Display nearby tags/heads"
 msgstr "近くの タグ/head を表示する"
 
-#: gitk:11392
 msgid "Maximum # tags/heads to show"
 msgstr "タグ/head の最大表示数"
 
-#: gitk:11395
 msgid "Limit diffs to listed paths"
 msgstr "diff をリストのパスに制限"
 
-#: gitk:11398
 msgid "Support per-file encodings"
 msgstr "ファイルごとのエンコーディングのサポート"
 
-#: gitk:11404 gitk:11551
 msgid "External diff tool"
 msgstr "外部diffツール"
 
-#: gitk:11405
 msgid "Choose..."
 msgstr "選択..."
 
-#: gitk:11410
 msgid "General options"
 msgstr "全体設定"
 
-#: gitk:11413
 msgid "Use themed widgets"
 msgstr "テーマウィジェットを使用する"
 
-#: gitk:11415
 msgid "(change requires restart)"
 msgstr "(変更には再起動が必要です)"
 
-#: gitk:11417
 msgid "(currently unavailable)"
 msgstr "(現在は使用出来ません)"
 
-#: gitk:11428
 msgid "Colors: press to choose"
 msgstr "色: ボタンを押して選択"
 
-#: gitk:11431
 msgid "Interface"
 msgstr "インターフェイス"
 
-#: gitk:11432
 msgid "interface"
 msgstr "インターフェイス"
 
-#: gitk:11435
 msgid "Background"
 msgstr "背景"
 
-#: gitk:11436 gitk:11466
 msgid "background"
 msgstr "背景"
 
-#: gitk:11439
 msgid "Foreground"
 msgstr "前景"
 
-#: gitk:11440
 msgid "foreground"
 msgstr "前景"
 
-#: gitk:11443
 msgid "Diff: old lines"
 msgstr "Diff: 旧バージョン"
 
-#: gitk:11444
 msgid "diff old lines"
 msgstr "diff 旧バージョン"
 
-#: gitk:11448
 msgid "Diff: new lines"
 msgstr "Diff: 新バージョン"
 
-#: gitk:11449
 msgid "diff new lines"
 msgstr "diff 新バージョン"
 
-#: gitk:11453
 msgid "Diff: hunk header"
 msgstr "Diff: hunkヘッダ"
 
-#: gitk:11455
 msgid "diff hunk header"
 msgstr "diff hunkヘッダ"
 
-#: gitk:11459
 msgid "Marked line bg"
 msgstr "マーク行の背景"
 
-#: gitk:11461
 msgid "marked line background"
 msgstr "マーク行の背景"
 
-#: gitk:11465
 msgid "Select bg"
 msgstr "選択の背景"
 
-#: gitk:11474
 msgid "Fonts: press to choose"
 msgstr "フォント: ボタンを押して選択"
 
-#: gitk:11476
 msgid "Main font"
 msgstr "主フォント"
 
-#: gitk:11477
 msgid "Diff display font"
 msgstr "Diff表示用フォント"
 
-#: gitk:11478
 msgid "User interface font"
 msgstr "UI用フォント"
 
-#: gitk:11500
 msgid "Gitk preferences"
 msgstr "Gitk 設定"
 
-#: gitk:11509
 msgid "General"
 msgstr "一般"
 
-#: gitk:11510
 msgid "Colors"
 msgstr "色"
 
-#: gitk:11511
 msgid "Fonts"
 msgstr "フォント"
 
-#: gitk:11561
 #, tcl-format
 msgid "Gitk: choose color for %s"
 msgstr "Gitk: 「%s」 の色を選択"
 
-#: gitk:12074
 msgid ""
 "Sorry, gitk cannot run with this version of Tcl/Tk.\n"
 " Gitk requires at least Tcl/Tk 8.4."
@@ -1365,15 +1059,12 @@
 "申し訳ありませんが、このバージョンの Tcl/Tk では gitk を実行出来ません。\n"
 "Gitkの実行には Tcl/Tk 8.4 以上が必要です。"
 
-#: gitk:12284
 msgid "Cannot find a git repository here."
 msgstr "ここにはgitリポジトリがありません。"
 
-#: gitk:12331
 #, tcl-format
 msgid "Ambiguous argument '%s': both revision and filename"
 msgstr "あいまいな引数 '%s': リビジョンとファイル名の両方に解釈できます"
 
-#: gitk:12343
 msgid "Bad arguments to gitk:"
 msgstr "gitkへの不正な引数:"
diff --git a/gitk-git/po/pt_br.po b/gitk-git/po/pt_br.po
index 1feb348..e78fb26 100644
--- a/gitk-git/po/pt_br.po
+++ b/gitk-git/po/pt_br.po
@@ -7,7 +7,7 @@
 #, fuzzy
 msgid ""
 msgstr ""
-"Project-Id-Version: gitk\n"
+"Project-Id-Version: Gitk\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2015-05-17 14:32+1000\n"
 "PO-Revision-Date: 2010-12-06 23:39-0200\n"
@@ -18,33 +18,26 @@
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: gitk:140
 msgid "Couldn't get list of unmerged files:"
 msgstr "Não foi possível obter a lista dos arquivos não mesclados:"
 
-#: gitk:212 gitk:2381
 msgid "Color words"
 msgstr ""
 
-#: gitk:217 gitk:2381 gitk:8220 gitk:8253
 msgid "Markup words"
 msgstr ""
 
-#: gitk:324
 msgid "Error parsing revisions:"
 msgstr "Erro ao interpretar revisões:"
 
-#: gitk:380
 msgid "Error executing --argscmd command:"
 msgstr "Erro ao executar o comando--argscmd:"
 
-#: gitk:393
 msgid "No files selected: --merge specified but no files are unmerged."
 msgstr ""
 "Nenhum arquivo foi selecionado: --merge especificado mas não há arquivos não-"
 "mesclados."
 
-#: gitk:396
 msgid ""
 "No files selected: --merge specified but no unmerged files are within file "
 "limit."
@@ -52,317 +45,237 @@
 "Nenhum arquivo foi selecionado: --merge especificado mas não há arquivos não-"
 "mesclados dentro dos limites."
 
-#: gitk:418 gitk:566
 msgid "Error executing git log:"
 msgstr "Erro ao executar git log:"
 
-#: gitk:436 gitk:582
 msgid "Reading"
 msgstr "Lendo"
 
-#: gitk:496 gitk:4525
 msgid "Reading commits..."
 msgstr "Lendo revisões..."
 
-#: gitk:499 gitk:1637 gitk:4528
 msgid "No commits selected"
 msgstr "Nenhuma revisão foi selecionada"
 
-#: gitk:1445 gitk:4045 gitk:12432
 msgid "Command line"
 msgstr "Linha de comando"
 
-#: gitk:1511
 msgid "Can't parse git log output:"
 msgstr "Não foi possível interpretar a saída do \"git log\":"
 
-#: gitk:1740
 msgid "No commit information available"
 msgstr "Não há informações disponíveis sobre a revisão"
 
-#: gitk:1903 gitk:1932 gitk:4315 gitk:9669 gitk:11241 gitk:11521
 msgid "OK"
 msgstr "Ok"
 
-#: gitk:1934 gitk:4317 gitk:9196 gitk:9275 gitk:9391 gitk:9440 gitk:9671
-#: gitk:11242 gitk:11522
 msgid "Cancel"
 msgstr "Cancelar"
 
-#: gitk:2069
 msgid "&Update"
 msgstr "Atualizar"
 
-#: gitk:2070
 msgid "&Reload"
 msgstr "Recarregar"
 
-#: gitk:2071
 msgid "Reread re&ferences"
 msgstr "Ler as referências novamente"
 
-#: gitk:2072
 msgid "&List references"
 msgstr "Listar referências"
 
-#: gitk:2074
 msgid "Start git &gui"
 msgstr "Iniciar Git GUI"
 
-#: gitk:2076
 msgid "&Quit"
 msgstr "Sair"
 
-#: gitk:2068
 msgid "&File"
 msgstr "Arquivo"
 
-#: gitk:2080
 msgid "&Preferences"
 msgstr "Preferências"
 
-#: gitk:2079
 msgid "&Edit"
 msgstr "Editar"
 
-#: gitk:2084
 msgid "&New view..."
 msgstr "Nova vista..."
 
-#: gitk:2085
 msgid "&Edit view..."
 msgstr "Editar vista..."
 
-#: gitk:2086
 msgid "&Delete view"
 msgstr "Apagar vista"
 
-#: gitk:2088 gitk:4043
 msgid "&All files"
 msgstr "Todos os arquivos"
 
-#: gitk:2083 gitk:4067
 msgid "&View"
 msgstr "Exibir"
 
-#: gitk:2093 gitk:2103 gitk:3012
 msgid "&About gitk"
 msgstr "Sobre o gitk"
 
-#: gitk:2094 gitk:2108
 msgid "&Key bindings"
 msgstr "Atalhos de teclado"
 
-#: gitk:2092 gitk:2107
 msgid "&Help"
 msgstr "Ajuda"
 
-#: gitk:2185 gitk:8652
 msgid "SHA1 ID:"
 msgstr "SHA1 ID:"
 
-#: gitk:2229
 msgid "Row"
 msgstr "Linha"
 
-#: gitk:2267
 msgid "Find"
 msgstr "Encontrar"
 
-#: gitk:2295
 msgid "commit"
 msgstr "Revisão"
 
-#: gitk:2299 gitk:2301 gitk:4687 gitk:4710 gitk:4734 gitk:6755 gitk:6827
-#: gitk:6912
 msgid "containing:"
 msgstr "contendo:"
 
-#: gitk:2302 gitk:3526 gitk:3531 gitk:4763
 msgid "touching paths:"
 msgstr "envolvendo os caminhos:"
 
-#: gitk:2303 gitk:4777
 msgid "adding/removing string:"
 msgstr "Adicionando/removendo texto:"
 
-#: gitk:2304 gitk:4779
 msgid "changing lines matching:"
 msgstr ""
 
-#: gitk:2313 gitk:2315 gitk:4766
 msgid "Exact"
 msgstr "Exatamente"
 
-#: gitk:2315 gitk:4854 gitk:6723
 msgid "IgnCase"
 msgstr "Ignorar maiúsculas/minúsculas"
 
-#: gitk:2315 gitk:4736 gitk:4852 gitk:6719
 msgid "Regexp"
 msgstr "Expressão regular"
 
-#: gitk:2317 gitk:2318 gitk:4874 gitk:4904 gitk:4911 gitk:6848 gitk:6916
 msgid "All fields"
 msgstr "Todos os campos"
 
-#: gitk:2318 gitk:4871 gitk:4904 gitk:6786
 msgid "Headline"
 msgstr "Assunto"
 
-#: gitk:2319 gitk:4871 gitk:6786 gitk:6916 gitk:7389
 msgid "Comments"
 msgstr "Descrição da revisão"
 
-#: gitk:2319 gitk:4871 gitk:4876 gitk:4911 gitk:6786 gitk:7324 gitk:8830
-#: gitk:8845
 msgid "Author"
 msgstr "Autor"
 
-#: gitk:2319 gitk:4871 gitk:6786 gitk:7326
 msgid "Committer"
 msgstr "Revisor"
 
-#: gitk:2350
 msgid "Search"
 msgstr "Buscar"
 
-#: gitk:2358
 msgid "Diff"
 msgstr "Diferenças"
 
-#: gitk:2360
 msgid "Old version"
 msgstr "Versão antiga"
 
-#: gitk:2362
 msgid "New version"
 msgstr "Versão nova"
 
-#: gitk:2364
 msgid "Lines of context"
 msgstr "Número de linhas de contexto"
 
-#: gitk:2374
 msgid "Ignore space change"
 msgstr "Ignorar mudanças de caixa"
 
-#: gitk:2378 gitk:2380 gitk:7959 gitk:8206
 msgid "Line diff"
 msgstr ""
 
-#: gitk:2445
 msgid "Patch"
 msgstr "Diferenças"
 
-#: gitk:2447
 msgid "Tree"
 msgstr "Árvore"
 
-#: gitk:2617 gitk:2637
 msgid "Diff this -> selected"
 msgstr "Comparar esta revisão com a selecionada"
 
-#: gitk:2618 gitk:2638
 msgid "Diff selected -> this"
 msgstr "Comparar a revisão selecionada com esta"
 
-#: gitk:2619 gitk:2639
 msgid "Make patch"
 msgstr "Criar patch"
 
-#: gitk:2620 gitk:9254
 msgid "Create tag"
 msgstr "Criar etiqueta"
 
-#: gitk:2621 gitk:9371
 msgid "Write commit to file"
 msgstr "Salvar revisão para um arquivo"
 
-#: gitk:2622 gitk:9428
 msgid "Create new branch"
 msgstr "Criar novo ramo"
 
-#: gitk:2623
 msgid "Cherry-pick this commit"
 msgstr "Fazer cherry-pick desta revisão"
 
-#: gitk:2624
 msgid "Reset HEAD branch to here"
 msgstr "Redefinir HEAD para cá"
 
-#: gitk:2625
 msgid "Mark this commit"
 msgstr "Marcar esta revisão"
 
-#: gitk:2626
 msgid "Return to mark"
 msgstr "Voltar à marca"
 
-#: gitk:2627
 msgid "Find descendant of this and mark"
 msgstr "Encontrar descendente e marcar"
 
-#: gitk:2628
 msgid "Compare with marked commit"
 msgstr "Comparar com a revisão marcada"
 
-#: gitk:2629 gitk:2640
 #, fuzzy
 msgid "Diff this -> marked commit"
 msgstr "Comparar esta revisão com a selecionada"
 
-#: gitk:2630 gitk:2641
 #, fuzzy
 msgid "Diff marked commit -> this"
 msgstr "Comparar a revisão selecionada com esta"
 
-#: gitk:2631
 #, fuzzy
 msgid "Revert this commit"
 msgstr "Marcar esta revisão"
 
-#: gitk:2647
 msgid "Check out this branch"
 msgstr "Efetuar checkout deste ramo"
 
-#: gitk:2648
 msgid "Remove this branch"
 msgstr "Excluir este ramo"
 
-#: gitk:2649
 msgid "Copy branch name"
 msgstr ""
 
-#: gitk:2656
 msgid "Highlight this too"
 msgstr "Marcar este também"
 
-#: gitk:2657
 msgid "Highlight this only"
 msgstr "Marcar apenas este"
 
-#: gitk:2658
 msgid "External diff"
 msgstr "Diff externo"
 
-#: gitk:2659
 msgid "Blame parent commit"
 msgstr "Anotar revisão anterior"
 
-#: gitk:2660
 msgid "Copy path"
 msgstr ""
 
-#: gitk:2667
 msgid "Show origin of this line"
 msgstr "Exibir origem desta linha"
 
-#: gitk:2668
 msgid "Run git gui blame on this line"
 msgstr "Executar 'git blame' nesta linha"
 
-#: gitk:3014
 #, fuzzy
 msgid ""
 "\n"
@@ -379,320 +292,248 @@
 "\n"
 "Uso e distribuição segundo os termos da Licença Pública Geral GNU"
 
-#: gitk:3022 gitk:3089 gitk:9857
 msgid "Close"
 msgstr "Fechar"
 
-#: gitk:3043
 msgid "Gitk key bindings"
 msgstr "Atalhos de teclado"
 
-#: gitk:3046
 msgid "Gitk key bindings:"
 msgstr "Atalhos de teclado:"
 
-#: gitk:3048
 #, tcl-format
 msgid "<%s-Q>\t\tQuit"
 msgstr "<%s-Q>\t\tSair"
 
-#: gitk:3049
 #, tcl-format
 msgid "<%s-W>\t\tClose window"
 msgstr "<%s-W>\t\tFechar janela"
 
-#: gitk:3050
 msgid "<Home>\t\tMove to first commit"
 msgstr "<Home>\t\tIr para a primeira revisão"
 
-#: gitk:3051
 msgid "<End>\t\tMove to last commit"
 msgstr "<End>\t\tIr para a última revisão"
 
-#: gitk:3052
 #, fuzzy
 msgid "<Up>, p, k\tMove up one commit"
 msgstr "<Up>, p, i\tIr para uma revisão acima"
 
-#: gitk:3053
 #, fuzzy
 msgid "<Down>, n, j\tMove down one commit"
 msgstr "<Down>, n, k\tIr para uma revisão abaixo"
 
-#: gitk:3054
 #, fuzzy
 msgid "<Left>, z, h\tGo back in history list"
 msgstr "<Left>, z, j\tVoltar no histórico"
 
-#: gitk:3055
 msgid "<Right>, x, l\tGo forward in history list"
 msgstr "<Right>, x, l\tAvançar no histórico"
 
-#: gitk:3056
 #, tcl-format
 msgid "<%s-n>\tGo to n-th parent of current commit in history list"
 msgstr ""
 
-#: gitk:3057
 msgid "<PageUp>\tMove up one page in commit list"
 msgstr "<PageUp>\tSubir uma página na lista de revisões"
 
-#: gitk:3058
 msgid "<PageDown>\tMove down one page in commit list"
 msgstr "<PageDown>\tDescer uma página na lista de revisões"
 
-#: gitk:3059
 #, tcl-format
 msgid "<%s-Home>\tScroll to top of commit list"
 msgstr "<%s-Home>\tRolar para o início da lista de revisões"
 
-#: gitk:3060
 #, tcl-format
 msgid "<%s-End>\tScroll to bottom of commit list"
 msgstr "<%s-End>\tRolar para o final da lista de revisões"
 
-#: gitk:3061
 #, tcl-format
 msgid "<%s-Up>\tScroll commit list up one line"
 msgstr "<%s-Up>\tRolar uma linha acima na lista de revisões"
 
-#: gitk:3062
 #, tcl-format
 msgid "<%s-Down>\tScroll commit list down one line"
 msgstr "<%s-Down>\tRolar uma linha abaixo na lista de revisões"
 
-#: gitk:3063
 #, tcl-format
 msgid "<%s-PageUp>\tScroll commit list up one page"
 msgstr "<%s-PageUp>\tRolar uma página acima na lista de revisões"
 
-#: gitk:3064
 #, tcl-format
 msgid "<%s-PageDown>\tScroll commit list down one page"
 msgstr "<%s-PageDown>\tRolar uma página abaixo na lista de revisões"
 
-#: gitk:3065
 msgid "<Shift-Up>\tFind backwards (upwards, later commits)"
 msgstr "<Shift-Up>\tProcurar próxima (revisões mas recentes)"
 
-#: gitk:3066
 msgid "<Shift-Down>\tFind forwards (downwards, earlier commits)"
 msgstr "<Shift-Down>\tProcurar anterior (revisões mais antigas)"
 
-#: gitk:3067
 msgid "<Delete>, b\tScroll diff view up one page"
 msgstr "<Delete>, b\tRola alterações uma página acima"
 
-#: gitk:3068
 msgid "<Backspace>\tScroll diff view up one page"
 msgstr "<Backspace>\tRolar alterações uma página abaixo"
 
-#: gitk:3069
 msgid "<Space>\t\tScroll diff view down one page"
 msgstr "<Space>\t\tRolar alterações uma página abaixo"
 
-#: gitk:3070
 msgid "u\t\tScroll diff view up 18 lines"
 msgstr "u\t\tRolar alterações 18 linhas acima"
 
-#: gitk:3071
 msgid "d\t\tScroll diff view down 18 lines"
 msgstr "d\t\tRolar alterações 18 linhas abaixo"
 
-#: gitk:3072
 #, tcl-format
 msgid "<%s-F>\t\tFind"
 msgstr "<%s-F>\t\tProcurar"
 
-#: gitk:3073
 #, tcl-format
 msgid "<%s-G>\t\tMove to next find hit"
 msgstr "<%s-G>\t\tIr para a próxima ocorrência"
 
-#: gitk:3074
 msgid "<Return>\tMove to next find hit"
 msgstr "<Return>\tIr para a próxima ocorrência"
 
-#: gitk:3075
 #, fuzzy
 msgid "g\t\tGo to commit"
 msgstr "<End>\t\tIr para a última revisão"
 
-#: gitk:3076
 msgid "/\t\tFocus the search box"
 msgstr "/\t\tPor foco na caixa de busca"
 
-#: gitk:3077
 msgid "?\t\tMove to previous find hit"
 msgstr "?\t\tIr para a ocorrência anterior"
 
-#: gitk:3078
 msgid "f\t\tScroll diff view to next file"
 msgstr "f\t\tRolar alterações para o próximo arquivo"
 
-#: gitk:3079
 #, tcl-format
 msgid "<%s-S>\t\tSearch for next hit in diff view"
 msgstr "<%s-S>\t\tProcurar a próxima ocorrência na lista de alterações"
 
-#: gitk:3080
 #, tcl-format
 msgid "<%s-R>\t\tSearch for previous hit in diff view"
 msgstr "<%s-R>\t\tProcurar ocorrência anterior na lista de alterações"
 
-#: gitk:3081
 #, tcl-format
 msgid "<%s-KP+>\tIncrease font size"
 msgstr "<%s-KP+>\tAumentar tamanho da fonte"
 
-#: gitk:3082
 #, tcl-format
 msgid "<%s-plus>\tIncrease font size"
 msgstr "<%s-plus>\tAumentar tamanho da fonte"
 
-#: gitk:3083
 #, tcl-format
 msgid "<%s-KP->\tDecrease font size"
 msgstr "<%s-KP->\tReduzir tamanho da fonte"
 
-#: gitk:3084
 #, tcl-format
 msgid "<%s-minus>\tDecrease font size"
 msgstr "<%s-minus>\tReduzir tamanho da fonte"
 
-#: gitk:3085
 msgid "<F5>\t\tUpdate"
 msgstr "<F5>\t\tAtualizar"
 
-#: gitk:3550 gitk:3559
 #, tcl-format
 msgid "Error creating temporary directory %s:"
 msgstr "Erro ao criar o diretório temporário %s:"
 
-#: gitk:3572
 #, tcl-format
 msgid "Error getting \"%s\" from %s:"
 msgstr "Erro ao ler \"%s\" de %s:"
 
-#: gitk:3635
 msgid "command failed:"
 msgstr "O comando falhou:"
 
-#: gitk:3784
 msgid "No such commit"
 msgstr "Revisão não encontrada"
 
-#: gitk:3798
 msgid "git gui blame: command failed:"
 msgstr "Comando 'git gui blame' falhou:"
 
-#: gitk:3829
 #, tcl-format
 msgid "Couldn't read merge head: %s"
 msgstr "Impossível ler merge head: %s"
 
-#: gitk:3837
 #, tcl-format
 msgid "Error reading index: %s"
 msgstr "Erro ao ler o índice: %s"
 
-#: gitk:3862
 #, tcl-format
 msgid "Couldn't start git blame: %s"
 msgstr "Não foi possível inciar o 'git blame': %s"
 
-#: gitk:3865 gitk:6754
 msgid "Searching"
 msgstr "Procurando"
 
-#: gitk:3897
 #, tcl-format
 msgid "Error running git blame: %s"
 msgstr "Erro ao executar 'git blame': %s"
 
-#: gitk:3925
 #, tcl-format
 msgid "That line comes from commit %s,  which is not in this view"
 msgstr "Esta linha vem da revisão %s, que não está nesta vista"
 
-#: gitk:3939
 msgid "External diff viewer failed:"
 msgstr "Erro do visualizador de alterações externo:"
 
-#: gitk:4070
 msgid "Gitk view definition"
 msgstr "Definir vista"
 
-#: gitk:4074
 msgid "Remember this view"
 msgstr "Lembrar esta vista"
 
-#: gitk:4075
 msgid "References (space separated list):"
 msgstr "Referências (separar a lista com um espaço):"
 
-#: gitk:4076
 msgid "Branches & tags:"
 msgstr "Ramos & etiquetas:"
 
-#: gitk:4077
 msgid "All refs"
 msgstr "Todas as referências"
 
-#: gitk:4078
 msgid "All (local) branches"
 msgstr "Todos os ramos locais"
 
-#: gitk:4079
 msgid "All tags"
 msgstr "Todas as etiquetas"
 
-#: gitk:4080
 msgid "All remote-tracking branches"
 msgstr "Todos os ramos de rastreio"
 
-#: gitk:4081
 msgid "Commit Info (regular expressions):"
 msgstr "Informações da revisão (expressões regulares):"
 
-#: gitk:4082
 msgid "Author:"
 msgstr "Autor:"
 
-#: gitk:4083
 msgid "Committer:"
 msgstr "Revisor:"
 
-#: gitk:4084
 msgid "Commit Message:"
 msgstr "Descrição da revisão:"
 
-#: gitk:4085
 msgid "Matches all Commit Info criteria"
 msgstr "Coincidir todos os critérios de informações da revisão"
 
-#: gitk:4086
 #, fuzzy
 msgid "Matches no Commit Info criteria"
 msgstr "Coincidir todos os critérios de informações da revisão"
 
-#: gitk:4087
 msgid "Changes to Files:"
 msgstr "Mudanças para os arquivos:"
 
-#: gitk:4088
 msgid "Fixed String"
 msgstr "Texto fixo"
 
-#: gitk:4089
 msgid "Regular Expression"
 msgstr "Expressão regular"
 
-#: gitk:4090
 msgid "Search string:"
 msgstr "Texto de busca"
 
-#: gitk:4091
 msgid ""
 "Commit Dates (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 "
 "15:27:38\"):"
@@ -700,201 +541,153 @@
 "Datas de revisão (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 "
 "15:27:38\"):"
 
-#: gitk:4092
 msgid "Since:"
 msgstr "Desde:"
 
-#: gitk:4093
 msgid "Until:"
 msgstr "Até:"
 
-#: gitk:4094
 msgid "Limit and/or skip a number of revisions (positive integer):"
 msgstr "Limitar e/ou ignorar um número de revisões (inteiro positivo):"
 
-#: gitk:4095
 msgid "Number to show:"
 msgstr "Número para mostrar:"
 
-#: gitk:4096
 msgid "Number to skip:"
 msgstr "Número para ignorar:"
 
-#: gitk:4097
 msgid "Miscellaneous options:"
 msgstr "Opções diversas:"
 
-#: gitk:4098
 msgid "Strictly sort by date"
 msgstr "Ordenar estritamente pela data"
 
-#: gitk:4099
 msgid "Mark branch sides"
 msgstr "Marcar os dois lados do ramo"
 
-#: gitk:4100
 msgid "Limit to first parent"
 msgstr "Limitar ao primeiro antecessor"
 
-#: gitk:4101
 msgid "Simple history"
 msgstr "Histórico simplificado"
 
-#: gitk:4102
 msgid "Additional arguments to git log:"
 msgstr "Argumentos adicionais para o 'git log':"
 
-#: gitk:4103
 msgid "Enter files and directories to include, one per line:"
 msgstr "Arquivos e diretórios para incluir, um por linha"
 
-#: gitk:4104
 msgid "Command to generate more commits to include:"
 msgstr "Comando para gerar mais revisões para incluir:"
 
-#: gitk:4228
 msgid "Gitk: edit view"
 msgstr "Gitk: editar vista"
 
-#: gitk:4236
 msgid "-- criteria for selecting revisions"
 msgstr "-- critérios para selecionar revisões"
 
-#: gitk:4241
 msgid "View Name"
 msgstr "Nome da vista"
 
-#: gitk:4316
 msgid "Apply (F5)"
 msgstr "Aplicar (F5)"
 
-#: gitk:4354
 msgid "Error in commit selection arguments:"
 msgstr "Erro nos argumentos de seleção de revisões:"
 
-#: gitk:4409 gitk:4462 gitk:4924 gitk:4938 gitk:6208 gitk:12373 gitk:12374
 msgid "None"
 msgstr "Nenhum"
 
-#: gitk:5021 gitk:5026
 msgid "Descendant"
 msgstr "Descendente de"
 
-#: gitk:5022
 msgid "Not descendant"
 msgstr "Não descendente de"
 
-#: gitk:5029 gitk:5034
 msgid "Ancestor"
 msgstr "Antecessor de"
 
-#: gitk:5030
 msgid "Not ancestor"
 msgstr "Não antecessor de"
 
-#: gitk:5324
 msgid "Local changes checked in to index but not committed"
 msgstr "Mudanças locais marcadas, porém não salvas"
 
-#: gitk:5360
 msgid "Local uncommitted changes, not checked in to index"
 msgstr "Mudanças locais não marcadas"
 
-#: gitk:7134
 msgid "and many more"
 msgstr ""
 
-#: gitk:7137
 msgid "many"
 msgstr "muitas"
 
-#: gitk:7328
 msgid "Tags:"
 msgstr "Etiquetas:"
 
-#: gitk:7345 gitk:7351 gitk:8825
 msgid "Parent"
 msgstr "Antecessor"
 
-#: gitk:7356
 msgid "Child"
 msgstr "Descendente"
 
-#: gitk:7365
 msgid "Branch"
 msgstr "Ramo"
 
-#: gitk:7368
 msgid "Follows"
 msgstr "Segue"
 
-#: gitk:7371
 msgid "Precedes"
 msgstr "Precede"
 
-#: gitk:7966
 #, tcl-format
 msgid "Error getting diffs: %s"
 msgstr "Erro ao obter diferenças: %s"
 
-#: gitk:8650
 msgid "Goto:"
 msgstr "Ir para:"
 
-#: gitk:8671
 #, tcl-format
 msgid "Short SHA1 id %s is ambiguous"
 msgstr "O id SHA1 %s é ambíguo"
 
-#: gitk:8678
 #, tcl-format
 msgid "Revision %s is not known"
 msgstr "Revisão %s desconhecida"
 
-#: gitk:8688
 #, tcl-format
 msgid "SHA1 id %s is not known"
 msgstr "Id SHA1 %s desconhecido"
 
-#: gitk:8690
 #, tcl-format
 msgid "Revision %s is not in the current view"
 msgstr "A revisão %s não está na vista atual"
 
-#: gitk:8832 gitk:8847
 msgid "Date"
 msgstr "Data"
 
-#: gitk:8835
 msgid "Children"
 msgstr "Descendentes"
 
-#: gitk:8898
 #, tcl-format
 msgid "Reset %s branch to here"
 msgstr "Redefinir ramo %s para este ponto"
 
-#: gitk:8900
 msgid "Detached head: can't reset"
 msgstr "Detached head: impossível redefinir"
 
-#: gitk:9005 gitk:9011
 msgid "Skipping merge commit "
 msgstr "Saltando revisão de mesclagem"
 
-#: gitk:9020 gitk:9025
 msgid "Error getting patch ID for "
 msgstr "Erro ao obter patch ID para"
 
-#: gitk:9021 gitk:9026
 msgid " - stopping\n"
 msgstr "- parando\n"
 
-#: gitk:9031 gitk:9034 gitk:9042 gitk:9056 gitk:9065
 msgid "Commit "
 msgstr "Revisão"
 
-#: gitk:9035
 msgid ""
 " is the same patch as\n"
 "       "
@@ -902,13 +695,11 @@
 "é o mesmo patch que\n"
 "       "
 
-#: gitk:9043
 msgid ""
 " differs from\n"
 "       "
 msgstr "difere de"
 
-#: gitk:9045
 msgid ""
 "Diff of commits:\n"
 "\n"
@@ -916,129 +707,99 @@
 "Diferença de revisões:\n"
 "\n"
 
-#: gitk:9057 gitk:9066
 #, tcl-format
 msgid " has %s children - stopping\n"
 msgstr "possui %s descendentes - parando\n"
 
-#: gitk:9085
 #, tcl-format
 msgid "Error writing commit to file: %s"
 msgstr "Erro ao salvar revisão para o arquivo: %s"
 
-#: gitk:9091
 #, tcl-format
 msgid "Error diffing commits: %s"
 msgstr "Erro ao comparar revisões: %s"
 
-#: gitk:9137
 msgid "Top"
 msgstr "Início"
 
-#: gitk:9138
 msgid "From"
 msgstr "De"
 
-#: gitk:9143
 msgid "To"
 msgstr "Para"
 
-#: gitk:9167
 msgid "Generate patch"
 msgstr "Gerar patch"
 
-#: gitk:9169
 msgid "From:"
 msgstr "De:"
 
-#: gitk:9178
 msgid "To:"
 msgstr "Para:"
 
-#: gitk:9187
 msgid "Reverse"
 msgstr "Inverter"
 
-#: gitk:9189 gitk:9385
 msgid "Output file:"
 msgstr "Arquivo de saída:"
 
-#: gitk:9195
 msgid "Generate"
 msgstr "Gerar"
 
-#: gitk:9233
 msgid "Error creating patch:"
 msgstr "Erro ao criar patch:"
 
-#: gitk:9256 gitk:9373 gitk:9430
 msgid "ID:"
 msgstr "ID:"
 
-#: gitk:9265
 msgid "Tag name:"
 msgstr "Nome da etiqueta:"
 
-#: gitk:9268
 msgid "Tag message is optional"
 msgstr "A descrição da etiqueta é opcional"
 
-#: gitk:9270
 msgid "Tag message:"
 msgstr "Descrição da etiqueta"
 
-#: gitk:9274 gitk:9439
 msgid "Create"
 msgstr "Criar"
 
-#: gitk:9292
 msgid "No tag name specified"
 msgstr "Nome da etiqueta não indicado"
 
-#: gitk:9296
 #, tcl-format
 msgid "Tag \"%s\" already exists"
 msgstr "Etiqueta \"%s\" já existe"
 
-#: gitk:9306
 msgid "Error creating tag:"
 msgstr "Erro ao criar etiqueta:"
 
-#: gitk:9382
 msgid "Command:"
 msgstr "Comando:"
 
-#: gitk:9390
 msgid "Write"
 msgstr "Exportar"
 
-#: gitk:9408
 msgid "Error writing commit:"
 msgstr "Erro ao exportar revisão"
 
-#: gitk:9435
 msgid "Name:"
 msgstr "Nome:"
 
-#: gitk:9458
 msgid "Please specify a name for the new branch"
 msgstr "Indique um nome para o novo ramo"
 
-#: gitk:9463
 #, tcl-format
 msgid "Branch '%s' already exists. Overwrite?"
 msgstr "O ramo \"%s\" já existe. Sobrescrever?"
 
-#: gitk:9530
 #, tcl-format
 msgid "Commit %s is already included in branch %s -- really re-apply it?"
 msgstr "Revisão %s já inclusa no ramo %s -- você realmente deseja reaplicá-la?"
 
-#: gitk:9535
 msgid "Cherry-picking"
 msgstr "Cherry-picking"
 
-#: gitk:9544
 #, tcl-format
 msgid ""
 "Cherry-pick failed because of local changes to file '%s'.\n"
@@ -1048,7 +809,6 @@
 "Salve a uma revisão, redefina ou armazene (stash) suas mudanças e tente "
 "novamente."
 
-#: gitk:9550
 msgid ""
 "Cherry-pick failed because of merge conflict.\n"
 "Do you wish to run git citool to resolve it?"
@@ -1056,21 +816,17 @@
 "O cherry-pick falhou porque houve um conflito na mesclagem.\n"
 "Executar o 'git citool' para resolvê-lo?"
 
-#: gitk:9566 gitk:9624
 msgid "No changes committed"
 msgstr "Nenhuma revisão foi salva"
 
-#: gitk:9593
 #, fuzzy, tcl-format
 msgid "Commit %s is not included in branch %s -- really revert it?"
 msgstr "Revisão %s já inclusa no ramo %s -- você realmente deseja reaplicá-la?"
 
-#: gitk:9598
 #, fuzzy
 msgid "Reverting"
 msgstr "Redefinindo"
 
-#: gitk:9606
 #, fuzzy, tcl-format
 msgid ""
 "Revert failed because of local changes to the following files:%s Please "
@@ -1080,7 +836,6 @@
 "Salve a uma revisão, redefina ou armazene (stash) suas mudanças e tente "
 "novamente."
 
-#: gitk:9610
 #, fuzzy
 msgid ""
 "Revert failed because of merge conflict.\n"
@@ -1089,28 +844,22 @@
 "O cherry-pick falhou porque houve um conflito na mesclagem.\n"
 "Executar o 'git citool' para resolvê-lo?"
 
-#: gitk:9653
 msgid "Confirm reset"
 msgstr "Confirmar redefinição"
 
-#: gitk:9655
 #, tcl-format
 msgid "Reset branch %s to %s?"
 msgstr "Você realmente deseja redefinir o ramo %s para %s?"
 
-#: gitk:9657
 msgid "Reset type:"
 msgstr "Tipo de redefinição"
 
-#: gitk:9660
 msgid "Soft: Leave working tree and index untouched"
 msgstr "Soft: deixa a árvore de trabalho e o índice intocados"
 
-#: gitk:9663
 msgid "Mixed: Leave working tree untouched, reset index"
 msgstr "Misto: Deixa a árvore de trabalho intocada, redefine o índice"
 
-#: gitk:9666
 msgid ""
 "Hard: Reset working tree and index\n"
 "(discard ALL local changes)"
@@ -1118,19 +867,15 @@
 "Hard: Redefine a árvore de trabalho e o índice\n"
 "(descarta TODAS as mudanças locais)"
 
-#: gitk:9683
 msgid "Resetting"
 msgstr "Redefinindo"
 
-#: gitk:9743
 msgid "Checking out"
 msgstr "Abrindo"
 
-#: gitk:9796
 msgid "Cannot delete the currently checked-out branch"
 msgstr "Impossível excluir o ramo atualmente aberto"
 
-#: gitk:9802
 #, tcl-format
 msgid ""
 "The commits on branch %s aren't on any other branch.\n"
@@ -1139,16 +884,13 @@
 "As revisões do ramo \"%s\" não existem em nenhum outro ramo.\n"
 "Você realmente deseja excluir ramo \"%s\"?"
 
-#: gitk:9833
 #, tcl-format
 msgid "Tags and heads: %s"
 msgstr "Referências: %s"
 
-#: gitk:9850
 msgid "Filter"
 msgstr "Filtro"
 
-#: gitk:10146
 msgid ""
 "Error reading commit topology information; branch and preceding/following "
 "tag information will be incomplete."
@@ -1156,221 +898,169 @@
 "Erro ao ler a topologia das revisões; as informações dos ramos e etiquetas "
 "antecessoras/sucessoras estarão incompletas"
 
-#: gitk:11123
 msgid "Tag"
 msgstr "Etiqueta"
 
-#: gitk:11127
 msgid "Id"
 msgstr "Id"
 
-#: gitk:11210
 msgid "Gitk font chooser"
 msgstr "Selecionar fontes do Gitk"
 
-#: gitk:11227
 msgid "B"
 msgstr "B"
 
-#: gitk:11230
 msgid "I"
 msgstr "I"
 
-#: gitk:11348
 msgid "Commit list display options"
 msgstr "Opções da lista de revisões"
 
-#: gitk:11351
 msgid "Maximum graph width (lines)"
 msgstr "Largura máxima do grafo (linhas)"
 
-#: gitk:11355
 #, no-tcl-format
 msgid "Maximum graph width (% of pane)"
 msgstr "Largura máxima do grafo (% do painel)"
 
-#: gitk:11358
 msgid "Show local changes"
 msgstr "Exibir mudanças locais"
 
-#: gitk:11361
 #, fuzzy
 msgid "Auto-select SHA1 (length)"
 msgstr "Selecionar o SHA1 automaticamente"
 
-#: gitk:11365
 msgid "Hide remote refs"
 msgstr "Ocultar referências remotas"
 
-#: gitk:11369
 msgid "Diff display options"
 msgstr "Opções de exibição das alterações"
 
-#: gitk:11371
 msgid "Tab spacing"
 msgstr "Espaços por tabulação"
 
-#: gitk:11374
 #, fuzzy
 msgid "Display nearby tags/heads"
 msgstr "Exibir etiquetas próximas"
 
-#: gitk:11377
 msgid "Maximum # tags/heads to show"
 msgstr ""
 
-#: gitk:11380
 msgid "Limit diffs to listed paths"
 msgstr "Limitar diferenças aos caminhos listados"
 
-#: gitk:11383
 msgid "Support per-file encodings"
 msgstr "Usar codificações distintas por arquivo"
 
-#: gitk:11389 gitk:11536
 msgid "External diff tool"
 msgstr "Ferramenta 'diff' externa"
 
-#: gitk:11390
 msgid "Choose..."
 msgstr "Selecionar..."
 
-#: gitk:11395
 msgid "General options"
 msgstr "Opções gerais"
 
-#: gitk:11398
 msgid "Use themed widgets"
 msgstr "Usar temas para as janelas"
 
-#: gitk:11400
 msgid "(change requires restart)"
 msgstr "(exige reinicialização)"
 
-#: gitk:11402
 msgid "(currently unavailable)"
 msgstr "(atualmente indisponível)"
 
-#: gitk:11413
 msgid "Colors: press to choose"
 msgstr "Cores: clique para escolher"
 
-#: gitk:11416
 msgid "Interface"
 msgstr "Interface"
 
-#: gitk:11417
 msgid "interface"
 msgstr "interface"
 
-#: gitk:11420
 msgid "Background"
 msgstr "Segundo plano"
 
-#: gitk:11421 gitk:11451
 msgid "background"
 msgstr "segundo plano"
 
-#: gitk:11424
 msgid "Foreground"
 msgstr "Primeiro plano"
 
-#: gitk:11425
 msgid "foreground"
 msgstr "primeiro plano"
 
-#: gitk:11428
 msgid "Diff: old lines"
 msgstr "Diff: linhas excluídas"
 
-#: gitk:11429
 msgid "diff old lines"
 msgstr "linhas excluídas"
 
-#: gitk:11433
 msgid "Diff: new lines"
 msgstr "Diff: linhas adicionadas"
 
-#: gitk:11434
 msgid "diff new lines"
 msgstr "linhas adicionadas"
 
-#: gitk:11438
 msgid "Diff: hunk header"
 msgstr "Diff: cabeçalho do bloco"
 
-#: gitk:11440
 msgid "diff hunk header"
 msgstr "cabeçalho do bloco"
 
-#: gitk:11444
 msgid "Marked line bg"
 msgstr "2º plano da linha marcada"
 
-#: gitk:11446
 msgid "marked line background"
 msgstr "segundo plano da linha marcada"
 
-#: gitk:11450
 msgid "Select bg"
 msgstr "2º plano da seleção"
 
-#: gitk:11459
 msgid "Fonts: press to choose"
 msgstr "Fontes: clique para escolher"
 
-#: gitk:11461
 msgid "Main font"
 msgstr "Fonte principal"
 
-#: gitk:11462
 msgid "Diff display font"
 msgstr "Fonte da lista de mudanças"
 
-#: gitk:11463
 msgid "User interface font"
 msgstr "Fonte da interface"
 
-#: gitk:11485
 msgid "Gitk preferences"
 msgstr "Preferências do Gitk"
 
-#: gitk:11494
 #, fuzzy
 msgid "General"
 msgstr "Gerar"
 
-#: gitk:11495
 msgid "Colors"
 msgstr ""
 
-#: gitk:11496
 msgid "Fonts"
 msgstr ""
 
-#: gitk:11546
 #, tcl-format
 msgid "Gitk: choose color for %s"
 msgstr "Gitk: selecionar cor para %s"
 
-#: gitk:12059
 msgid ""
 "Sorry, gitk cannot run with this version of Tcl/Tk.\n"
 " Gitk requires at least Tcl/Tk 8.4."
 msgstr ""
 
-#: gitk:12269
 msgid "Cannot find a git repository here."
 msgstr "Não há nenhum repositório git aqui."
 
-#: gitk:12316
 #, tcl-format
 msgid "Ambiguous argument '%s': both revision and filename"
 msgstr ""
 "O argumento \"%s\" é ambíguo (especifica tanto uma revisão e um nome de "
 "arquivo)"
 
-#: gitk:12328
 msgid "Bad arguments to gitk:"
 msgstr "Argumentos incorretos para o gitk:"
 
diff --git a/gitk-git/po/pt_pt.po b/gitk-git/po/pt_pt.po
index f680ea8..66d3159 100644
--- a/gitk-git/po/pt_pt.po
+++ b/gitk-git/po/pt_pt.po
@@ -4,7 +4,7 @@
 # Vasco Almeida <vascomalmeida@sapo.pt>, 2016.
 msgid ""
 msgstr ""
-"Project-Id-Version: gitk\n"
+"Project-Id-Version: Gitk\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2016-04-15 16:52+0000\n"
 "PO-Revision-Date: 2016-05-06 15:35+0000\n"
@@ -17,33 +17,26 @@
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 "X-Generator: Virtaal 0.7.1\n"
 
-#: gitk:140
 msgid "Couldn't get list of unmerged files:"
 msgstr "Não foi possível obter lista de ficheiros não integrados:"
 
-#: gitk:212 gitk:2399
 msgid "Color words"
 msgstr "Colorir palavras"
 
-#: gitk:217 gitk:2399 gitk:8239 gitk:8272
 msgid "Markup words"
 msgstr "Marcar palavras"
 
-#: gitk:324
 msgid "Error parsing revisions:"
 msgstr "Erro ao analisar revisões:"
 
-#: gitk:380
 msgid "Error executing --argscmd command:"
 msgstr "Erro ao executar o comando de --argscmd:"
 
-#: gitk:393
 msgid "No files selected: --merge specified but no files are unmerged."
 msgstr ""
 "Nenhum ficheiro selecionado: --merge especificado mas não há ficheiros por "
 "integrar."
 
-#: gitk:396
 msgid ""
 "No files selected: --merge specified but no unmerged files are within file "
 "limit."
@@ -51,322 +44,240 @@
 "Nenhum ficheiro selecionado: --merge especificado mas não há ficheiros por "
 "integrar ao nível de ficheiro."
 
-#: gitk:418 gitk:566
 msgid "Error executing git log:"
 msgstr "Erro ao executar git log:"
 
-#: gitk:436 gitk:582
 msgid "Reading"
 msgstr "A ler"
 
-#: gitk:496 gitk:4544
 msgid "Reading commits..."
 msgstr "A ler commits..."
 
-#: gitk:499 gitk:1637 gitk:4547
 msgid "No commits selected"
 msgstr "Nenhum commit selecionado"
 
-#: gitk:1445 gitk:4064 gitk:12469
 msgid "Command line"
 msgstr "Linha de comandos"
 
-#: gitk:1511
 msgid "Can't parse git log output:"
 msgstr "Não é possível analisar a saída de git log:"
 
-#: gitk:1740
 msgid "No commit information available"
 msgstr "Não há informação disponível sobre o commit"
 
-#: gitk:1903 gitk:1932 gitk:4334 gitk:9702 gitk:11274 gitk:11554
 msgid "OK"
 msgstr "OK"
 
-#: gitk:1934 gitk:4336 gitk:9215 gitk:9294 gitk:9424 gitk:9473 gitk:9704
-#: gitk:11275 gitk:11555
 msgid "Cancel"
 msgstr "Cancelar"
 
-#: gitk:2083
 msgid "&Update"
 msgstr "At&ualizar"
 
-#: gitk:2084
 msgid "&Reload"
 msgstr "&Recarregar"
 
-#: gitk:2085
 msgid "Reread re&ferences"
 msgstr "Reler re&ferências"
 
-#: gitk:2086
 msgid "&List references"
 msgstr "&Listar referências"
 
-#: gitk:2088
 msgid "Start git &gui"
 msgstr "Iniciar git &gui"
 
-#: gitk:2090
 msgid "&Quit"
 msgstr "&Sair"
 
-#: gitk:2082
 msgid "&File"
 msgstr "&Ficheiro"
 
-#: gitk:2094
 msgid "&Preferences"
 msgstr "&Preferências"
 
-#: gitk:2093
 msgid "&Edit"
 msgstr "&Editar"
 
-#: gitk:2098
 msgid "&New view..."
 msgstr "&Nova vista..."
 
-#: gitk:2099
 msgid "&Edit view..."
 msgstr "&Editar vista..."
 
-#: gitk:2100
 msgid "&Delete view"
 msgstr "Elimina&r vista"
 
-#: gitk:2102
 msgid "&All files"
 msgstr "&Todos os ficheiros"
 
-#: gitk:2097
 msgid "&View"
 msgstr "&Ver"
 
-#: gitk:2107 gitk:2117
 msgid "&About gitk"
 msgstr "&Sobre gitk"
 
-#: gitk:2108 gitk:2122
 msgid "&Key bindings"
 msgstr "&Atalhos"
 
-#: gitk:2106 gitk:2121
 msgid "&Help"
 msgstr "&Ajuda"
 
-#: gitk:2199 gitk:8671
 msgid "SHA1 ID:"
 msgstr "ID SHA1:"
 
-#: gitk:2243
 msgid "Row"
 msgstr "Linha"
 
-#: gitk:2281
 msgid "Find"
 msgstr "Procurar"
 
-#: gitk:2309
 msgid "commit"
 msgstr "commit"
 
-#: gitk:2313 gitk:2315 gitk:4706 gitk:4729 gitk:4753 gitk:6774 gitk:6846
-#: gitk:6931
 msgid "containing:"
 msgstr "contendo:"
 
-#: gitk:2316 gitk:3545 gitk:3550 gitk:4782
 msgid "touching paths:"
 msgstr "altera os caminhos:"
 
-#: gitk:2317 gitk:4796
 msgid "adding/removing string:"
 msgstr "adiciona/remove a cadeia:"
 
-#: gitk:2318 gitk:4798
 msgid "changing lines matching:"
 msgstr "altera linhas com:"
 
-#: gitk:2327 gitk:2329 gitk:4785
 msgid "Exact"
 msgstr "Exato"
 
-#: gitk:2329 gitk:4873 gitk:6742
 msgid "IgnCase"
 msgstr "IgnMaiúsculas"
 
-#: gitk:2329 gitk:4755 gitk:4871 gitk:6738
 msgid "Regexp"
 msgstr "Expr. regular"
 
-#: gitk:2331 gitk:2332 gitk:4893 gitk:4923 gitk:4930 gitk:6867 gitk:6935
 msgid "All fields"
 msgstr "Todos os campos"
 
-#: gitk:2332 gitk:4890 gitk:4923 gitk:6805
 msgid "Headline"
 msgstr "Cabeçalho"
 
-#: gitk:2333 gitk:4890 gitk:6805 gitk:6935 gitk:7408
 msgid "Comments"
 msgstr "Comentários"
 
-#: gitk:2333 gitk:4890 gitk:4895 gitk:4930 gitk:6805 gitk:7343 gitk:8849
-#: gitk:8864
 msgid "Author"
 msgstr "Autor"
 
-#: gitk:2333 gitk:4890 gitk:6805 gitk:7345
 msgid "Committer"
 msgstr "Committer"
 
-#: gitk:2367
 msgid "Search"
 msgstr "Pesquisar"
 
-#: gitk:2375
 msgid "Diff"
 msgstr "Diff"
 
-#: gitk:2377
 msgid "Old version"
 msgstr "Versão antiga"
 
-#: gitk:2379
 msgid "New version"
 msgstr "Versão nova"
 
-#: gitk:2382
 msgid "Lines of context"
 msgstr "Linhas de contexto"
 
-#: gitk:2392
 msgid "Ignore space change"
 msgstr "Ignorar espaços"
 
-#: gitk:2396 gitk:2398 gitk:7978 gitk:8225
 msgid "Line diff"
 msgstr "Diff de linha"
 
-#: gitk:2463
 msgid "Patch"
 msgstr "Patch"
 
-#: gitk:2465
 msgid "Tree"
 msgstr "Árvore"
 
-#: gitk:2635 gitk:2656
 msgid "Diff this -> selected"
 msgstr "Diff este -> seleção"
 
-#: gitk:2636 gitk:2657
 msgid "Diff selected -> this"
 msgstr "Diff seleção -> este"
 
-#: gitk:2637 gitk:2658
 msgid "Make patch"
 msgstr "Gerar patch"
 
-#: gitk:2638 gitk:9273
 msgid "Create tag"
 msgstr "Criar tag"
 
-#: gitk:2639
 msgid "Copy commit summary"
 msgstr "Copiar sumário do commit"
 
-#: gitk:2640 gitk:9404
 msgid "Write commit to file"
 msgstr "Escrever commit num ficheiro"
 
-#: gitk:2641 gitk:9461
 msgid "Create new branch"
 msgstr "Criar novo ramo"
 
-#: gitk:2642
 msgid "Cherry-pick this commit"
 msgstr "Efetuar cherry-pick deste commit"
 
-#: gitk:2643
 msgid "Reset HEAD branch to here"
 msgstr "Repor ramo HEAD para aqui"
 
-#: gitk:2644
 msgid "Mark this commit"
 msgstr "Marcar este commit"
 
-#: gitk:2645
 msgid "Return to mark"
 msgstr "Voltar à marca"
 
-#: gitk:2646
 msgid "Find descendant of this and mark"
 msgstr "Encontrar descendeste deste e da marca"
 
-#: gitk:2647
 msgid "Compare with marked commit"
 msgstr "Comparar com o commit marcado"
 
-#: gitk:2648 gitk:2659
 msgid "Diff this -> marked commit"
 msgstr "Diff este -> commit marcado"
 
-#: gitk:2649 gitk:2660
 msgid "Diff marked commit -> this"
 msgstr "Diff commit marcado -> este"
 
-#: gitk:2650
 msgid "Revert this commit"
 msgstr "Reverter este commit"
 
-#: gitk:2666
 msgid "Check out this branch"
 msgstr "Extrair este ramo"
 
-#: gitk:2667
 msgid "Remove this branch"
 msgstr "Remover este ramo"
 
-#: gitk:2668
 msgid "Copy branch name"
 msgstr "Copiar nome do ramo"
 
-#: gitk:2675
 msgid "Highlight this too"
 msgstr "Realçar este também"
 
-#: gitk:2676
 msgid "Highlight this only"
 msgstr "Realçar apenas este"
 
-#: gitk:2677
 msgid "External diff"
 msgstr "Diff externo"
 
-#: gitk:2678
 msgid "Blame parent commit"
 msgstr "Culpar commit pai"
 
-#: gitk:2679
 msgid "Copy path"
 msgstr "Copiar caminho"
 
-#: gitk:2686
 msgid "Show origin of this line"
 msgstr "Mostrar origem deste ficheiro"
 
-#: gitk:2687
 msgid "Run git gui blame on this line"
 msgstr "Executar git gui blame sobre esta linha"
 
-#: gitk:3031
 msgid "About gitk"
 msgstr "Sobre gitk"
 
-#: gitk:3033
 msgid ""
 "\n"
 "Gitk - a commit viewer for git\n"
@@ -382,323 +293,249 @@
 "\n"
 "Use e redistribua sob os termos da GNU General Public License"
 
-#: gitk:3041 gitk:3108 gitk:9890
 msgid "Close"
 msgstr "Fechar"
 
-#: gitk:3062
 msgid "Gitk key bindings"
 msgstr "Atalhos do gitk"
 
-#: gitk:3065
 msgid "Gitk key bindings:"
 msgstr "Atalhos do gitk:"
 
-#: gitk:3067
 #, tcl-format
 msgid "<%s-Q>\t\tQuit"
 msgstr "<%s-Q>\t\tSair"
 
-#: gitk:3068
 #, tcl-format
 msgid "<%s-W>\t\tClose window"
 msgstr "<%s-W>\t\tFechar janela"
 
-#: gitk:3069
 msgid "<Home>\t\tMove to first commit"
 msgstr "<Home>\t\tMover para o primeiro commit"
 
-#: gitk:3070
 msgid "<End>\t\tMove to last commit"
 msgstr "<End>\t\tMover para o último commit"
 
-#: gitk:3071
 msgid "<Up>, p, k\tMove up one commit"
 msgstr "<Cima>, p, k\tMover para o commit acima"
 
-#: gitk:3072
 msgid "<Down>, n, j\tMove down one commit"
 msgstr "<Baixo>, n, j\tMover para o commit abaixo"
 
-#: gitk:3073
 msgid "<Left>, z, h\tGo back in history list"
 msgstr "<Esquerda>, z, h\tRecuar no histórico"
 
-#: gitk:3074
 msgid "<Right>, x, l\tGo forward in history list"
 msgstr "<Direita>, x, l\tAvançar no histórico"
 
-#: gitk:3075
 #, tcl-format
 msgid "<%s-n>\tGo to n-th parent of current commit in history list"
 msgstr "<%s-n>\tIr para o n-ésimo pai do commit atual no histórico"
 
-#: gitk:3076
 msgid "<PageUp>\tMove up one page in commit list"
 msgstr "<PageUp>\tMover a lista de commits uma página para cima"
 
-#: gitk:3077
 msgid "<PageDown>\tMove down one page in commit list"
 msgstr "<PageDown>\tMover a lista de commits uma página para baixo"
 
-#: gitk:3078
 #, tcl-format
 msgid "<%s-Home>\tScroll to top of commit list"
 msgstr "<%s-Home>\tDeslocar para o topo da lista"
 
-#: gitk:3079
 #, tcl-format
 msgid "<%s-End>\tScroll to bottom of commit list"
 msgstr "<%s-End>\tDeslocar para o fim da lista"
 
-#: gitk:3080
 #, tcl-format
 msgid "<%s-Up>\tScroll commit list up one line"
 msgstr "<%s-Cima>\tDeslocar a lista de commits uma linha para cima"
 
-#: gitk:3081
 #, tcl-format
 msgid "<%s-Down>\tScroll commit list down one line"
 msgstr "<%s-Baixo>\tDeslocar a lista de commits uma linha para baixo"
 
-#: gitk:3082
 #, tcl-format
 msgid "<%s-PageUp>\tScroll commit list up one page"
 msgstr "<%s-PageUp>\tDeslocar a lista de commits uma página para cima"
 
-#: gitk:3083
 #, tcl-format
 msgid "<%s-PageDown>\tScroll commit list down one page"
 msgstr "<%s-PageDown>\tDeslocar a lista de commits uma página para baixo"
 
-#: gitk:3084
 msgid "<Shift-Up>\tFind backwards (upwards, later commits)"
 msgstr "<Shift-Cima>\tProcurar para trás (para cima, commits posteriores)"
 
-#: gitk:3085
 msgid "<Shift-Down>\tFind forwards (downwards, earlier commits)"
 msgstr "<Shift-Baixo>\tProcurar para a frente (para baixo, commits anteriores)"
 
-#: gitk:3086
 msgid "<Delete>, b\tScroll diff view up one page"
 msgstr "<Delete>, b\tDeslocar vista diff uma página para cima"
 
-#: gitk:3087
 msgid "<Backspace>\tScroll diff view up one page"
 msgstr "<Retrocesso>\tDeslocar vista diff uma página para cima"
 
-#: gitk:3088
 msgid "<Space>\t\tScroll diff view down one page"
 msgstr "<Espaço>\tDeslocar vista diff uma página para baixo"
 
-#: gitk:3089
 msgid "u\t\tScroll diff view up 18 lines"
 msgstr "u\t\tDeslocar vista diff 18 linhas para cima"
 
-#: gitk:3090
 msgid "d\t\tScroll diff view down 18 lines"
 msgstr "d\t\tDeslocar vista diff 18 linhas para baixo"
 
-#: gitk:3091
 #, tcl-format
 msgid "<%s-F>\t\tFind"
 msgstr "<%s-F>\t\tProcurar"
 
-#: gitk:3092
 #, tcl-format
 msgid "<%s-G>\t\tMove to next find hit"
 msgstr "<%s-G>\t\tMover para a ocorrência seguinte"
 
-#: gitk:3093
 msgid "<Return>\tMove to next find hit"
 msgstr "<Return>\tMover para a ocorrência seguinte"
 
-#: gitk:3094
 msgid "g\t\tGo to commit"
 msgstr "g\t\tIr para o commit"
 
-#: gitk:3095
 msgid "/\t\tFocus the search box"
 msgstr "/\t\tFocar a caixa de pesquisa"
 
-#: gitk:3096
 msgid "?\t\tMove to previous find hit"
 msgstr "?\t\tMover para a ocorrência anterior"
 
-#: gitk:3097
 msgid "f\t\tScroll diff view to next file"
 msgstr "f\t\tDeslocar vista diff para o ficheiro seguinte"
 
-#: gitk:3098
 #, tcl-format
 msgid "<%s-S>\t\tSearch for next hit in diff view"
 msgstr "<%s-S>\t\tProcurar pela ocorrência seguinte na vista diff"
 
-#: gitk:3099
 #, tcl-format
 msgid "<%s-R>\t\tSearch for previous hit in diff view"
 msgstr "<%s-R>\t\tProcurar pela ocorrência anterior na vista diff"
 
-#: gitk:3100
 #, tcl-format
 msgid "<%s-KP+>\tIncrease font size"
 msgstr "<%s-KP+>\tAumentar o tamanho da letra"
 
-#: gitk:3101
 #, tcl-format
 msgid "<%s-plus>\tIncrease font size"
 msgstr "<%s-mais>\tAumentar o tamanho da letra"
 
-#: gitk:3102
 #, tcl-format
 msgid "<%s-KP->\tDecrease font size"
 msgstr "<%s-KP->\tDiminuir o tamanho da letra"
 
-#: gitk:3103
 #, tcl-format
 msgid "<%s-minus>\tDecrease font size"
 msgstr "<%s-menos>\tDiminuir o tamanho da letra"
 
-#: gitk:3104
 msgid "<F5>\t\tUpdate"
 msgstr "<F5>\t\tAtualizar"
 
-#: gitk:3569 gitk:3578
 #, tcl-format
 msgid "Error creating temporary directory %s:"
 msgstr "Erro ao criar ficheiro temporário %s:"
 
-#: gitk:3591
 #, tcl-format
 msgid "Error getting \"%s\" from %s:"
 msgstr "Erro ao obter \"%s\" de %s:"
 
-#: gitk:3654
 msgid "command failed:"
 msgstr "o comando falhou:"
 
-#: gitk:3803
 msgid "No such commit"
 msgstr "Commit inexistente"
 
-#: gitk:3817
 msgid "git gui blame: command failed:"
 msgstr "git gui blame: o comando falhou:"
 
-#: gitk:3848
 #, tcl-format
 msgid "Couldn't read merge head: %s"
 msgstr "Não foi possível ler a cabeça de integração: %s"
 
-#: gitk:3856
 #, tcl-format
 msgid "Error reading index: %s"
 msgstr "Erro ao ler o índice: %s"
 
-#: gitk:3881
 #, tcl-format
 msgid "Couldn't start git blame: %s"
 msgstr "Não foi possível iniciar git blame: %s"
 
-#: gitk:3884 gitk:6773
 msgid "Searching"
 msgstr "A procurar"
 
-#: gitk:3916
 #, tcl-format
 msgid "Error running git blame: %s"
 msgstr "Erro ao executar git blame: %s"
 
-#: gitk:3944
 #, tcl-format
 msgid "That line comes from commit %s,  which is not in this view"
 msgstr "Essa linha provém do commit %s, que não está nesta vista"
 
-#: gitk:3958
 msgid "External diff viewer failed:"
 msgstr "Visualizador diff externo falhou:"
 
-#: gitk:4062
 msgid "All files"
 msgstr "Todos os ficheiros"
 
-#: gitk:4086
 msgid "View"
 msgstr "Vista"
 
-#: gitk:4089
 msgid "Gitk view definition"
 msgstr "Definição de vistas do gitk"
 
-#: gitk:4093
 msgid "Remember this view"
 msgstr "Recordar esta vista"
 
-#: gitk:4094
 msgid "References (space separated list):"
 msgstr "Referências (lista separada por espaço):"
 
-#: gitk:4095
 msgid "Branches & tags:"
 msgstr "Ramos e tags:"
 
-#: gitk:4096
 msgid "All refs"
 msgstr "Todas as referências"
 
-#: gitk:4097
 msgid "All (local) branches"
 msgstr "Todos os ramos (locais)"
 
-#: gitk:4098
 msgid "All tags"
 msgstr "Todas as tags"
 
-#: gitk:4099
 msgid "All remote-tracking branches"
 msgstr "Todos os ramos remotos de monitorização"
 
-#: gitk:4100
 msgid "Commit Info (regular expressions):"
 msgstr "Informação Sobre o Commit (expressões regulares):"
 
-#: gitk:4101
 msgid "Author:"
 msgstr "Autor:"
 
-#: gitk:4102
 msgid "Committer:"
 msgstr "Committer:"
 
-#: gitk:4103
 msgid "Commit Message:"
 msgstr "Mensagem de Commit:"
 
-#: gitk:4104
 msgid "Matches all Commit Info criteria"
 msgstr "Corresponde a todos os critérios da Informação Sobre o Commit"
 
-#: gitk:4105
 msgid "Matches no Commit Info criteria"
 msgstr "Não corresponde a nenhum critério da Informação Sobre o Commit"
 
-#: gitk:4106
 msgid "Changes to Files:"
 msgstr "Alterações nos Ficheiros:"
 
-#: gitk:4107
 msgid "Fixed String"
 msgstr "Cadeia Fixa"
 
-#: gitk:4108
 msgid "Regular Expression"
 msgstr "Expressão Regular"
 
-#: gitk:4109
 msgid "Search string:"
 msgstr "Procurar pela cadeia:"
 
-#: gitk:4110
 msgid ""
 "Commit Dates (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 "
 "15:27:38\"):"
@@ -706,201 +543,153 @@
 "Datas de Commit (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 "
 "15:27:38\"):"
 
-#: gitk:4111
 msgid "Since:"
 msgstr "Desde:"
 
-#: gitk:4112
 msgid "Until:"
 msgstr "Até:"
 
-#: gitk:4113
 msgid "Limit and/or skip a number of revisions (positive integer):"
 msgstr "Limitar e/ou ignorar um número de revisões (inteiro positivo):"
 
-#: gitk:4114
 msgid "Number to show:"
 msgstr "Número a mostrar:"
 
-#: gitk:4115
 msgid "Number to skip:"
 msgstr "Número a ignorar:"
 
-#: gitk:4116
 msgid "Miscellaneous options:"
 msgstr "Opções diversas:"
 
-#: gitk:4117
 msgid "Strictly sort by date"
 msgstr "Ordenar estritamente pela data"
 
-#: gitk:4118
 msgid "Mark branch sides"
 msgstr "Marcar lado dos ramos"
 
-#: gitk:4119
 msgid "Limit to first parent"
 msgstr "Restringir ao primeiro pai"
 
-#: gitk:4120
 msgid "Simple history"
 msgstr "Histórico simples"
 
-#: gitk:4121
 msgid "Additional arguments to git log:"
 msgstr "Argumentos adicionais ao git log:"
 
-#: gitk:4122
 msgid "Enter files and directories to include, one per line:"
 msgstr "Introduza ficheiros e diretórios para incluir, um por linha:"
 
-#: gitk:4123
 msgid "Command to generate more commits to include:"
 msgstr "Comando para gerar mais commits para incluir:"
 
-#: gitk:4247
 msgid "Gitk: edit view"
 msgstr "Gitk: editar vista"
 
-#: gitk:4255
 msgid "-- criteria for selecting revisions"
 msgstr "-- critério para selecionar revisões"
 
-#: gitk:4260
 msgid "View Name"
 msgstr "Nome da Vista"
 
-#: gitk:4335
 msgid "Apply (F5)"
 msgstr "Aplicar (F5)"
 
-#: gitk:4373
 msgid "Error in commit selection arguments:"
 msgstr "Erro nos argumentos de seleção de commits:"
 
-#: gitk:4428 gitk:4481 gitk:4943 gitk:4957 gitk:6227 gitk:12410 gitk:12411
 msgid "None"
 msgstr "Nenhum"
 
-#: gitk:5040 gitk:5045
 msgid "Descendant"
 msgstr "Descendente"
 
-#: gitk:5041
 msgid "Not descendant"
 msgstr "Não descendente"
 
-#: gitk:5048 gitk:5053
 msgid "Ancestor"
 msgstr "Antecessor"
 
-#: gitk:5049
 msgid "Not ancestor"
 msgstr "Não antecessor"
 
-#: gitk:5343
 msgid "Local changes checked in to index but not committed"
 msgstr "Alterações locais preparadas no índice mas não submetidas"
 
-#: gitk:5379
 msgid "Local uncommitted changes, not checked in to index"
 msgstr "Alterações locais não submetidas, não preparadas no índice"
 
-#: gitk:7153
 msgid "and many more"
 msgstr "e muitos mais"
 
-#: gitk:7156
 msgid "many"
 msgstr "muitos"
 
-#: gitk:7347
 msgid "Tags:"
 msgstr "Tags:"
 
-#: gitk:7364 gitk:7370 gitk:8844
 msgid "Parent"
 msgstr "Pai"
 
-#: gitk:7375
 msgid "Child"
 msgstr "Filho"
 
-#: gitk:7384
 msgid "Branch"
 msgstr "Ramo"
 
-#: gitk:7387
 msgid "Follows"
 msgstr "Sucede"
 
-#: gitk:7390
 msgid "Precedes"
 msgstr "Precede"
 
-#: gitk:7985
 #, tcl-format
 msgid "Error getting diffs: %s"
 msgstr "Erro ao obter diferenças: %s"
 
-#: gitk:8669
 msgid "Goto:"
 msgstr "Ir para:"
 
-#: gitk:8690
 #, tcl-format
 msgid "Short SHA1 id %s is ambiguous"
 msgstr "O id SHA1 abreviado %s é ambíguo"
 
-#: gitk:8697
 #, tcl-format
 msgid "Revision %s is not known"
 msgstr "A revisão %s não é conhecida"
 
-#: gitk:8707
 #, tcl-format
 msgid "SHA1 id %s is not known"
 msgstr "O id SHA1 %s não é conhecido"
 
-#: gitk:8709
 #, tcl-format
 msgid "Revision %s is not in the current view"
 msgstr "A revisão %s não se encontra na vista atual"
 
-#: gitk:8851 gitk:8866
 msgid "Date"
 msgstr "Data"
 
-#: gitk:8854
 msgid "Children"
 msgstr "Filhos"
 
-#: gitk:8917
 #, tcl-format
 msgid "Reset %s branch to here"
 msgstr "Repor o ramo %s para aqui"
 
-#: gitk:8919
 msgid "Detached head: can't reset"
 msgstr "Cabeça destacada: não é possível repor"
 
-#: gitk:9024 gitk:9030
 msgid "Skipping merge commit "
 msgstr "A ignorar commit de integração "
 
-#: gitk:9039 gitk:9044
 msgid "Error getting patch ID for "
 msgstr "Erro ao obter ID de patch de "
 
-#: gitk:9040 gitk:9045
 msgid " - stopping\n"
 msgstr " - a interromper\n"
 
-#: gitk:9050 gitk:9053 gitk:9061 gitk:9075 gitk:9084
 msgid "Commit "
 msgstr "Commit "
 
-#: gitk:9054
 msgid ""
 " is the same patch as\n"
 "       "
@@ -908,7 +697,6 @@
 " é o mesmo patch que\n"
 "       "
 
-#: gitk:9062
 msgid ""
 " differs from\n"
 "       "
@@ -916,7 +704,6 @@
 " difere de\n"
 "       "
 
-#: gitk:9064
 msgid ""
 "Diff of commits:\n"
 "\n"
@@ -924,129 +711,99 @@
 "Diferença dos commits:\n"
 "\n"
 
-#: gitk:9076 gitk:9085
 #, tcl-format
 msgid " has %s children - stopping\n"
 msgstr " tem %s filhos - a interromper\n"
 
-#: gitk:9104
 #, tcl-format
 msgid "Error writing commit to file: %s"
 msgstr "Erro ao escrever commit no ficheiro: %s"
 
-#: gitk:9110
 #, tcl-format
 msgid "Error diffing commits: %s"
 msgstr "Erro ao calcular as diferenças dos commits: %s"
 
-#: gitk:9156
 msgid "Top"
 msgstr "Topo"
 
-#: gitk:9157
 msgid "From"
 msgstr "De"
 
-#: gitk:9162
 msgid "To"
 msgstr "Para"
 
-#: gitk:9186
 msgid "Generate patch"
 msgstr "Gerar patch"
 
-#: gitk:9188
 msgid "From:"
 msgstr "De:"
 
-#: gitk:9197
 msgid "To:"
 msgstr "Para:"
 
-#: gitk:9206
 msgid "Reverse"
 msgstr "Reverter"
 
-#: gitk:9208 gitk:9418
 msgid "Output file:"
 msgstr "Ficheiro de saída:"
 
-#: gitk:9214
 msgid "Generate"
 msgstr "Gerar"
 
-#: gitk:9252
 msgid "Error creating patch:"
 msgstr "Erro ao criar patch:"
 
-#: gitk:9275 gitk:9406 gitk:9463
 msgid "ID:"
 msgstr "ID:"
 
-#: gitk:9284
 msgid "Tag name:"
 msgstr "Nome da tag:"
 
-#: gitk:9287
 msgid "Tag message is optional"
 msgstr "A mensagem da tag é opcional"
 
-#: gitk:9289
 msgid "Tag message:"
 msgstr "Mensagem da tag:"
 
-#: gitk:9293 gitk:9472
 msgid "Create"
 msgstr "Criar"
 
-#: gitk:9311
 msgid "No tag name specified"
 msgstr "Nenhum nome de tag especificado"
 
-#: gitk:9315
 #, tcl-format
 msgid "Tag \"%s\" already exists"
 msgstr "A tag \"%s\" já existe"
 
-#: gitk:9325
 msgid "Error creating tag:"
 msgstr "Erro ao criar tag:"
 
-#: gitk:9415
 msgid "Command:"
 msgstr "Comando:"
 
-#: gitk:9423
 msgid "Write"
 msgstr "Escrever"
 
-#: gitk:9441
 msgid "Error writing commit:"
 msgstr "Erro ao escrever commit:"
 
-#: gitk:9468
 msgid "Name:"
 msgstr "Nome:"
 
-#: gitk:9491
 msgid "Please specify a name for the new branch"
 msgstr "Especifique um nome para o novo ramo"
 
-#: gitk:9496
 #, tcl-format
 msgid "Branch '%s' already exists. Overwrite?"
 msgstr "O ramo '%s' já existe. Substituí-lo?"
 
-#: gitk:9563
 #, tcl-format
 msgid "Commit %s is already included in branch %s -- really re-apply it?"
 msgstr "O commit %s já está incluído no ramo %s -- reaplicá-lo mesmo assim?"
 
-#: gitk:9568
 msgid "Cherry-picking"
 msgstr "A efetuar cherry-pick"
 
-#: gitk:9577
 #, tcl-format
 msgid ""
 "Cherry-pick failed because of local changes to file '%s'.\n"
@@ -1055,7 +812,6 @@
 "Falha ao efetuar cherry-pick devido a alterações locais no ficheiro '%s'.\n"
 "Submeta, empilhe ou reponha as alterações e tente de novo."
 
-#: gitk:9583
 msgid ""
 "Cherry-pick failed because of merge conflict.\n"
 "Do you wish to run git citool to resolve it?"
@@ -1063,20 +819,16 @@
 "Falha ao efetuar cherry-pick devido a conflito de integração.\n"
 "Deseja executar git citool para resolvê-lo?"
 
-#: gitk:9599 gitk:9657
 msgid "No changes committed"
 msgstr "Não foi submetida nenhum alteração"
 
-#: gitk:9626
 #, tcl-format
 msgid "Commit %s is not included in branch %s -- really revert it?"
 msgstr "O commit %s não está incluído no ramo %s -- revertê-lo mesmo assim?"
 
-#: gitk:9631
 msgid "Reverting"
 msgstr "A reverter"
 
-#: gitk:9639
 #, tcl-format
 msgid ""
 "Revert failed because of local changes to the following files:%s Please "
@@ -1085,7 +837,6 @@
 "Falha ao reverter devido a alterações locais nos seguintes ficheiros:%s "
 "Submeta, empilhe ou reponha as alterações e tente de novo."
 
-#: gitk:9643
 msgid ""
 "Revert failed because of merge conflict.\n"
 " Do you wish to run git citool to resolve it?"
@@ -1093,28 +844,22 @@
 "Falha ao reverter devido a conflito de integração.\n"
 "Deseja executar git citool para resolvê-lo?"
 
-#: gitk:9686
 msgid "Confirm reset"
 msgstr "Confirmar reposição"
 
-#: gitk:9688
 #, tcl-format
 msgid "Reset branch %s to %s?"
 msgstr "Repor o ramo %s para %s?"
 
-#: gitk:9690
 msgid "Reset type:"
 msgstr "Tipo de reposição:"
 
-#: gitk:9693
 msgid "Soft: Leave working tree and index untouched"
 msgstr "Suave: Deixar a árvore de trabalho e o índice intactos"
 
-#: gitk:9696
 msgid "Mixed: Leave working tree untouched, reset index"
 msgstr "Misto: Deixar a árvore de trabalho intacta, repor índice"
 
-#: gitk:9699
 msgid ""
 "Hard: Reset working tree and index\n"
 "(discard ALL local changes)"
@@ -1122,19 +867,15 @@
 "Forte: Repor árvore de trabalho e índice\n"
 "(descartar TODAS as alterações locais)"
 
-#: gitk:9716
 msgid "Resetting"
 msgstr "A repor"
 
-#: gitk:9776
 msgid "Checking out"
 msgstr "A extrair"
 
-#: gitk:9829
 msgid "Cannot delete the currently checked-out branch"
 msgstr "Não é possível eliminar o ramo atual extraído"
 
-#: gitk:9835
 #, tcl-format
 msgid ""
 "The commits on branch %s aren't on any other branch.\n"
@@ -1143,16 +884,13 @@
 "Os commits no ramo %s não estão presentes em mais nenhum ramo.\n"
 "Eliminar o ramo %s mesmo assim?"
 
-#: gitk:9866
 #, tcl-format
 msgid "Tags and heads: %s"
 msgstr "Tags e cabeças: %s"
 
-#: gitk:9883
 msgid "Filter"
 msgstr "Filtrar"
 
-#: gitk:10179
 msgid ""
 "Error reading commit topology information; branch and preceding/following "
 "tag information will be incomplete."
@@ -1160,201 +898,152 @@
 "Erro ao ler informação de topologia do commit; a informação do ramo e da tag "
 "precedente/seguinte ficará incompleta."
 
-#: gitk:11156
 msgid "Tag"
 msgstr "Tag"
 
-#: gitk:11160
 msgid "Id"
 msgstr "Id"
 
-#: gitk:11243
 msgid "Gitk font chooser"
 msgstr "Escolha de tipo de letra do gitk"
 
-#: gitk:11260
 msgid "B"
 msgstr "B"
 
-#: gitk:11263
 msgid "I"
 msgstr "I"
 
-#: gitk:11381
 msgid "Commit list display options"
 msgstr "Opções de visualização da lista de commits"
 
-#: gitk:11384
 msgid "Maximum graph width (lines)"
 msgstr "Largura máxima do gráfico (linhas)"
 
-#: gitk:11388
 #, no-tcl-format
 msgid "Maximum graph width (% of pane)"
 msgstr "Largura máxima do gráfico (% do painel)"
 
-#: gitk:11391
 msgid "Show local changes"
 msgstr "Mostrar alterações locais"
 
-#: gitk:11394
 msgid "Auto-select SHA1 (length)"
 msgstr "Selecionar automaticamente SHA1 (largura)"
 
-#: gitk:11398
 msgid "Hide remote refs"
 msgstr "Ocultar referências remotas"
 
-#: gitk:11402
 msgid "Diff display options"
 msgstr "Opções de visualização de diferenças"
 
-#: gitk:11404
 msgid "Tab spacing"
 msgstr "Espaçamento da tabulação"
 
-#: gitk:11407
 msgid "Display nearby tags/heads"
 msgstr "Mostrar tags/cabeças próximas"
 
-#: gitk:11410
 msgid "Maximum # tags/heads to show"
 msgstr "Nº máximo de tags/cabeças a mostrar"
 
-#: gitk:11413
 msgid "Limit diffs to listed paths"
 msgstr "Limitar diferenças aos caminhos listados"
 
-#: gitk:11416
 msgid "Support per-file encodings"
 msgstr "Suportar codificação por cada ficheiro"
 
-#: gitk:11422 gitk:11569
 msgid "External diff tool"
 msgstr "Ferramenta diff externa"
 
-#: gitk:11423
 msgid "Choose..."
 msgstr "Escolher..."
 
-#: gitk:11428
 msgid "General options"
 msgstr "Opções gerais"
 
-#: gitk:11431
 msgid "Use themed widgets"
 msgstr "Usar widgets com estilo"
 
-#: gitk:11433
 msgid "(change requires restart)"
 msgstr "(alteração exige reiniciar)"
 
-#: gitk:11435
 msgid "(currently unavailable)"
 msgstr "(não disponível de momento)"
 
-#: gitk:11446
 msgid "Colors: press to choose"
 msgstr "Cores: pressione para escolher"
 
-#: gitk:11449
 msgid "Interface"
 msgstr "Interface"
 
-#: gitk:11450
 msgid "interface"
 msgstr "interface"
 
-#: gitk:11453
 msgid "Background"
 msgstr "Fundo"
 
-#: gitk:11454 gitk:11484
 msgid "background"
 msgstr "fundo"
 
-#: gitk:11457
 msgid "Foreground"
 msgstr "Primeiro plano"
 
-#: gitk:11458
 msgid "foreground"
 msgstr "primeiro plano"
 
-#: gitk:11461
 msgid "Diff: old lines"
 msgstr "Diff: linhas antigas"
 
-#: gitk:11462
 msgid "diff old lines"
 msgstr "diff linhas antigas"
 
-#: gitk:11466
 msgid "Diff: new lines"
 msgstr "Diff: linhas novas"
 
-#: gitk:11467
 msgid "diff new lines"
 msgstr "diff linhas novas"
 
-#: gitk:11471
 msgid "Diff: hunk header"
 msgstr "Diff: cabeçalho do excerto"
 
-#: gitk:11473
 msgid "diff hunk header"
 msgstr "diff cabeçalho do excerto"
 
-#: gitk:11477
 msgid "Marked line bg"
 msgstr "Fundo da linha marcada"
 
-#: gitk:11479
 msgid "marked line background"
 msgstr "fundo da linha marcada"
 
-#: gitk:11483
 msgid "Select bg"
 msgstr "Selecionar fundo"
 
-#: gitk:11492
 msgid "Fonts: press to choose"
 msgstr "Tipo de letra: pressione para escolher"
 
-#: gitk:11494
 msgid "Main font"
 msgstr "Tipo de letra principal"
 
-#: gitk:11495
 msgid "Diff display font"
 msgstr "Tipo de letra ao mostrar diferenças"
 
-#: gitk:11496
 msgid "User interface font"
 msgstr "Tipo de letra da interface de utilizador"
 
-#: gitk:11518
 msgid "Gitk preferences"
 msgstr "Preferências do gitk"
 
-#: gitk:11527
 msgid "General"
 msgstr "Geral"
 
-#: gitk:11528
 msgid "Colors"
 msgstr "Cores"
 
-#: gitk:11529
 msgid "Fonts"
 msgstr "Tipos de letra"
 
-#: gitk:11579
 #, tcl-format
 msgid "Gitk: choose color for %s"
 msgstr "Gitk: escolher cor de %s"
 
-#: gitk:12092
 msgid ""
 "Sorry, gitk cannot run with this version of Tcl/Tk.\n"
 " Gitk requires at least Tcl/Tk 8.4."
@@ -1362,15 +1051,12 @@
 "Não é possível executar o gitk com esta versão do Tcl/Tk.\n"
 "O gitk requer pelo menos Tcl/Tk 8.4."
 
-#: gitk:12302
 msgid "Cannot find a git repository here."
 msgstr "Não foi encontrado nenhum repositório git aqui."
 
-#: gitk:12349
 #, tcl-format
 msgid "Ambiguous argument '%s': both revision and filename"
 msgstr "Argumento '%s' ambíguo: pode ser uma revisão ou um ficheiro"
 
-#: gitk:12361
 msgid "Bad arguments to gitk:"
 msgstr "Argumentos do gitk incorretos:"
diff --git a/gitk-git/po/ru.po b/gitk-git/po/ru.po
index 9b08c26..e102fb7 100644
--- a/gitk-git/po/ru.po
+++ b/gitk-git/po/ru.po
@@ -8,368 +8,285 @@
 # Skip <bsvskip@rambler.ru>, 2011
 msgid ""
 msgstr ""
-"Project-Id-Version: Git Russian Localization Project\n"
+"Project-Id-Version: Gitk Russian Localization Project\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2016-12-15 00:18+0200\n"
 "PO-Revision-Date: 2016-12-14 22:23+0000\n"
 "Last-Translator: Dimitriy Ryazantcev <DJm00n@mail.ru>\n"
-"Language-Team: Russian (http://www.transifex.com/djm00n/git-po-ru/language/ru/)\n"
+"Language-Team: Russian (http://www.transifex.com/djm00n/git-po-ru/language/"
+"ru/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: ru\n"
-"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n"
+"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
+"n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || "
+"(n%100>=11 && n%100<=14)? 2 : 3);\n"
 
-#: gitk:140
 msgid "Couldn't get list of unmerged files:"
 msgstr "Невозможно получить список файлов незавершённой операции слияния:"
 
-#: gitk:212 gitk:2403
 msgid "Color words"
 msgstr "Цветные слова"
 
-#: gitk:217 gitk:2403 gitk:8249 gitk:8282
 msgid "Markup words"
 msgstr "Помеченые слова"
 
-#: gitk:324
 msgid "Error parsing revisions:"
 msgstr "Ошибка при разборе редакции:"
 
-#: gitk:380
 msgid "Error executing --argscmd command:"
 msgstr "Ошибка выполнения команды заданной --argscmd:"
 
-#: gitk:393
 msgid "No files selected: --merge specified but no files are unmerged."
-msgstr "Файлы не выбраны: указан --merge, но не было найдено ни одного файла где эта операция должна быть завершена."
+msgstr ""
+"Файлы не выбраны: указан --merge, но не было найдено ни одного файла где эта "
+"операция должна быть завершена."
 
-#: gitk:396
 msgid ""
 "No files selected: --merge specified but no unmerged files are within file "
 "limit."
-msgstr "Файлы не выбраны: указан --merge, но в рамках указанного ограничения на имена файлов нет ни одного где эта операция должна быть завершена."
+msgstr ""
+"Файлы не выбраны: указан --merge, но в рамках указанного ограничения на "
+"имена файлов нет ни одного где эта операция должна быть завершена."
 
-#: gitk:418 gitk:566
 msgid "Error executing git log:"
 msgstr "Ошибка запуска git log:"
 
-#: gitk:436 gitk:582
 msgid "Reading"
 msgstr "Чтение"
 
-#: gitk:496 gitk:4549
 msgid "Reading commits..."
 msgstr "Чтение коммитов..."
 
-#: gitk:499 gitk:1641 gitk:4552
 msgid "No commits selected"
 msgstr "Ничего не выбрано"
 
-#: gitk:1449 gitk:4069 gitk:12583
 msgid "Command line"
 msgstr "Командная строка"
 
-#: gitk:1515
 msgid "Can't parse git log output:"
 msgstr "Ошибка обработки вывода команды git log:"
 
-#: gitk:1744
 msgid "No commit information available"
 msgstr "Нет информации о коммите"
 
-#: gitk:1907 gitk:1936 gitk:4339 gitk:9789 gitk:11388 gitk:11668
 msgid "OK"
 msgstr "Ok"
 
-#: gitk:1938 gitk:4341 gitk:9225 gitk:9304 gitk:9434 gitk:9520 gitk:9791
-#: gitk:11389 gitk:11669
 msgid "Cancel"
 msgstr "Отмена"
 
-#: gitk:2087
 msgid "&Update"
 msgstr "Обновить"
 
-#: gitk:2088
 msgid "&Reload"
 msgstr "Перечитать"
 
-#: gitk:2089
 msgid "Reread re&ferences"
 msgstr "Обновить список ссылок"
 
-#: gitk:2090
 msgid "&List references"
 msgstr "Список ссылок"
 
-#: gitk:2092
 msgid "Start git &gui"
 msgstr "Запустить git gui"
 
-#: gitk:2094
 msgid "&Quit"
 msgstr "Завершить"
 
-#: gitk:2086
 msgid "&File"
 msgstr "Файл"
 
-#: gitk:2098
 msgid "&Preferences"
 msgstr "Настройки"
 
-#: gitk:2097
 msgid "&Edit"
 msgstr "Редактировать"
 
-#: gitk:2102
 msgid "&New view..."
 msgstr "Новое представление..."
 
-#: gitk:2103
 msgid "&Edit view..."
 msgstr "Редактировать представление..."
 
-#: gitk:2104
 msgid "&Delete view"
 msgstr "Удалить представление"
 
-#: gitk:2106
 msgid "&All files"
 msgstr "Все файлы"
 
-#: gitk:2101
 msgid "&View"
 msgstr "Представление"
 
-#: gitk:2111 gitk:2121
 msgid "&About gitk"
 msgstr "О gitk"
 
-#: gitk:2112 gitk:2126
 msgid "&Key bindings"
 msgstr "Назначения клавиатуры"
 
-#: gitk:2110 gitk:2125
 msgid "&Help"
 msgstr "Подсказка"
 
-#: gitk:2203 gitk:8681
 msgid "SHA1 ID:"
 msgstr "SHA1 ID:"
 
-#: gitk:2247
 msgid "Row"
 msgstr "Строка"
 
-#: gitk:2285
 msgid "Find"
 msgstr "Поиск"
 
-#: gitk:2313
 msgid "commit"
 msgstr "коммит"
 
-#: gitk:2317 gitk:2319 gitk:4711 gitk:4734 gitk:4758 gitk:6779 gitk:6851
-#: gitk:6936
 msgid "containing:"
 msgstr "содержащее:"
 
-#: gitk:2320 gitk:3550 gitk:3555 gitk:4787
 msgid "touching paths:"
 msgstr "касательно файлов:"
 
-#: gitk:2321 gitk:4801
 msgid "adding/removing string:"
 msgstr "добавив/удалив строку:"
 
-#: gitk:2322 gitk:4803
 msgid "changing lines matching:"
 msgstr "изменяя совпадающие строки:"
 
-#: gitk:2331 gitk:2333 gitk:4790
 msgid "Exact"
 msgstr "Точно"
 
-#: gitk:2333 gitk:4878 gitk:6747
 msgid "IgnCase"
 msgstr "Игнорировать большие/маленькие"
 
-#: gitk:2333 gitk:4760 gitk:4876 gitk:6743
 msgid "Regexp"
 msgstr "Регулярные выражения"
 
-#: gitk:2335 gitk:2336 gitk:4898 gitk:4928 gitk:4935 gitk:6872 gitk:6940
 msgid "All fields"
 msgstr "Во всех полях"
 
-#: gitk:2336 gitk:4895 gitk:4928 gitk:6810
 msgid "Headline"
 msgstr "Заголовок"
 
-#: gitk:2337 gitk:4895 gitk:6810 gitk:6940 gitk:7413
 msgid "Comments"
 msgstr "Комментарии"
 
-#: gitk:2337 gitk:4895 gitk:4900 gitk:4935 gitk:6810 gitk:7348 gitk:8859
-#: gitk:8874
 msgid "Author"
 msgstr "Автор"
 
-#: gitk:2337 gitk:4895 gitk:6810 gitk:7350
 msgid "Committer"
 msgstr "Коммитер"
 
-#: gitk:2371
 msgid "Search"
 msgstr "Найти"
 
-#: gitk:2379
 msgid "Diff"
 msgstr "Сравнить"
 
-#: gitk:2381
 msgid "Old version"
 msgstr "Старая версия"
 
-#: gitk:2383
 msgid "New version"
 msgstr "Новая версия"
 
-#: gitk:2386
 msgid "Lines of context"
 msgstr "Строк контекста"
 
-#: gitk:2396
 msgid "Ignore space change"
 msgstr "Игнорировать пробелы"
 
-#: gitk:2400 gitk:2402 gitk:7983 gitk:8235
 msgid "Line diff"
 msgstr "Изменения строк"
 
-#: gitk:2467
 msgid "Patch"
 msgstr "Патч"
 
-#: gitk:2469
 msgid "Tree"
 msgstr "Файлы"
 
-#: gitk:2639 gitk:2660
 msgid "Diff this -> selected"
 msgstr "Сравнить этот коммит с выделенным"
 
-#: gitk:2640 gitk:2661
 msgid "Diff selected -> this"
 msgstr "Сравнить выделенный с этим коммитом"
 
-#: gitk:2641 gitk:2662
 msgid "Make patch"
 msgstr "Создать патч"
 
-#: gitk:2642 gitk:9283
 msgid "Create tag"
 msgstr "Создать метку"
 
-#: gitk:2643
 msgid "Copy commit summary"
 msgstr "Копировать информацию о коммите"
 
-#: gitk:2644 gitk:9414
 msgid "Write commit to file"
 msgstr "Сохранить коммит в файл"
 
-#: gitk:2645
 msgid "Create new branch"
 msgstr "Создать ветку"
 
-#: gitk:2646
 msgid "Cherry-pick this commit"
 msgstr "Копировать этот коммит в текущую ветку"
 
-#: gitk:2647
 msgid "Reset HEAD branch to here"
 msgstr "Установить HEAD на этот коммит"
 
-#: gitk:2648
 msgid "Mark this commit"
 msgstr "Пометить этот коммит"
 
-#: gitk:2649
 msgid "Return to mark"
 msgstr "Вернуться на пометку"
 
-#: gitk:2650
 msgid "Find descendant of this and mark"
 msgstr "Найти и пометить потомка этого коммита"
 
-#: gitk:2651
 msgid "Compare with marked commit"
 msgstr "Сравнить с помеченным коммитом"
 
-#: gitk:2652 gitk:2663
 msgid "Diff this -> marked commit"
 msgstr "Сравнить выделенное с помеченным коммитом"
 
-#: gitk:2653 gitk:2664
 msgid "Diff marked commit -> this"
 msgstr "Сравнить помеченный с этим коммитом"
 
-#: gitk:2654
 msgid "Revert this commit"
 msgstr "Обратить изменения этого коммита"
 
-#: gitk:2670
 msgid "Check out this branch"
 msgstr "Перейти на эту ветку"
 
-#: gitk:2671
 msgid "Rename this branch"
 msgstr "Переименовать эту ветку"
 
-#: gitk:2672
 msgid "Remove this branch"
 msgstr "Удалить эту ветку"
 
-#: gitk:2673
 msgid "Copy branch name"
 msgstr "Копировать имя ветки"
 
-#: gitk:2680
 msgid "Highlight this too"
 msgstr "Подсветить этот тоже"
 
-#: gitk:2681
 msgid "Highlight this only"
 msgstr "Подсветить только этот"
 
-#: gitk:2682
 msgid "External diff"
 msgstr "Программа сравнения"
 
-#: gitk:2683
 msgid "Blame parent commit"
 msgstr "Авторы изменений родительского коммита"
 
-#: gitk:2684
 msgid "Copy path"
 msgstr "Копировать путь"
 
-#: gitk:2691
 msgid "Show origin of this line"
 msgstr "Показать источник этой строки"
 
-#: gitk:2692
 msgid "Run git gui blame on this line"
 msgstr "Запустить git gui blame для этой строки"
 
-#: gitk:3036
 msgid "About gitk"
 msgstr "О gitk"
 
-#: gitk:3038
 msgid ""
 "\n"
 "Gitk - a commit viewer for git\n"
@@ -377,995 +294,797 @@
 "Copyright © 2005-2016 Paul Mackerras\n"
 "\n"
 "Use and redistribute under the terms of the GNU General Public License"
-msgstr "\nGitk — программа просмотра истории репозиториев git\n\n© 2005-2016 Paul Mackerras\n\nИспользование и распространение согласно условиям GNU General Public License"
+msgstr ""
+"\n"
+"Gitk — программа просмотра истории репозиториев git\n"
+"\n"
+"© 2005-2016 Paul Mackerras\n"
+"\n"
+"Использование и распространение согласно условиям GNU General Public License"
 
-#: gitk:3046 gitk:3113 gitk:10004
 msgid "Close"
 msgstr "Закрыть"
 
-#: gitk:3067
 msgid "Gitk key bindings"
 msgstr "Назначения клавиатуры в Gitk"
 
-#: gitk:3070
 msgid "Gitk key bindings:"
 msgstr "Назначения клавиатуры в Gitk:"
 
-#: gitk:3072
 #, tcl-format
 msgid "<%s-Q>\t\tQuit"
 msgstr "<%s-Q>\t\tЗавершить"
 
-#: gitk:3073
 #, tcl-format
 msgid "<%s-W>\t\tClose window"
 msgstr "<%s-W>\t\tЗакрыть окно"
 
-#: gitk:3074
 msgid "<Home>\t\tMove to first commit"
 msgstr "<Home>\t\tПерейти к первому коммиту"
 
-#: gitk:3075
 msgid "<End>\t\tMove to last commit"
 msgstr "<End>\t\tПерейти к последнему коммиту"
 
-#: gitk:3076
 msgid "<Up>, p, k\tMove up one commit"
 msgstr "<Up>, p, k\tПерейти на один коммит вверх"
 
-#: gitk:3077
 msgid "<Down>, n, j\tMove down one commit"
 msgstr "<Down>, n, j\tПерейти на один коммит вниз"
 
-#: gitk:3078
 msgid "<Left>, z, h\tGo back in history list"
 msgstr "<Left>, z, h\tПоказать ранее посещённое состояние"
 
-#: gitk:3079
 msgid "<Right>, x, l\tGo forward in history list"
 msgstr "<Right>, x, l\tПоказать следующий посещённый коммит"
 
-#: gitk:3080
 #, tcl-format
 msgid "<%s-n>\tGo to n-th parent of current commit in history list"
 msgstr "<%s-n>\tПерейти на n родителя от текущего коммита"
 
-#: gitk:3081
 msgid "<PageUp>\tMove up one page in commit list"
 msgstr "<PageUp>\tПерейти на страницу выше в списке коммитов"
 
-#: gitk:3082
 msgid "<PageDown>\tMove down one page in commit list"
 msgstr "<PageDown>\tПерейти на страницу ниже в списке коммитов"
 
-#: gitk:3083
 #, tcl-format
 msgid "<%s-Home>\tScroll to top of commit list"
 msgstr "<%s-Home>\tПерейти на начало списка коммитов"
 
-#: gitk:3084
 #, tcl-format
 msgid "<%s-End>\tScroll to bottom of commit list"
 msgstr "<%s-End>\tПерейти на конец списка коммитов"
 
-#: gitk:3085
 #, tcl-format
 msgid "<%s-Up>\tScroll commit list up one line"
 msgstr "<%s-Up>\tПровернуть список коммитов вверх"
 
-#: gitk:3086
 #, tcl-format
 msgid "<%s-Down>\tScroll commit list down one line"
 msgstr "<%s-Down>\tПровернуть список коммитов вниз"
 
-#: gitk:3087
 #, tcl-format
 msgid "<%s-PageUp>\tScroll commit list up one page"
 msgstr "<%s-PageUp>\tПровернуть список коммитов на страницу вверх"
 
-#: gitk:3088
 #, tcl-format
 msgid "<%s-PageDown>\tScroll commit list down one page"
 msgstr "<%s-PageDown>\tПровернуть список коммитов на страницу вниз"
 
-#: gitk:3089
 msgid "<Shift-Up>\tFind backwards (upwards, later commits)"
 msgstr "<Shift-Up>\tПоиск в обратном порядке (вверх, среди новых коммитов)"
 
-#: gitk:3090
 msgid "<Shift-Down>\tFind forwards (downwards, earlier commits)"
 msgstr "<Shift-Down>\tПоиск (вниз, среди старых коммитов)"
 
-#: gitk:3091
 msgid "<Delete>, b\tScroll diff view up one page"
 msgstr "<Delete>, b\tПрокрутить список изменений на страницу выше"
 
-#: gitk:3092
 msgid "<Backspace>\tScroll diff view up one page"
 msgstr "<Backspace>\tПрокрутить список изменений на страницу выше"
 
-#: gitk:3093
 msgid "<Space>\t\tScroll diff view down one page"
 msgstr "<Leertaste>\t\tПрокрутить список изменений на страницу ниже"
 
-#: gitk:3094
 msgid "u\t\tScroll diff view up 18 lines"
 msgstr "u\t\tПрокрутить список изменений на 18 строк вверх"
 
-#: gitk:3095
 msgid "d\t\tScroll diff view down 18 lines"
 msgstr "d\t\tПрокрутить список изменений на 18 строк вниз"
 
-#: gitk:3096
 #, tcl-format
 msgid "<%s-F>\t\tFind"
 msgstr "<%s-F>\t\tПоиск"
 
-#: gitk:3097
 #, tcl-format
 msgid "<%s-G>\t\tMove to next find hit"
 msgstr "<%s-G>\t\tПерейти к следующему найденному коммиту"
 
-#: gitk:3098
 msgid "<Return>\tMove to next find hit"
 msgstr "<Return>\tПерейти к следующему найденному коммиту"
 
-#: gitk:3099
 msgid "g\t\tGo to commit"
 msgstr "g\t\tПерейти на коммит"
 
-#: gitk:3100
 msgid "/\t\tFocus the search box"
 msgstr "/\t\tПерейти к полю поиска"
 
-#: gitk:3101
 msgid "?\t\tMove to previous find hit"
 msgstr "?\t\tПерейти к предыдущему найденному коммиту"
 
-#: gitk:3102
 msgid "f\t\tScroll diff view to next file"
 msgstr "f\t\tПрокрутить список изменений к следующему файлу"
 
-#: gitk:3103
 #, tcl-format
 msgid "<%s-S>\t\tSearch for next hit in diff view"
 msgstr "<%s-S>\t\tПродолжить поиск в списке изменений"
 
-#: gitk:3104
 #, tcl-format
 msgid "<%s-R>\t\tSearch for previous hit in diff view"
 msgstr "<%s-R>\t\tПерейти к предыдущему найденному тексту в списке изменений"
 
-#: gitk:3105
 #, tcl-format
 msgid "<%s-KP+>\tIncrease font size"
 msgstr "<%s-KP+>\tУвеличить размер шрифта"
 
-#: gitk:3106
 #, tcl-format
 msgid "<%s-plus>\tIncrease font size"
 msgstr "<%s-plus>\tУвеличить размер шрифта"
 
-#: gitk:3107
 #, tcl-format
 msgid "<%s-KP->\tDecrease font size"
 msgstr "<%s-KP->\tУменьшить размер шрифта"
 
-#: gitk:3108
 #, tcl-format
 msgid "<%s-minus>\tDecrease font size"
 msgstr "<%s-minus>\tУменьшить размер шрифта"
 
-#: gitk:3109
 msgid "<F5>\t\tUpdate"
 msgstr "<F5>\t\tОбновить"
 
-#: gitk:3574 gitk:3583
 #, tcl-format
 msgid "Error creating temporary directory %s:"
 msgstr "Ошибка создания временного каталога %s:"
 
-#: gitk:3596
 #, tcl-format
 msgid "Error getting \"%s\" from %s:"
 msgstr "Ошибка получения «%s» из %s:"
 
-#: gitk:3659
 msgid "command failed:"
 msgstr "ошибка выполнения команды:"
 
-#: gitk:3808
 msgid "No such commit"
 msgstr "Коммит не найден"
 
-#: gitk:3822
 msgid "git gui blame: command failed:"
 msgstr "git gui blame: ошибка выполнения команды:"
 
-#: gitk:3853
 #, tcl-format
 msgid "Couldn't read merge head: %s"
 msgstr "Ошибка чтения MERGE_HEAD: %s"
 
-#: gitk:3861
 #, tcl-format
 msgid "Error reading index: %s"
 msgstr "Ошибка чтения индекса: %s"
 
-#: gitk:3886
 #, tcl-format
 msgid "Couldn't start git blame: %s"
 msgstr "Ошибка запуска git blame: %s"
 
-#: gitk:3889 gitk:6778
 msgid "Searching"
 msgstr "Поиск"
 
-#: gitk:3921
 #, tcl-format
 msgid "Error running git blame: %s"
 msgstr "Ошибка выполнения git blame: %s"
 
-#: gitk:3949
 #, tcl-format
 msgid "That line comes from commit %s,  which is not in this view"
-msgstr "Эта строка принадлежит коммиту %s, который не показан в этом представлении"
+msgstr ""
+"Эта строка принадлежит коммиту %s, который не показан в этом представлении"
 
-#: gitk:3963
 msgid "External diff viewer failed:"
 msgstr "Ошибка выполнения программы сравнения:"
 
-#: gitk:4067
 msgid "All files"
 msgstr "Все файлы"
 
-#: gitk:4091
 msgid "View"
 msgstr "Представление"
 
-#: gitk:4094
 msgid "Gitk view definition"
 msgstr "Gitk определение представлений"
 
-#: gitk:4098
 msgid "Remember this view"
 msgstr "Запомнить представление"
 
-#: gitk:4099
 msgid "References (space separated list):"
 msgstr "Ссылки (разделённые пробелом):"
 
-#: gitk:4100
 msgid "Branches & tags:"
 msgstr "Ветки и метки"
 
-#: gitk:4101
 msgid "All refs"
 msgstr "Все ссылки"
 
-#: gitk:4102
 msgid "All (local) branches"
 msgstr "Все (локальные) ветки"
 
-#: gitk:4103
 msgid "All tags"
 msgstr "Все метки"
 
-#: gitk:4104
 msgid "All remote-tracking branches"
 msgstr "Все внешние отслеживаемые ветки"
 
-#: gitk:4105
 msgid "Commit Info (regular expressions):"
 msgstr "Информация о коммите (регулярные выражения):"
 
-#: gitk:4106
 msgid "Author:"
 msgstr "Автор:"
 
-#: gitk:4107
 msgid "Committer:"
 msgstr "Коммитер:"
 
-#: gitk:4108
 msgid "Commit Message:"
 msgstr "Сообщение коммита:"
 
-#: gitk:4109
 msgid "Matches all Commit Info criteria"
 msgstr "Совпадает со всеми условиями информации о коммите"
 
-#: gitk:4110
 msgid "Matches no Commit Info criteria"
 msgstr "Не совпадает с условиями информации о коммите"
 
-#: gitk:4111
 msgid "Changes to Files:"
 msgstr "Изменения файлов:"
 
-#: gitk:4112
 msgid "Fixed String"
 msgstr "Обычная строка"
 
-#: gitk:4113
 msgid "Regular Expression"
 msgstr "Регулярное выражение:"
 
-#: gitk:4114
 msgid "Search string:"
 msgstr "Строка для поиска:"
 
-#: gitk:4115
 msgid ""
 "Commit Dates (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 "
 "15:27:38\"):"
-msgstr "Даты коммита («2 недели назад», «2009-03-17 15:27:38», «17 марта 2009 15:27:38»):"
+msgstr ""
+"Даты коммита («2 недели назад», «2009-03-17 15:27:38», «17 марта 2009 "
+"15:27:38»):"
 
-#: gitk:4116
 msgid "Since:"
 msgstr "С даты:"
 
-#: gitk:4117
 msgid "Until:"
 msgstr "По дату:"
 
-#: gitk:4118
 msgid "Limit and/or skip a number of revisions (positive integer):"
 msgstr "Ограничить и/или пропустить количество редакций (положительное число):"
 
-#: gitk:4119
 msgid "Number to show:"
 msgstr "Показать количество:"
 
-#: gitk:4120
 msgid "Number to skip:"
 msgstr "Пропустить количество:"
 
-#: gitk:4121
 msgid "Miscellaneous options:"
 msgstr "Различные опции:"
 
-#: gitk:4122
 msgid "Strictly sort by date"
 msgstr "Строгая сортировка по дате"
 
-#: gitk:4123
 msgid "Mark branch sides"
 msgstr "Отметить стороны веток"
 
-#: gitk:4124
 msgid "Limit to first parent"
 msgstr "Ограничить первым предком"
 
-#: gitk:4125
 msgid "Simple history"
 msgstr "Упрощенная история"
 
-#: gitk:4126
 msgid "Additional arguments to git log:"
 msgstr "Дополнительные аргументы для git log:"
 
-#: gitk:4127
 msgid "Enter files and directories to include, one per line:"
 msgstr "Файлы и каталоги для ограничения истории, по одному на строку:"
 
-#: gitk:4128
 msgid "Command to generate more commits to include:"
 msgstr "Дополнительная команда для списка коммитов:"
 
-#: gitk:4252
 msgid "Gitk: edit view"
 msgstr "Gitk: изменить представление"
 
-#: gitk:4260
 msgid "-- criteria for selecting revisions"
 msgstr "— критерий поиска редакций"
 
-#: gitk:4265
 msgid "View Name"
 msgstr "Имя представления"
 
-#: gitk:4340
 msgid "Apply (F5)"
 msgstr "Применить (F5)"
 
-#: gitk:4378
 msgid "Error in commit selection arguments:"
 msgstr "Ошибка в параметрах выбора коммитов:"
 
-#: gitk:4433 gitk:4486 gitk:4948 gitk:4962 gitk:6232 gitk:12524 gitk:12525
 msgid "None"
 msgstr "Ни одного"
 
-#: gitk:5045 gitk:5050
 msgid "Descendant"
 msgstr "Порождённое"
 
-#: gitk:5046
 msgid "Not descendant"
 msgstr "Не порождённое"
 
-#: gitk:5053 gitk:5058
 msgid "Ancestor"
 msgstr "Предок"
 
-#: gitk:5054
 msgid "Not ancestor"
 msgstr "Не предок"
 
-#: gitk:5348
 msgid "Local changes checked in to index but not committed"
 msgstr "Проиндексированные изменения"
 
-#: gitk:5384
 msgid "Local uncommitted changes, not checked in to index"
 msgstr "Непроиндексированные изменения"
 
-#: gitk:7158
 msgid "and many more"
 msgstr "и многое другое"
 
-#: gitk:7161
 msgid "many"
 msgstr "много"
 
-#: gitk:7352
 msgid "Tags:"
 msgstr "Метки:"
 
-#: gitk:7369 gitk:7375 gitk:8854
 msgid "Parent"
 msgstr "Предок"
 
-#: gitk:7380
 msgid "Child"
 msgstr "Потомок"
 
-#: gitk:7389
 msgid "Branch"
 msgstr "Ветка"
 
-#: gitk:7392
 msgid "Follows"
 msgstr "Следует за"
 
-#: gitk:7395
 msgid "Precedes"
 msgstr "Предшествует"
 
-#: gitk:7990
 #, tcl-format
 msgid "Error getting diffs: %s"
 msgstr "Ошибка получения изменений: %s"
 
-#: gitk:8679
 msgid "Goto:"
 msgstr "Перейти к:"
 
-#: gitk:8700
 #, tcl-format
 msgid "Short SHA1 id %s is ambiguous"
 msgstr "Сокращённый SHA1 идентификатор %s неоднозначен"
 
-#: gitk:8707
 #, tcl-format
 msgid "Revision %s is not known"
 msgstr "Редакция %s не найдена"
 
-#: gitk:8717
 #, tcl-format
 msgid "SHA1 id %s is not known"
 msgstr "SHA1 идентификатор %s не найден"
 
-#: gitk:8719
 #, tcl-format
 msgid "Revision %s is not in the current view"
 msgstr "Редакция %s не найдена в текущем представлении"
 
-#: gitk:8861 gitk:8876
 msgid "Date"
 msgstr "Дата"
 
-#: gitk:8864
 msgid "Children"
 msgstr "Потомки"
 
-#: gitk:8927
 #, tcl-format
 msgid "Reset %s branch to here"
 msgstr "Сбросить ветку %s на этот коммит"
 
-#: gitk:8929
 msgid "Detached head: can't reset"
 msgstr "Коммит не принадлежит ни одной ветке, сбросить невозможно"
 
-#: gitk:9034 gitk:9040
 msgid "Skipping merge commit "
 msgstr "Пропускаю коммит-слияние"
 
-#: gitk:9049 gitk:9054
 msgid "Error getting patch ID for "
 msgstr "Не удалось получить идентификатор патча для "
 
-#: gitk:9050 gitk:9055
 msgid " - stopping\n"
 msgstr " — останов\n"
 
-#: gitk:9060 gitk:9063 gitk:9071 gitk:9085 gitk:9094
 msgid "Commit "
 msgstr "Коммит"
 
-#: gitk:9064
 msgid ""
 " is the same patch as\n"
 "       "
-msgstr " такой же патч, как и\n       "
+msgstr ""
+" такой же патч, как и\n"
+"       "
 
-#: gitk:9072
 msgid ""
 " differs from\n"
 "       "
-msgstr " отличается от\n       "
+msgstr ""
+" отличается от\n"
+"       "
 
-#: gitk:9074
 msgid ""
 "Diff of commits:\n"
 "\n"
-msgstr "Различия коммитов:\n\n"
+msgstr ""
+"Различия коммитов:\n"
+"\n"
 
-#: gitk:9086 gitk:9095
 #, tcl-format
 msgid " has %s children - stopping\n"
 msgstr " является %s потомком — останов\n"
 
-#: gitk:9114
 #, tcl-format
 msgid "Error writing commit to file: %s"
 msgstr "Произошла ошибка при записи коммита в файл: %s"
 
-#: gitk:9120
 #, tcl-format
 msgid "Error diffing commits: %s"
 msgstr "Произошла ошибка при выводе различий коммитов: %s"
 
-#: gitk:9166
 msgid "Top"
 msgstr "Верх"
 
-#: gitk:9167
 msgid "From"
 msgstr "От"
 
-#: gitk:9172
 msgid "To"
 msgstr "До"
 
-#: gitk:9196
 msgid "Generate patch"
 msgstr "Создать патч"
 
-#: gitk:9198
 msgid "From:"
 msgstr "От:"
 
-#: gitk:9207
 msgid "To:"
 msgstr "До:"
 
-#: gitk:9216
 msgid "Reverse"
 msgstr "В обратном порядке"
 
-#: gitk:9218 gitk:9428
 msgid "Output file:"
 msgstr "Файл для сохранения:"
 
-#: gitk:9224
 msgid "Generate"
 msgstr "Создать"
 
-#: gitk:9262
 msgid "Error creating patch:"
 msgstr "Ошибка создания патча:"
 
-#: gitk:9285 gitk:9416 gitk:9504
 msgid "ID:"
 msgstr "ID:"
 
-#: gitk:9294
 msgid "Tag name:"
 msgstr "Имя метки:"
 
-#: gitk:9297
 msgid "Tag message is optional"
 msgstr "Описание метки указывать не обязательно"
 
-#: gitk:9299
 msgid "Tag message:"
 msgstr "Описание метки:"
 
-#: gitk:9303 gitk:9474
 msgid "Create"
 msgstr "Создать"
 
-#: gitk:9321
 msgid "No tag name specified"
 msgstr "Не задано имя метки"
 
-#: gitk:9325
 #, tcl-format
 msgid "Tag \"%s\" already exists"
 msgstr "Метка «%s» уже существует"
 
-#: gitk:9335
 msgid "Error creating tag:"
 msgstr "Ошибка создания метки:"
 
-#: gitk:9425
 msgid "Command:"
 msgstr "Команда:"
 
-#: gitk:9433
 msgid "Write"
 msgstr "Запись"
 
-#: gitk:9451
 msgid "Error writing commit:"
 msgstr "Произошла ошибка при записи коммита:"
 
-#: gitk:9473
 msgid "Create branch"
 msgstr "Создать ветку"
 
-#: gitk:9489
 #, tcl-format
 msgid "Rename branch %s"
 msgstr "Переименовать ветку %s"
 
-#: gitk:9490
 msgid "Rename"
 msgstr "Переименовать"
 
-#: gitk:9514
 msgid "Name:"
 msgstr "Имя:"
 
-#: gitk:9538
 msgid "Please specify a name for the new branch"
 msgstr "Укажите имя для новой ветки"
 
-#: gitk:9543
 #, tcl-format
 msgid "Branch '%s' already exists. Overwrite?"
 msgstr "Ветка «%s» уже существует. Переписать?"
 
-#: gitk:9587
 msgid "Please specify a new name for the branch"
 msgstr "Укажите имя для новой ветки"
 
-#: gitk:9650
 #, tcl-format
 msgid "Commit %s is already included in branch %s -- really re-apply it?"
 msgstr "Коммит %s уже включён в ветку %s. Продолжить операцию?"
 
-#: gitk:9655
 msgid "Cherry-picking"
 msgstr "Копирование коммита"
 
-#: gitk:9664
 #, tcl-format
 msgid ""
 "Cherry-pick failed because of local changes to file '%s'.\n"
 "Please commit, reset or stash your changes and try again."
-msgstr "Копирование коммита невозможно из-за изменений в файле «%s».\nЗакоммитьте, сбросьте или спрячьте изменения и повторите операцию."
+msgstr ""
+"Копирование коммита невозможно из-за изменений в файле «%s».\n"
+"Закоммитьте, сбросьте или спрячьте изменения и повторите операцию."
 
-#: gitk:9670
 msgid ""
 "Cherry-pick failed because of merge conflict.\n"
 "Do you wish to run git citool to resolve it?"
-msgstr "Копирование изменений невозможно из-за незавершённой операции слияния.\nЗапустить git citool для завершения этой операции?"
+msgstr ""
+"Копирование изменений невозможно из-за незавершённой операции слияния.\n"
+"Запустить git citool для завершения этой операции?"
 
-#: gitk:9686 gitk:9744
 msgid "No changes committed"
 msgstr "Изменения не закоммичены"
 
-#: gitk:9713
 #, tcl-format
 msgid "Commit %s is not included in branch %s -- really revert it?"
 msgstr "Коммит %s не включён в ветку %s. Продолжить операцию?"
 
-#: gitk:9718
 msgid "Reverting"
 msgstr "Обращение изменений"
 
-#: gitk:9726
 #, tcl-format
 msgid ""
 "Revert failed because of local changes to the following files:%s Please "
 "commit, reset or stash  your changes and try again."
-msgstr "Возврат изменений коммита не удался из-за локальных изменений в указанных файлах: %s\nЗакоммитьте, сбросьте или спрячьте изменения и повторите операцию."
+msgstr ""
+"Возврат изменений коммита не удался из-за локальных изменений в указанных "
+"файлах: %s\n"
+"Закоммитьте, сбросьте или спрячьте изменения и повторите операцию."
 
-#: gitk:9730
 msgid ""
 "Revert failed because of merge conflict.\n"
 " Do you wish to run git citool to resolve it?"
-msgstr "Возврат изменений невозможен из-за незавершённой операции слияния.\nЗапустить git citool для завершения этой операции?"
+msgstr ""
+"Возврат изменений невозможен из-за незавершённой операции слияния.\n"
+"Запустить git citool для завершения этой операции?"
 
-#: gitk:9773
 msgid "Confirm reset"
 msgstr "Подтвердите операцию перехода"
 
-#: gitk:9775
 #, tcl-format
 msgid "Reset branch %s to %s?"
 msgstr "Сбросить ветку %s на коммит %s?"
 
-#: gitk:9777
 msgid "Reset type:"
 msgstr "Тип операции перехода:"
 
-#: gitk:9780
 msgid "Soft: Leave working tree and index untouched"
 msgstr "Лёгкий: оставить рабочий каталог и индекс неизменными"
 
-#: gitk:9783
 msgid "Mixed: Leave working tree untouched, reset index"
 msgstr "Смешанный: оставить рабочий каталог неизменным, установить индекс"
 
-#: gitk:9786
 msgid ""
 "Hard: Reset working tree and index\n"
 "(discard ALL local changes)"
-msgstr "Жесткий: переписать индекс и рабочий каталог\n(все изменения в рабочем каталоге будут потеряны)"
+msgstr ""
+"Жесткий: переписать индекс и рабочий каталог\n"
+"(все изменения в рабочем каталоге будут потеряны)"
 
-#: gitk:9803
 msgid "Resetting"
 msgstr "Сброс"
 
-#: gitk:9876
 #, tcl-format
 msgid "A local branch named %s exists already"
 msgstr "Локальная ветка с именем %s уже существует"
 
-#: gitk:9884
 msgid "Checking out"
 msgstr "Переход"
 
-#: gitk:9943
 msgid "Cannot delete the currently checked-out branch"
 msgstr "Активная ветка не может быть удалена"
 
-#: gitk:9949
 #, tcl-format
 msgid ""
 "The commits on branch %s aren't on any other branch.\n"
 "Really delete branch %s?"
-msgstr "Коммиты из ветки %s не принадлежат больше никакой другой ветке.\nДействительно удалить ветку %s?"
+msgstr ""
+"Коммиты из ветки %s не принадлежат больше никакой другой ветке.\n"
+"Действительно удалить ветку %s?"
 
-#: gitk:9980
 #, tcl-format
 msgid "Tags and heads: %s"
 msgstr "Метки и ветки: %s"
 
-#: gitk:9997
 msgid "Filter"
 msgstr "Фильтровать"
 
-#: gitk:10293
 msgid ""
 "Error reading commit topology information; branch and preceding/following "
 "tag information will be incomplete."
-msgstr "Ошибка чтения истории проекта; информация о ветках и коммитах вокруг меток (до/после) может быть неполной."
+msgstr ""
+"Ошибка чтения истории проекта; информация о ветках и коммитах вокруг меток "
+"(до/после) может быть неполной."
 
-#: gitk:11270
 msgid "Tag"
 msgstr "Метка"
 
-#: gitk:11274
 msgid "Id"
 msgstr "Id"
 
-#: gitk:11357
 msgid "Gitk font chooser"
 msgstr "Шрифт Gitk"
 
-#: gitk:11374
 msgid "B"
 msgstr "Ж"
 
-#: gitk:11377
 msgid "I"
 msgstr "К"
 
-#: gitk:11495
 msgid "Commit list display options"
 msgstr "Параметры показа списка коммитов"
 
-#: gitk:11498
 msgid "Maximum graph width (lines)"
 msgstr "Макс. ширина графа (строк)"
 
-#: gitk:11502
 #, no-tcl-format
 msgid "Maximum graph width (% of pane)"
 msgstr "Макс. ширина графа (% ширины панели)"
 
-#: gitk:11505
 msgid "Show local changes"
 msgstr "Показывать изменения в рабочем каталоге"
 
-#: gitk:11508
 msgid "Auto-select SHA1 (length)"
 msgstr "Автоматически выделить SHA1 (длинна)"
 
-#: gitk:11512
 msgid "Hide remote refs"
 msgstr "Скрыть внешние ссылки"
 
-#: gitk:11516
 msgid "Diff display options"
 msgstr "Параметры показа изменений"
 
-#: gitk:11518
 msgid "Tab spacing"
 msgstr "Ширина табуляции"
 
-#: gitk:11521
 msgid "Display nearby tags/heads"
 msgstr "Показывать близкие метки/ветки"
 
-#: gitk:11524
 msgid "Maximum # tags/heads to show"
 msgstr "Показывать максимальное количество меток/веток"
 
-#: gitk:11527
 msgid "Limit diffs to listed paths"
 msgstr "Ограничить показ изменений выбранными файлами"
 
-#: gitk:11530
 msgid "Support per-file encodings"
 msgstr "Поддержка кодировок в отдельных файлах"
 
-#: gitk:11536 gitk:11683
 msgid "External diff tool"
 msgstr "Программа для показа изменений"
 
-#: gitk:11537
 msgid "Choose..."
 msgstr "Выберите..."
 
-#: gitk:11542
 msgid "General options"
 msgstr "Общие опции"
 
-#: gitk:11545
 msgid "Use themed widgets"
 msgstr "Использовать стили виджетов"
 
-#: gitk:11547
 msgid "(change requires restart)"
 msgstr "(изменение потребует перезапуск)"
 
-#: gitk:11549
 msgid "(currently unavailable)"
 msgstr "(недоступно в данный момент)"
 
-#: gitk:11560
 msgid "Colors: press to choose"
 msgstr "Цвета: нажмите для выбора"
 
-#: gitk:11563
 msgid "Interface"
 msgstr "Интерфейс"
 
-#: gitk:11564
 msgid "interface"
 msgstr "интерфейс"
 
-#: gitk:11567
 msgid "Background"
 msgstr "Фон"
 
-#: gitk:11568 gitk:11598
 msgid "background"
 msgstr "фон"
 
-#: gitk:11571
 msgid "Foreground"
 msgstr "Передний план"
 
-#: gitk:11572
 msgid "foreground"
 msgstr "передний план"
 
-#: gitk:11575
 msgid "Diff: old lines"
 msgstr "Изменения: старый текст"
 
-#: gitk:11576
 msgid "diff old lines"
 msgstr "старый текст изменения"
 
-#: gitk:11580
 msgid "Diff: new lines"
 msgstr "Изменения: новый текст"
 
-#: gitk:11581
 msgid "diff new lines"
 msgstr "новый текст изменения"
 
-#: gitk:11585
 msgid "Diff: hunk header"
 msgstr "Изменения: заголовок блока"
 
-#: gitk:11587
 msgid "diff hunk header"
 msgstr "заголовок блока изменений"
 
-#: gitk:11591
 msgid "Marked line bg"
 msgstr "Фон выбранной строки"
 
-#: gitk:11593
 msgid "marked line background"
 msgstr "фон выбранной строки"
 
-#: gitk:11597
 msgid "Select bg"
 msgstr "Выберите фон"
 
-#: gitk:11606
 msgid "Fonts: press to choose"
 msgstr "Шрифт: нажмите для выбора"
 
-#: gitk:11608
 msgid "Main font"
 msgstr "Основной шрифт"
 
-#: gitk:11609
 msgid "Diff display font"
 msgstr "Шрифт показа изменений"
 
-#: gitk:11610
 msgid "User interface font"
 msgstr "Шрифт интерфейса"
 
-#: gitk:11632
 msgid "Gitk preferences"
 msgstr "Настройки Gitk"
 
-#: gitk:11641
 msgid "General"
 msgstr "Общие"
 
-#: gitk:11642
 msgid "Colors"
 msgstr "Цвета"
 
-#: gitk:11643
 msgid "Fonts"
 msgstr "Шрифты"
 
-#: gitk:11693
 #, tcl-format
 msgid "Gitk: choose color for %s"
 msgstr "Gitk: выберите цвет для %s"
 
-#: gitk:12206
 msgid ""
 "Sorry, gitk cannot run with this version of Tcl/Tk.\n"
 " Gitk requires at least Tcl/Tk 8.4."
-msgstr "К сожалению gitk не может работать с этой версий Tcl/Tk.\nТребуется как минимум Tcl/Tk 8.4."
+msgstr ""
+"К сожалению gitk не может работать с этой версий Tcl/Tk.\n"
+"Требуется как минимум Tcl/Tk 8.4."
 
-#: gitk:12416
 msgid "Cannot find a git repository here."
 msgstr "Git-репозитарий не найден в текущем каталоге."
 
-#: gitk:12463
 #, tcl-format
 msgid "Ambiguous argument '%s': both revision and filename"
 msgstr "Неоднозначный аргумент «%s»: существует как редакция и как имя файла"
 
-#: gitk:12475
 msgid "Bad arguments to gitk:"
 msgstr "Неправильные аргументы для gitk:"
diff --git a/gitk-git/po/sv.po b/gitk-git/po/sv.po
index 5afbe6d..c929062 100644
--- a/gitk-git/po/sv.po
+++ b/gitk-git/po/sv.po
@@ -7,7 +7,7 @@
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: sv\n"
+"Project-Id-Version: Gitk\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2023-10-26 21:39+0100\n"
 "PO-Revision-Date: 2023-10-26 21:42+0100\n"
@@ -20,33 +20,26 @@
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 "X-Generator: Gtranslator 3.38.0\n"
 
-#: gitk:139
 msgid "Couldn't get list of unmerged files:"
 msgstr "Kunde inte hämta lista över ej sammanslagna filer:"
 
-#: gitk:211 gitk:2406
 msgid "Color words"
 msgstr "Färga ord"
 
-#: gitk:216 gitk:2406 gitk:8307 gitk:8340
 msgid "Markup words"
 msgstr "Märk upp ord"
 
-#: gitk:323
 msgid "Error parsing revisions:"
 msgstr "Fel vid tolkning av revisioner:"
 
-#: gitk:379
 msgid "Error executing --argscmd command:"
 msgstr "Fel vid körning av --argscmd-kommando:"
 
-#: gitk:392
 msgid "No files selected: --merge specified but no files are unmerged."
 msgstr ""
 "Inga filer valdes: --merge angavs men det finns inga filer som inte har "
 "slagits samman."
 
-#: gitk:395
 msgid ""
 "No files selected: --merge specified but no unmerged files are within file "
 "limit."
@@ -54,326 +47,243 @@
 "Inga filer valdes: --merge angavs men det finns inga filer inom "
 "filbegränsningen."
 
-#: gitk:417 gitk:565
 msgid "Error executing git log:"
 msgstr "Fel vid körning av git log:"
 
-#: gitk:435 gitk:581
 msgid "Reading"
 msgstr "Läser"
 
-#: gitk:495 gitk:4572
 msgid "Reading commits..."
 msgstr "Läser incheckningar..."
 
-#: gitk:498 gitk:1640 gitk:4575
 msgid "No commits selected"
 msgstr "Inga incheckningar markerade"
 
-#: gitk:1448 gitk:4092 gitk:12674
 msgid "Command line"
 msgstr "Kommandorad"
 
-#: gitk:1514
 msgid "Can't parse git log output:"
 msgstr "Kan inte tolka utdata från git log:"
 
-#: gitk:1743
 msgid "No commit information available"
 msgstr "Ingen incheckningsinformation är tillgänglig"
 
-#: gitk:1910 gitk:1939 gitk:4362 gitk:9847 gitk:11451 gitk:11751
 msgid "OK"
 msgstr "OK"
 
-#: gitk:1941 gitk:4364 gitk:9283 gitk:9362 gitk:9492 gitk:9578 gitk:9849
-#: gitk:11452 gitk:11752
 msgid "Cancel"
 msgstr "Avbryt"
 
-#: gitk:2090
 msgid "&Update"
 msgstr "&Uppdatera"
 
-#: gitk:2091
 msgid "&Reload"
 msgstr "Läs &om"
 
-#: gitk:2092
 msgid "Reread re&ferences"
 msgstr "Läs om &referenser"
 
-#: gitk:2093
 msgid "&List references"
 msgstr "&Visa referenser"
 
-#: gitk:2095
 msgid "Start git &gui"
 msgstr "Starta git &gui"
 
-#: gitk:2097
 msgid "&Quit"
 msgstr "&Avsluta"
 
-#: gitk:2089
 msgid "&File"
 msgstr "&Arkiv"
 
-#: gitk:2101
 msgid "&Preferences"
 msgstr "&Inställningar"
 
-#: gitk:2100
 msgid "&Edit"
 msgstr "&Redigera"
 
-#: gitk:2105
 msgid "&New view..."
 msgstr "&Ny vy..."
 
-#: gitk:2106
 msgid "&Edit view..."
 msgstr "&Ändra vy..."
 
-#: gitk:2107
 msgid "&Delete view"
 msgstr "&Ta bort vy"
 
-#: gitk:2109
 msgid "&All files"
 msgstr "&Alla filer"
 
-#: gitk:2104
 msgid "&View"
 msgstr "&Visa"
 
-#: gitk:2114 gitk:2124
 msgid "&About gitk"
 msgstr "&Om gitk"
 
-#: gitk:2115 gitk:2129
 msgid "&Key bindings"
 msgstr "&Tangentbordsbindningar"
 
-#: gitk:2113 gitk:2128
 msgid "&Help"
 msgstr "&Hjälp"
 
-#: gitk:2206 gitk:8739
 msgid "SHA1 ID:"
 msgstr "SHA1-id:"
 
-#: gitk:2250
 msgid "Row"
 msgstr "Rad"
 
-#: gitk:2288
 msgid "Find"
 msgstr "Sök"
 
-#: gitk:2316
 msgid "commit"
 msgstr "incheckning"
 
-#: gitk:2320 gitk:2322 gitk:4734 gitk:4757 gitk:4781 gitk:6802 gitk:6874
-#: gitk:6959
 msgid "containing:"
 msgstr "som innehåller:"
 
-#: gitk:2323 gitk:3573 gitk:3578 gitk:4810
 msgid "touching paths:"
 msgstr "som rör sökväg:"
 
-#: gitk:2324 gitk:4824
 msgid "adding/removing string:"
 msgstr "som lägger/till tar bort sträng:"
 
-#: gitk:2325 gitk:4826
 msgid "changing lines matching:"
 msgstr "ändrar rader som matchar:"
 
-#: gitk:2334 gitk:2336 gitk:4813
 msgid "Exact"
 msgstr "Exakt"
 
-#: gitk:2336 gitk:4901 gitk:6770
 msgid "IgnCase"
 msgstr "IgnVersaler"
 
-#: gitk:2336 gitk:4783 gitk:4899 gitk:6766
 msgid "Regexp"
 msgstr "Reg.uttr."
 
-#: gitk:2338 gitk:2339 gitk:4921 gitk:4951 gitk:4958 gitk:6895 gitk:6963
 msgid "All fields"
 msgstr "Alla fält"
 
-#: gitk:2339 gitk:4918 gitk:4951 gitk:6833
 msgid "Headline"
 msgstr "Rubrik"
 
-#: gitk:2340 gitk:4918 gitk:6833 gitk:6963 gitk:7471
 msgid "Comments"
 msgstr "Kommentarer"
 
-#: gitk:2340 gitk:4918 gitk:4923 gitk:4958 gitk:6833 gitk:7406 gitk:8917
-#: gitk:8932
 msgid "Author"
 msgstr "Författare"
 
-#: gitk:2340 gitk:4918 gitk:6833 gitk:7408
 msgid "Committer"
 msgstr "Incheckare"
 
-#: gitk:2374
 msgid "Search"
 msgstr "Sök"
 
-#: gitk:2382
 msgid "Diff"
 msgstr "Diff"
 
-#: gitk:2384
 msgid "Old version"
 msgstr "Gammal version"
 
-#: gitk:2386
 msgid "New version"
 msgstr "Ny version"
 
-#: gitk:2389
 msgid "Lines of context"
 msgstr "Rader sammanhang"
 
-#: gitk:2399
 msgid "Ignore space change"
 msgstr "Ignorera ändringar i blanksteg"
 
-#: gitk:2403 gitk:2405 gitk:8041 gitk:8293
 msgid "Line diff"
 msgstr "Rad-diff"
 
-#: gitk:2478
 msgid "Patch"
 msgstr "Patch"
 
-#: gitk:2480
 msgid "Tree"
 msgstr "Träd"
 
-#: gitk:2650 gitk:2671
 msgid "Diff this -> selected"
 msgstr "Diff denna -> markerad"
 
-#: gitk:2651 gitk:2672
 msgid "Diff selected -> this"
 msgstr "Diff markerad -> denna"
 
-#: gitk:2652 gitk:2673
 msgid "Make patch"
 msgstr "Skapa patch"
 
-#: gitk:2653 gitk:9341
 msgid "Create tag"
 msgstr "Skapa tagg"
 
-#: gitk:2654
 msgid "Copy commit reference"
 msgstr "Kopiera incheckningsreferens"
 
-#: gitk:2655 gitk:9472
 msgid "Write commit to file"
 msgstr "Skriv incheckning till fil"
 
-#: gitk:2656
 msgid "Create new branch"
 msgstr "Skapa ny gren"
 
-#: gitk:2657
 msgid "Cherry-pick this commit"
 msgstr "Plocka denna incheckning"
 
-#: gitk:2658
 msgid "Reset HEAD branch to here"
 msgstr "Återställ HEAD-grenen hit"
 
-#: gitk:2659
 msgid "Mark this commit"
 msgstr "Markera denna incheckning"
 
-#: gitk:2660
 msgid "Return to mark"
 msgstr "Återgå till markering"
 
-#: gitk:2661
 msgid "Find descendant of this and mark"
 msgstr "Hitta efterföljare till denna och markera"
 
-#: gitk:2662
 msgid "Compare with marked commit"
 msgstr "Jämför med markerad incheckning"
 
-#: gitk:2663 gitk:2674
 msgid "Diff this -> marked commit"
 msgstr "Diff denna -> markerad incheckning"
 
-#: gitk:2664 gitk:2675
 msgid "Diff marked commit -> this"
 msgstr "Diff markerad incheckning -> denna"
 
-#: gitk:2665
 msgid "Revert this commit"
 msgstr "Ångra denna incheckning"
 
-#: gitk:2681
 msgid "Check out this branch"
 msgstr "Checka ut denna gren"
 
-#: gitk:2682
 msgid "Rename this branch"
 msgstr "Byt namn på denna gren"
 
-#: gitk:2683
 msgid "Remove this branch"
 msgstr "Ta bort denna gren"
 
-#: gitk:2684
 msgid "Copy branch name"
 msgstr "Kopiera namn på gren"
 
-#: gitk:2691
 msgid "Highlight this too"
 msgstr "Markera även detta"
 
-#: gitk:2692
 msgid "Highlight this only"
 msgstr "Markera bara detta"
 
-#: gitk:2693
 msgid "External diff"
 msgstr "Extern diff"
 
-#: gitk:2694
 msgid "Blame parent commit"
 msgstr "Klandra föräldraincheckning"
 
-#: gitk:2695
 msgid "Copy path"
 msgstr "Kopiera sökväg"
 
-#: gitk:2702
 msgid "Show origin of this line"
 msgstr "Visa ursprunget för den här raden"
 
-#: gitk:2703
 msgid "Run git gui blame on this line"
 msgstr "Kör git gui blame på den här raden"
 
-#: gitk:3057
 msgid "About gitk"
 msgstr "Om gitk"
 
-#: gitk:3059
 msgid ""
 "\n"
 "Gitk - a commit viewer for git\n"
@@ -389,323 +299,249 @@
 "\n"
 "Använd och vidareförmedla enligt villkoren i GNU General Public License"
 
-#: gitk:3067 gitk:3134 gitk:10062
 msgid "Close"
 msgstr "Stäng"
 
-#: gitk:3088
 msgid "Gitk key bindings"
 msgstr "Tangentbordsbindningar för Gitk"
 
-#: gitk:3091
 msgid "Gitk key bindings:"
 msgstr "Tangentbordsbindningar för Gitk:"
 
-#: gitk:3093
 #, tcl-format
 msgid "<%s-Q>\t\tQuit"
 msgstr "<%s-Q>\t\tAvsluta"
 
-#: gitk:3094
 #, tcl-format
 msgid "<%s-W>\t\tClose window"
 msgstr "<%s-W>\t\tStäng fönster"
 
-#: gitk:3095
 msgid "<Home>\t\tMove to first commit"
 msgstr "<Home>\t\tGå till första incheckning"
 
-#: gitk:3096
 msgid "<End>\t\tMove to last commit"
 msgstr "<End>\t\tGå till sista incheckning"
 
-#: gitk:3097
 msgid "<Up>, p, k\tMove up one commit"
 msgstr "<Upp>, p, k\tGå en incheckning upp"
 
-#: gitk:3098
 msgid "<Down>, n, j\tMove down one commit"
 msgstr "<Ned>, n, j\tGå en incheckning ned"
 
-#: gitk:3099
 msgid "<Left>, z, h\tGo back in history list"
 msgstr "<Vänster>, z, h\tGå bakåt i historiken"
 
-#: gitk:3100
 msgid "<Right>, x, l\tGo forward in history list"
 msgstr "<Höger>, x, l\tGå framåt i historiken"
 
-#: gitk:3101
 #, tcl-format
 msgid "<%s-n>\tGo to n-th parent of current commit in history list"
 msgstr "<%s-n>\tGå till aktuell inchecknings n:te förälder i historielistan"
 
-#: gitk:3102
 msgid "<PageUp>\tMove up one page in commit list"
 msgstr "<PageUp>\tGå upp en sida i incheckningslistan"
 
-#: gitk:3103
 msgid "<PageDown>\tMove down one page in commit list"
 msgstr "<PageDown>\tGå ned en sida i incheckningslistan"
 
-#: gitk:3104
 #, tcl-format
 msgid "<%s-Home>\tScroll to top of commit list"
 msgstr "<%s-Home>\tRulla till början av incheckningslistan"
 
-#: gitk:3105
 #, tcl-format
 msgid "<%s-End>\tScroll to bottom of commit list"
 msgstr "<%s-End>\tRulla till slutet av incheckningslistan"
 
-#: gitk:3106
 #, tcl-format
 msgid "<%s-Up>\tScroll commit list up one line"
 msgstr "<%s-Upp>\tRulla incheckningslistan upp ett steg"
 
-#: gitk:3107
 #, tcl-format
 msgid "<%s-Down>\tScroll commit list down one line"
 msgstr "<%s-Ned>\tRulla incheckningslistan ned ett steg"
 
-#: gitk:3108
 #, tcl-format
 msgid "<%s-PageUp>\tScroll commit list up one page"
 msgstr "<%s-PageUp>\tRulla incheckningslistan upp en sida"
 
-#: gitk:3109
 #, tcl-format
 msgid "<%s-PageDown>\tScroll commit list down one page"
 msgstr "<%s-PageDown>\tRulla incheckningslistan ned en sida"
 
-#: gitk:3110
 msgid "<Shift-Up>\tFind backwards (upwards, later commits)"
 msgstr "<Skift-Upp>\tSök bakåt (uppåt, senare incheckningar)"
 
-#: gitk:3111
 msgid "<Shift-Down>\tFind forwards (downwards, earlier commits)"
 msgstr "<Skift-Ned>\tSök framåt (nedåt, tidigare incheckningar)"
 
-#: gitk:3112
 msgid "<Delete>, b\tScroll diff view up one page"
 msgstr "<Delete>, b\tRulla diffvisningen upp en sida"
 
-#: gitk:3113
 msgid "<Backspace>\tScroll diff view up one page"
 msgstr "<Baksteg>\tRulla diffvisningen upp en sida"
 
-#: gitk:3114
 msgid "<Space>\t\tScroll diff view down one page"
 msgstr "<Blanksteg>\tRulla diffvisningen ned en sida"
 
-#: gitk:3115
 msgid "u\t\tScroll diff view up 18 lines"
 msgstr "u\t\tRulla diffvisningen upp 18 rader"
 
-#: gitk:3116
 msgid "d\t\tScroll diff view down 18 lines"
 msgstr "d\t\tRulla diffvisningen ned 18 rader"
 
-#: gitk:3117
 #, tcl-format
 msgid "<%s-F>\t\tFind"
 msgstr "<%s-F>\t\tSök"
 
-#: gitk:3118
 #, tcl-format
 msgid "<%s-G>\t\tMove to next find hit"
 msgstr "<%s-G>\t\tGå till nästa sökträff"
 
-#: gitk:3119
 msgid "<Return>\tMove to next find hit"
 msgstr "<Return>\t\tGå till nästa sökträff"
 
-#: gitk:3120
 msgid "g\t\tGo to commit"
 msgstr "g\t\tGå till incheckning"
 
-#: gitk:3121
 msgid "/\t\tFocus the search box"
 msgstr "/\t\tFokusera sökrutan"
 
-#: gitk:3122
 msgid "?\t\tMove to previous find hit"
 msgstr "?\t\tGå till föregående sökträff"
 
-#: gitk:3123
 msgid "f\t\tScroll diff view to next file"
 msgstr "f\t\tRulla diffvisningen till nästa fil"
 
-#: gitk:3124
 #, tcl-format
 msgid "<%s-S>\t\tSearch for next hit in diff view"
 msgstr "<%s-S>\t\tGå till nästa sökträff i diffvisningen"
 
-#: gitk:3125
 #, tcl-format
 msgid "<%s-R>\t\tSearch for previous hit in diff view"
 msgstr "<%s-R>\t\tGå till föregående sökträff i diffvisningen"
 
-#: gitk:3126
 #, tcl-format
 msgid "<%s-KP+>\tIncrease font size"
 msgstr "<%s-Num+>\tÖka teckenstorlek"
 
-#: gitk:3127
 #, tcl-format
 msgid "<%s-plus>\tIncrease font size"
 msgstr "<%s-plus>\tÖka teckenstorlek"
 
-#: gitk:3128
 #, tcl-format
 msgid "<%s-KP->\tDecrease font size"
 msgstr "<%s-Num->\tMinska teckenstorlek"
 
-#: gitk:3129
 #, tcl-format
 msgid "<%s-minus>\tDecrease font size"
 msgstr "<%s-minus>\tMinska teckenstorlek"
 
-#: gitk:3130
 msgid "<F5>\t\tUpdate"
 msgstr "<F5>\t\tUppdatera"
 
-#: gitk:3597 gitk:3606
 #, tcl-format
 msgid "Error creating temporary directory %s:"
 msgstr "Fel vid skapande av temporär katalog %s:"
 
-#: gitk:3619
 #, tcl-format
 msgid "Error getting \"%s\" from %s:"
 msgstr "Fel vid hämtning av  ”%s” från %s:"
 
-#: gitk:3682
 msgid "command failed:"
 msgstr "kommando misslyckades:"
 
-#: gitk:3831
 msgid "No such commit"
 msgstr "Incheckning saknas"
 
-#: gitk:3845
 msgid "git gui blame: command failed:"
 msgstr "git gui blame: kommando misslyckades:"
 
-#: gitk:3876
 #, tcl-format
 msgid "Couldn't read merge head: %s"
 msgstr "Kunde inte läsa sammanslagningshuvud: %s"
 
-#: gitk:3884
 #, tcl-format
 msgid "Error reading index: %s"
 msgstr "Fel vid läsning av index: %s"
 
-#: gitk:3909
 #, tcl-format
 msgid "Couldn't start git blame: %s"
 msgstr "Kunde inte starta git blame: %s"
 
-#: gitk:3912 gitk:6801
 msgid "Searching"
 msgstr "Söker"
 
-#: gitk:3944
 #, tcl-format
 msgid "Error running git blame: %s"
 msgstr "Fel vid körning av git blame: %s"
 
-#: gitk:3972
 #, tcl-format
 msgid "That line comes from commit %s,  which is not in this view"
 msgstr "Raden kommer från incheckningen %s, som inte finns i denna vy"
 
-#: gitk:3986
 msgid "External diff viewer failed:"
 msgstr "Externt diff-verktyg misslyckades:"
 
-#: gitk:4090
 msgid "All files"
 msgstr "Alla filer"
 
-#: gitk:4114
 msgid "View"
 msgstr "Visa"
 
-#: gitk:4117
 msgid "Gitk view definition"
 msgstr "Definition av Gitk-vy"
 
-#: gitk:4121
 msgid "Remember this view"
 msgstr "Spara denna vy"
 
-#: gitk:4122
 msgid "References (space separated list):"
 msgstr "Referenser (blankstegsavdelad lista):"
 
-#: gitk:4123
 msgid "Branches & tags:"
 msgstr "Grenar & taggar:"
 
-#: gitk:4124
 msgid "All refs"
 msgstr "Alla referenser"
 
-#: gitk:4125
 msgid "All (local) branches"
 msgstr "Alla (lokala) grenar"
 
-#: gitk:4126
 msgid "All tags"
 msgstr "Alla taggar"
 
-#: gitk:4127
 msgid "All remote-tracking branches"
 msgstr "Alla fjärrspårande grenar"
 
-#: gitk:4128
 msgid "Commit Info (regular expressions):"
 msgstr "Incheckningsinfo (reguljära uttryck):"
 
-#: gitk:4129
 msgid "Author:"
 msgstr "Författare:"
 
-#: gitk:4130
 msgid "Committer:"
 msgstr "Incheckare:"
 
-#: gitk:4131
 msgid "Commit Message:"
 msgstr "Incheckningsmeddelande:"
 
-#: gitk:4132
 msgid "Matches all Commit Info criteria"
 msgstr "Motsvarar alla kriterier för incheckningsinfo"
 
-#: gitk:4133
 msgid "Matches no Commit Info criteria"
 msgstr "Motsvarar inga kriterier för incheckningsinfo"
 
-#: gitk:4134
 msgid "Changes to Files:"
 msgstr "Ändringar av filer:"
 
-#: gitk:4135
 msgid "Fixed String"
 msgstr "Fast sträng"
 
-#: gitk:4136
 msgid "Regular Expression"
 msgstr "Reguljärt uttryck"
 
-#: gitk:4137
 msgid "Search string:"
 msgstr "Söksträng:"
 
-#: gitk:4138
 msgid ""
 "Commit Dates (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 "
 "15:27:38\"):"
@@ -713,205 +549,156 @@
 "Incheckningsdatum (”2 weeks ago”, ”2009-03-17 15:27:38”, ”March 17, 2009 "
 "15:27:38”):"
 
-#: gitk:4139
 msgid "Since:"
 msgstr "Från:"
 
-#: gitk:4140
 msgid "Until:"
 msgstr "Till:"
 
-#: gitk:4141
 msgid "Limit and/or skip a number of revisions (positive integer):"
 msgstr "Begränsa och/eller hoppa över ett antal revisioner (positivt heltal):"
 
-#: gitk:4142
 msgid "Number to show:"
 msgstr "Antal att visa:"
 
-#: gitk:4143
 msgid "Number to skip:"
 msgstr "Antal att hoppa över:"
 
-#: gitk:4144
 msgid "Miscellaneous options:"
 msgstr "Diverse alternativ:"
 
-#: gitk:4145
 msgid "Strictly sort by date"
 msgstr "Strikt datumsortering"
 
-#: gitk:4146
 msgid "Mark branch sides"
 msgstr "Markera sidogrenar"
 
-#: gitk:4147
 msgid "Limit to first parent"
 msgstr "Begränsa till första förälder"
 
-#: gitk:4148
 msgid "Simple history"
 msgstr "Enkel historik"
 
-#: gitk:4149
 msgid "Additional arguments to git log:"
 msgstr "Ytterligare argument till git log:"
 
-#: gitk:4150
 msgid "Enter files and directories to include, one per line:"
 msgstr "Ange filer och kataloger att ta med, en per rad:"
 
-#: gitk:4151
 msgid "Command to generate more commits to include:"
 msgstr "Kommando för att generera fler incheckningar att ta med:"
 
-#: gitk:4275
 msgid "Gitk: edit view"
 msgstr "Gitk: redigera vy"
 
-#: gitk:4283
 msgid "-- criteria for selecting revisions"
 msgstr " - kriterier för val av revisioner"
 
-#: gitk:4288
 msgid "View Name"
 msgstr "Namn på vy"
 
-#: gitk:4363
 msgid "Apply (F5)"
 msgstr "Använd (F5)"
 
-#: gitk:4401
 msgid "Error in commit selection arguments:"
 msgstr "Fel i argument för val av incheckningar:"
 
-#: gitk:4456 gitk:4509 gitk:4971 gitk:4985 gitk:6255 gitk:12615 gitk:12616
 msgid "None"
 msgstr "Inget"
 
-#: gitk:5068 gitk:5073
 msgid "Descendant"
 msgstr "Avkomling"
 
-#: gitk:5069
 msgid "Not descendant"
 msgstr "Inte avkomling"
 
-#: gitk:5076 gitk:5081
 msgid "Ancestor"
 msgstr "Förfader"
 
-#: gitk:5077
 msgid "Not ancestor"
 msgstr "Inte förfader"
 
-#: gitk:5371
 msgid "Local changes checked in to index but not committed"
 msgstr "Lokala ändringar sparade i indexet men inte incheckade"
 
-#: gitk:5407
 msgid "Local uncommitted changes, not checked in to index"
 msgstr "Lokala ändringar, ej sparade i indexet"
 
-#: gitk:7155
 msgid "Error starting web browser:"
 msgstr "Fel när webbläsaren skulle startas:"
 
-#: gitk:7216
 msgid "and many more"
 msgstr "med många flera"
 
-#: gitk:7219
 msgid "many"
 msgstr "många"
 
-#: gitk:7410
 msgid "Tags:"
 msgstr "Taggar:"
 
-#: gitk:7427 gitk:7433 gitk:8912
 msgid "Parent"
 msgstr "Förälder"
 
-#: gitk:7438
 msgid "Child"
 msgstr "Barn"
 
-#: gitk:7447
 msgid "Branch"
 msgstr "Gren"
 
-#: gitk:7450
 msgid "Follows"
 msgstr "Följer"
 
-#: gitk:7453
 msgid "Precedes"
 msgstr "Föregår"
 
-#: gitk:8048
 #, tcl-format
 msgid "Error getting diffs: %s"
 msgstr "Fel vid hämtning av diff: %s"
 
-#: gitk:8737
 msgid "Goto:"
 msgstr "Gå till:"
 
-#: gitk:8758
 #, tcl-format
 msgid "Short SHA1 id %s is ambiguous"
 msgstr "Förkortat SHA1-id %s är tvetydigt"
 
-#: gitk:8765
 #, tcl-format
 msgid "Revision %s is not known"
 msgstr "Revisionen %s är inte känd"
 
-#: gitk:8775
 #, tcl-format
 msgid "SHA1 id %s is not known"
 msgstr "SHA-id:t %s är inte känt"
 
-#: gitk:8777
 #, tcl-format
 msgid "Revision %s is not in the current view"
 msgstr "Revisionen %s finns inte i den nuvarande vyn"
 
-#: gitk:8919 gitk:8934
 msgid "Date"
 msgstr "Datum"
 
-#: gitk:8922
 msgid "Children"
 msgstr "Barn"
 
-#: gitk:8985
 #, tcl-format
 msgid "Reset %s branch to here"
 msgstr "Återställ grenen %s hit"
 
-#: gitk:8987
 msgid "Detached head: can't reset"
 msgstr "Frånkopplad head: kan inte återställa"
 
-#: gitk:9092 gitk:9098
 msgid "Skipping merge commit "
 msgstr "Hoppar över sammanslagningsincheckning "
 
-#: gitk:9107 gitk:9112
 msgid "Error getting patch ID for "
 msgstr "Fel vid hämtning av patch-id för "
 
-#: gitk:9108 gitk:9113
 msgid " - stopping\n"
 msgstr " - stannar\n"
 
-#: gitk:9118 gitk:9121 gitk:9129 gitk:9143 gitk:9152
 msgid "Commit "
 msgstr "Incheckning "
 
-#: gitk:9122
 msgid ""
 " is the same patch as\n"
 "       "
@@ -919,7 +706,6 @@
 " är samma patch som\n"
 "       "
 
-#: gitk:9130
 msgid ""
 " differs from\n"
 "       "
@@ -927,7 +713,6 @@
 " skiljer sig från\n"
 "       "
 
-#: gitk:9132
 msgid ""
 "Diff of commits:\n"
 "\n"
@@ -935,148 +720,114 @@
 "Skillnad mellan incheckningar:\n"
 "\n"
 
-#: gitk:9144 gitk:9153
 #, tcl-format
 msgid " has %s children - stopping\n"
 msgstr " har %s barn - stannar\n"
 
-#: gitk:9172
 #, tcl-format
 msgid "Error writing commit to file: %s"
 msgstr "Fel vid skrivning av incheckning till fil: %s"
 
-#: gitk:9178
 #, tcl-format
 msgid "Error diffing commits: %s"
 msgstr "Fel vid jämförelse av incheckningar: %s"
 
-#: gitk:9224
 msgid "Top"
 msgstr "Topp"
 
-#: gitk:9225
 msgid "From"
 msgstr "Från"
 
-#: gitk:9230
 msgid "To"
 msgstr "Till"
 
-#: gitk:9254
 msgid "Generate patch"
 msgstr "Generera patch"
 
-#: gitk:9256
 msgid "From:"
 msgstr "Från:"
 
-#: gitk:9265
 msgid "To:"
 msgstr "Till:"
 
-#: gitk:9274
 msgid "Reverse"
 msgstr "Vänd"
 
-#: gitk:9276 gitk:9486
 msgid "Output file:"
 msgstr "Utdatafil:"
 
-#: gitk:9282
 msgid "Generate"
 msgstr "Generera"
 
-#: gitk:9320
 msgid "Error creating patch:"
 msgstr "Fel vid generering av patch:"
 
-#: gitk:9343 gitk:9474 gitk:9562
 msgid "ID:"
 msgstr "Id:"
 
-#: gitk:9352
 msgid "Tag name:"
 msgstr "Taggnamn:"
 
-#: gitk:9355
 msgid "Tag message is optional"
 msgstr "Taggmeddelandet är valfritt"
 
-#: gitk:9357
 msgid "Tag message:"
 msgstr "Taggmeddelande:"
 
-#: gitk:9361 gitk:9532
 msgid "Create"
 msgstr "Skapa"
 
-#: gitk:9379
 msgid "No tag name specified"
 msgstr "Inget taggnamn angavs"
 
-#: gitk:9383
 #, tcl-format
 msgid "Tag \"%s\" already exists"
 msgstr "Taggen ”%s” finns redan"
 
-#: gitk:9393
 msgid "Error creating tag:"
 msgstr "Fel vid skapande av tagg:"
 
-#: gitk:9483
 msgid "Command:"
 msgstr "Kommando:"
 
-#: gitk:9491
 msgid "Write"
 msgstr "Skriv"
 
-#: gitk:9509
 msgid "Error writing commit:"
 msgstr "Fel vid skrivning av incheckning:"
 
-#: gitk:9531
 msgid "Create branch"
 msgstr "Skapa gren"
 
-#: gitk:9547
 #, tcl-format
 msgid "Rename branch %s"
 msgstr "Byt namn på grenen %s"
 
-#: gitk:9548
 msgid "Rename"
 msgstr "Byt namn"
 
-#: gitk:9572
 msgid "Name:"
 msgstr "Namn:"
 
-#: gitk:9596
 msgid "Please specify a name for the new branch"
 msgstr "Ange ett namn för den nya grenen"
 
-#: gitk:9601
 #, tcl-format
 msgid "Branch '%s' already exists. Overwrite?"
 msgstr "Grenen ”%s” finns redan. Skriva över?"
 
-#: gitk:9645
 msgid "Please specify a new name for the branch"
 msgstr "Ange ett nytt namn för grenen"
 
-#: gitk:9708
 #, tcl-format
 msgid "Commit %s is already included in branch %s -- really re-apply it?"
 msgstr ""
 "Incheckningen %s finns redan på grenen %s -- skall den verkligen appliceras "
 "på nytt?"
 
-#: gitk:9713
 msgid "Cherry-picking"
 msgstr "Plockar"
 
-#: gitk:9722
 #, tcl-format
 msgid ""
 "Cherry-pick failed because of local changes to file '%s'.\n"
@@ -1086,7 +837,6 @@
 "Checka in, återställ eller spara undan (stash) dina ändringar och försök "
 "igen."
 
-#: gitk:9728
 msgid ""
 "Cherry-pick failed because of merge conflict.\n"
 "Do you wish to run git citool to resolve it?"
@@ -1094,20 +844,16 @@
 "Cherry-pick misslyckades på grund av en sammanslagningskonflikt.\n"
 "Vill du köra git citool för att lösa den?"
 
-#: gitk:9744 gitk:9802
 msgid "No changes committed"
 msgstr "Inga ändringar incheckade"
 
-#: gitk:9771
 #, tcl-format
 msgid "Commit %s is not included in branch %s -- really revert it?"
 msgstr "Incheckningen %s finns inte på grenen %s -- vill du verkligen ångra?"
 
-#: gitk:9776
 msgid "Reverting"
 msgstr "Ångrar"
 
-#: gitk:9784
 #, tcl-format
 msgid ""
 "Revert failed because of local changes to the following files:%s Please "
@@ -1117,7 +863,6 @@
 "Checka in, återställ eller spara undan (stash) dina ändringar och försök "
 "igen."
 
-#: gitk:9788
 msgid ""
 "Revert failed because of merge conflict.\n"
 " Do you wish to run git citool to resolve it?"
@@ -1125,28 +870,22 @@
 "Misslyckades med att ångra på grund av en sammanslagningskonflikt.\n"
 " Vill du köra git citool för att lösa den?"
 
-#: gitk:9831
 msgid "Confirm reset"
 msgstr "Bekräfta återställning"
 
-#: gitk:9833
 #, tcl-format
 msgid "Reset branch %s to %s?"
 msgstr "Återställa grenen %s till %s?"
 
-#: gitk:9835
 msgid "Reset type:"
 msgstr "Typ av återställning:"
 
-#: gitk:9838
 msgid "Soft: Leave working tree and index untouched"
 msgstr "Mjuk: Rör inte utcheckning och index"
 
-#: gitk:9841
 msgid "Mixed: Leave working tree untouched, reset index"
 msgstr "Blandad: Rör inte utcheckning, återställ index"
 
-#: gitk:9844
 msgid ""
 "Hard: Reset working tree and index\n"
 "(discard ALL local changes)"
@@ -1154,24 +893,19 @@
 "Hård: Återställ utcheckning och index\n"
 "(förkastar ALLA lokala ändringar)"
 
-#: gitk:9861
 msgid "Resetting"
 msgstr "Återställer"
 
-#: gitk:9934
 #, tcl-format
 msgid "A local branch named %s exists already"
 msgstr "Det finns redan en lokal gren som heter %s"
 
-#: gitk:9942
 msgid "Checking out"
 msgstr "Checkar ut"
 
-#: gitk:10001
 msgid "Cannot delete the currently checked-out branch"
 msgstr "Kan inte ta bort den just nu utcheckade grenen"
 
-#: gitk:10007
 #, tcl-format
 msgid ""
 "The commits on branch %s aren't on any other branch.\n"
@@ -1180,16 +914,13 @@
 "Incheckningarna på grenen %s existerar inte på någon annan gren.\n"
 "Vill du verkligen ta bort grenen %s?"
 
-#: gitk:10038
 #, tcl-format
 msgid "Tags and heads: %s"
 msgstr "Taggar och huvuden: %s"
 
-#: gitk:10055
 msgid "Filter"
 msgstr "Filter"
 
-#: gitk:10356
 msgid ""
 "Error reading commit topology information; branch and preceding/following "
 "tag information will be incomplete."
@@ -1197,221 +928,167 @@
 "Fel vid läsning av information om incheckningstopologi; information om "
 "grenar och föregående/senare taggar kommer inte vara komplett."
 
-#: gitk:11333
 msgid "Tag"
 msgstr "Tagg"
 
-#: gitk:11337
 msgid "Id"
 msgstr "Id"
 
-#: gitk:11420
 msgid "Gitk font chooser"
 msgstr "Teckensnittsväljare för Gitk"
 
-#: gitk:11437
 msgid "B"
 msgstr "F"
 
-#: gitk:11440
 msgid "I"
 msgstr "K"
 
-#: gitk:11558
 msgid "Commit list display options"
 msgstr "Alternativ för incheckningslistvy"
 
-#: gitk:11561
 msgid "Maximum graph width (lines)"
 msgstr "Maximal grafbredd (rader)"
 
-#: gitk:11565
 #, no-tcl-format
 msgid "Maximum graph width (% of pane)"
 msgstr "Maximal grafbredd (% av ruta)"
 
-#: gitk:11568
 msgid "Show local changes"
 msgstr "Visa lokala ändringar"
 
-#: gitk:11571
 msgid "Auto-select SHA1 (length)"
 msgstr "Välj SHA1 (längd) automatiskt"
 
-#: gitk:11575
 msgid "Hide remote refs"
 msgstr "Dölj fjärr-referenser"
 
-#: gitk:11579
 msgid "Diff display options"
 msgstr "Alternativ för diffvy"
 
-#: gitk:11581
 msgid "Tab spacing"
 msgstr "Blanksteg för tabulatortecken"
 
-#: gitk:11584
 msgid "Display nearby tags/heads"
 msgstr "Visa närliggande taggar/huvuden"
 
-#: gitk:11587
 msgid "Maximum # tags/heads to show"
 msgstr "Maximalt antal taggar/huvuden att visa"
 
-#: gitk:11590
 msgid "Limit diffs to listed paths"
 msgstr "Begränsa diff till listade sökvägar"
 
-#: gitk:11593
 msgid "Support per-file encodings"
 msgstr "Stöd för filspecifika teckenkodningar"
 
-#: gitk:11599 gitk:11766
 msgid "External diff tool"
 msgstr "Externt diff-verktyg"
 
-#: gitk:11600
 msgid "Choose..."
 msgstr "Välj..."
 
-#: gitk:11607
 msgid "Web browser"
 msgstr "Webbläsare"
 
-#: gitk:11612
 msgid "General options"
 msgstr "Allmänna inställningar"
 
-#: gitk:11615
 msgid "Use themed widgets"
 msgstr "Använd tema på fönsterelement"
 
-#: gitk:11617
 msgid "(change requires restart)"
 msgstr "(ändringen kräver omstart)"
 
-#: gitk:11619
 msgid "(currently unavailable)"
 msgstr "(för närvarande inte tillgängligt)"
 
-#: gitk:11631
 msgid "Colors: press to choose"
 msgstr "Färger: tryck för att välja"
 
-#: gitk:11634
 msgid "Interface"
 msgstr "Gränssnitt"
 
-#: gitk:11635
 msgid "interface"
 msgstr "gränssnitt"
 
-#: gitk:11638
 msgid "Background"
 msgstr "Bakgrund"
 
-#: gitk:11639 gitk:11681
 msgid "background"
 msgstr "bakgrund"
 
-#: gitk:11642
 msgid "Foreground"
 msgstr "Förgrund"
 
-#: gitk:11643
 msgid "foreground"
 msgstr "förgrund"
 
-#: gitk:11646
 msgid "Diff: old lines"
 msgstr "Diff: gamla rader"
 
-#: gitk:11647
 msgid "diff old lines"
 msgstr "diff gamla rader"
 
-#: gitk:11651
 msgid "Diff: old lines bg"
 msgstr "Diff: gamla rader bg"
 
-#: gitk:11653
 msgid "diff old lines bg"
 msgstr "diff gamla rader bg"
 
-#: gitk:11657
 msgid "Diff: new lines"
 msgstr "Diff: nya rader"
 
-#: gitk:11658
 msgid "diff new lines"
 msgstr "diff nya rader"
 
-#: gitk:11662
 msgid "Diff: new lines bg"
 msgstr "Diff: nya rader bg"
 
-#: gitk:11664
 msgid "diff new lines bg"
 msgstr "diff nya rader bg"
 
-#: gitk:11668
 msgid "Diff: hunk header"
 msgstr "Diff: delhuvud"
 
-#: gitk:11670
 msgid "diff hunk header"
 msgstr "diff delhuvud"
 
-#: gitk:11674
 msgid "Marked line bg"
 msgstr "Markerad rad bakgrund"
 
-#: gitk:11676
 msgid "marked line background"
 msgstr "markerad rad bakgrund"
 
-#: gitk:11680
 msgid "Select bg"
 msgstr "Markerad bakgrund"
 
-#: gitk:11689
 msgid "Fonts: press to choose"
 msgstr "Teckensnitt: tryck för att välja"
 
-#: gitk:11691
 msgid "Main font"
 msgstr "Huvudteckensnitt"
 
-#: gitk:11692
 msgid "Diff display font"
 msgstr "Teckensnitt för diffvisning"
 
-#: gitk:11693
 msgid "User interface font"
 msgstr "Teckensnitt för användargränssnitt"
 
-#: gitk:11715
 msgid "Gitk preferences"
 msgstr "Inställningar för Gitk"
 
-#: gitk:11724
 msgid "General"
 msgstr "Allmänt"
 
-#: gitk:11725
 msgid "Colors"
 msgstr "Färger"
 
-#: gitk:11726
 msgid "Fonts"
 msgstr "Teckensnitt"
 
-#: gitk:11776
 #, tcl-format
 msgid "Gitk: choose color for %s"
 msgstr "Gitk: välj färg för %s"
 
-#: gitk:12289
 msgid ""
 "Sorry, gitk cannot run with this version of Tcl/Tk.\n"
 " Gitk requires at least Tcl/Tk 8.4."
@@ -1419,15 +1096,12 @@
 "Gitk kan tyvärr inte köra med denna version av Tcl/Tk.\n"
 " Gitk kräver åtminstone Tcl/Tk 8.4."
 
-#: gitk:12507
 msgid "Cannot find a git repository here."
 msgstr "Hittar inget git-arkiv här."
 
-#: gitk:12554
 #, tcl-format
 msgid "Ambiguous argument '%s': both revision and filename"
 msgstr "Tvetydigt argument ”%s”: både revision och filnamn"
 
-#: gitk:12566
 msgid "Bad arguments to gitk:"
 msgstr "Felaktiga argument till gitk:"
diff --git a/gitk-git/po/ta.po b/gitk-git/po/ta.po
index 0e390c5..9b9176a 100644
--- a/gitk-git/po/ta.po
+++ b/gitk-git/po/ta.po
@@ -6,7 +6,7 @@
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: gitk\n"
+"Project-Id-Version: Gitk\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2025-05-07 08:01+0530\n"
 "PO-Revision-Date: 2025-05-07 09:17\n"
@@ -17,360 +17,270 @@
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: gitk:274
 msgid "Couldn't get list of unmerged files:"
 msgstr "ஒருங்கிணைக்கப்படாத கோப்புகளின் பட்டியலைப் பெற முடியவில்லை:"
 
-#: gitk:346 gitk:2565
 msgid "Color words"
 msgstr "வண்ண சொற்கள்"
 
-#: gitk:351 gitk:2565 gitk:8476 gitk:8509
 msgid "Markup words"
 msgstr "குறிக்கப்பட்ட சொற்கள்"
 
-#: gitk:458
 msgid "Error parsing revisions:"
 msgstr "பிழைகளை பாகுபடுத்துதல்:"
 
-#: gitk:524
 msgid "Error executing --argscmd command:"
 msgstr "--argscmd கட்டளையை இயக்குவதில் பிழை:"
 
-#: gitk:537
 msgid "No files selected: --merge specified but no files are unmerged."
 msgstr ""
-"கோப்புகள் எதுவும் தேர்ந்தெடுக்கப்படவில்லை: --ஒன்றிணை குறிப்பிடப்பட்டுள்ளது, "
-"ஆனால் கோப்புகள் எதுவும் அவிழ்க்கப்படவில்லை."
+"கோப்புகள் எதுவும் தேர்ந்தெடுக்கப்படவில்லை: --ஒன்றிணை குறிப்பிடப்பட்டுள்ளது, ஆனால் கோப்புகள் "
+"எதுவும் அவிழ்க்கப்படவில்லை."
 
-#: gitk:540
 msgid ""
 "No files selected: --merge specified but no unmerged files are within file "
 "limit."
 msgstr ""
-"கோப்புகள் எதுவும் தேர்ந்தெடுக்கப்படவில்லை: --ஒன்றிணை குறிப்பிடப்பட்டுள்ளது, "
-"ஆனால் அவிழ்க்கப்படாத கோப்புகள் எதுவும் கோப்பு வரம்பிற்குள் இல்லை."
+"கோப்புகள் எதுவும் தேர்ந்தெடுக்கப்படவில்லை: --ஒன்றிணை குறிப்பிடப்பட்டுள்ளது, ஆனால் "
+"அவிழ்க்கப்படாத கோப்புகள் எதுவும் கோப்பு வரம்பிற்குள் இல்லை."
 
-#: gitk:565 gitk:720
 msgid "Error executing git log:"
 msgstr "அறிவிலி பதிவை இயக்குவதில் பிழை:"
 
-#: gitk:583 gitk:736
 msgid "Reading"
 msgstr "படித்தல்"
 
-#: gitk:643 gitk:4736
 msgid "Reading commits..."
 msgstr "உறுதிமொழிகளைப் படித்தல்..."
 
-#: gitk:646 gitk:1795 gitk:4739
 msgid "No commits selected"
 msgstr "எந்த உறுதிமொழிகளும் தேர்ந்தெடுக்கப்படவில்லை"
 
-#: gitk:1603 gitk:4256 gitk:12883
 msgid "Command line"
 msgstr "கட்டளை வரி"
 
-#: gitk:1669
 msgid "Can't parse git log output:"
 msgstr "அறிவிலி பதிவு வெளியீட்டை அலச முடியாது:"
 
-#: gitk:1898
 msgid "No commit information available"
 msgstr "உறுதிமொழி செய்தி எதுவும் கிடைக்கவில்லை"
 
-#: gitk:2065 gitk:2094 gitk:4526 gitk:10016 gitk:11626 gitk:11946
 msgid "OK"
 msgstr "சரி"
 
-#: gitk:2096 gitk:4528 gitk:9452 gitk:9531 gitk:9661 gitk:9747 gitk:10018
-#: gitk:11627 gitk:11947
 msgid "Cancel"
 msgstr "நீக்கறல்"
 
-#: gitk:2249
 msgid "&Update"
 msgstr "புதுப்பித்தல்"
 
-#: gitk:2250
 msgid "&Reload"
 msgstr "மீண்டும் ஏற்று"
 
-#: gitk:2251
 msgid "Reread re&ferences"
 msgstr "குறிப்புகளை மீண்டும் படி"
 
-#: gitk:2252
 msgid "&List references"
 msgstr "பட்டியல் குறிப்புகள்"
 
-#: gitk:2254
 msgid "Start git &gui"
 msgstr "அறிவிலி இடைமுகத்தைத் தொடங்கு"
 
-#: gitk:2256
 msgid "&Quit"
 msgstr "வெளியேறு"
 
-#: gitk:2248
 msgid "&File"
 msgstr "கோப்பு"
 
-#: gitk:2260
 msgid "&Preferences"
 msgstr "விருப்பத்தேர்வுகள்"
 
-#: gitk:2259
 msgid "&Edit"
 msgstr "திருத்து"
 
-#: gitk:2264
 msgid "&New view..."
 msgstr "புதிய பார்வை..."
 
-#: gitk:2265
 msgid "&Edit view..."
 msgstr "பார்வையைத் திருத்து..."
 
-#: gitk:2266
 msgid "&Delete view"
 msgstr "பார்வையை நீக்கு"
 
-#: gitk:2268
 msgid "&All files"
 msgstr "அனைத்து கோப்புகளும்"
 
-#: gitk:2263
 msgid "&View"
 msgstr "காண்க"
 
-#: gitk:2273 gitk:2283
 msgid "&About gitk"
 msgstr "அறிவிலிகே பற்றி"
 
-#: gitk:2274 gitk:2288
 msgid "&Key bindings"
 msgstr "முக்கிய பிணைப்புகள்"
 
-#: gitk:2272 gitk:2287
 msgid "&Help"
 msgstr "உதவி"
 
-#: gitk:2365 gitk:8908
 msgid "Commit ID:"
 msgstr "உறுதிமொழி அடையாளம்:"
 
-#: gitk:2409
 msgid "Row"
 msgstr "நிரை"
 
-#: gitk:2447
 msgid "Find"
 msgstr "கண்டுபிடி"
 
-#: gitk:2475
 msgid "commit"
 msgstr "உறுதிமொழி"
 
-#: gitk:2479 gitk:2481 gitk:4898 gitk:4921 gitk:4945 gitk:6966 gitk:7038
-#: gitk:7123
 msgid "containing:"
 msgstr "கொண்டிருக்கிறது:"
 
-#: gitk:2482 gitk:3737 gitk:3742 gitk:4974
 msgid "touching paths:"
 msgstr "தொடும் பாதைகள்:"
 
-#: gitk:2483 gitk:4988
 msgid "adding/removing string:"
 msgstr "சரத்தைச் சேர்ப்பது/அகற்றுவது:"
 
-#: gitk:2484 gitk:4990
 msgid "changing lines matching:"
 msgstr "பொருந்தக்கூடிய வரிகளை மாற்றுதல்:"
 
-#: gitk:2493 gitk:2495 gitk:4977
 msgid "Exact"
 msgstr "சரியான"
 
-#: gitk:2495 gitk:5065 gitk:6934
 msgid "IgnCase"
 msgstr "வழக்குதவிர்"
 
-#: gitk:2495 gitk:4947 gitk:5063 gitk:6930
 msgid "Regexp"
 msgstr "வழக்கவெளி"
 
-#: gitk:2497 gitk:2498 gitk:5085 gitk:5115 gitk:5122 gitk:7059 gitk:7127
 msgid "All fields"
 msgstr "அனைத்து புலங்களும்"
 
-#: gitk:2498 gitk:5082 gitk:5115 gitk:6997
 msgid "Headline"
 msgstr "தலைப்பு"
 
-#: gitk:2499 gitk:5082 gitk:6997 gitk:7127 gitk:7639
 msgid "Comments"
 msgstr "கருத்துகள்"
 
-#: gitk:2499 gitk:5082 gitk:5087 gitk:5122 gitk:6997 gitk:7574 gitk:9086
-#: gitk:9101
 msgid "Author"
 msgstr "நூலாசிரியர்"
 
-#: gitk:2499 gitk:5082 gitk:6997 gitk:7576
 msgid "Committer"
 msgstr "உறுதிமொழிபவர்"
 
-#: gitk:2533
 msgid "Search"
 msgstr "தேடு"
 
-#: gitk:2541
 msgid "Diff"
 msgstr "வேறுபாடு"
 
-#: gitk:2543
 msgid "Old version"
 msgstr "பழைய பதிப்பு"
 
-#: gitk:2545
 msgid "New version"
 msgstr "புதிய பதிப்பு"
 
-#: gitk:2548
 msgid "Lines of context"
 msgstr "சூழலின் வரிகள்"
 
-#: gitk:2558
 msgid "Ignore space change"
 msgstr "இடைவெளி மாற்றத்தை புறக்கணி"
 
-#: gitk:2562 gitk:2564 gitk:8209 gitk:8462
 msgid "Line diff"
 msgstr "வரி வேறுபாடு"
 
-#: gitk:2637
 msgid "Patch"
 msgstr "ஒட்டு"
 
-#: gitk:2639
 msgid "Tree"
 msgstr "மரம்"
 
-#: gitk:2814 gitk:2835
 msgid "Diff this -> selected"
 msgstr "இதை வேறுபடுத்துங்கள் -> தேர்ந்தெடுக்கப்பட்டது"
 
-#: gitk:2815 gitk:2836
 msgid "Diff selected -> this"
 msgstr "வேறுபாடு தேர்ந்தெடுக்கப்பட்டது -> இது"
 
-#: gitk:2816 gitk:2837
 msgid "Make patch"
 msgstr "ஒட்டு செய்"
 
-#: gitk:2817 gitk:9510
 msgid "Create tag"
 msgstr "குறிச்சொல்லை உருவாக்கு"
 
-#: gitk:2818
 msgid "Copy commit reference"
 msgstr "உறுதிமொழி குறிப்பு நகலெடு"
 
-#: gitk:2819 gitk:9641
 msgid "Write commit to file"
 msgstr "கோப்பில் உறவை எழுதுங்கள்"
 
-#: gitk:2820
 msgid "Create new branch"
 msgstr "புதிய கிளையை உருவாக்கு"
 
-#: gitk:2821
 msgid "Cherry-pick this commit"
 msgstr "கனி-எடு இந்த உறுதிமொழி"
 
-#: gitk:2822
 msgid "Reset HEAD branch to here"
 msgstr "தலை கிளையை இங்கே மீட்டமை"
 
-#: gitk:2823
 msgid "Mark this commit"
 msgstr "இந்த உறுதிமொழியைக் குறி"
 
-#: gitk:2824
 msgid "Return to mark"
 msgstr "மார்க்குக்குத் திரும்பு"
 
-#: gitk:2825
 msgid "Find descendant of this and mark"
 msgstr "இதன் வழித்தோன்றலைக் கண்டுபிடித்து குறி"
 
-#: gitk:2826
 msgid "Compare with marked commit"
 msgstr "குறிக்கப்பட்ட உறுதிப்பாட்டுடன் ஒப்பிடுக"
 
-#: gitk:2827 gitk:2838
 msgid "Diff this -> marked commit"
 msgstr "இதை வேறுபடுத்துங்கள் -> குறிக்கப்பட்ட உறுதிமொழி"
 
-#: gitk:2828 gitk:2839
 msgid "Diff marked commit -> this"
 msgstr "வேறுபாடு குறிக்கப்பட்ட உறுதிமொழி -> இது"
 
-#: gitk:2829
 msgid "Revert this commit"
 msgstr "இந்த உறுதிப்பாட்டை மாற்றவும்"
 
-#: gitk:2845
 msgid "Check out this branch"
 msgstr "இந்த கிளையைப் பாருங்கள்"
 
-#: gitk:2846
 msgid "Rename this branch"
 msgstr "இந்த கிளையை மறுபெயரிடு"
 
-#: gitk:2847
 msgid "Remove this branch"
 msgstr "இந்த கிளையை அகற்று"
 
-#: gitk:2848
 msgid "Copy branch name"
 msgstr "கிளை பெயரை நகலெடு"
 
-#: gitk:2855
 msgid "Highlight this too"
 msgstr "இதை முன்னிலைப்படுத்து"
 
-#: gitk:2856
 msgid "Highlight this only"
 msgstr "இதை முன்னிலைப்படுத்து"
 
-#: gitk:2857
 msgid "External diff"
 msgstr "வெளிப்புற வேறுபாடு"
 
-#: gitk:2858
 msgid "Blame parent commit"
 msgstr "பெற்றோரை குற்றம் சாட்டு"
 
-#: gitk:2859
 msgid "Copy path"
 msgstr "நகல் பாதை"
 
-#: gitk:2866
 msgid "Show origin of this line"
 msgstr "இந்த வரியின் தோற்றத்தைக் காட்டு"
 
-#: gitk:2867
 msgid "Run git gui blame on this line"
 msgstr "இந்த வரியில் அறிவிலி இடைமுகம் பழியை இயக்கு"
 
-#: gitk:3221
 msgid "About gitk"
 msgstr "அறிவிலிகே பற்றி"
 
-#: gitk:3223
 msgid ""
 "\n"
 "Gitk - a commit viewer for git\n"
@@ -386,697 +296,533 @@
 "\n"
 "குனு பொது பொதுமக்கள் உரிமத்தின் விதிமுறைகளின் கீழ் பயன்படுத்தவும் மறுபகிர்வு செய்யவும்"
 
-#: gitk:3231 gitk:3298 gitk:10231
 msgid "Close"
 msgstr "மூடு"
 
-#: gitk:3252
 msgid "Gitk key bindings"
 msgstr "அறிவிலிகே விசை பிணைப்புகள்"
 
-#: gitk:3255
 msgid "Gitk key bindings:"
 msgstr "அறிவிலிகே விசை பிணைப்புகள்:"
 
-#: gitk:3257
 #, tcl-format
 msgid "<%s-Q>\t\tQuit"
 msgstr "<%s-Q>\t\tவெளியேறு"
 
-#: gitk:3258
 #, tcl-format
 msgid "<%s-W>\t\tClose window"
 msgstr "<%s-w>\t\tசாளரத்தை மூடு"
 
-#: gitk:3259
 msgid "<Home>\t\tMove to first commit"
 msgstr "<வீடு> முதல் உறுதிமொழிக்கு நகர்த்து"
 
-#: gitk:3260
 msgid "<End>\t\tMove to last commit"
 msgstr "<முடி> கடைசி உறுதிமொழிக்கு நகர்த்து"
 
-#: gitk:3261
 msgid "<Up>, p, k\tMove up one commit"
 msgstr "<மேலே>, பி, கே\tஒரு உறுதிமொழியை மேலே நகர்த்து"
 
-#: gitk:3262
 msgid "<Down>, n, j\tMove down one commit"
 msgstr "<கீழ்>, n, j\tஒரு உறுதிமொழியை கீழே நகர்த்து"
 
-#: gitk:3263
 msgid "<Left>, z, h\tGo back in history list"
 msgstr "<இடது>, z, h\tவரலாற்று பட்டியலில் திரும்பிச் செல்"
 
-#: gitk:3264
 msgid "<Right>, x, l\tGo forward in history list"
 msgstr "<வலது>, x, l\tவரலாற்று பட்டியலில் முன்னோக்கி செல்"
 
-#: gitk:3265
 #, tcl-format
 msgid "<%s-n>\tGo to n-th parent of current commit in history list"
-msgstr ""
-"<%s-n> வரலாற்று பட்டியலில் தற்போதைய உறுதிப்பாட்டின் n- வது பெற்றோரிடம் "
-"செல்"
+msgstr "<%s-n> வரலாற்று பட்டியலில் தற்போதைய உறுதிப்பாட்டின் n- வது பெற்றோரிடம் செல்"
 
-#: gitk:3266
 msgid "<PageUp>\tMove up one page in commit list"
 msgstr "<பக்கம்மேல்>\tஉறுதிமொழி பட்டியலில் ஒரு பக்கத்தை நகர்த்து"
 
-#: gitk:3267
 msgid "<PageDown>\tMove down one page in commit list"
 msgstr "<பக்கம்கீழ்>\tஉறுதிமொழி பட்டியலில் ஒரு பக்கத்தை நகர்த்து"
 
-#: gitk:3268
 #, tcl-format
 msgid "<%s-Home>\tScroll to top of commit list"
 msgstr "<%s-வீடு>\tஉறுதிமொழி பட்டியலை மேல் பகுதிக்கு உருட்டவும்"
 
-#: gitk:3269
 #, tcl-format
 msgid "<%s-End>\tScroll to bottom of commit list"
 msgstr "<%s-முடி> உறுதிமொழி பட்டியலின் கீழ் பகுதிக்கு உருட்டவும்"
 
-#: gitk:3270
 #, tcl-format
 msgid "<%s-Up>\tScroll commit list up one line"
 msgstr "<%s-மேலே>\tஉறுதிமொழி பட்டியலை ஒரு வரி மேலே உருட்டவும்"
 
-#: gitk:3271
 #, tcl-format
 msgid "<%s-Down>\tScroll commit list down one line"
 msgstr "<%s-கீழ்>\tஉறுதிமொழி பட்டியலை ஒரு வரி கீழே உருட்டவும்"
 
-#: gitk:3272
 #, tcl-format
 msgid "<%s-PageUp>\tScroll commit list up one page"
 msgstr "<%s-பக்கம்மேலே>\tஉறுதிமொழி பட்டியலை ஒரு பக்கம் மேலே உருட்டவும்"
 
-#: gitk:3273
 #, tcl-format
 msgid "<%s-PageDown>\tScroll commit list down one page"
 msgstr "<%s-பக்கம்கீழ்>\tஉறுதிமொழி பட்டியலை ஒரு பக்கம் கீழே உருட்டவும்"
 
-#: gitk:3274
 msgid "<Shift-Up>\tFind backwards (upwards, later commits)"
 msgstr "<உயர்த்து-மேலே>\tபின்னோக்கி கண்டுபிடி (மேல்நோக்கி, பின்னர் உறுதிமொழிகள்)"
 
-#: gitk:3275
 msgid "<Shift-Down>\tFind forwards (downwards, earlier commits)"
-msgstr ""
-"<உயர்த்து-கீழே>\tமுன்னோக்குகளைக் கண்டறியவும் (கீழ்நோக்கி, முந்தைய "
-"உறுதிமொழிகள்)"
+msgstr "<உயர்த்து-கீழே>\tமுன்னோக்குகளைக் கண்டறியவும் (கீழ்நோக்கி, முந்தைய உறுதிமொழிகள்)"
 
-#: gitk:3276
 msgid "<Delete>, b\tScroll diff view up one page"
 msgstr "<நீக்கு>, b\tசுருள் வேறுபாடு ஒரு பக்கத்தை மேலே காண்க"
 
-#: gitk:3277
 msgid "<Backspace>\tScroll diff view up one page"
 msgstr "<பின்வெளி>\tசுருள் வேறுபாடு ஒரு பக்கத்தை மேலே காண்க"
 
-#: gitk:3278
 msgid "<Space>\t\tScroll diff view down one page"
 msgstr "<Space>\t\tசுருள் வேறுபாடு ஒரு பக்கத்தைக் கீழே காண்க"
 
-#: gitk:3279
 msgid "u\t\tScroll diff view up 18 lines"
 msgstr "u\t\tசுருள் வேறுபாடு 18 வரிகளை மேலே காண்க"
 
-#: gitk:3280
 msgid "d\t\tScroll diff view down 18 lines"
 msgstr "d\t\tசுருள் வேறுபாடு 18 வரிகளைக் கீழே காண்க"
 
-#: gitk:3281
 #, tcl-format
 msgid "<%s-F>\t\tFind"
 msgstr "<%s-F>\t\tகண்டுபிடி"
 
-#: gitk:3282
 #, tcl-format
 msgid "<%s-G>\t\tMove to next find hit"
 msgstr "<%s-G>\t\tஅடுத்த கண்டுபிடிப்பு வெற்றிக்கு செல்"
 
-#: gitk:3283
 msgid "<Return>\tMove to next find hit"
 msgstr "<திரும்பு>\tஅடுத்ததைக் கண்டுபிடி"
 
-#: gitk:3284
 msgid "g\t\tGo to commit"
 msgstr "g\t\tஉறுதிமொழிக்கு செல்"
 
-#: gitk:3285
 msgid "/\t\tFocus the search box"
 msgstr "/\t\tதேடல் பெட்டியில் கவனம் செலுத்து"
 
-#: gitk:3286
 msgid "?\t\tMove to previous find hit"
 msgstr "?\t\tமுந்தைய கண்டுபிடிப்பு வெற்றிக்கு செல்"
 
-#: gitk:3287
 msgid "f\t\tScroll diff view to next file"
 msgstr "f\t\tஅடுத்த கோப்பிற்கு உருள் வேறுபாடு பார்வை"
 
-#: gitk:3288
 #, tcl-format
 msgid "<%s-S>\t\tSearch for next hit in diff view"
 msgstr "<%s-S>\t\tவேறுபாடு பார்வையில் அடுத்த வெற்றியைத் தேடுங்கள்"
 
-#: gitk:3289
 #, tcl-format
 msgid "<%s-R>\t\tSearch for previous hit in diff view"
 msgstr "<%s-r> வேறுபட்ட பார்வையில் முந்தைய வெற்றியைத் தேடுங்கள்"
 
-#: gitk:3290
 #, tcl-format
 msgid "<%s-KP+>\tIncrease font size"
 msgstr "<%s-KP+>\tஎழுத்துரு அளவை அதிகரி"
 
-#: gitk:3291
 #, tcl-format
 msgid "<%s-plus>\tIncrease font size"
 msgstr "<%s-plus>\tஎழுத்துரு அளவை அதிகரி"
 
-#: gitk:3292
 #, tcl-format
 msgid "<%s-KP->\tDecrease font size"
 msgstr "<%s-KP->\tஎழுத்துரு அளவைக் குறை"
 
-#: gitk:3293
 #, tcl-format
 msgid "<%s-minus>\tDecrease font size"
 msgstr "<%s-minus>\tஎழுத்துரு அளவைக் குறை"
 
-#: gitk:3294
 msgid "<F5>\t\tUpdate"
 msgstr "<F5>\t\tபுதுப்பிப்பு"
 
-#: gitk:3761 gitk:3770
 #, tcl-format
 msgid "Error creating temporary directory %s:"
 msgstr "தற்காலிக அடைவு %s ஐ உருவாக்குவது பிழை:"
 
-#: gitk:3783
 #, tcl-format
 msgid "Error getting \"%s\" from %s:"
 msgstr "%s இலிருந்து \" %s\" பெறுவது பிழை:"
 
-#: gitk:3846
 msgid "command failed:"
 msgstr "கட்டளை தோல்வியுற்றது:"
 
-#: gitk:3995
 msgid "No such commit"
 msgstr "அத்தகைய உறுதிமொழி இல்லை"
 
-#: gitk:4009
 msgid "git gui blame: command failed:"
 msgstr "அறிவிலி இடைமுக பழி: கட்டளை தோல்வியுற்றது:"
 
-#: gitk:4040
 #, tcl-format
 msgid "Couldn't read merge head: %s"
 msgstr "ஒன்றிணைப்பு தலையைப் படிக்க முடியவில்லை: %s"
 
-#: gitk:4048
 #, tcl-format
 msgid "Error reading index: %s"
 msgstr "பிழை வாசிப்பு குறியீடு: %s"
 
-#: gitk:4073
 #, tcl-format
 msgid "Couldn't start git blame: %s"
 msgstr "அறிவிலி பழியைத் தொடங்க முடியவில்லை: %s"
 
-#: gitk:4076 gitk:6965
 msgid "Searching"
 msgstr "தேடுகிறது"
 
-#: gitk:4108
 #, tcl-format
 msgid "Error running git blame: %s"
 msgstr "பிழை இயங்கும் அறிவிலி பழி: %s"
 
-#: gitk:4136
 #, tcl-format
 msgid "That line comes from commit %s,  which is not in this view"
-msgstr ""
-"அந்த வரி உறுதிமொழி %s என்பதிலிருந்து வருகிறது, இது இந்த பார்வையில் இல்லை"
+msgstr "அந்த வரி உறுதிமொழி %s என்பதிலிருந்து வருகிறது, இது இந்த பார்வையில் இல்லை"
 
-#: gitk:4150
 msgid "External diff viewer failed:"
 msgstr "வெளிப்புற வேறுபாடு பார்வையாளர் தோல்வியுற்றது:"
 
-#: gitk:4254
 msgid "All files"
 msgstr "அனைத்து கோப்புகளும்"
 
-#: gitk:4278
 msgid "View"
 msgstr "காண்க"
 
-#: gitk:4281
 msgid "Gitk view definition"
 msgstr "அறிவிலிகே பார்வை வரையறை"
 
-#: gitk:4285
 msgid "Remember this view"
 msgstr "இந்த பார்வையை நினைவில் கொள்ளுங்கள்"
 
-#: gitk:4286
 msgid "References (space separated list):"
 msgstr "குறிப்புகள் (இடைவெளி பிரிக்கப்பட்ட பட்டியல்):"
 
-#: gitk:4287
 msgid "Branches & tags:"
 msgstr "கிளைகள் மற்றும் குறிச்சொற்கள்:"
 
-#: gitk:4288
 msgid "All refs"
 msgstr "அனைத்து குறிப்புகள்"
 
-#: gitk:4289
 msgid "All (local) branches"
 msgstr "அனைத்து (உள்ளக) கிளைகளும்"
 
-#: gitk:4290
 msgid "All tags"
 msgstr "அனைத்து குறிச்சொற்களும்"
 
-#: gitk:4291
 msgid "All remote-tracking branches"
 msgstr "அனைத்து தொலை-கண்காணிப்பு கிளைகளும்"
 
-#: gitk:4292
 msgid "Commit Info (regular expressions):"
 msgstr "உறுதிமொழி செய்தி (வழக்கமான வெளிப்பாடுகள்):"
 
-#: gitk:4293
 msgid "Author:"
 msgstr "ஆசிரியர்:"
 
-#: gitk:4294
 msgid "Committer:"
 msgstr "உறுதிமொழிபவர்:"
 
-#: gitk:4295
 msgid "Commit Message:"
 msgstr "உறுதிமொழி செய்தி:"
 
-#: gitk:4296
 msgid "Matches all Commit Info criteria"
 msgstr "அனைத்து உறுதிமொழி செய்தி அளவுகோல்களையும் பொருத்துகிறது"
 
-#: gitk:4297
 msgid "Matches no Commit Info criteria"
 msgstr "உறுதிமொழி செய்தி அளவுகோல்களுடன் பொருந்தவில்லை"
 
-#: gitk:4298
 msgid "Changes to Files:"
 msgstr "கோப்புகளில் மாற்றங்கள்:"
 
-#: gitk:4299
 msgid "Fixed String"
 msgstr "நிலையான சரம்"
 
-#: gitk:4300
 msgid "Regular Expression"
 msgstr "வழக்கமான வெளிப்பாடு"
 
-#: gitk:4301
 msgid "Search string:"
 msgstr "தேடல் சரம்:"
 
-#: gitk:4302
 msgid ""
 "Commit Dates (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 "
 "15:27:38\"):"
 msgstr ""
-"உறுதிமொழி தேதிகள் (\"2 வாரங்களுக்கு முன்பு\", \"2009-01-16 15:27:38\", \"மார்ச் 17, "
-"2009 15:27:38\"):"
+"உறுதிமொழி தேதிகள் (\"2 வாரங்களுக்கு முன்பு\", \"2009-01-16 15:27:38\", \"மார்ச் "
+"17, 2009 15:27:38\"):"
 
-#: gitk:4303
 msgid "Since:"
 msgstr "பின்னர்:"
 
-#: gitk:4304
 msgid "Until:"
 msgstr "வரை:"
 
-#: gitk:4305
 msgid "Limit and/or skip a number of revisions (positive integer):"
-msgstr ""
-"பல திருத்தங்களை (நேர்மறை முழு எண்) கட்டுப்படுத்து மற்றும்/அல்லது தவிர்:"
+msgstr "பல திருத்தங்களை (நேர்மறை முழு எண்) கட்டுப்படுத்து மற்றும்/அல்லது தவிர்:"
 
-#: gitk:4306
 msgid "Number to show:"
 msgstr "காண்பிக்க எண்:"
 
-#: gitk:4307
 msgid "Number to skip:"
 msgstr "தவிர்க்க எண்:"
 
-#: gitk:4308
 msgid "Miscellaneous options:"
 msgstr "இதர விருப்பங்கள்:"
 
-#: gitk:4309
 msgid "Strictly sort by date"
 msgstr "கண்டிப்பாக தேதியின்படி வரிசைப்படுத்து"
 
-#: gitk:4310
 msgid "Mark branch sides"
 msgstr "கிளை பக்கங்களைக் குறி"
 
-#: gitk:4311
 msgid "Limit to first parent"
 msgstr "முதல் பெற்றோருக்கு வரம்பு"
 
-#: gitk:4312
 msgid "Simple history"
 msgstr "எளிய வரலாறு"
 
-#: gitk:4313
 msgid "Additional arguments to git log:"
 msgstr "அறிவிலி பதிவுக்கு கூடுதல் வாதங்கள்:"
 
-#: gitk:4314
 msgid "Enter files and directories to include, one per line:"
 msgstr "சேர்க்க கோப்புகள் மற்றும் கோப்பகங்களை உள்ளிடவும், ஒரு வரிக்கு ஒன்று:"
 
-#: gitk:4315
 msgid "Command to generate more commits to include:"
 msgstr "சேர்க்க கூடுதல் உறுதிமொழிகளை உருவாக்க கட்டளை:"
 
-#: gitk:4439
 msgid "Gitk: edit view"
 msgstr "அறிவிலிகே: திருத்து பார்வை"
 
-#: gitk:4447
 msgid "-- criteria for selecting revisions"
 msgstr "-- திருத்தங்களைத் தேர்ந்தெடுப்பதற்கான அளவுகோல்கள்"
 
-#: gitk:4452
 msgid "View Name"
 msgstr "பெயரைக் காண்க"
 
-#: gitk:4527
 msgid "Apply (F5)"
 msgstr "இடு (F5)"
 
-#: gitk:4565
 msgid "Error in commit selection arguments:"
 msgstr "உறுதிமொழி தேர்வு வாதங்களில் பிழை:"
 
-#: gitk:4620 gitk:4673 gitk:5135 gitk:5149 gitk:6419 gitk:12820 gitk:12821
 msgid "None"
 msgstr "எதுவுமில்லை"
 
-#: gitk:5232 gitk:5237
 msgid "Descendant"
 msgstr "வழித்தோன்றல்"
 
-#: gitk:5233
 msgid "Not descendant"
 msgstr "வழித்தோன்றல் அல்ல"
 
-#: gitk:5240 gitk:5245
 msgid "Ancestor"
 msgstr "மூதாதையர்"
 
-#: gitk:5241
 msgid "Not ancestor"
 msgstr "மூதாதையர் அல்ல"
 
-#: gitk:5535
 msgid "Local changes checked in to index but not committed"
-msgstr ""
-"உள்ளக மாற்றங்கள் குறியீட்டில் சரிபார்க்கப்பட்டன, ஆனால் உறுதிமொழியவில்லை"
+msgstr "உள்ளக மாற்றங்கள் குறியீட்டில் சரிபார்க்கப்பட்டன, ஆனால் உறுதிமொழியவில்லை"
 
-#: gitk:5571
 msgid "Local uncommitted changes, not checked in to index"
 msgstr "உள்ளக உறுதிமொழியாத மாற்றங்கள், குறியீட்டில் சரிபார்க்கப்படவில்லை"
 
-#: gitk:7319
 msgid "Error starting web browser:"
 msgstr "வலை உலாவியைத் தொடங்குவதில் பிழை:"
 
-#: gitk:7380
 msgid "and many more"
 msgstr "மற்றும் மேலும் பல"
 
-#: gitk:7383
 msgid "many"
 msgstr "பல"
 
-#: gitk:7578
 msgid "Tags:"
 msgstr "குறிச்சொற்கள்:"
 
-#: gitk:7595 gitk:7601 gitk:9081
 msgid "Parent"
 msgstr "பெற்றோர்"
 
-#: gitk:7606
 msgid "Child"
 msgstr "குழந்தை"
 
-#: gitk:7615
 msgid "Branch"
 msgstr "கிளை"
 
-#: gitk:7618
 msgid "Follows"
 msgstr "பின்வருமாறு"
 
-#: gitk:7621
 msgid "Precedes"
 msgstr "முன்னால்"
 
-#: gitk:8216
 #, tcl-format
 msgid "Error getting diffs: %s"
 msgstr "வேறுபாடு பெறுவதில் பிழை: %s"
 
-#: gitk:8906
 msgid "Goto:"
 msgstr "செல்:"
 
-#: gitk:8927
 #, tcl-format
 msgid "Short commit ID %s is ambiguous"
 msgstr "குறுகிய உறுதிமொழி அடையாளம் %s தெளிவற்றவை"
 
-#: gitk:8934
 #, tcl-format
 msgid "Revision %s is not known"
 msgstr "திருத்தம் %s தெரியவில்லை"
 
-#: gitk:8944
 #, tcl-format
 msgid "Commit ID %s is not known"
 msgstr "உறுதிமொழி அடையாளம் %s அறியப்படவில்லை"
 
-#: gitk:8946
 #, tcl-format
 msgid "Revision %s is not in the current view"
 msgstr "திருத்தம் %s தற்போதைய பார்வையில் இல்லை"
 
-#: gitk:9088 gitk:9103
 msgid "Date"
 msgstr "திகதி"
 
-#: gitk:9091
 msgid "Children"
 msgstr "குழந்தைகள்"
 
-#: gitk:9154
 #, tcl-format
 msgid "Reset %s branch to here"
 msgstr "%s கிளையை இங்கே மீட்டமை"
 
-#: gitk:9156
 msgid "Detached head: can't reset"
 msgstr "பிரிக்கப்பட்ட தலை: மீட்டமைக்க முடியாது"
 
-#: gitk:9261 gitk:9267
 msgid "Skipping merge commit "
 msgstr "ஒன்றிணை உறுதிமொழியை தவர்கிறது "
 
-#: gitk:9276 gitk:9281
 msgid "Error getting patch ID for "
 msgstr "ஒட்டு அடையாளத்தைப் பெறுவதில் பிழை"
 
-#: gitk:9277 gitk:9282
 msgid " - stopping\n"
 msgstr "- நிறுத்துதல்\n"
 
-#: gitk:9287 gitk:9290 gitk:9298 gitk:9312 gitk:9321
 msgid "Commit "
 msgstr "உறுதிமொழி"
 
-#: gitk:9291
 msgid ""
 " is the same patch as\n"
 "       "
-msgstr "அதே ஒட்டு\n"
+msgstr ""
+"அதே ஒட்டு\n"
 "       "
 
-#: gitk:9299
 msgid ""
 " differs from\n"
 "       "
-msgstr "இருந்து வேறுபடுகிறது\n"
+msgstr ""
+"இருந்து வேறுபடுகிறது\n"
 "       "
 
-#: gitk:9301
 msgid ""
 "Diff of commits:\n"
 "\n"
-msgstr "உறுதிமொழியின் வேறுபாடு:\n"
+msgstr ""
+"உறுதிமொழியின் வேறுபாடு:\n"
 "\n"
 
-#: gitk:9313 gitk:9322
 #, tcl-format
 msgid " has %s children - stopping\n"
 msgstr "%s குழந்தைகள் உள்ளனர் - நிறுத்துதல்\n"
 
-#: gitk:9341
 #, tcl-format
 msgid "Error writing commit to file: %s"
 msgstr "உறுதிமொழி கோப்பில் எழுதுதல்  பிழை: %s"
 
-#: gitk:9347
 #, tcl-format
 msgid "Error diffing commits: %s"
 msgstr "உறுதிமொழிகள் வேறுபாடு பிழை: %s"
 
-#: gitk:9393
 msgid "Top"
 msgstr "மேலே"
 
-#: gitk:9394
 msgid "From"
 msgstr "இருந்து"
 
-#: gitk:9399
 msgid "To"
 msgstr "பெறுநர்"
 
-#: gitk:9423
 msgid "Generate patch"
 msgstr "ஒட்டை உருவாக்கு"
 
-#: gitk:9425
 msgid "From:"
 msgstr "இருந்து:"
 
-#: gitk:9434
 msgid "To:"
 msgstr "இதற்கு:"
 
-#: gitk:9443
 msgid "Reverse"
 msgstr "தலைகீழ்"
 
-#: gitk:9445 gitk:9655
 msgid "Output file:"
 msgstr "வெளியீட்டு கோப்பு:"
 
-#: gitk:9451
 msgid "Generate"
 msgstr "உருவாக்கு"
 
-#: gitk:9489
 msgid "Error creating patch:"
 msgstr "ஒட்டை உருவாக்கு பிழை:"
 
-#: gitk:9512 gitk:9643 gitk:9731
 msgid "ID:"
 msgstr "அடையாளம்:"
 
-#: gitk:9521
 msgid "Tag name:"
 msgstr "குறிச்சொல் பெயர்:"
 
-#: gitk:9524
 msgid "Tag message is optional"
 msgstr "குறிச்சொல் செய்தி விருப்பமானது"
 
-#: gitk:9526
 msgid "Tag message:"
 msgstr "குறிச்சொல் செய்தி:"
 
-#: gitk:9530 gitk:9701
 msgid "Create"
 msgstr "உருவாக்கு"
 
-#: gitk:9548
 msgid "No tag name specified"
 msgstr "குறிச்சொல் பெயர் குறிப்பிடப்படவில்லை"
 
-#: gitk:9552
 #, tcl-format
 msgid "Tag \"%s\" already exists"
 msgstr "குறிச்சொல் \"%s\" ஏற்கனவே உள்ளது"
 
-#: gitk:9562
 msgid "Error creating tag:"
 msgstr "குறிச்சொல்லை உருவாக்கு பிழை:"
 
-#: gitk:9652
 msgid "Command:"
 msgstr "கட்டளை:"
 
-#: gitk:9660
 msgid "Write"
 msgstr "எழுது"
 
-#: gitk:9678
 msgid "Error writing commit:"
 msgstr "பிழை எழுதுதல் உறுதிமொழி:"
 
-#: gitk:9700
 msgid "Create branch"
 msgstr "கிளையை உருவாக்கு"
 
-#: gitk:9716
 #, tcl-format
 msgid "Rename branch %s"
 msgstr "%s கிளையை மறுபெயரிடு"
 
-#: gitk:9717
 msgid "Rename"
 msgstr "மறுபெயரிடு"
 
-#: gitk:9741
 msgid "Name:"
 msgstr "பெயர்:"
 
-#: gitk:9765
 msgid "Please specify a name for the new branch"
 msgstr "புதிய கிளைக்கு ஒரு பெயரைக் குறிப்பிடு"
 
-#: gitk:9770
 #, tcl-format
 msgid "Branch '%s' already exists. Overwrite?"
 msgstr "கிளை '%s' ஏற்கனவே உள்ளது. மேலெழுதவா?"
 
-#: gitk:9814
 msgid "Please specify a new name for the branch"
 msgstr "கிளைக்கு ஒரு புதிய பெயரைக் குறிப்பிடு"
 
-#: gitk:9877
 #, tcl-format
 msgid "Commit %s is already included in branch %s -- really re-apply it?"
-msgstr ""
-"உறுதிமொழி %s ஏற்கனவே கிளை %s சேர்க்கப்பட்டுள்ளன-உண்மையில் அதை மீண்டும் இடவா?"
+msgstr "உறுதிமொழி %s ஏற்கனவே கிளை %s சேர்க்கப்பட்டுள்ளன-உண்மையில் அதை மீண்டும் இடவா?"
 
-#: gitk:9882
 msgid "Cherry-picking"
 msgstr "கனி எடுக்கும்"
 
-#: gitk:9891
 #, tcl-format
 msgid ""
 "Cherry-pick failed because of local changes to file '%s'.\n"
@@ -1085,7 +831,6 @@
 "'%s' கோப்பில் உள்ளக மாற்றங்கள் காரணமாக கனி-எடு தோல்வியடைந்தது. \n"
 "தயவுசெய்து உங்கள் மாற்றங்களைச் உறுதிமொழி, மீட்டமை அல்லது சேமி பிறகு மீண்டும் முயற்சி."
 
-#: gitk:9897
 msgid ""
 "Cherry-pick failed because of merge conflict.\n"
 "Do you wish to run git citool to resolve it?"
@@ -1093,31 +838,24 @@
 "ஒன்றிணைக்கும் மோதல் காரணமாக கனி-எடு தோல்வியடைந்தது. \n"
 "அதை தீர்க்க அறிவிலி சிஐகருவியை இயக்க விரும்புகிறீர்களா?"
 
-#: gitk:9913 gitk:9971
 msgid "No changes committed"
 msgstr "எந்த மாற்றங்களும் உறுதிமொழியப்படவில்லை"
 
-#: gitk:9940
 #, tcl-format
 msgid "Commit %s is not included in branch %s -- really revert it?"
-msgstr ""
-"உறுதிமொழி %s கிளை %s சேர்க்கப்படவில்லை - உண்மையில் அதை மீட்டெடுக்கவா?"
+msgstr "உறுதிமொழி %s கிளை %s சேர்க்கப்படவில்லை - உண்மையில் அதை மீட்டெடுக்கவா?"
 
-#: gitk:9945
 msgid "Reverting"
 msgstr "மீட்டெடுத்தல்"
 
-#: gitk:9953
 #, tcl-format
 msgid ""
 "Revert failed because of local changes to the following files:%s Please "
 "commit, reset or stash  your changes and try again."
 msgstr ""
-"பின்வரும் கோப்புகளில் உள்ளக மாற்றங்கள் காரணமாக மீட்டெடு தோல்வியுற்றது:%s "
-"தயவுசெய்து உங்கள் மாற்றங்களைச் உறுதிமொழி, மீட்டமை அல்லது "
-"சேமி மற்றும் மீண்டும் முயற்சி."
+"பின்வரும் கோப்புகளில் உள்ளக மாற்றங்கள் காரணமாக மீட்டெடு தோல்வியுற்றது:%s தயவுசெய்து உங்கள் "
+"மாற்றங்களைச் உறுதிமொழி, மீட்டமை அல்லது சேமி மற்றும் மீண்டும் முயற்சி."
 
-#: gitk:9957
 msgid ""
 "Revert failed because of merge conflict.\n"
 " Do you wish to run git citool to resolve it?"
@@ -1125,30 +863,22 @@
 "ஒன்றிணைக்கும் மோதல் காரணமாக மீட்டெடு தோல்வியடைந்தது. \n"
 "அதை தீர்க்க அறிவிலி சிஐகருவியை இயக்க விரும்புகிறீர்களா?"
 
-#: gitk:10000
 msgid "Confirm reset"
 msgstr "மீட்டமைப்பை உறுதிப்படுத்து"
 
-#: gitk:10002
 #, tcl-format
 msgid "Reset branch %s to %s?"
 msgstr "%s கிளையை %s க்கு மீட்டமைக்கவா?"
 
-#: gitk:10004
 msgid "Reset type:"
 msgstr "மீட்டமை வகை:"
 
-#: gitk:10007
 msgid "Soft: Leave working tree and index untouched"
-msgstr ""
-"மென்மை: வேலை செய்யும் மரம் மற்றும் குறியீட்டைத் தீண்டாமல் விடு"
+msgstr "மென்மை: வேலை செய்யும் மரம் மற்றும் குறியீட்டைத் தீண்டாமல் விடு"
 
-#: gitk:10010
 msgid "Mixed: Leave working tree untouched, reset index"
-msgstr ""
-"கலப்பு: வேலை செய்யும் மரத்தை தீண்டாமல் விடு, குறியீட்டை மீட்டமை"
+msgstr "கலப்பு: வேலை செய்யும் மரத்தை தீண்டாமல் விடு, குறியீட்டை மீட்டமை"
 
-#: gitk:10013
 msgid ""
 "Hard: Reset working tree and index\n"
 "(discard ALL local changes)"
@@ -1156,24 +886,19 @@
 "கடினம்: வேலை செய்யும் மரம் மற்றும் குறியீட்டை மீட்டமை \n"
 "(அனைத்து உள்ளக மாற்றங்களையும் நிராகரி)"
 
-#: gitk:10030
 msgid "Resetting"
 msgstr "மீட்டமைத்தல்"
 
-#: gitk:10103
 #, tcl-format
 msgid "A local branch named %s exists already"
 msgstr "%s என்ற உள்ளக கிளை ஏற்கனவே உள்ளது"
 
-#: gitk:10111
 msgid "Checking out"
 msgstr "சரிபார்"
 
-#: gitk:10170
 msgid "Cannot delete the currently checked-out branch"
 msgstr "தற்போது சரிபார்க்கப்பட்ட கிளையை நீக்க முடியாது"
 
-#: gitk:10176
 #, tcl-format
 msgid ""
 "The commits on branch %s aren't on any other branch.\n"
@@ -1182,254 +907,193 @@
 "கிளை %s மீதான உறுதிமொழிகள் வேறு எந்த கிளையிலும் இல்லை. \n"
 "உண்மையில் கிளை %s நீக்கவா?"
 
-#: gitk:10207
 #, tcl-format
 msgid "Tags and heads: %s"
 msgstr "குறிச்சொற்கள் மற்றும் தலைகள்: %s"
 
-#: gitk:10224
 msgid "Filter"
 msgstr "வடிப்பி"
 
-#: gitk:10531
 msgid ""
 "Error reading commit topology information; branch and preceding/following "
 "tag information will be incomplete."
 msgstr ""
-"உறுதிமொழி இடவியல் தகவலை படிப்பதில் பிழை; கிளை மற்றும் அதற்கு "
-"முந்தைய/பின்வரும் குறிச்சொல் செய்தி முழுமையடையாது."
+"உறுதிமொழி இடவியல் தகவலை படிப்பதில் பிழை; கிளை மற்றும் அதற்கு முந்தைய/பின்வரும் "
+"குறிச்சொல் செய்தி முழுமையடையாது."
 
-#: gitk:11508
 msgid "Tag"
 msgstr "குறிச்சொல்"
 
-#: gitk:11512
 msgid "Id"
 msgstr "அடையாளம்"
 
-#: gitk:11595
 msgid "Gitk font chooser"
 msgstr "அறிவிலிகே எழுத்துரு தேர்வு"
 
-#: gitk:11612
 msgid "B"
 msgstr "பி"
 
-#: gitk:11615
 msgid "I"
 msgstr "ஐ"
 
-#: gitk:11734
 msgid "Commit list display options"
 msgstr "உறுதிமொழி பட்டியல் காட்சி விருப்பங்கள்"
 
-#: gitk:11737
 msgid "Maximum graph width (lines)"
 msgstr "அதிகபட்ச வரைபட அகலம் (கோடுகள்)"
 
-#: gitk:11741
 #, no-tcl-format
 msgid "Maximum graph width (% of pane)"
 msgstr "அதிகபட்ச வரைபட அகலம் (பலகத்தின் %)"
 
-#: gitk:11744
 msgid "Show local changes"
 msgstr "உள்ளக மாற்றங்களைக் காட்டு"
 
-#: gitk:11747
 msgid "Hide remote refs"
 msgstr "தொலை குறிகளை மறை"
 
-#: gitk:11751
 msgid "Copy commit ID to clipboard"
 msgstr "இடைநிலைப்பலகைக்கு அடையாளத்தை நகலெடு"
 
-#: gitk:11755
 msgid "Copy commit ID to X11 selection"
 msgstr "உறுதிமொழி அடையாளத்தை ஃ11 பகுதிக்கு நகலெடு"
 
-#: gitk:11760
 msgid "Length of commit ID to copy"
 msgstr "நகலெடுக்க உறுதிமொழி அடையாளத்தின் நீளம்"
 
-#: gitk:11763
 msgid "Diff display options"
 msgstr "வேறுபாடு காட்சி விருப்பங்கள்"
 
-#: gitk:11765
 msgid "Tab spacing"
 msgstr "தாவல் இடைவெளி"
 
-#: gitk:11769
 msgid "Wrap comment text"
 msgstr "கருத்து உரையை மடி"
 
-#: gitk:11774
 msgid "Wrap other text"
 msgstr "மற்ற உரையை மடி"
 
-#: gitk:11779
 msgid "Display nearby tags/heads"
 msgstr "அருகிலுள்ள குறிச்சொற்கள்/தலைகளைக் காண்பி"
 
-#: gitk:11782
 msgid "Maximum # tags/heads to show"
 msgstr "காண்பிக்க அதிகபட்ச # குறிச்சொற்கள்/தலைகள்"
 
-#: gitk:11785
 msgid "Limit diffs to listed paths"
 msgstr "பட்டியலிடப்பட்ட பாதைகளுக்கு வரம்பு வேறுபடுகிறது"
 
-#: gitk:11788
 msgid "Support per-file encodings"
 msgstr "ஒரு கோப்பு குறியீடுகளை ஆதரி"
 
-#: gitk:11794 gitk:11961
 msgid "External diff tool"
 msgstr "வெளிப்புற வேறுபாடு கருவி"
 
-#: gitk:11795
 msgid "Choose..."
 msgstr "தேர்வு..."
 
-#: gitk:11802
 msgid "Web browser"
 msgstr "வலை உலாவி"
 
-#: gitk:11807
 msgid "General options"
 msgstr "பொது விருப்பங்கள்"
 
-#: gitk:11810
 msgid "Use themed widgets"
 msgstr "கருப்பொருள் நிரல்பலகைகளைப் பயன்படுத்து"
 
-#: gitk:11812
 msgid "(change requires restart)"
 msgstr "(மாற்றத்திற்கு மறுதொடக்கம் தேவை)"
 
-#: gitk:11814
 msgid "(currently unavailable)"
 msgstr "(தற்போது கிடைக்கவில்லை)"
 
-#: gitk:11826
 msgid "Colors: press to choose"
 msgstr "நிறங்கள்: தேர்வு செய்ய அழுத்தவும்"
 
-#: gitk:11829
 msgid "Interface"
 msgstr "இடைமுகம்"
 
-#: gitk:11830
 msgid "interface"
 msgstr "இடைமுகம்"
 
-#: gitk:11833
 msgid "Background"
 msgstr "பின்னணி"
 
-#: gitk:11834 gitk:11876
 msgid "background"
 msgstr "பின்னணி"
 
-#: gitk:11837
 msgid "Foreground"
 msgstr "முன்புறம்"
 
-#: gitk:11838
 msgid "foreground"
 msgstr "முன்புறம்"
 
-#: gitk:11841
 msgid "Diff: old lines"
 msgstr "வேறுபாடு: பழைய வரிகள்"
 
-#: gitk:11842
 msgid "diff old lines"
 msgstr "பழைய வரிகள் வேறுபாடு"
 
-#: gitk:11846
 msgid "Diff: old lines bg"
 msgstr "வேறுபாடு: பழைய வரிகள் பின்ணனி"
 
-#: gitk:11848
 msgid "diff old lines bg"
 msgstr "பழைய வரிகள் பின்ணனி வேறுபாடு"
 
-#: gitk:11852
 msgid "Diff: new lines"
 msgstr "வேறுபாடு: புதிய கோடுகள்"
 
-#: gitk:11853
 msgid "diff new lines"
 msgstr "புதிய வரிகள் வேறுபாடு"
 
-#: gitk:11857
 msgid "Diff: new lines bg"
 msgstr "வேறுபாடு: புதிய வரிகள் பின்ணனி"
 
-#: gitk:11859
 msgid "diff new lines bg"
 msgstr "புதிய வரிகளை பின்ணனி வேறுபாடு"
 
-#: gitk:11863
 msgid "Diff: hunk header"
 msgstr "வேறுபாடு: அங்க் தலைப்பு"
 
-#: gitk:11865
 msgid "diff hunk header"
 msgstr "அங்க் தலைப்பு வேறுபாடு"
 
-#: gitk:11869
 msgid "Marked line bg"
 msgstr "குறிக்கப்பட்ட வரி பின்னணி"
 
-#: gitk:11871
 msgid "marked line background"
 msgstr "குறிக்கப்பட்ட வரி பின்னணி"
 
-#: gitk:11875
 msgid "Select bg"
 msgstr "பின்னணி தேர்வு"
 
-#: gitk:11884
 msgid "Fonts: press to choose"
 msgstr "எழுத்துருக்கள்: தேர்வு செய்ய அழுத்து"
 
-#: gitk:11886
 msgid "Main font"
 msgstr "முதன்மையான எழுத்துரு"
 
-#: gitk:11887
 msgid "Diff display font"
 msgstr "காட்சி எழுத்துரு வேறுபாடு"
 
-#: gitk:11888
 msgid "User interface font"
 msgstr "பயனர் இடைமுக எழுத்துரு"
 
-#: gitk:11910
 msgid "Gitk preferences"
 msgstr "அறிவிலிகே விருப்பத்தேர்வுகள்"
 
-#: gitk:11919
 msgid "General"
 msgstr "பொது"
 
-#: gitk:11920
 msgid "Colors"
 msgstr "நிறங்கள்"
 
-#: gitk:11921
 msgid "Fonts"
 msgstr "எழுத்துருக்கள்"
 
-#: gitk:11971
 #, tcl-format
 msgid "Gitk: choose color for %s"
 msgstr "அறிவிலிகே: %s க்கு வண்ணத்தைத் தேர்வுசெய்க"
 
-#: gitk:12490
 msgid ""
 "Sorry, gitk cannot run with this version of Tcl/Tk.\n"
 " Gitk requires at least Tcl/Tk 8.4."
@@ -1437,16 +1101,13 @@
 "மன்னிக்கவும், டிசிஎல்/டிகேயின் இந்த பதிப்பைக் கொண்டு அறிவிலிகே இயக்க முடியாது. \n"
 "அறிவிலிகேவுக்கு குறைந்தபட்சம் டிசிஎல்/டிகே 8.4 தேவைப்படுகிறது."
 
-#: gitk:12711
 msgid "Cannot find a git repository here."
 msgstr "இங்கே ஒரு அறிவிலி களஞ்சியத்தைக் கண்டுபிடிக்க முடியவில்லை."
 
-#: gitk:12758
 #, tcl-format
 msgid "Ambiguous argument '%s': both revision and filename"
 msgstr "தெளிவற்ற வாதம் '%s': திருத்தம் மற்றும் கோப்பு பெயர்"
 
-#: gitk:12770
 msgid "Bad arguments to gitk:"
 msgstr "அறிவிலிகேவிற்கு மோசமான வாதங்கள்:"
 
diff --git a/gitk-git/po/vi.po b/gitk-git/po/vi.po
index 5967498..52c9d09 100644
--- a/gitk-git/po/vi.po
+++ b/gitk-git/po/vi.po
@@ -5,7 +5,7 @@
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: gitk @@GIT_VERSION@@\n"
+"Project-Id-Version: Gitk @@GIT_VERSION@@\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2015-05-17 14:32+1000\n"
 "PO-Revision-Date: 2015-09-15 07:33+0700\n"
@@ -18,32 +18,25 @@
 "Plural-Forms: nplurals=1; plural=0;\n"
 "X-Generator: Gtranslator 2.91.7\n"
 
-#: gitk:140
 msgid "Couldn't get list of unmerged files:"
 msgstr "Không thể lấy danh sách các tập-tin chưa được hòa trộn:"
 
-#: gitk:212 gitk:2381
 msgid "Color words"
 msgstr "Tô màu chữ"
 
-#: gitk:217 gitk:2381 gitk:8220 gitk:8253
 msgid "Markup words"
 msgstr "Đánh dấu chữ"
 
-#: gitk:324
 msgid "Error parsing revisions:"
 msgstr "Gặp lỗi khi phân tích điểm xét duyệt:"
 
-#: gitk:380
 msgid "Error executing --argscmd command:"
 msgstr "Gặp lỗi khi thực hiện lệnh --argscmd:"
 
-#: gitk:393
 msgid "No files selected: --merge specified but no files are unmerged."
 msgstr ""
 "Chưa chọn tập tin: --merge đã chỉ định nhưng không có tập tin chưa hòa trộn."
 
-#: gitk:396
 msgid ""
 "No files selected: --merge specified but no unmerged files are within file "
 "limit."
@@ -51,314 +44,234 @@
 "Chưa chọn tập tin: --merge đã chỉ định nhưng không có tập tin chưa hòa trộn "
 "trong giới hạn tập tin."
 
-#: gitk:418 gitk:566
 msgid "Error executing git log:"
 msgstr "Gặp lỗi khi thực hiện lệnh git log:"
 
-#: gitk:436 gitk:582
 msgid "Reading"
 msgstr "Đang đọc"
 
-#: gitk:496 gitk:4525
 msgid "Reading commits..."
 msgstr "Đang đọc các lần chuyển giao…"
 
-#: gitk:499 gitk:1637 gitk:4528
 msgid "No commits selected"
 msgstr "Chưa chọn các lần chuyển giao"
 
-#: gitk:1445 gitk:4045 gitk:12432
 msgid "Command line"
 msgstr "Dòng lệnh"
 
-#: gitk:1511
 msgid "Can't parse git log output:"
 msgstr "Không thể phân tích kết xuất từ lệnh git log:"
 
-#: gitk:1740
 msgid "No commit information available"
 msgstr "Không có thông tin về lần chuyển giao nào"
 
-#: gitk:1903 gitk:1932 gitk:4315 gitk:9669 gitk:11241 gitk:11521
 msgid "OK"
 msgstr "Đồng ý"
 
-#: gitk:1934 gitk:4317 gitk:9196 gitk:9275 gitk:9391 gitk:9440 gitk:9671
-#: gitk:11242 gitk:11522
 msgid "Cancel"
 msgstr "Thôi"
 
-#: gitk:2069
 msgid "&Update"
 msgstr "Cập nhật"
 
-#: gitk:2070
 msgid "&Reload"
 msgstr "Tải lại"
 
-#: gitk:2071
 msgid "Reread re&ferences"
 msgstr "Đọc lại tham chiếu"
 
-#: gitk:2072
 msgid "&List references"
 msgstr "Liệt kê các tham chiếu"
 
-#: gitk:2074
 msgid "Start git &gui"
 msgstr "Khởi chạy git gui"
 
-#: gitk:2076
 msgid "&Quit"
 msgstr "Thoát"
 
-#: gitk:2068
 msgid "&File"
 msgstr "Chính"
 
-#: gitk:2080
 msgid "&Preferences"
 msgstr "Tùy thích"
 
-#: gitk:2079
 msgid "&Edit"
 msgstr "Chỉnh sửa"
 
-#: gitk:2084
 msgid "&New view..."
 msgstr "Thêm trình bày mới…"
 
-#: gitk:2085
 msgid "&Edit view..."
 msgstr "Sửa cách trình bày…"
 
-#: gitk:2086
 msgid "&Delete view"
 msgstr "Xóa cách trình bày"
 
-#: gitk:2088 gitk:4043
 msgid "&All files"
 msgstr "Mọi tập tin"
 
-#: gitk:2083 gitk:4067
 msgid "&View"
 msgstr "Trình bày"
 
-#: gitk:2093 gitk:2103 gitk:3012
 msgid "&About gitk"
 msgstr "Giới thiệu về gitk"
 
-#: gitk:2094 gitk:2108
 msgid "&Key bindings"
 msgstr "Tổ hợp phím"
 
-#: gitk:2092 gitk:2107
 msgid "&Help"
 msgstr "Trợ giúp"
 
-#: gitk:2185 gitk:8652
 msgid "SHA1 ID:"
 msgstr "SHA1 ID:"
 
-#: gitk:2229
 msgid "Row"
 msgstr "Hàng"
 
-#: gitk:2267
 msgid "Find"
 msgstr "Tìm"
 
-#: gitk:2295
 msgid "commit"
 msgstr "lần chuyển giao"
 
-#: gitk:2299 gitk:2301 gitk:4687 gitk:4710 gitk:4734 gitk:6755 gitk:6827
-#: gitk:6912
 msgid "containing:"
 msgstr "có chứa:"
 
-#: gitk:2302 gitk:3526 gitk:3531 gitk:4763
 msgid "touching paths:"
 msgstr "đang chạm đường dẫn:"
 
-#: gitk:2303 gitk:4777
 msgid "adding/removing string:"
 msgstr "thêm/gỡ bỏ chuỗi:"
 
-#: gitk:2304 gitk:4779
 msgid "changing lines matching:"
 msgstr "những dòng thay đổi khớp mẫu:"
 
-#: gitk:2313 gitk:2315 gitk:4766
 msgid "Exact"
 msgstr "Chính xác"
 
-#: gitk:2315 gitk:4854 gitk:6723
 msgid "IgnCase"
 msgstr "BquaHt"
 
-#: gitk:2315 gitk:4736 gitk:4852 gitk:6719
 msgid "Regexp"
 msgstr "BTCQ"
 
-#: gitk:2317 gitk:2318 gitk:4874 gitk:4904 gitk:4911 gitk:6848 gitk:6916
 msgid "All fields"
 msgstr "Mọi trường"
 
-#: gitk:2318 gitk:4871 gitk:4904 gitk:6786
 msgid "Headline"
 msgstr "Nội dung chính"
 
-#: gitk:2319 gitk:4871 gitk:6786 gitk:6916 gitk:7389
 msgid "Comments"
 msgstr "Ghi chú"
 
-#: gitk:2319 gitk:4871 gitk:4876 gitk:4911 gitk:6786 gitk:7324 gitk:8830
-#: gitk:8845
 msgid "Author"
 msgstr "Tác giả"
 
-#: gitk:2319 gitk:4871 gitk:6786 gitk:7326
 msgid "Committer"
 msgstr "Người chuyển giao"
 
-#: gitk:2350
 msgid "Search"
 msgstr "Tìm kiếm"
 
-#: gitk:2358
 msgid "Diff"
 msgstr "So sánh"
 
-#: gitk:2360
 msgid "Old version"
 msgstr "Phiên bản cũ"
 
-#: gitk:2362
 msgid "New version"
 msgstr "Phiên bản mới"
 
-#: gitk:2364
 msgid "Lines of context"
 msgstr "Các dòng của nội dung"
 
-#: gitk:2374
 msgid "Ignore space change"
 msgstr "Không xét đến thay đổi do khoảng trắng"
 
-#: gitk:2378 gitk:2380 gitk:7959 gitk:8206
 msgid "Line diff"
 msgstr "Khác biệt theo dòng"
 
-#: gitk:2445
 msgid "Patch"
 msgstr "Vá"
 
-#: gitk:2447
 msgid "Tree"
 msgstr "Cây"
 
-#: gitk:2617 gitk:2637
 msgid "Diff this -> selected"
 msgstr "So sánh cái này -> cái đã chọn"
 
-#: gitk:2618 gitk:2638
 msgid "Diff selected -> this"
 msgstr "So sánh cái đã chọn -> cái này"
 
-#: gitk:2619 gitk:2639
 msgid "Make patch"
 msgstr "Tạo miếng vá"
 
-#: gitk:2620 gitk:9254
 msgid "Create tag"
 msgstr "Tạo thẻ"
 
-#: gitk:2621 gitk:9371
 msgid "Write commit to file"
 msgstr "Ghi lần chuyển giao ra tập tin"
 
-#: gitk:2622 gitk:9428
 msgid "Create new branch"
 msgstr "Tạo nhánh mới"
 
-#: gitk:2623
 msgid "Cherry-pick this commit"
 msgstr "Cherry-pick lần chuyển giao này"
 
-#: gitk:2624
 msgid "Reset HEAD branch to here"
 msgstr "Đặt lại HEAD của nhánh vào đây"
 
-#: gitk:2625
 msgid "Mark this commit"
 msgstr "Đánh dấu lần chuyển giao này"
 
-#: gitk:2626
 msgid "Return to mark"
 msgstr "Quay lại vị trí dấu"
 
-#: gitk:2627
 msgid "Find descendant of this and mark"
 msgstr "Tìm con cháu của cái này và cái đã đánh dấu"
 
-#: gitk:2628
 msgid "Compare with marked commit"
 msgstr "So sánh với lần chuyển giao đã đánh dấu"
 
-#: gitk:2629 gitk:2640
 msgid "Diff this -> marked commit"
 msgstr "So sánh cái này -> lần chuyển giao đã đánh dấu"
 
-#: gitk:2630 gitk:2641
 msgid "Diff marked commit -> this"
 msgstr "So sánh lần chuyển giao đã đánh dấu -> cái này"
 
-#: gitk:2631
 msgid "Revert this commit"
 msgstr "Hoàn lại lần chuyển giao này"
 
-#: gitk:2647
 msgid "Check out this branch"
 msgstr "Lấy ra nhánh này"
 
-#: gitk:2648
 msgid "Remove this branch"
 msgstr "Gỡ bỏ nhánh này"
 
-#: gitk:2649
 msgid "Copy branch name"
 msgstr "Chép tên nhánh"
 
-#: gitk:2656
 msgid "Highlight this too"
 msgstr "Cũng tô sáng nó"
 
-#: gitk:2657
 msgid "Highlight this only"
 msgstr "Chỉ tô sáng cái này"
 
-#: gitk:2658
 msgid "External diff"
 msgstr "diff từ bên ngoài"
 
-#: gitk:2659
 msgid "Blame parent commit"
 msgstr "Xem công trạng lần chuyển giao cha mẹ"
 
-#: gitk:2660
 msgid "Copy path"
 msgstr "Chép đường dẫn"
 
-#: gitk:2667
 msgid "Show origin of this line"
 msgstr "Hiển thị nguyên gốc của dòng này"
 
-#: gitk:2668
 msgid "Run git gui blame on this line"
 msgstr "Chạy lệnh git gui blame cho dòng này"
 
-#: gitk:3014
 msgid ""
 "\n"
 "Gitk - a commit viewer for git\n"
@@ -374,318 +287,246 @@
 "\n"
 "Dùng và phân phối lại phần mềm này theo các điều khoản của Giấy Phép Công GNU"
 
-#: gitk:3022 gitk:3089 gitk:9857
 msgid "Close"
 msgstr "Đóng"
 
-#: gitk:3043
 msgid "Gitk key bindings"
 msgstr "Tổ hợp phím gitk"
 
-#: gitk:3046
 msgid "Gitk key bindings:"
 msgstr "Tổ hợp phím gitk:"
 
-#: gitk:3048
 #, tcl-format
 msgid "<%s-Q>\t\tQuit"
 msgstr "<%s-Q>\t\tThoát"
 
-#: gitk:3049
 #, tcl-format
 msgid "<%s-W>\t\tClose window"
 msgstr "<%s-W>\t\tĐóng cửa sổ"
 
-#: gitk:3050
 msgid "<Home>\t\tMove to first commit"
 msgstr "<Home>\t\tChuyển đến lần chuyển giao đầu tiên"
 
-#: gitk:3051
 msgid "<End>\t\tMove to last commit"
 msgstr "<End>\t\tChuyển đến lần chuyển giao cuối"
 
-#: gitk:3052
 msgid "<Up>, p, k\tMove up one commit"
 msgstr "<Up>, p, k\tDi chuyển lên một lần chuyển giao"
 
-#: gitk:3053
 msgid "<Down>, n, j\tMove down one commit"
 msgstr "<Down>, n, j\tDi chuyển xuống một lần chuyển giao"
 
-#: gitk:3054
 msgid "<Left>, z, h\tGo back in history list"
 msgstr "<Left>, z, h\tQuay trở lại danh sách lịch sử"
 
-#: gitk:3055
 msgid "<Right>, x, l\tGo forward in history list"
 msgstr "<Right>, x, l\tDi chuyển tiếp trong danh sách lịch sử"
 
-#: gitk:3056
 #, tcl-format
 msgid "<%s-n>\tGo to n-th parent of current commit in history list"
 msgstr ""
 "<%s-n>\tĐến cha thứ n của lần chuyển giao hiện tại trong danh sách lịch sử"
 
-#: gitk:3057
 msgid "<PageUp>\tMove up one page in commit list"
 msgstr "<PageUp>\tDi chuyển lên một trang trong danh sách lần chuyển giao"
 
-#: gitk:3058
 msgid "<PageDown>\tMove down one page in commit list"
 msgstr "<PageDown>\tDi chuyển xuống một trang trong danh sách lần chuyển giao"
 
-#: gitk:3059
 #, tcl-format
 msgid "<%s-Home>\tScroll to top of commit list"
 msgstr "<%s-Home>\tCuộn lên trên cùng của danh sách lần chuyển giao"
 
-#: gitk:3060
 #, tcl-format
 msgid "<%s-End>\tScroll to bottom of commit list"
 msgstr "<%s-End>\tCuộn xuống dưới cùng của danh sách lần chuyển giao"
 
-#: gitk:3061
 #, tcl-format
 msgid "<%s-Up>\tScroll commit list up one line"
 msgstr "<%s-Up>\tCuộn danh sách lần chuyển giao lên một dòng"
 
-#: gitk:3062
 #, tcl-format
 msgid "<%s-Down>\tScroll commit list down one line"
 msgstr "<%s-Down>\tCuộn danh sách lần chuyển giao xuống một dòng"
 
-#: gitk:3063
 #, tcl-format
 msgid "<%s-PageUp>\tScroll commit list up one page"
 msgstr "<%s-PageUp>\tCuộn danh sách lần chuyển giao lên một trang"
 
-#: gitk:3064
 #, tcl-format
 msgid "<%s-PageDown>\tScroll commit list down one page"
 msgstr "<%s-PageDown>\tCuộn danh sách lần chuyển giao xuống một trang"
 
-#: gitk:3065
 msgid "<Shift-Up>\tFind backwards (upwards, later commits)"
 msgstr "<Shift-Up>\tTìm về phía sau (hướng lên trên, lần chuyển giao sau này)"
 
-#: gitk:3066
 msgid "<Shift-Down>\tFind forwards (downwards, earlier commits)"
 msgstr ""
 "<Shift-Down>\tTìm về phía trước (hướng xuống dưới, lần chuyển giao trước đây)"
 
-#: gitk:3067
 msgid "<Delete>, b\tScroll diff view up one page"
 msgstr "<Delete>, b\tCuộn phần trình bày diff lên một trang"
 
-#: gitk:3068
 msgid "<Backspace>\tScroll diff view up one page"
 msgstr "<Backspace>\tCuộn phần trình bày diff lên một trang"
 
-#: gitk:3069
 msgid "<Space>\t\tScroll diff view down one page"
 msgstr "<Space>\t\tCuộn phần trình bày diff xuống một trang"
 
-#: gitk:3070
 msgid "u\t\tScroll diff view up 18 lines"
 msgstr "u\t\tCuộn phần trình bày diff lên 18 dòng"
 
-#: gitk:3071
 msgid "d\t\tScroll diff view down 18 lines"
 msgstr "d\t\tCuộn phần trình bày diff xuống 18 dòng"
 
-#: gitk:3072
 #, tcl-format
 msgid "<%s-F>\t\tFind"
 msgstr "<%s-F>\t\tTìm kiếm"
 
-#: gitk:3073
 #, tcl-format
 msgid "<%s-G>\t\tMove to next find hit"
 msgstr "<%s-G>\t\tDi chuyển đến chỗ gặp kế tiếp"
 
-#: gitk:3074
 msgid "<Return>\tMove to next find hit"
 msgstr "<Return>\t\tDi chuyển đến chỗ gặp kế tiếp"
 
-#: gitk:3075
 msgid "g\t\tGo to commit"
 msgstr "g\t\tChuyển đến lần chuyển giao"
 
-#: gitk:3076
 msgid "/\t\tFocus the search box"
 msgstr "/\t\tĐưa con trỏ chuột vào ô tìm kiếm"
 
-#: gitk:3077
 msgid "?\t\tMove to previous find hit"
 msgstr "?\t\tDi chuyển đến chỗ gặp kế trước"
 
-#: gitk:3078
 msgid "f\t\tScroll diff view to next file"
 msgstr "f\t\tCuộn phần trình bày diff sang tập-tin kế"
 
-#: gitk:3079
 #, tcl-format
 msgid "<%s-S>\t\tSearch for next hit in diff view"
 msgstr "<%s-S>\t\tTìm đến chỗ khác biệt kế tiếp"
 
-#: gitk:3080
 #, tcl-format
 msgid "<%s-R>\t\tSearch for previous hit in diff view"
 msgstr "<%s-R>\t\tTìm đến chỗ khác biệt kế trước"
 
-#: gitk:3081
 #, tcl-format
 msgid "<%s-KP+>\tIncrease font size"
 msgstr "<%s-KP+>\tTăng cỡ chữ"
 
-#: gitk:3082
 #, tcl-format
 msgid "<%s-plus>\tIncrease font size"
 msgstr "<%s-plus>\tTăng cỡ chữ"
 
-#: gitk:3083
 #, tcl-format
 msgid "<%s-KP->\tDecrease font size"
 msgstr "<%s-KP->\tGiảm cỡ chữ"
 
-#: gitk:3084
 #, tcl-format
 msgid "<%s-minus>\tDecrease font size"
 msgstr "<%s-minus>\tGiảm cỡ chữ"
 
-#: gitk:3085
 msgid "<F5>\t\tUpdate"
 msgstr "<F5>\t\tCập nhật"
 
-#: gitk:3550 gitk:3559
 #, tcl-format
 msgid "Error creating temporary directory %s:"
 msgstr "Gặp lỗi khi tạo thư mục tạm %s:"
 
-#: gitk:3572
 #, tcl-format
 msgid "Error getting \"%s\" from %s:"
 msgstr "Lỗi chào hỏi \"%s\" từ %s:"
 
-#: gitk:3635
 msgid "command failed:"
 msgstr "lệnh gặp lỗi:"
 
-#: gitk:3784
 msgid "No such commit"
 msgstr "Không có lần chuyển giao như vậy"
 
-#: gitk:3798
 msgid "git gui blame: command failed:"
 msgstr "git gui blame: lệnh gặp lỗi:"
 
-#: gitk:3829
 #, tcl-format
 msgid "Couldn't read merge head: %s"
 msgstr "Không thể độc đầu của hòa trộn: %s"
 
 # tcl-format
-#: gitk:3837
 #, tcl-format
 msgid "Error reading index: %s"
 msgstr "Gặp lỗi khi đọc chỉ mục: %s"
 
-#: gitk:3862
 #, tcl-format
 msgid "Couldn't start git blame: %s"
 msgstr "Không thể khởi chạy git blame: %s"
 
-#: gitk:3865 gitk:6754
 msgid "Searching"
 msgstr "Đang tìm kiếm"
 
-#: gitk:3897
 #, tcl-format
 msgid "Error running git blame: %s"
 msgstr "Gặp lỗi khi chạy git blame: %s"
 
-#: gitk:3925
 #, tcl-format
 msgid "That line comes from commit %s,  which is not in this view"
 msgstr "Dòng đến từ lần chuyển giao %s, cái mà không trong trình bày này"
 
-#: gitk:3939
 msgid "External diff viewer failed:"
 msgstr "Bộ trình bày diff từ bên ngoài gặp lỗi:"
 
-#: gitk:4070
 msgid "Gitk view definition"
 msgstr "Định nghĩa cách trình bày gitk"
 
-#: gitk:4074
 msgid "Remember this view"
 msgstr "Nhớ cách trình bày này"
 
-#: gitk:4075
 msgid "References (space separated list):"
 msgstr "Tham chiếu (danh sách ngăn cách bằng dấu cách):"
 
-#: gitk:4076
 msgid "Branches & tags:"
 msgstr "Nhánh & thẻ:"
 
-#: gitk:4077
 msgid "All refs"
 msgstr "Mọi tham chiếu"
 
-#: gitk:4078
 msgid "All (local) branches"
 msgstr "Mọi nhánh (nội bộ)"
 
-#: gitk:4079
 msgid "All tags"
 msgstr "Mọi thẻ"
 
-#: gitk:4080
 msgid "All remote-tracking branches"
 msgstr "Mọi nhánh remote-tracking"
 
-#: gitk:4081
 msgid "Commit Info (regular expressions):"
 msgstr "Thông tin chuyển giao (biểu thức chính quy):"
 
-#: gitk:4082
 msgid "Author:"
 msgstr "Tác giả:"
 
-#: gitk:4083
 msgid "Committer:"
 msgstr "Người chuyển giao:"
 
-#: gitk:4084
 msgid "Commit Message:"
 msgstr "Chú thích của lần chuyển giao:"
 
-#: gitk:4085
 msgid "Matches all Commit Info criteria"
 msgstr "Khớp mọi điều kiện Thông tin Chuyển giao"
 
-#: gitk:4086
 msgid "Matches no Commit Info criteria"
 msgstr "Khớp không điều kiện Thông tin Chuyển giao"
 
-#: gitk:4087
 msgid "Changes to Files:"
 msgstr "Đổi thành Tập tin:"
 
-#: gitk:4088
 msgid "Fixed String"
 msgstr "Chuỗi cố định"
 
-#: gitk:4089
 msgid "Regular Expression"
 msgstr "Biểu thức chính quy"
 
-#: gitk:4090
 msgid "Search string:"
 msgstr "Chuỗi tìm kiếm:"
 
-#: gitk:4091
 msgid ""
 "Commit Dates (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 "
 "15:27:38\"):"
@@ -693,203 +534,155 @@
 "Ngày chuyển giao (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 "
 "15:27:38\"):"
 
-#: gitk:4092
 msgid "Since:"
 msgstr "Kể từ:"
 
-#: gitk:4093
 msgid "Until:"
 msgstr "Đến:"
 
-#: gitk:4094
 msgid "Limit and/or skip a number of revisions (positive integer):"
 msgstr "Giới hạn và/hoặc bỏ số của điểm xét (số nguyên âm):"
 
-#: gitk:4095
 msgid "Number to show:"
 msgstr "Số lượng hiển thị:"
 
-#: gitk:4096
 msgid "Number to skip:"
 msgstr "Số lượng sẽ bỏ qua:"
 
-#: gitk:4097
 msgid "Miscellaneous options:"
 msgstr "Tùy chọn hỗn hợp:"
 
-#: gitk:4098
 msgid "Strictly sort by date"
 msgstr "Sắp xếp chặt chẽ theo ngày"
 
-#: gitk:4099
 msgid "Mark branch sides"
 msgstr "Đánh dấu các cạnh nhánh"
 
-#: gitk:4100
 msgid "Limit to first parent"
 msgstr "Giới hạn thành cha mẹ đầu tiên"
 
-#: gitk:4101
 msgid "Simple history"
 msgstr "Lịch sử dạng đơn giản"
 
-#: gitk:4102
 msgid "Additional arguments to git log:"
 msgstr "Đối số bổ xung cho lệnh git log:"
 
-#: gitk:4103
 msgid "Enter files and directories to include, one per line:"
 msgstr "Nhập vào các tập tin và thư mục bao gồm, mỗi dòng một cái:"
 
-#: gitk:4104
 msgid "Command to generate more commits to include:"
 msgstr "Lệnh tạo ra nhiều lần chuyển giao hơn bao gồm:"
 
-#: gitk:4228
 msgid "Gitk: edit view"
 msgstr "Gitk: sửa cách trình bày"
 
-#: gitk:4236
 msgid "-- criteria for selecting revisions"
 msgstr "-- tiêu chuẩn chọn điểm xét duyệt"
 
-#: gitk:4241
 msgid "View Name"
 msgstr "Tên cách trình bày"
 
-#: gitk:4316
 msgid "Apply (F5)"
 msgstr "Áp dụng (F5)"
 
-#: gitk:4354
 msgid "Error in commit selection arguments:"
 msgstr "Lỗi trong các đối số chọn chuyển giao:"
 
-#: gitk:4409 gitk:4462 gitk:4924 gitk:4938 gitk:6208 gitk:12373 gitk:12374
 msgid "None"
 msgstr "Không"
 
-#: gitk:5021 gitk:5026
 msgid "Descendant"
 msgstr "Con cháu"
 
-#: gitk:5022
 msgid "Not descendant"
 msgstr "Không có con cháu"
 
-#: gitk:5029 gitk:5034
 msgid "Ancestor"
 msgstr "Tổ tiên chung"
 
-#: gitk:5030
 msgid "Not ancestor"
 msgstr "Không có chung tổ tiên"
 
-#: gitk:5324
 msgid "Local changes checked in to index but not committed"
 msgstr ""
 "Có thay đổi nội bộ đã được đưa vào bảng mục lục, nhưng chưa được chuyển giao"
 
-#: gitk:5360
 msgid "Local uncommitted changes, not checked in to index"
 msgstr "Có thay đổi nội bộ, nhưng chưa được đưa vào bảng mục lục"
 
-#: gitk:7134
 msgid "and many more"
 msgstr "và nhiều nữa"
 
-#: gitk:7137
 msgid "many"
 msgstr "nhiều"
 
-#: gitk:7328
 msgid "Tags:"
 msgstr "Thẻ:"
 
-#: gitk:7345 gitk:7351 gitk:8825
 msgid "Parent"
 msgstr "Cha"
 
-#: gitk:7356
 msgid "Child"
 msgstr "Con"
 
-#: gitk:7365
 msgid "Branch"
 msgstr "Nhánh"
 
-#: gitk:7368
 msgid "Follows"
 msgstr "Đứng sau"
 
-#: gitk:7371
 msgid "Precedes"
 msgstr "Đứng trước"
 
 # tcl-format
-#: gitk:7966
 #, tcl-format
 msgid "Error getting diffs: %s"
 msgstr "Lỗi lấy diff: %s"
 
-#: gitk:8650
 msgid "Goto:"
 msgstr "Nhảy tới:"
 
-#: gitk:8671
 #, tcl-format
 msgid "Short SHA1 id %s is ambiguous"
 msgstr "Định danh SHA1 dạng ngắn %s là chưa đủ rõ ràng"
 
-#: gitk:8678
 #, tcl-format
 msgid "Revision %s is not known"
 msgstr "Không hiểu điểm xét duyệt %s"
 
-#: gitk:8688
 #, tcl-format
 msgid "SHA1 id %s is not known"
 msgstr "Không hiểu định danh SHA1 %s"
 
-#: gitk:8690
 #, tcl-format
 msgid "Revision %s is not in the current view"
 msgstr "Điểm %s không ở trong phần hiển thị hiện tại"
 
-#: gitk:8832 gitk:8847
 msgid "Date"
 msgstr "Ngày"
 
-#: gitk:8835
 msgid "Children"
 msgstr "Con cháu"
 
-#: gitk:8898
 #, tcl-format
 msgid "Reset %s branch to here"
 msgstr "Đặt lại nhánh %s tại đây"
 
-#: gitk:8900
 msgid "Detached head: can't reset"
 msgstr "Head đã bị tách rời: không thể đặt lại"
 
-#: gitk:9005 gitk:9011
 msgid "Skipping merge commit "
 msgstr "Bỏ qua lần chuyển giao hòa trộn "
 
-#: gitk:9020 gitk:9025
 msgid "Error getting patch ID for "
 msgstr "Gặp lỗi khi lấy ID miếng vá cho "
 
-#: gitk:9021 gitk:9026
 msgid " - stopping\n"
 msgstr " - dừng\n"
 
-#: gitk:9031 gitk:9034 gitk:9042 gitk:9056 gitk:9065
 msgid "Commit "
 msgstr "Commit "
 
-#: gitk:9035
 msgid ""
 " is the same patch as\n"
 "       "
@@ -897,7 +690,6 @@
 " là cùng một miếng vá với\n"
 "       "
 
-#: gitk:9043
 msgid ""
 " differs from\n"
 "       "
@@ -905,7 +697,6 @@
 " khác biệt từ\n"
 "       "
 
-#: gitk:9045
 msgid ""
 "Diff of commits:\n"
 "\n"
@@ -913,131 +704,101 @@
 "Khác biệt của lần chuyển giao (commit):\n"
 "\n"
 
-#: gitk:9057 gitk:9066
 #, tcl-format
 msgid " has %s children - stopping\n"
 msgstr " có %s con - dừng\n"
 
-#: gitk:9085
 #, tcl-format
 msgid "Error writing commit to file: %s"
 msgstr "Gặp lỗi trong quá trình ghi lần chuyển giao vào tập tin: %s"
 
-#: gitk:9091
 #, tcl-format
 msgid "Error diffing commits: %s"
 msgstr "Gặp lỗi khi so sánh sự khác biệt giữa các lần chuyển giao: %s"
 
-#: gitk:9137
 msgid "Top"
 msgstr "Đỉnh"
 
-#: gitk:9138
 msgid "From"
 msgstr "Từ"
 
-#: gitk:9143
 msgid "To"
 msgstr "Đến"
 
-#: gitk:9167
 msgid "Generate patch"
 msgstr "Tạo miếng vá"
 
-#: gitk:9169
 msgid "From:"
 msgstr "Từ:"
 
-#: gitk:9178
 msgid "To:"
 msgstr "Đến:"
 
-#: gitk:9187
 msgid "Reverse"
 msgstr "Đảo ngược"
 
-#: gitk:9189 gitk:9385
 msgid "Output file:"
 msgstr "Tập tin kết xuất:"
 
-#: gitk:9195
 msgid "Generate"
 msgstr "Tạo"
 
-#: gitk:9233
 msgid "Error creating patch:"
 msgstr "Gặp lỗi khi tạo miếng vá:"
 
-#: gitk:9256 gitk:9373 gitk:9430
 msgid "ID:"
 msgstr "Mã số:"
 
-#: gitk:9265
 msgid "Tag name:"
 msgstr "Tên thẻ:"
 
-#: gitk:9268
 msgid "Tag message is optional"
 msgstr "Ghi chú thẻ chỉ là tùy chọn"
 
-#: gitk:9270
 msgid "Tag message:"
 msgstr "Ghi chú cho thẻ:"
 
-#: gitk:9274 gitk:9439
 msgid "Create"
 msgstr "Tạo"
 
-#: gitk:9292
 msgid "No tag name specified"
 msgstr "Chưa chỉ ra tên của thẻ"
 
-#: gitk:9296
 #, tcl-format
 msgid "Tag \"%s\" already exists"
 msgstr "Thẻ “%s” đã có sẵn rồi"
 
-#: gitk:9306
 msgid "Error creating tag:"
 msgstr "Gặp lỗi khi tạo thẻ:"
 
-#: gitk:9382
 msgid "Command:"
 msgstr "Lệnh:"
 
-#: gitk:9390
 msgid "Write"
 msgstr "Ghi"
 
-#: gitk:9408
 msgid "Error writing commit:"
 msgstr "Gặp lỗi trong quá trình ghi chuyển giao:"
 
-#: gitk:9435
 msgid "Name:"
 msgstr "Tên:"
 
-#: gitk:9458
 msgid "Please specify a name for the new branch"
 msgstr "Vui lòng chỉ định tên cho nhánh mới"
 
-#: gitk:9463
 #, tcl-format
 msgid "Branch '%s' already exists. Overwrite?"
 msgstr "Nhánh “%s” đã có từ trước rồi. Ghi đè?"
 
-#: gitk:9530
 #, tcl-format
 msgid "Commit %s is already included in branch %s -- really re-apply it?"
 msgstr ""
 "Lần chuyển giao %s đã sẵn được bao gồm trong nhánh %s -- bạn có thực sự muốn "
 "áp dụng lại nó không?"
 
-#: gitk:9535
 msgid "Cherry-picking"
 msgstr "Đang cherry-pick"
 
-#: gitk:9544
 #, tcl-format
 msgid ""
 "Cherry-pick failed because of local changes to file '%s'.\n"
@@ -1046,7 +807,6 @@
 "Cherry-pick gặp lỗi bởi vì các thay đổi nội bộ tập tin “%s”.\n"
 "Xin hãy chuyển giao, reset hay stash các thay đổi của bạn sau đó thử lại."
 
-#: gitk:9550
 msgid ""
 "Cherry-pick failed because of merge conflict.\n"
 "Do you wish to run git citool to resolve it?"
@@ -1054,22 +814,18 @@
 "Cherry-pick gặp lỗi bởi vì xung đột trong hòa trộn.\n"
 "Bạn có muốn chạy lệnh “git citool” để giải quyết vấn đề này không?"
 
-#: gitk:9566 gitk:9624
 msgid "No changes committed"
 msgstr "Không có thay đổi nào cần chuyển giao"
 
-#: gitk:9593
 #, tcl-format
 msgid "Commit %s is not included in branch %s -- really revert it?"
 msgstr ""
 "Lần chuyển giao %s không được bao gồm trong nhánh %s -- bạn có thực sự muốn "
 "“revert” nó không?"
 
-#: gitk:9598
 msgid "Reverting"
 msgstr "Đang hoàn tác"
 
-#: gitk:9606
 #, tcl-format
 msgid ""
 "Revert failed because of local changes to the following files:%s Please "
@@ -1078,7 +834,6 @@
 "Revert gặp lỗi bởi vì tập tin sau đã được thay đổi nội bộ:%s\n"
 "Xin hãy chạy lệnh “commit”, “reset” hoặc “stash” rồi thử lại."
 
-#: gitk:9610
 msgid ""
 "Revert failed because of merge conflict.\n"
 " Do you wish to run git citool to resolve it?"
@@ -1086,29 +841,23 @@
 "Revert gặp lỗi bởi vì xung đột hòa trộn.\n"
 " Bạn có muốn chạy lệnh “git citool” để phân giải nó không?"
 
-#: gitk:9653
 msgid "Confirm reset"
 msgstr "Xác nhật đặt lại"
 
-#: gitk:9655
 #, tcl-format
 msgid "Reset branch %s to %s?"
 msgstr "Đặt lại nhánh “%s” thành “%s”?"
 
-#: gitk:9657
 msgid "Reset type:"
 msgstr "Kiểu đặt lại:"
 
-#: gitk:9660
 msgid "Soft: Leave working tree and index untouched"
 msgstr "Mềm: Không động đến thư mục làm việc và bảng mục lục"
 
-#: gitk:9663
 msgid "Mixed: Leave working tree untouched, reset index"
 msgstr ""
 "Pha trộn: Không động chạm đến thư mục làm việc nhưng đặt lại bảng mục lục"
 
-#: gitk:9666
 msgid ""
 "Hard: Reset working tree and index\n"
 "(discard ALL local changes)"
@@ -1116,19 +865,15 @@
 "Hard: Đặt lại cây làm việc và mục lục\n"
 "(hủy bỏ MỌI thay đổi nội bộ)"
 
-#: gitk:9683
 msgid "Resetting"
 msgstr "Đang đặt lại"
 
-#: gitk:9743
 msgid "Checking out"
 msgstr "Đang checkout"
 
-#: gitk:9796
 msgid "Cannot delete the currently checked-out branch"
 msgstr "Không thể xóa nhánh hiện tại đang được lấy ra"
 
-#: gitk:9802
 #, tcl-format
 msgid ""
 "The commits on branch %s aren't on any other branch.\n"
@@ -1137,16 +882,13 @@
 "Các lần chuyển giao trên nhánh %s không ở trên nhánh khác.\n"
 "Thực sự muốn xóa nhánh %s?"
 
-#: gitk:9833
 #, tcl-format
 msgid "Tags and heads: %s"
 msgstr "Thẻ và Đầu: %s"
 
-#: gitk:9850
 msgid "Filter"
 msgstr "Bộ lọc"
 
-#: gitk:10146
 msgid ""
 "Error reading commit topology information; branch and preceding/following "
 "tag information will be incomplete."
@@ -1154,201 +896,152 @@
 "Gặp lỗi khi đọc thông tin hình học lần chuyển giao; thông tin nhánh và thẻ "
 "trước/sau sẽ không hoàn thiện."
 
-#: gitk:11123
 msgid "Tag"
 msgstr "Thẻ"
 
-#: gitk:11127
 msgid "Id"
 msgstr "Id"
 
-#: gitk:11210
 msgid "Gitk font chooser"
 msgstr "Hộp thoại chọn phông Gitk"
 
-#: gitk:11227
 msgid "B"
 msgstr "B"
 
-#: gitk:11230
 msgid "I"
 msgstr "I"
 
-#: gitk:11348
 msgid "Commit list display options"
 msgstr "Các tùy chọn về hiển thị danh sách lần chuyển giao"
 
-#: gitk:11351
 msgid "Maximum graph width (lines)"
 msgstr "Độ rộng biểu đồ tối đa (dòng)"
 
-#: gitk:11355
 #, no-tcl-format
 msgid "Maximum graph width (% of pane)"
 msgstr "Độ rộng đồ thị tối đa (% của bảng)"
 
-#: gitk:11358
 msgid "Show local changes"
 msgstr "Hiển thị các thay đổi nội bộ"
 
-#: gitk:11361
 msgid "Auto-select SHA1 (length)"
 msgstr "Tự chọn (độ dài) SHA1"
 
-#: gitk:11365
 msgid "Hide remote refs"
 msgstr "Ẩn tham chiếu đến máy chủ"
 
-#: gitk:11369
 msgid "Diff display options"
 msgstr "Các tùy chọn trình bày các khác biệt"
 
-#: gitk:11371
 msgid "Tab spacing"
 msgstr "Khoảng cách tab"
 
-#: gitk:11374
 msgid "Display nearby tags/heads"
 msgstr "Hiển thị các thẻ/đầu xung quanh"
 
-#: gitk:11377
 msgid "Maximum # tags/heads to show"
 msgstr "Số lượng thẻ/đầu tối đa sẽ hiển thị"
 
-#: gitk:11380
 msgid "Limit diffs to listed paths"
 msgstr "Giới hạn các khác biệt cho đường dẫn đã liệt kê"
 
-#: gitk:11383
 msgid "Support per-file encodings"
 msgstr "Hỗ trợ mã hóa mỗi-dòng"
 
-#: gitk:11389 gitk:11536
 msgid "External diff tool"
 msgstr "Công cụ so sánh từ bên ngoài"
 
-#: gitk:11390
 msgid "Choose..."
 msgstr "Chọn…"
 
-#: gitk:11395
 msgid "General options"
 msgstr "Các tùy chọn chung"
 
-#: gitk:11398
 msgid "Use themed widgets"
 msgstr "Dùng các widget chủ đề"
 
-#: gitk:11400
 msgid "(change requires restart)"
 msgstr "(để thay đổi cần khởi động lại)"
 
-#: gitk:11402
 msgid "(currently unavailable)"
 msgstr "(hiện tại không sẵn sàng)"
 
-#: gitk:11413
 msgid "Colors: press to choose"
 msgstr "Màu sắc: bấm vào nút phía dưới để chọn màu"
 
-#: gitk:11416
 msgid "Interface"
 msgstr "Giao diện"
 
-#: gitk:11417
 msgid "interface"
 msgstr "giao diện"
 
-#: gitk:11420
 msgid "Background"
 msgstr "Nền"
 
-#: gitk:11421 gitk:11451
 msgid "background"
 msgstr "nền"
 
-#: gitk:11424
 msgid "Foreground"
 msgstr "Tiền cảnh"
 
-#: gitk:11425
 msgid "foreground"
 msgstr "tiền cảnh"
 
-#: gitk:11428
 msgid "Diff: old lines"
 msgstr "So sánh: dòng cũ"
 
-#: gitk:11429
 msgid "diff old lines"
 msgstr "diff dòng cũ"
 
-#: gitk:11433
 msgid "Diff: new lines"
 msgstr "So sánh: dòng mới"
 
-#: gitk:11434
 msgid "diff new lines"
 msgstr "màu dòng mới"
 
-#: gitk:11438
 msgid "Diff: hunk header"
 msgstr "So sánh: phần đầu của đoạn"
 
-#: gitk:11440
 msgid "diff hunk header"
 msgstr "màu của phần đầu của đoạn khi so sánh"
 
-#: gitk:11444
 msgid "Marked line bg"
 msgstr "Nền dòng đánh dấu"
 
-#: gitk:11446
 msgid "marked line background"
 msgstr "nền dòng được đánh dấu"
 
-#: gitk:11450
 msgid "Select bg"
 msgstr "Màu nền"
 
-#: gitk:11459
 msgid "Fonts: press to choose"
 msgstr "Phông chữ: bấm vào các nút ở dưới để chọn"
 
-#: gitk:11461
 msgid "Main font"
 msgstr "Phông chữ chính"
 
-#: gitk:11462
 msgid "Diff display font"
 msgstr "Phông chữ dùng khi so sánh"
 
-#: gitk:11463
 msgid "User interface font"
 msgstr "Phông chữ giao diện"
 
-#: gitk:11485
 msgid "Gitk preferences"
 msgstr "Cá nhân hóa các cài đặt cho Gitk"
 
-#: gitk:11494
 msgid "General"
 msgstr "Chung"
 
-#: gitk:11495
 msgid "Colors"
 msgstr "Màu sắc"
 
-#: gitk:11496
 msgid "Fonts"
 msgstr "Phông chữ"
 
-#: gitk:11546
 #, tcl-format
 msgid "Gitk: choose color for %s"
 msgstr "Gitk: chọn màu cho %s"
 
-#: gitk:12059
 msgid ""
 "Sorry, gitk cannot run with this version of Tcl/Tk.\n"
 " Gitk requires at least Tcl/Tk 8.4."
@@ -1356,16 +1049,13 @@
 "Rất tiếc, gitk không thể chạy Tcl/Tk phiên bản này.\n"
 " Gitk cần ít nhất là Tcl/Tk 8.4."
 
-#: gitk:12269
 msgid "Cannot find a git repository here."
 msgstr "Không thể tìm thấy kho git ở đây."
 
-#: gitk:12316
 #, tcl-format
 msgid "Ambiguous argument '%s': both revision and filename"
 msgstr "Đối số “%s” chưa rõ ràng: vừa là điểm xét duyệt vừa là tên tập tin"
 
-#: gitk:12328
 msgid "Bad arguments to gitk:"
 msgstr "Đối số cho gitk không hợp lệ:"
 
diff --git a/gitk-git/po/zh_cn.po b/gitk-git/po/zh_cn.po
index 17b7f89..71a9878 100644
--- a/gitk-git/po/zh_cn.po
+++ b/gitk-git/po/zh_cn.po
@@ -2,10 +2,9 @@
 #
 # Translators:
 # YanKe <imyanke@163.com>, 2017
-
 msgid ""
 msgstr ""
-"Project-Id-Version: Git Chinese Localization Project\n"
+"Project-Id-Version: Gitk Chinese Localization Project\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2017-02-28 23:11+0800\n"
 "PO-Revision-Date: 2017-03-11 02:27+0800\n"
@@ -16,356 +15,266 @@
 "Content-Transfer-Encoding: 8bit\n"
 "Language: zh_CN\n"
 
-#: gitk:140
 msgid "Couldn't get list of unmerged files:"
 msgstr "不能获取未合并文件列表:"
 
-#: gitk:212 gitk:2403
 msgid "Color words"
 msgstr "着色显示差异"
 
-#: gitk:217 gitk:2403 gitk:8249 gitk:8282
 msgid "Markup words"
 msgstr "标记显示差异"
 
-#: gitk:324
 msgid "Error parsing revisions:"
 msgstr "解析版本错误:"
 
-#: gitk:380
 msgid "Error executing --argscmd command:"
 msgstr "运行 --argscmd命令出错"
 
-#: gitk:393
 msgid "No files selected: --merge specified but no files are unmerged."
 msgstr "没有选中文件:--指定merge参数但没有未合并的文件。"
 
-#: gitk:396
 msgid ""
 "No files selected: --merge specified but no unmerged files are within file "
 "limit."
 msgstr "没有选中文件:--指定merge参数但没有未合并的文件在文件中"
 
-#: gitk:418 gitk:566
 msgid "Error executing git log:"
 msgstr "执行git log命令出错:"
 
-#: gitk:436 gitk:582
 msgid "Reading"
 msgstr "读取中"
 
-#: gitk:496 gitk:4549
 msgid "Reading commits..."
 msgstr "提交记录读取中..."
 
-#: gitk:499 gitk:1641 gitk:4552
 msgid "No commits selected"
 msgstr "未选中任何提交"
 
-#: gitk:1449 gitk:4069 gitk:12583
 msgid "Command line"
 msgstr "命令行"
 
-#: gitk:1515
 msgid "Can't parse git log output:"
 msgstr "不能解析git log输出:"
 
-#: gitk:1744
 msgid "No commit information available"
 msgstr "无可用提交信息"
 
-#: gitk:1907 gitk:1936 gitk:4339 gitk:9789 gitk:11388 gitk:11668
 msgid "OK"
 msgstr "确定"
 
-#: gitk:1938 gitk:4341 gitk:9225 gitk:9304 gitk:9434 gitk:9520 gitk:9791
-#: gitk:11389 gitk:11669
 msgid "Cancel"
 msgstr "取消"
 
-#: gitk:2087
 msgid "&Update"
 msgstr "更新"
 
-#: gitk:2088
 msgid "&Reload"
 msgstr "重新加载"
 
-#: gitk:2089
 msgid "Reread re&ferences"
 msgstr "重新读取引用"
 
-#: gitk:2090
 msgid "&List references"
 msgstr "列出引用(分支以及tag)"
 
-#: gitk:2092
 msgid "Start git &gui"
 msgstr "启动git gui客户端"
 
-#: gitk:2094
 msgid "&Quit"
 msgstr "退出"
 
-#: gitk:2086
 msgid "&File"
 msgstr "文件"
 
-#: gitk:2098
 msgid "&Preferences"
 msgstr "偏好设置"
 
-#: gitk:2097
 msgid "&Edit"
 msgstr "编辑"
 
-#: gitk:2102
 msgid "&New view..."
 msgstr "新视图..."
 
-#: gitk:2103
 msgid "&Edit view..."
 msgstr "编辑视图..."
 
-#: gitk:2104
 msgid "&Delete view"
 msgstr "删除视图"
 
-#: gitk:2106
 msgid "&All files"
 msgstr "所有文件"
 
-#: gitk:2101
 msgid "&View"
 msgstr "视图"
 
-#: gitk:2111 gitk:2121
 msgid "&About gitk"
 msgstr "关于gitk"
 
-#: gitk:2112 gitk:2126
 msgid "&Key bindings"
 msgstr "快捷键"
 
-#: gitk:2110 gitk:2125
 msgid "&Help"
 msgstr "帮助"
 
-#: gitk:2203 gitk:8681
 msgid "SHA1 ID:"
 msgstr "SHA1 ID:"
 
-#: gitk:2247
 msgid "Row"
 msgstr "行"
 
-#: gitk:2285
 msgid "Find"
 msgstr "查找"
 
-#: gitk:2313
 msgid "commit"
 msgstr "提交"
 
-#: gitk:2317 gitk:2319 gitk:4711 gitk:4734 gitk:4758 gitk:6779 gitk:6851
-#: gitk:6936
 msgid "containing:"
 msgstr "包含:"
 
-#: gitk:2320 gitk:3550 gitk:3555 gitk:4787
 msgid "touching paths:"
 msgstr "影响路径:"
 
-#: gitk:2321 gitk:4801
 msgid "adding/removing string:"
 msgstr "增加/删除字符串:"
 
-#: gitk:2322 gitk:4803
 msgid "changing lines matching:"
 msgstr "改变行匹配:"
 
-#: gitk:2331 gitk:2333 gitk:4790
 msgid "Exact"
 msgstr "精确匹配"
 
-#: gitk:2333 gitk:4878 gitk:6747
 msgid "IgnCase"
 msgstr "忽略大小写"
 
-#: gitk:2333 gitk:4760 gitk:4876 gitk:6743
 msgid "Regexp"
 msgstr "正则"
 
-#: gitk:2335 gitk:2336 gitk:4898 gitk:4928 gitk:4935 gitk:6872 gitk:6940
 msgid "All fields"
 msgstr "所有字段"
 
-#: gitk:2336 gitk:4895 gitk:4928 gitk:6810
 msgid "Headline"
 msgstr "标题"
 
-#: gitk:2337 gitk:4895 gitk:6810 gitk:6940 gitk:7413
 msgid "Comments"
 msgstr "提交注释"
 
-#: gitk:2337 gitk:4895 gitk:4900 gitk:4935 gitk:6810 gitk:7348 gitk:8859
-#: gitk:8874
 msgid "Author"
 msgstr "作者"
 
-#: gitk:2337 gitk:4895 gitk:6810 gitk:7350
 msgid "Committer"
 msgstr "提交者"
 
-#: gitk:2371
 msgid "Search"
 msgstr "搜索"
 
-#: gitk:2379
 msgid "Diff"
 msgstr "差异"
 
-#: gitk:2381
 msgid "Old version"
 msgstr "老版本"
 
-#: gitk:2383
 msgid "New version"
 msgstr "新版本"
 
-#: gitk:2386
 msgid "Lines of context"
 msgstr "Diff上下文显示行数"
 
-#: gitk:2396
 msgid "Ignore space change"
 msgstr "忽略空格修改"
 
-#: gitk:2400 gitk:2402 gitk:7983 gitk:8235
 msgid "Line diff"
 msgstr "按行显示差异"
 
-#: gitk:2467
 msgid "Patch"
 msgstr "补丁"
 
-#: gitk:2469
 msgid "Tree"
 msgstr "树"
 
-#: gitk:2639 gitk:2660
 msgid "Diff this -> selected"
 msgstr "比较从当前提交到选中提交的差异"
 
-#: gitk:2640 gitk:2661
 msgid "Diff selected -> this"
 msgstr "比较从选中提交到当前提交的差异"
 
-#: gitk:2641 gitk:2662
 msgid "Make patch"
 msgstr "制作补丁"
 
-#: gitk:2642 gitk:9283
 msgid "Create tag"
 msgstr "创建tag"
 
-#: gitk:2643
 msgid "Copy commit summary"
 msgstr "复制提交摘要"
 
-#: gitk:2644 gitk:9414
 msgid "Write commit to file"
 msgstr "写入提交到文件"
 
-#: gitk:2645
 msgid "Create new branch"
 msgstr "创建新分支"
 
-#: gitk:2646
 msgid "Cherry-pick this commit"
 msgstr "在此提交运用补丁(cherry-pick)命令"
 
-#: gitk:2647
 msgid "Reset HEAD branch to here"
 msgstr "将分支头(HEAD)重置到此处"
 
-#: gitk:2648
 msgid "Mark this commit"
 msgstr "标记此提交"
 
-#: gitk:2649
 msgid "Return to mark"
 msgstr "返回到标记"
 
-#: gitk:2650
 msgid "Find descendant of this and mark"
 msgstr "查找本次提交的子提交并标记"
 
-#: gitk:2651
 msgid "Compare with marked commit"
 msgstr "和已标记的提交作比较"
 
-#: gitk:2652 gitk:2663
 msgid "Diff this -> marked commit"
 msgstr "比较从当前提交到已标记提交的差异"
 
-#: gitk:2653 gitk:2664
 msgid "Diff marked commit -> this"
 msgstr "比较从已标记提交到当前提交的差异"
 
-#: gitk:2654
 msgid "Revert this commit"
 msgstr "撤销(revert)此提交"
 
-#: gitk:2670
 msgid "Check out this branch"
 msgstr "检出(checkout)此分支"
 
-#: gitk:2671
 msgid "Rename this branch"
 msgstr "重命名(Rename)此分支"
 
-#: gitk:2672
 msgid "Remove this branch"
 msgstr "删除(Remove)此分支"
 
-#: gitk:2673
 msgid "Copy branch name"
 msgstr "复制分支名称"
 
-#: gitk:2680
 msgid "Highlight this too"
 msgstr "高亮此处"
 
-#: gitk:2681
 msgid "Highlight this only"
 msgstr "只高亮此处"
 
-#: gitk:2682
 msgid "External diff"
 msgstr "外部diff"
 
-#: gitk:2683
 msgid "Blame parent commit"
 msgstr "Blame父提交"
 
-#: gitk:2684
 msgid "Copy path"
 msgstr "复制路径"
 
-#: gitk:2691
 msgid "Show origin of this line"
 msgstr "显示此行原始提交"
 
-#: gitk:2692
 msgid "Run git gui blame on this line"
 msgstr "在此行运行git gui客户端的blame"
 
-#: gitk:3036
 msgid "About gitk"
 msgstr "关于gitk"
 
-#: gitk:3038
 msgid ""
 "\n"
 "Gitk - a commit viewer for git\n"
@@ -373,995 +282,792 @@
 "Copyright © 2005-2016 Paul Mackerras\n"
 "\n"
 "Use and redistribute under the terms of the GNU General Public License"
-msgstr "\nGitk — 一个git的提交查看器\n\n© 2005-2016 Paul Mackerras\n\n在GNU许可证下使用以及分发"
+msgstr ""
+"\n"
+"Gitk — 一个git的提交查看器\n"
+"\n"
+"© 2005-2016 Paul Mackerras\n"
+"\n"
+"在GNU许可证下使用以及分发"
 
-#: gitk:3046 gitk:3113 gitk:10004
 msgid "Close"
 msgstr "关闭"
 
-#: gitk:3067
 msgid "Gitk key bindings"
 msgstr "Gitk快捷键"
 
-#: gitk:3070
 msgid "Gitk key bindings:"
 msgstr "Gitk快捷键:"
 
-#: gitk:3072
 #, tcl-format
 msgid "<%s-Q>\t\tQuit"
 msgstr "<%s-Q>\t\t退出"
 
-#: gitk:3073
 #, tcl-format
 msgid "<%s-W>\t\tClose window"
 msgstr "<%s-W>\t\t关闭窗口"
 
-#: gitk:3074
 msgid "<Home>\t\tMove to first commit"
 msgstr "<Home>\t\t移动到第一次提交"
 
-#: gitk:3075
 msgid "<End>\t\tMove to last commit"
 msgstr "<End>\t\t移动到最后一次提交"
 
-#: gitk:3076
 msgid "<Up>, p, k\tMove up one commit"
 msgstr "<Up>, p, k\t移动到上一次提交"
 
-#: gitk:3077
 msgid "<Down>, n, j\tMove down one commit"
 msgstr "<Down>, n, j\t移动到下一次提交"
 
-#: gitk:3078
 msgid "<Left>, z, h\tGo back in history list"
 msgstr "<Left>, z, h\t历史列表的上一项"
 
-#: gitk:3079
 msgid "<Right>, x, l\tGo forward in history list"
 msgstr "<Right>, x, l\t历史列表的下一项"
 
-#: gitk:3080
 #, tcl-format
 msgid "<%s-n>\tGo to n-th parent of current commit in history list"
 msgstr "<%s-n>\t在历史列表中前往本次提交的第n个父提交"
 
-#: gitk:3081
 msgid "<PageUp>\tMove up one page in commit list"
 msgstr "<PageUp>\t上一页提交列表"
 
-#: gitk:3082
 msgid "<PageDown>\tMove down one page in commit list"
 msgstr "<PageDown>\t下一页提交列表"
 
-#: gitk:3083
 #, tcl-format
 msgid "<%s-Home>\tScroll to top of commit list"
 msgstr "<%s-Home>\t滚动到提交列表顶部"
 
-#: gitk:3084
 #, tcl-format
 msgid "<%s-End>\tScroll to bottom of commit list"
 msgstr "<%s-End>\t滚动到提交列表底部"
 
-#: gitk:3085
 #, tcl-format
 msgid "<%s-Up>\tScroll commit list up one line"
 msgstr "<%s-Up>\t向上滚动一行提交列表"
 
-#: gitk:3086
 #, tcl-format
 msgid "<%s-Down>\tScroll commit list down one line"
 msgstr "<%s-Down>\t向下滚动一行提交列表"
 
-#: gitk:3087
 #, tcl-format
 msgid "<%s-PageUp>\tScroll commit list up one page"
 msgstr "<%s-PageUp>\t向上滚动一页提交列表"
 
-#: gitk:3088
 #, tcl-format
 msgid "<%s-PageDown>\tScroll commit list down one page"
 msgstr "<%s-PageDown>\t向下滚动一页提交列表"
 
-#: gitk:3089
 msgid "<Shift-Up>\tFind backwards (upwards, later commits)"
 msgstr "<Shift-Up>\t向后查找(向上的,更晚的提交)"
 
-#: gitk:3090
 msgid "<Shift-Down>\tFind forwards (downwards, earlier commits)"
 msgstr "<Shift-Down>\t向前查找(向下的,更早的提交)"
 
-#: gitk:3091
 msgid "<Delete>, b\tScroll diff view up one page"
 msgstr "<Delete>, b\t向上滚动diff视图一页"
 
-#: gitk:3092
 msgid "<Backspace>\tScroll diff view up one page"
 msgstr "<Backspace>\t向上滚动diff视图一页"
 
-#: gitk:3093
 msgid "<Space>\t\tScroll diff view down one page"
 msgstr "<Space>\t\t向下滚动diff视图一页"
 
-#: gitk:3094
 msgid "u\t\tScroll diff view up 18 lines"
 msgstr "u\t\t向上滚动diff视图18行"
 
-#: gitk:3095
 msgid "d\t\tScroll diff view down 18 lines"
 msgstr "d\t\t向下滚动diff视图18行"
 
-#: gitk:3096
 #, tcl-format
 msgid "<%s-F>\t\tFind"
 msgstr "<%s-F>\t\t查找"
 
-#: gitk:3097
 #, tcl-format
 msgid "<%s-G>\t\tMove to next find hit"
 msgstr "<%s-G>\t\t移动到下一次查找命中"
 
-#: gitk:3098
 msgid "<Return>\tMove to next find hit"
 msgstr "<Return>\t\t移动到下一次查找命中"
 
-#: gitk:3099
 msgid "g\t\tGo to commit"
 msgstr "g\t\t转到提交"
 
-#: gitk:3100
 msgid "/\t\tFocus the search box"
 msgstr "/\t\t选中搜索框"
 
-#: gitk:3101
 msgid "?\t\tMove to previous find hit"
 msgstr "?\t\t移动到上一次查找命中"
 
-#: gitk:3102
 msgid "f\t\tScroll diff view to next file"
 msgstr "f\t\t滚动diff视图到下一个文件"
 
-#: gitk:3103
 #, tcl-format
 msgid "<%s-S>\t\tSearch for next hit in diff view"
 msgstr "<%s-S>\t\t在diff视图中查找下一此命中"
 
-#: gitk:3104
 #, tcl-format
 msgid "<%s-R>\t\tSearch for previous hit in diff view"
 msgstr "<%s-R>\t\t在diff视图中查找上一次命中"
 
-#: gitk:3105
 #, tcl-format
 msgid "<%s-KP+>\tIncrease font size"
 msgstr "<%s-KP+>\t增大字体大小"
 
-#: gitk:3106
 #, tcl-format
 msgid "<%s-plus>\tIncrease font size"
 msgstr "<%s-plus>\t增大字体大小"
 
-#: gitk:3107
 #, tcl-format
 msgid "<%s-KP->\tDecrease font size"
 msgstr "<%s-KP->\t减小字体大小"
 
-#: gitk:3108
 #, tcl-format
 msgid "<%s-minus>\tDecrease font size"
 msgstr "<%s-minus>\t减小字体大小"
 
-#: gitk:3109
 msgid "<F5>\t\tUpdate"
 msgstr "<F5>\t\t更新"
 
-#: gitk:3574 gitk:3583
 #, tcl-format
 msgid "Error creating temporary directory %s:"
 msgstr "创建临时目录出错%s:"
 
-#: gitk:3596
 #, tcl-format
 msgid "Error getting \"%s\" from %s:"
 msgstr "从%s获取\"%s\"出错:"
 
-#: gitk:3659
 msgid "command failed:"
 msgstr "执行命令失败:"
 
-#: gitk:3808
 msgid "No such commit"
 msgstr "无此提交"
 
-#: gitk:3822
 msgid "git gui blame: command failed:"
 msgstr "git gui blame:执行命令失败:"
 
-#: gitk:3853
 #, tcl-format
 msgid "Couldn't read merge head: %s"
 msgstr "不能读取合并头(merge head):%s"
 
-#: gitk:3861
 #, tcl-format
 msgid "Error reading index: %s"
 msgstr "读取索引出错:%s"
 
-#: gitk:3886
 #, tcl-format
 msgid "Couldn't start git blame: %s"
 msgstr "不能执行git blame:%s"
 
-#: gitk:3889 gitk:6778
 msgid "Searching"
 msgstr "搜索中"
 
-#: gitk:3921
 #, tcl-format
 msgid "Error running git blame: %s"
 msgstr "运行git blame出错:%s"
 
-#: gitk:3949
 #, tcl-format
 msgid "That line comes from commit %s,  which is not in this view"
 msgstr "此行来自提交%s,不在此视图中"
 
-#: gitk:3963
 msgid "External diff viewer failed:"
 msgstr "外部diff查看器失败:"
 
-#: gitk:4067
 msgid "All files"
 msgstr "所有文件"
 
-#: gitk:4091
 msgid "View"
 msgstr "视图"
 
-#: gitk:4094
 msgid "Gitk view definition"
 msgstr "Gitk视图定义"
 
-#: gitk:4098
 msgid "Remember this view"
 msgstr "记住此视图"
 
-#: gitk:4099
 msgid "References (space separated list):"
 msgstr "引用(空格切分的列表):"
 
-#: gitk:4100
 msgid "Branches & tags:"
 msgstr "分支和tags"
 
-#: gitk:4101
 msgid "All refs"
 msgstr "所有引用"
 
-#: gitk:4102
 msgid "All (local) branches"
 msgstr "所有(本地)分支"
 
-#: gitk:4103
 msgid "All tags"
 msgstr "所有tag"
 
-#: gitk:4104
 msgid "All remote-tracking branches"
 msgstr "所有远程跟踪分支"
 
-#: gitk:4105
 msgid "Commit Info (regular expressions):"
 msgstr "提交信息 (正则表达式):"
 
-#: gitk:4106
 msgid "Author:"
 msgstr "作者:"
 
-#: gitk:4107
 msgid "Committer:"
 msgstr "提交者:"
 
-#: gitk:4108
 msgid "Commit Message:"
 msgstr "提交信息:"
 
-#: gitk:4109
 msgid "Matches all Commit Info criteria"
 msgstr "匹配所有提交信息标准"
 
-#: gitk:4110
 msgid "Matches no Commit Info criteria"
 msgstr "匹配无提交信息标准"
 
-#: gitk:4111
 msgid "Changes to Files:"
 msgstr "文件修改列表:"
 
-#: gitk:4112
 msgid "Fixed String"
 msgstr "固定字符串"
 
-#: gitk:4113
 msgid "Regular Expression"
 msgstr "正则表达式:"
 
-#: gitk:4114
 msgid "Search string:"
 msgstr "搜索字符串:"
 
-#: gitk:4115
 msgid ""
 "Commit Dates (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 "
 "15:27:38\"):"
-msgstr "提交日期 (\"2星期之前\", \"2009-03-17 15:27:38\", \"5月 17, 2009 15:27:38\"):"
+msgstr ""
+"提交日期 (\"2星期之前\", \"2009-03-17 15:27:38\", \"5月 17, 2009 15:27:38\"):"
 
-#: gitk:4116
 msgid "Since:"
 msgstr "自:"
 
-#: gitk:4117
 msgid "Until:"
 msgstr "到:"
 
-#: gitk:4118
 msgid "Limit and/or skip a number of revisions (positive integer):"
 msgstr "限制 且/或 跳过一定数量的版本(正整数):"
 
-#: gitk:4119
 msgid "Number to show:"
 msgstr "显示数量:"
 
-#: gitk:4120
 msgid "Number to skip:"
 msgstr "跳过数量:"
 
-#: gitk:4121
 msgid "Miscellaneous options:"
 msgstr "其他选项:"
 
-#: gitk:4122
 msgid "Strictly sort by date"
 msgstr "严格按日期整理"
 
-#: gitk:4123
 msgid "Mark branch sides"
 msgstr "标记分支边界"
 
-#: gitk:4124
 msgid "Limit to first parent"
 msgstr "限制到第一个父提交"
 
-#: gitk:4125
 msgid "Simple history"
 msgstr "简易历史"
 
-#: gitk:4126
 msgid "Additional arguments to git log:"
 msgstr "git log命令的额外参数:"
 
-#: gitk:4127
 msgid "Enter files and directories to include, one per line:"
 msgstr "输入文件和文件夹来引用,每行一个:"
 
-#: gitk:4128
 msgid "Command to generate more commits to include:"
 msgstr "命令产生更多的提交来引用:"
 
-#: gitk:4252
 msgid "Gitk: edit view"
 msgstr "Gitk: 编辑视图"
 
-#: gitk:4260
 msgid "-- criteria for selecting revisions"
 msgstr "-- 用来选择版本的规则"
 
-#: gitk:4265
 msgid "View Name"
 msgstr "视图名称"
 
-#: gitk:4340
 msgid "Apply (F5)"
 msgstr "应用(F5)"
 
-#: gitk:4378
 msgid "Error in commit selection arguments:"
 msgstr "提交选择参数错误:"
 
-#: gitk:4433 gitk:4486 gitk:4948 gitk:4962 gitk:6232 gitk:12524 gitk:12525
 msgid "None"
 msgstr "无"
 
-#: gitk:5045 gitk:5050
 msgid "Descendant"
 msgstr "子提交"
 
-#: gitk:5046
 msgid "Not descendant"
 msgstr "非子提交"
 
-#: gitk:5053 gitk:5058
 msgid "Ancestor"
 msgstr "父提交"
 
-#: gitk:5054
 msgid "Not ancestor"
 msgstr "非父提交"
 
-#: gitk:5348
 msgid "Local changes checked in to index but not committed"
 msgstr "已添加到索引但未提交的修改"
 
-#: gitk:5384
 msgid "Local uncommitted changes, not checked in to index"
 msgstr "未添加到索引且未提交的修改"
 
-#: gitk:7158
 msgid "and many more"
 msgstr "更多"
 
-#: gitk:7161
 msgid "many"
 msgstr "很多"
 
-#: gitk:7352
 msgid "Tags:"
 msgstr "Tags:"
 
-#: gitk:7369 gitk:7375 gitk:8854
 msgid "Parent"
 msgstr "父节点"
 
-#: gitk:7380
 msgid "Child"
 msgstr "子节点"
 
-#: gitk:7389
 msgid "Branch"
 msgstr "分支"
 
-#: gitk:7392
 msgid "Follows"
 msgstr "之后的tag"
 
-#: gitk:7395
 msgid "Precedes"
 msgstr "之前的tag"
 
-#: gitk:7990
 #, tcl-format
 msgid "Error getting diffs: %s"
 msgstr "获取差异错误:%s"
 
-#: gitk:8679
 msgid "Goto:"
 msgstr "转到:"
 
-#: gitk:8700
 #, tcl-format
 msgid "Short SHA1 id %s is ambiguous"
 msgstr "短格式的SHA1提交号%s不明确、有歧义"
 
-#: gitk:8707
 #, tcl-format
 msgid "Revision %s is not known"
 msgstr "版本%s未知"
 
-#: gitk:8717
 #, tcl-format
 msgid "SHA1 id %s is not known"
 msgstr "提交号(SHA1 id)%s未知"
 
-#: gitk:8719
 #, tcl-format
 msgid "Revision %s is not in the current view"
 msgstr "版本%s不在当前视图中"
 
-#: gitk:8861 gitk:8876
 msgid "Date"
 msgstr "日期"
 
-#: gitk:8864
 msgid "Children"
 msgstr "子节点"
 
-#: gitk:8927
 #, tcl-format
 msgid "Reset %s branch to here"
 msgstr "重置分支%s到此处"
 
-#: gitk:8929
 msgid "Detached head: can't reset"
 msgstr "分离的头(head):不能重置(reset)"
 
-#: gitk:9034 gitk:9040
 msgid "Skipping merge commit "
 msgstr "跳过合并提交"
 
-#: gitk:9049 gitk:9054
 msgid "Error getting patch ID for "
 msgstr "获取补丁ID出错"
 
-#: gitk:9050 gitk:9055
 msgid " - stopping\n"
 msgstr " — 停止中\n"
 
-#: gitk:9060 gitk:9063 gitk:9071 gitk:9085 gitk:9094
 msgid "Commit "
 msgstr "提交"
 
-#: gitk:9064
 msgid ""
 " is the same patch as\n"
 "       "
-msgstr " 是相同的补丁(patch)\n       "
+msgstr ""
+" 是相同的补丁(patch)\n"
+"       "
 
-#: gitk:9072
 msgid ""
 " differs from\n"
 "       "
-msgstr " 差异来自\n       "
+msgstr ""
+" 差异来自\n"
+"       "
 
-#: gitk:9074
 msgid ""
 "Diff of commits:\n"
 "\n"
-msgstr "提交的差异(Diff):\n\n"
+msgstr ""
+"提交的差异(Diff):\n"
+"\n"
 
-#: gitk:9086 gitk:9095
 #, tcl-format
 msgid " has %s children - stopping\n"
 msgstr "有%s子节点 — 停止中\n"
 
-#: gitk:9114
 #, tcl-format
 msgid "Error writing commit to file: %s"
 msgstr "写入提交到文件出错:%s"
 
-#: gitk:9120
 #, tcl-format
 msgid "Error diffing commits: %s"
 msgstr "比较提交差异出错:%s"
 
-#: gitk:9166
 msgid "Top"
 msgstr "顶部"
 
-#: gitk:9167
 msgid "From"
 msgstr "从"
 
-#: gitk:9172
 msgid "To"
 msgstr "到"
 
-#: gitk:9196
 msgid "Generate patch"
 msgstr "生成补丁(patch)"
 
-#: gitk:9198
 msgid "From:"
 msgstr "从:"
 
-#: gitk:9207
 msgid "To:"
 msgstr "到:"
 
-#: gitk:9216
 msgid "Reverse"
 msgstr "反向(Reverse)"
 
-#: gitk:9218 gitk:9428
 msgid "Output file:"
 msgstr "输出文件:"
 
-#: gitk:9224
 msgid "Generate"
 msgstr "生成"
 
-#: gitk:9262
 msgid "Error creating patch:"
 msgstr "创建补丁(patch)出错:"
 
-#: gitk:9285 gitk:9416 gitk:9504
 msgid "ID:"
 msgstr "ID:"
 
-#: gitk:9294
 msgid "Tag name:"
 msgstr "Tag名称:"
 
-#: gitk:9297
 msgid "Tag message is optional"
 msgstr "Tag信息是可选的"
 
-#: gitk:9299
 msgid "Tag message:"
 msgstr "Tag信息:"
 
-#: gitk:9303 gitk:9474
 msgid "Create"
 msgstr "创建"
 
-#: gitk:9321
 msgid "No tag name specified"
 msgstr "未指定tag名称"
 
-#: gitk:9325
 #, tcl-format
 msgid "Tag \"%s\" already exists"
 msgstr "Tag\"%s\"已经存在"
 
-#: gitk:9335
 msgid "Error creating tag:"
 msgstr "创建tag出错:"
 
-#: gitk:9425
 msgid "Command:"
 msgstr "命令:"
 
-#: gitk:9433
 msgid "Write"
 msgstr "写入"
 
-#: gitk:9451
 msgid "Error writing commit:"
 msgstr "写入提交出错:"
 
-#: gitk:9473
 msgid "Create branch"
 msgstr "创建分支"
 
-#: gitk:9489
 #, tcl-format
 msgid "Rename branch %s"
 msgstr "重命名分支%s"
 
-#: gitk:9490
 msgid "Rename"
 msgstr "重命名"
 
-#: gitk:9514
 msgid "Name:"
 msgstr "名称:"
 
-#: gitk:9538
 msgid "Please specify a name for the new branch"
 msgstr "请指定新分支的名称"
 
-#: gitk:9543
 #, tcl-format
 msgid "Branch '%s' already exists. Overwrite?"
 msgstr "分支\"%s\"已经存在。覆盖它?"
 
-#: gitk:9587
 msgid "Please specify a new name for the branch"
 msgstr "请重新指定新分支的名称"
 
-#: gitk:9650
 #, tcl-format
 msgid "Commit %s is already included in branch %s -- really re-apply it?"
 msgstr "提交%s已经存在于分支%s。确定重新应用它?"
 
-#: gitk:9655
 msgid "Cherry-picking"
 msgstr "打补丁中(Cherry-picking)"
 
-#: gitk:9664
 #, tcl-format
 msgid ""
 "Cherry-pick failed because of local changes to file '%s'.\n"
 "Please commit, reset or stash your changes and try again."
-msgstr "打补丁(Cherry-pick)失败,因为本地修改了文件\"%s\"。\n请提交(commit)、重置(reset)或暂存(stash)修改后重试。"
+msgstr ""
+"打补丁(Cherry-pick)失败,因为本地修改了文件\"%s\"。\n"
+"请提交(commit)、重置(reset)或暂存(stash)修改后重试。"
 
-#: gitk:9670
 msgid ""
 "Cherry-pick failed because of merge conflict.\n"
 "Do you wish to run git citool to resolve it?"
-msgstr "打补丁(Cherry-pick)失败因为合并冲突。\n你是否希望运行git citool 来解决冲突?"
+msgstr ""
+"打补丁(Cherry-pick)失败因为合并冲突。\n"
+"你是否希望运行git citool 来解决冲突?"
 
-#: gitk:9686 gitk:9744
 msgid "No changes committed"
 msgstr "无已经提交的修改"
 
-#: gitk:9713
 #, tcl-format
 msgid "Commit %s is not included in branch %s -- really revert it?"
 msgstr "提交%s不包含在分支%s中,确认回滚(revert)它?"
 
-#: gitk:9718
 msgid "Reverting"
 msgstr "回滚中(Reverting)"
 
-#: gitk:9726
 #, tcl-format
 msgid ""
 "Revert failed because of local changes to the following files:%s Please "
 "commit, reset or stash  your changes and try again."
-msgstr "回滚(revert)失败,因为如下的本地文件修改:%s\n请提交(commit)、重置(reset)或者暂存(stash)改变后重试。"
+msgstr ""
+"回滚(revert)失败,因为如下的本地文件修改:%s\n"
+"请提交(commit)、重置(reset)或者暂存(stash)改变后重试。"
 
-#: gitk:9730
 msgid ""
 "Revert failed because of merge conflict.\n"
 " Do you wish to run git citool to resolve it?"
-msgstr "回滚(revert)失败,因为合并冲突。\n你是否希望运行git citool来解决冲突?"
+msgstr ""
+"回滚(revert)失败,因为合并冲突。\n"
+"你是否希望运行git citool来解决冲突?"
 
-#: gitk:9773
 msgid "Confirm reset"
 msgstr "确认重置(reset)"
 
-#: gitk:9775
 #, tcl-format
 msgid "Reset branch %s to %s?"
 msgstr "重置(reset)分支%s到%s?"
 
-#: gitk:9777
 msgid "Reset type:"
 msgstr "重置(reset)类型:"
 
-#: gitk:9780
 msgid "Soft: Leave working tree and index untouched"
 msgstr "软性:离开工作树,索引未改变"
 
-#: gitk:9783
 msgid "Mixed: Leave working tree untouched, reset index"
 msgstr "混合:离开工作树(未改变),索引重置"
 
-#: gitk:9786
 msgid ""
 "Hard: Reset working tree and index\n"
 "(discard ALL local changes)"
-msgstr "硬性:重置工作树和索引\n(丢弃所有的本地修改)"
+msgstr ""
+"硬性:重置工作树和索引\n"
+"(丢弃所有的本地修改)"
 
-#: gitk:9803
 msgid "Resetting"
 msgstr "重置中(Resetting)"
 
-#: gitk:9876
 #, tcl-format
 msgid "A local branch named %s exists already"
 msgstr "本地分支%s已经存在"
 
-#: gitk:9884
 msgid "Checking out"
 msgstr "检出中(Checking out)"
 
-#: gitk:9943
 msgid "Cannot delete the currently checked-out branch"
 msgstr "不能删除当前检出(checkout)分支"
 
-#: gitk:9949
 #, tcl-format
 msgid ""
 "The commits on branch %s aren't on any other branch.\n"
 "Really delete branch %s?"
-msgstr "在分支%s上的提交不在其他任何分支上。\n确认删除分支%s?"
+msgstr ""
+"在分支%s上的提交不在其他任何分支上。\n"
+"确认删除分支%s?"
 
-#: gitk:9980
 #, tcl-format
 msgid "Tags and heads: %s"
 msgstr "Tags和头指针(heads):%s"
 
-#: gitk:9997
 msgid "Filter"
 msgstr "过滤器"
 
-#: gitk:10293
 msgid ""
 "Error reading commit topology information; branch and preceding/following "
 "tag information will be incomplete."
 msgstr "读取提交拓扑信息出错;分支和之前/之后的tag信息将不能完成。"
 
-#: gitk:11270
 msgid "Tag"
 msgstr "标签(Tag)"
 
-#: gitk:11274
 msgid "Id"
 msgstr "Id"
 
-#: gitk:11357
 msgid "Gitk font chooser"
 msgstr "Gitk字体选择"
 
-#: gitk:11374
 msgid "B"
 msgstr "粗体"
 
-#: gitk:11377
 msgid "I"
 msgstr "斜体"
 
-#: gitk:11495
 msgid "Commit list display options"
 msgstr "提交列表展示选项"
 
-#: gitk:11498
 msgid "Maximum graph width (lines)"
 msgstr "最大图宽度(行数)"
 
-#: gitk:11502
 #, no-tcl-format
 msgid "Maximum graph width (% of pane)"
 msgstr "最大图宽度(%窗口百分比)"
 
-#: gitk:11505
 msgid "Show local changes"
 msgstr "显示本地修改"
 
-#: gitk:11508
 msgid "Auto-select SHA1 (length)"
 msgstr "自动选择SHA1(长度)"
 
-#: gitk:11512
 msgid "Hide remote refs"
 msgstr "隐藏远程引用"
 
-#: gitk:11516
 msgid "Diff display options"
 msgstr "差异(Diff)展示选项"
 
-#: gitk:11518
 msgid "Tab spacing"
 msgstr "制表符宽度"
 
-#: gitk:11521
 msgid "Display nearby tags/heads"
 msgstr "显示临近的tags/heads"
 
-#: gitk:11524
 msgid "Maximum # tags/heads to show"
 msgstr "最大tags/heads展示数量"
 
-#: gitk:11527
 msgid "Limit diffs to listed paths"
 msgstr "diff中列出文件限制"
 
-#: gitk:11530
 msgid "Support per-file encodings"
 msgstr "单独文件编码支持"
 
-#: gitk:11536 gitk:11683
 msgid "External diff tool"
 msgstr "外部差异(diff)工具"
 
-#: gitk:11537
 msgid "Choose..."
 msgstr "选择..."
 
-#: gitk:11542
 msgid "General options"
 msgstr "常规选项"
 
-#: gitk:11545
 msgid "Use themed widgets"
 msgstr "使用主题小部件"
 
-#: gitk:11547
 msgid "(change requires restart)"
 msgstr "(需重启生效)"
 
-#: gitk:11549
 msgid "(currently unavailable)"
 msgstr "(当前不可用)"
 
-#: gitk:11560
 msgid "Colors: press to choose"
 msgstr "颜色:点击来选择"
 
-#: gitk:11563
 msgid "Interface"
 msgstr "界面"
 
-#: gitk:11564
 msgid "interface"
 msgstr "界面"
 
-#: gitk:11567
 msgid "Background"
 msgstr "背景"
 
-#: gitk:11568 gitk:11598
 msgid "background"
 msgstr "背景"
 
-#: gitk:11571
 msgid "Foreground"
 msgstr "前景"
 
-#: gitk:11572
 msgid "foreground"
 msgstr "前景"
 
-#: gitk:11575
 msgid "Diff: old lines"
 msgstr "差异(Diff):老代码行"
 
-#: gitk:11576
 msgid "diff old lines"
 msgstr "差异(diff)老代码行"
 
-#: gitk:11580
 msgid "Diff: new lines"
 msgstr "差异(Diff):新代码行"
 
-#: gitk:11581
 msgid "diff new lines"
 msgstr "差异(diff)新代码行"
 
-#: gitk:11585
 msgid "Diff: hunk header"
 msgstr "差异(Diff):补丁片段头信息"
 
-#: gitk:11587
 msgid "diff hunk header"
 msgstr "差异(diff)补丁片段头信息"
 
-#: gitk:11591
 msgid "Marked line bg"
 msgstr "已标记代码行背景"
 
-#: gitk:11593
 msgid "marked line background"
 msgstr "已标记代码行背景"
 
-#: gitk:11597
 msgid "Select bg"
 msgstr "选择背景"
 
-#: gitk:11606
 msgid "Fonts: press to choose"
 msgstr "字体:点击来选择"
 
-#: gitk:11608
 msgid "Main font"
 msgstr "主字体"
 
-#: gitk:11609
 msgid "Diff display font"
 msgstr "差异(Diff)显示字体"
 
-#: gitk:11610
 msgid "User interface font"
 msgstr "用户界面字体"
 
-#: gitk:11632
 msgid "Gitk preferences"
 msgstr "Gitk偏好设置"
 
-#: gitk:11641
 msgid "General"
 msgstr "常规"
 
-#: gitk:11642
 msgid "Colors"
 msgstr "颜色"
 
-#: gitk:11643
 msgid "Fonts"
 msgstr "字体"
 
-#: gitk:11693
 #, tcl-format
 msgid "Gitk: choose color for %s"
 msgstr "Gitk:选择颜色用于%s"
 
-#: gitk:12206
 msgid ""
 "Sorry, gitk cannot run with this version of Tcl/Tk.\n"
 " Gitk requires at least Tcl/Tk 8.4."
-msgstr "对不起,gitk不能运行在当前版本的Tcl/Tk中。\nGitk运行需要最低版本为Tcl/Tk8.4。"
+msgstr ""
+"对不起,gitk不能运行在当前版本的Tcl/Tk中。\n"
+"Gitk运行需要最低版本为Tcl/Tk8.4。"
 
-#: gitk:12416
 msgid "Cannot find a git repository here."
 msgstr "在此位置未发现git仓库。"
 
-#: gitk:12463
 #, tcl-format
 msgid "Ambiguous argument '%s': both revision and filename"
 msgstr "不明确有歧义的参数\"%s\":版本和文件名称"
 
-#: gitk:12475
 msgid "Bad arguments to gitk:"
 msgstr "运行gitk参数错误:"
diff --git a/gpg-interface.c b/gpg-interface.c
index 7e6a152..d517425 100644
--- a/gpg-interface.c
+++ b/gpg-interface.c
@@ -974,11 +974,20 @@ const char *gpg_trust_level_to_str(enum signature_trust_level level)
 	return sigcheck_gpg_trust_level[level].display_key;
 }
 
-int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *signing_key)
+int sign_buffer(struct strbuf *buffer, struct strbuf *signature,
+		const char *signing_key, enum sign_buffer_flags flags)
 {
+	char *keyid_to_free = NULL;
+	int ret = 0;
+
 	gpg_interface_lazy_init();
 
-	return use_format->sign_buffer(buffer, signature, signing_key);
+	if ((flags & SIGN_BUFFER_USE_DEFAULT_KEY) && (!signing_key || !*signing_key))
+		signing_key = keyid_to_free = get_signing_key();
+
+	ret = use_format->sign_buffer(buffer, signature, signing_key);
+	free(keyid_to_free);
+	return ret;
 }
 
 /*
@@ -1143,21 +1152,28 @@ static int sign_buffer_ssh(struct strbuf *buffer, struct strbuf *signature,
 	return ret;
 }
 
-int parse_sign_mode(const char *arg, enum sign_mode *mode)
+int parse_sign_mode(const char *arg, enum sign_mode *mode, const char **keyid)
 {
-	if (!strcmp(arg, "abort"))
+	if (!strcmp(arg, "abort")) {
 		*mode = SIGN_ABORT;
-	else if (!strcmp(arg, "verbatim") || !strcmp(arg, "ignore"))
+	} else if (!strcmp(arg, "verbatim") || !strcmp(arg, "ignore")) {
 		*mode = SIGN_VERBATIM;
-	else if (!strcmp(arg, "warn-verbatim") || !strcmp(arg, "warn"))
+	} else if (!strcmp(arg, "warn-verbatim") || !strcmp(arg, "warn")) {
 		*mode = SIGN_WARN_VERBATIM;
-	else if (!strcmp(arg, "warn-strip"))
+	} else if (!strcmp(arg, "warn-strip")) {
 		*mode = SIGN_WARN_STRIP;
-	else if (!strcmp(arg, "strip"))
+	} else if (!strcmp(arg, "strip")) {
 		*mode = SIGN_STRIP;
-	else if (!strcmp(arg, "strip-if-invalid"))
+	} else if (!strcmp(arg, "strip-if-invalid")) {
 		*mode = SIGN_STRIP_IF_INVALID;
-	else
+	} else if (!strcmp(arg, "sign-if-invalid")) {
+		*mode = SIGN_SIGN_IF_INVALID;
+	} else if (skip_prefix(arg, "sign-if-invalid=", &arg)) {
+		*mode = SIGN_SIGN_IF_INVALID;
+		if (keyid)
+			*keyid = arg;
+	} else {
 		return -1;
+	}
 	return 0;
 }
diff --git a/gpg-interface.h b/gpg-interface.h
index 789d1ff..a365586 100644
--- a/gpg-interface.h
+++ b/gpg-interface.h
@@ -74,6 +74,15 @@ int parse_signature(const char *buf, size_t size, struct strbuf *payload, struct
  */
 size_t parse_signed_buffer(const char *buf, size_t size);
 
+/* Flags for sign_buffer(). */
+enum sign_buffer_flags {
+	/*
+	 * Use the default configured signing key as returned by `get_signing_key()`
+	 * when the provided "signing_key" is NULL or empty.
+	 */
+	SIGN_BUFFER_USE_DEFAULT_KEY = (1 << 0),
+};
+
 /*
  * Create a detached signature for the contents of "buffer" and append
  * it after "signature"; "buffer" and "signature" can be the same
@@ -81,8 +90,7 @@ size_t parse_signed_buffer(const char *buf, size_t size);
  * at the end.  Returns 0 on success, non-zero on failure.
  */
 int sign_buffer(struct strbuf *buffer, struct strbuf *signature,
-		const char *signing_key);
-
+		const char *signing_key, enum sign_buffer_flags flags);
 
 /*
  * Returns corresponding string in lowercase for a given member of
@@ -112,12 +120,15 @@ enum sign_mode {
 	SIGN_WARN_STRIP,
 	SIGN_STRIP,
 	SIGN_STRIP_IF_INVALID,
+	SIGN_SIGN_IF_INVALID,
 };
 
 /*
  * Return 0 if `arg` can be parsed into an `enum sign_mode`. Return -1
- * otherwise.
+ * otherwise. If the parsed mode is SIGN_SIGN_IF_INVALID and GPG key provided in
+ * the arguments in the form `sign-if-invalid=<keyid>`, the key-ID is parsed
+ * into `char **keyid`.
  */
-int parse_sign_mode(const char *arg, enum sign_mode *mode);
+int parse_sign_mode(const char *arg, enum sign_mode *mode, const char **keyid);
 
 #endif
diff --git a/http.c b/http.c
index 7815f14..d8d0168 100644
--- a/http.c
+++ b/http.c
@@ -22,6 +22,8 @@
 #include "object-file.h"
 #include "odb.h"
 #include "tempfile.h"
+#include "date.h"
+#include "trace2.h"
 
 static struct trace_key trace_curl = TRACE_KEY_INIT(CURL);
 static int trace_curl_data = 1;
@@ -149,6 +151,11 @@ static char *cached_accept_language;
 static char *http_ssl_backend;
 
 static int http_schannel_check_revoke = 1;
+
+static long http_retry_after = 0;
+static long http_max_retries = 0;
+static long http_max_retry_time = 300;
+
 /*
  * With the backend being set to `schannel`, setting sslCAinfo would override
  * the Certificate Store in cURL v7.60.0 and later, which is not what we want
@@ -209,7 +216,7 @@ static inline int is_hdr_continuation(const char *ptr, const size_t size)
 	return size && (*ptr == ' ' || *ptr == '\t');
 }
 
-static size_t fwrite_wwwauth(char *ptr, size_t eltsize, size_t nmemb, void *p UNUSED)
+static size_t fwrite_wwwauth(char *ptr, size_t eltsize, size_t nmemb, void *p MAYBE_UNUSED)
 {
 	size_t size = eltsize * nmemb;
 	struct strvec *values = &http_auth.wwwauth_headers;
@@ -575,6 +582,21 @@ static int http_options(const char *var, const char *value,
 		return 0;
 	}
 
+	if (!strcmp("http.retryafter", var)) {
+		http_retry_after = git_config_int(var, value, ctx->kvi);
+		return 0;
+	}
+
+	if (!strcmp("http.maxretries", var)) {
+		http_max_retries = git_config_int(var, value, ctx->kvi);
+		return 0;
+	}
+
+	if (!strcmp("http.maxretrytime", var)) {
+		http_max_retry_time = git_config_int(var, value, ctx->kvi);
+		return 0;
+	}
+
 	/* Fall back on the default ones */
 	return git_default_config(var, value, ctx, data);
 }
@@ -1422,6 +1444,10 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
 	set_long_from_env(&curl_tcp_keepintvl, "GIT_TCP_KEEPINTVL");
 	set_long_from_env(&curl_tcp_keepcnt, "GIT_TCP_KEEPCNT");
 
+	set_long_from_env(&http_retry_after, "GIT_HTTP_RETRY_AFTER");
+	set_long_from_env(&http_max_retries, "GIT_HTTP_MAX_RETRIES");
+	set_long_from_env(&http_max_retry_time, "GIT_HTTP_MAX_RETRY_TIME");
+
 	curl_default = get_curl_handle();
 }
 
@@ -1871,6 +1897,10 @@ static int handle_curl_result(struct slot_results *results)
 			}
 			return HTTP_REAUTH;
 		}
+	} else if (results->http_code == 429) {
+		trace2_data_intmax("http", the_repository, "http/429-retry-after",
+			results->retry_after);
+		return HTTP_RATE_LIMITED;
 	} else {
 		if (results->http_connectcode == 407)
 			credential_reject(the_repository, &proxy_auth);
@@ -1886,6 +1916,7 @@ int run_one_slot(struct active_request_slot *slot,
 		 struct slot_results *results)
 {
 	slot->results = results;
+
 	if (!start_active_slot(slot)) {
 		xsnprintf(curl_errorstr, sizeof(curl_errorstr),
 			  "failed to start HTTP request");
@@ -2119,10 +2150,10 @@ static void http_opt_request_remainder(CURL *curl, off_t pos)
 
 static int http_request(const char *url,
 			void *result, int target,
-			const struct http_get_options *options)
+			struct http_get_options *options)
 {
 	struct active_request_slot *slot;
-	struct slot_results results;
+	struct slot_results results = { .retry_after = -1 };
 	struct curl_slist *headers = http_copy_default_headers();
 	struct strbuf buf = STRBUF_INIT;
 	const char *accept_language;
@@ -2156,22 +2187,19 @@ static int http_request(const char *url,
 		headers = curl_slist_append(headers, accept_language);
 
 	strbuf_addstr(&buf, "Pragma:");
-	if (options && options->no_cache)
+	if (options->no_cache)
 		strbuf_addstr(&buf, " no-cache");
-	if (options && options->initial_request &&
+	if (options->initial_request &&
 	    http_follow_config == HTTP_FOLLOW_INITIAL)
 		curl_easy_setopt(slot->curl, CURLOPT_FOLLOWLOCATION, 1L);
 
 	headers = curl_slist_append(headers, buf.buf);
 
 	/* Add additional headers here */
-	if (options && options->extra_headers) {
+	if (options->extra_headers) {
 		const struct string_list_item *item;
-		if (options && options->extra_headers) {
-			for_each_string_list_item(item, options->extra_headers) {
-				headers = curl_slist_append(headers, item->string);
-			}
-		}
+		for_each_string_list_item(item, options->extra_headers)
+			headers = curl_slist_append(headers, item->string);
 	}
 
 	headers = http_append_auth_header(&http_auth, headers);
@@ -2183,7 +2211,18 @@ static int http_request(const char *url,
 
 	ret = run_one_slot(slot, &results);
 
-	if (options && options->content_type) {
+#ifdef GIT_CURL_HAVE_CURLINFO_RETRY_AFTER
+	if (ret == HTTP_RATE_LIMITED) {
+		curl_off_t retry_after;
+		if (curl_easy_getinfo(slot->curl, CURLINFO_RETRY_AFTER,
+				      &retry_after) == CURLE_OK && retry_after > 0)
+			results.retry_after = (long)retry_after;
+	}
+#endif
+
+	options->retry_after = results.retry_after;
+
+	if (options->content_type) {
 		struct strbuf raw = STRBUF_INIT;
 		curlinfo_strbuf(slot->curl, CURLINFO_CONTENT_TYPE, &raw);
 		extract_content_type(&raw, options->content_type,
@@ -2191,7 +2230,7 @@ static int http_request(const char *url,
 		strbuf_release(&raw);
 	}
 
-	if (options && options->effective_url)
+	if (options->effective_url)
 		curlinfo_strbuf(slot->curl, CURLINFO_EFFECTIVE_URL,
 				options->effective_url);
 
@@ -2253,22 +2292,66 @@ static int update_url_from_redirect(struct strbuf *base,
 	return 1;
 }
 
-static int http_request_reauth(const char *url,
+/*
+ * Compute the retry delay for an HTTP 429 response.
+ * Returns a negative value if configuration is invalid (delay exceeds
+ * http.maxRetryTime), otherwise returns the delay in seconds (>= 0).
+ */
+static long handle_rate_limit_retry(long slot_retry_after)
+{
+	/* Use the slot-specific retry_after value or configured default */
+	if (slot_retry_after >= 0) {
+		/* Check if retry delay exceeds maximum allowed */
+		if (slot_retry_after > http_max_retry_time) {
+			error(_("response requested a delay greater than http.maxRetryTime (%ld > %ld seconds)"),
+			      slot_retry_after, http_max_retry_time);
+			trace2_data_string("http", the_repository,
+				  "http/429-error", "exceeds-max-retry-time");
+			trace2_data_intmax("http", the_repository,
+				  "http/429-requested-delay", slot_retry_after);
+			return -1;
+		}
+		return slot_retry_after;
+	} else {
+		/* No Retry-After header provided, use configured default */
+		if (http_retry_after > http_max_retry_time) {
+			error(_("configured http.retryAfter exceeds http.maxRetryTime (%ld > %ld seconds)"),
+			      http_retry_after, http_max_retry_time);
+			trace2_data_string("http", the_repository,
+					"http/429-error", "config-exceeds-max-retry-time");
+			return -1;
+		}
+		trace2_data_string("http", the_repository,
+			"http/429-retry-source", "config-default");
+		return http_retry_after;
+	}
+}
+
+static int http_request_recoverable(const char *url,
 			       void *result, int target,
 			       struct http_get_options *options)
 {
+	static struct http_get_options empty_opts;
 	int i = 3;
 	int ret;
+	int rate_limit_retries = http_max_retries;
+
+	if (!options)
+		options = &empty_opts;
 
 	if (always_auth_proactively())
 		credential_fill(the_repository, &http_auth, 1);
 
 	ret = http_request(url, result, target, options);
 
-	if (ret != HTTP_OK && ret != HTTP_REAUTH)
+	if (ret != HTTP_OK && ret != HTTP_REAUTH && ret != HTTP_RATE_LIMITED)
 		return ret;
 
-	if (options && options->effective_url && options->base_url) {
+	/* If retries are disabled and we got a 429, fail immediately */
+	if (ret == HTTP_RATE_LIMITED && !http_max_retries)
+		return HTTP_ERROR;
+
+	if (options->effective_url && options->base_url) {
 		if (update_url_from_redirect(options->base_url,
 					     url, options->effective_url)) {
 			credential_from_url(&http_auth, options->base_url->buf);
@@ -2276,7 +2359,9 @@ static int http_request_reauth(const char *url,
 		}
 	}
 
-	while (ret == HTTP_REAUTH && --i) {
+	while ((ret == HTTP_REAUTH && --i) ||
+	       (ret == HTTP_RATE_LIMITED && --rate_limit_retries)) {
+		long retry_delay = -1;
 		/*
 		 * The previous request may have put cruft into our output stream; we
 		 * should clear it out before making our next request.
@@ -2301,11 +2386,28 @@ static int http_request_reauth(const char *url,
 		default:
 			BUG("Unknown http_request target");
 		}
+		if (ret == HTTP_RATE_LIMITED) {
+			retry_delay = handle_rate_limit_retry(options->retry_after);
+			if (retry_delay < 0)
+				return HTTP_ERROR;
 
-		credential_fill(the_repository, &http_auth, 1);
+			if (retry_delay > 0) {
+				warning(_("rate limited, waiting %ld seconds before retry"), retry_delay);
+				trace2_data_intmax("http", the_repository,
+						   "http/retry-sleep-seconds", retry_delay);
+				sleep(retry_delay);
+			}
+		} else if (ret == HTTP_REAUTH) {
+			credential_fill(the_repository, &http_auth, 1);
+		}
 
 		ret = http_request(url, result, target, options);
 	}
+	if (ret == HTTP_RATE_LIMITED) {
+		trace2_data_string("http", the_repository,
+				   "http/429-error", "retries-exhausted");
+		return HTTP_RATE_LIMITED;
+	}
 	return ret;
 }
 
@@ -2313,7 +2415,7 @@ int http_get_strbuf(const char *url,
 		    struct strbuf *result,
 		    struct http_get_options *options)
 {
-	return http_request_reauth(url, result, HTTP_REQUEST_STRBUF, options);
+	return http_request_recoverable(url, result, HTTP_REQUEST_STRBUF, options);
 }
 
 /*
@@ -2337,7 +2439,7 @@ int http_get_file(const char *url, const char *filename,
 		goto cleanup;
 	}
 
-	ret = http_request_reauth(url, result, HTTP_REQUEST_FILE, options);
+	ret = http_request_recoverable(url, result, HTTP_REQUEST_FILE, options);
 	fclose(result);
 
 	if (ret == HTTP_OK && finalize_object_file(the_repository, tmpfile.buf, filename))
@@ -2543,8 +2645,9 @@ int finish_http_pack_request(struct http_pack_request *preq)
 void http_install_packfile(struct packed_git *p,
 			   struct packfile_list *list_to_remove_from)
 {
+	struct odb_source_files *files = odb_source_files_downcast(the_repository->objects->sources);
 	packfile_list_remove(list_to_remove_from, p);
-	packfile_store_add_pack(the_repository->objects->sources->packfiles, p);
+	packfile_store_add_pack(files->packed, p);
 }
 
 struct http_pack_request *new_http_pack_request(
diff --git a/http.h b/http.h
index f9d4593..f9ee888 100644
--- a/http.h
+++ b/http.h
@@ -20,6 +20,7 @@ struct slot_results {
 	long http_code;
 	long auth_avail;
 	long http_connectcode;
+	long retry_after;
 };
 
 struct active_request_slot {
@@ -157,6 +158,13 @@ struct http_get_options {
 	 * request has completed.
 	 */
 	struct string_list *extra_headers;
+
+	/*
+	 * After a request completes, contains the Retry-After delay in seconds
+	 * if the server returned HTTP 429 with a Retry-After header (requires
+	 * libcurl 7.66.0 or later), or -1 if no such header was present.
+	 */
+	long retry_after;
 };
 
 /* Return values for http_get_*() */
@@ -167,6 +175,7 @@ struct http_get_options {
 #define HTTP_REAUTH	4
 #define HTTP_NOAUTH	5
 #define HTTP_NOMATCHPUBLICKEY	6
+#define HTTP_RATE_LIMITED	7
 
 /*
  * Requests a URL and stores the result in a strbuf.
diff --git a/imap-send.c b/imap-send.c
index 26dda7f..af02c6a 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -219,8 +219,14 @@ static int ssl_socket_connect(struct imap_socket *sock UNUSED,
 
 #else
 
-static int host_matches(const char *host, const char *pattern)
+static int host_matches(const char *host, const ASN1_STRING *asn1_str)
 {
+	const char *pattern = (const char *)ASN1_STRING_get0_data(asn1_str);
+
+	/* embedded NUL characters may open a security hole */
+	if (memchr(pattern, '\0', ASN1_STRING_length(asn1_str)))
+	    return 0;
+
 	if (pattern[0] == '*' && pattern[1] == '.') {
 		pattern += 2;
 		if (!(host = strchr(host, '.')))
@@ -233,9 +239,13 @@ static int host_matches(const char *host, const char *pattern)
 
 static int verify_hostname(X509 *cert, const char *hostname)
 {
-	int len;
+#if (OPENSSL_VERSION_NUMBER >= 0x40000000L)
+	const X509_NAME *subj;
+#else
 	X509_NAME *subj;
-	char cname[1000];
+#endif
+	const X509_NAME_ENTRY *cname_entry;
+	const ASN1_STRING *cname;
 	int i, found;
 	STACK_OF(GENERAL_NAME) *subj_alt_names;
 
@@ -244,10 +254,11 @@ static int verify_hostname(X509 *cert, const char *hostname)
 	if ((subj_alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL))) {
 		int num_subj_alt_names = sk_GENERAL_NAME_num(subj_alt_names);
 		for (i = 0; !found && i < num_subj_alt_names; i++) {
+			int ntype;
 			GENERAL_NAME *subj_alt_name = sk_GENERAL_NAME_value(subj_alt_names, i);
-			if (subj_alt_name->type == GEN_DNS &&
-			    strlen((const char *)subj_alt_name->d.ia5->data) == (size_t)subj_alt_name->d.ia5->length &&
-			    host_matches(hostname, (const char *)(subj_alt_name->d.ia5->data)))
+			ASN1_STRING *subj_alt_str = GENERAL_NAME_get0_value(subj_alt_name, &ntype);
+
+			if (ntype == GEN_DNS && host_matches(hostname, subj_alt_str))
 				found = 1;
 		}
 		sk_GENERAL_NAME_pop_free(subj_alt_names, GENERAL_NAME_free);
@@ -258,12 +269,14 @@ static int verify_hostname(X509 *cert, const char *hostname)
 	/* try the common name */
 	if (!(subj = X509_get_subject_name(cert)))
 		return error("cannot get certificate subject");
-	if ((len = X509_NAME_get_text_by_NID(subj, NID_commonName, cname, sizeof(cname))) < 0)
+	if ((i = X509_NAME_get_index_by_NID(subj, NID_commonName, -1)) < 0 ||
+	    (cname_entry = X509_NAME_get_entry(subj, i)) == NULL ||
+	    (cname = X509_NAME_ENTRY_get_data(cname_entry)) == NULL)
 		return error("cannot get certificate common name");
-	if (strlen(cname) == (size_t)len && host_matches(hostname, cname))
+	if (host_matches(hostname, cname))
 		return 0;
 	return error("certificate owner '%s' does not match hostname '%s'",
-		     cname, hostname);
+		     ASN1_STRING_get0_data(cname), hostname);
 }
 
 static int ssl_socket_connect(struct imap_socket *sock,
diff --git a/list-objects-filter-options.c b/list-objects-filter-options.c
index 7f3e7b8..cef67e5 100644
--- a/list-objects-filter-options.c
+++ b/list-objects-filter-options.c
@@ -125,9 +125,9 @@ int gently_parse_list_objects_filter(
 static const char *RESERVED_NON_WS = "~`!@#$^&*()[]{}\\;'\",<>?";
 
 static int has_reserved_character(
-	struct strbuf *sub_spec, struct strbuf *errbuf)
+	const char *sub_spec, struct strbuf *errbuf)
 {
-	const char *c = sub_spec->buf;
+	const char *c = sub_spec;
 	while (*c) {
 		if (*c <= ' ' || strchr(RESERVED_NON_WS, *c)) {
 			strbuf_addf(
@@ -144,7 +144,7 @@ static int has_reserved_character(
 
 static int parse_combine_subfilter(
 	struct list_objects_filter_options *filter_options,
-	struct strbuf *subspec,
+	const char *subspec,
 	struct strbuf *errbuf)
 {
 	size_t new_index = filter_options->sub_nr;
@@ -155,7 +155,7 @@ static int parse_combine_subfilter(
 		      filter_options->sub_alloc);
 	list_objects_filter_init(&filter_options->sub[new_index]);
 
-	decoded = url_percent_decode(subspec->buf);
+	decoded = url_percent_decode(subspec);
 
 	result = has_reserved_character(subspec, errbuf);
 	if (result)
@@ -182,34 +182,34 @@ static int parse_combine_filter(
 	const char *arg,
 	struct strbuf *errbuf)
 {
-	struct strbuf **subspecs = strbuf_split_str(arg, '+', 0);
-	size_t sub;
+	const char *p = arg;
+	struct strbuf sub = STRBUF_INIT;
 	int result = 0;
 
-	if (!subspecs[0]) {
+	if (!*p) {
 		strbuf_addstr(errbuf, _("expected something after combine:"));
 		result = 1;
 		goto cleanup;
 	}
 
-	for (sub = 0; subspecs[sub] && !result; sub++) {
-		if (subspecs[sub + 1]) {
-			/*
-			 * This is not the last subspec. Remove trailing "+" so
-			 * we can parse it.
-			 */
-			size_t last = subspecs[sub]->len - 1;
-			assert(subspecs[sub]->buf[last] == '+');
-			strbuf_remove(subspecs[sub], last, 1);
-		}
-		result = parse_combine_subfilter(
-			filter_options, subspecs[sub], errbuf);
+	while (*p && !result) {
+		const char *end = strchrnul(p, '+');
+
+		strbuf_reset(&sub);
+		strbuf_add(&sub, p, end - p);
+
+		if (sub.len)
+			result = parse_combine_subfilter(filter_options, sub.buf, errbuf);
+
+		if (!*end)
+			break;
+		p = end + 1;
 	}
+	strbuf_release(&sub);
 
 	filter_options->choice = LOFC_COMBINE;
 
 cleanup:
-	strbuf_list_free(subspecs);
 	if (result)
 		list_objects_filter_release(filter_options);
 	return result;
diff --git a/loose.c b/loose.c
index 56cf64b..07333be 100644
--- a/loose.c
+++ b/loose.c
@@ -3,6 +3,7 @@
 #include "path.h"
 #include "object-file.h"
 #include "odb.h"
+#include "odb/source-files.h"
 #include "hex.h"
 #include "repository.h"
 #include "wrapper.h"
@@ -49,27 +50,29 @@ static int insert_loose_map(struct odb_source *source,
 			    const struct object_id *oid,
 			    const struct object_id *compat_oid)
 {
-	struct loose_object_map *map = source->loose->map;
+	struct odb_source_files *files = odb_source_files_downcast(source);
+	struct loose_object_map *map = files->loose->map;
 	int inserted = 0;
 
 	inserted |= insert_oid_pair(map->to_compat, oid, compat_oid);
 	inserted |= insert_oid_pair(map->to_storage, compat_oid, oid);
 	if (inserted)
-		oidtree_insert(source->loose->cache, compat_oid);
+		oidtree_insert(files->loose->cache, compat_oid);
 
 	return inserted;
 }
 
 static int load_one_loose_object_map(struct repository *repo, struct odb_source *source)
 {
+	struct odb_source_files *files = odb_source_files_downcast(source);
 	struct strbuf buf = STRBUF_INIT, path = STRBUF_INIT;
 	FILE *fp;
 
-	if (!source->loose->map)
-		loose_object_map_init(&source->loose->map);
-	if (!source->loose->cache) {
-		ALLOC_ARRAY(source->loose->cache, 1);
-		oidtree_init(source->loose->cache);
+	if (!files->loose->map)
+		loose_object_map_init(&files->loose->map);
+	if (!files->loose->cache) {
+		ALLOC_ARRAY(files->loose->cache, 1);
+		oidtree_init(files->loose->cache);
 	}
 
 	insert_loose_map(source, repo->hash_algo->empty_tree, repo->compat_hash_algo->empty_tree);
@@ -125,7 +128,8 @@ int repo_read_loose_object_map(struct repository *repo)
 
 int repo_write_loose_object_map(struct repository *repo)
 {
-	kh_oid_map_t *map = repo->objects->sources->loose->map->to_compat;
+	struct odb_source_files *files = odb_source_files_downcast(repo->objects->sources);
+	kh_oid_map_t *map = files->loose->map->to_compat;
 	struct lock_file lock;
 	int fd;
 	khiter_t iter;
@@ -231,7 +235,8 @@ int repo_loose_object_map_oid(struct repository *repo,
 	khiter_t pos;
 
 	for (source = repo->objects->sources; source; source = source->next) {
-		struct loose_object_map *loose_map = source->loose->map;
+		struct odb_source_files *files = odb_source_files_downcast(source);
+		struct loose_object_map *loose_map = files->loose->map;
 		if (!loose_map)
 			continue;
 		map = (to == repo->compat_hash_algo) ?
diff --git a/mailinfo.c b/mailinfo.c
index a2f06db..13949ff 100644
--- a/mailinfo.c
+++ b/mailinfo.c
@@ -470,7 +470,7 @@ static int convert_to_utf8(struct mailinfo *mi,
 		return error("cannot convert from %s to %s",
 			     charset, mi->metainfo_charset);
 	}
-	strbuf_attach(line, out, out_len, out_len);
+	strbuf_attach(line, out, out_len, out_len + 1);
 	return 0;
 }
 
diff --git a/meson.build b/meson.build
index 1b9be3d..8309942 100644
--- a/meson.build
+++ b/meson.build
@@ -271,6 +271,13 @@
 
 compiler = meson.get_compiler('c')
 
+compat_sources = [
+  'compat/nonblock.c',
+  'compat/obstack.c',
+  'compat/open.c',
+  'compat/terminal.c',
+]
+
 libgit_sources = [
   'abspath.c',
   'add-interactive.c',
@@ -304,10 +311,6 @@
   'commit.c',
   'common-exit.c',
   'common-init.c',
-  'compat/nonblock.c',
-  'compat/obstack.c',
-  'compat/open.c',
-  'compat/terminal.c',
   'compiler-tricks/not-constant.c',
   'config.c',
   'connect.c',
@@ -399,6 +402,8 @@
   'object-name.c',
   'object.c',
   'odb.c',
+  'odb/source.c',
+  'odb/source-files.c',
   'odb/streaming.c',
   'oid-array.c',
   'oidmap.c',
@@ -554,7 +559,7 @@
 libgit_sources += custom_target(
   input: 'command-list.txt',
   output: 'command-list.h',
-  command: [shell, meson.current_source_dir() + '/generate-cmdlist.sh', meson.current_source_dir(), '@OUTPUT@'],
+  command: [shell, meson.current_source_dir() + '/tools/generate-cmdlist.sh', meson.current_source_dir(), '@OUTPUT@'],
   env: script_environment,
 )
 
@@ -723,10 +728,10 @@
 builtin_sources += custom_target(
   output: 'config-list.h',
   depfile: 'config-list.h.d',
-  depend_files: [ 'generate-configlist.sh' ],
+  depend_files: [ 'tools/generate-configlist.sh' ],
   command: [
     shell,
-    meson.current_source_dir() / 'generate-configlist.sh',
+    meson.current_source_dir() / 'tools/generate-configlist.sh',
     meson.current_source_dir(),
     '@OUTPUT@',
     '@DEPFILE@',
@@ -739,7 +744,7 @@
   output: 'hook-list.h',
   command: [
     shell,
-    meson.current_source_dir() + '/generate-hooklist.sh',
+    meson.current_source_dir() + '/tools/generate-hooklist.sh',
     meson.current_source_dir(),
     '@OUTPUT@',
   ],
@@ -1173,7 +1178,7 @@
 
 if not has_poll_h and not has_sys_poll_h
   libgit_c_args += '-DNO_POLL'
-  libgit_sources += 'compat/poll/poll.c'
+  compat_sources += 'compat/poll/poll.c'
   libgit_include_directories += 'compat/poll'
 endif
 
@@ -1189,7 +1194,7 @@
 # implementation to threat things like drive prefixes specially.
 if host_machine.system() == 'windows' or not compiler.has_header('libgen.h')
   libgit_c_args += '-DNO_LIBGEN_H'
-  libgit_sources += 'compat/basename.c'
+  compat_sources += 'compat/basename.c'
 endif
 
 if compiler.has_header('paths.h')
@@ -1219,7 +1224,7 @@
   foreach symbol : ['inet_ntop', 'inet_pton', 'hstrerror']
     if not compiler.has_function(symbol, dependencies: networking_dependencies)
       libgit_c_args += '-DNO_' + symbol.to_upper()
-      libgit_sources += 'compat/' + symbol + '.c'
+      compat_sources += 'compat/' + symbol + '.c'
     endif
   endforeach
 endif
@@ -1261,18 +1266,18 @@
 endif
 
 if host_machine.system() == 'darwin'
-  libgit_sources += 'compat/precompose_utf8.c'
+  compat_sources += 'compat/precompose_utf8.c'
   libgit_c_args += '-DPRECOMPOSE_UNICODE'
   libgit_c_args += '-DPROTECT_HFS_DEFAULT'
 endif
 
 # Configure general compatibility wrappers.
 if host_machine.system() == 'cygwin'
-  libgit_sources += [
+  compat_sources += [
     'compat/win32/path-utils.c',
   ]
 elif host_machine.system() == 'windows'
-  libgit_sources += [
+  compat_sources += [
     'compat/winansi.c',
     'compat/win32/dirent.c',
     'compat/win32/flush.c',
@@ -1299,20 +1304,20 @@
   libgit_include_directories += 'compat/win32'
   if compiler.get_id() == 'msvc'
     libgit_include_directories += 'compat/vcbuild/include'
-    libgit_sources += 'compat/msvc.c'
+    compat_sources += 'compat/msvc.c'
   else
-    libgit_sources += 'compat/mingw.c'
+    compat_sources += 'compat/mingw.c'
   endif
 endif
 
 if host_machine.system() == 'linux'
-  libgit_sources += 'compat/linux/procinfo.c'
+  compat_sources += 'compat/linux/procinfo.c'
 elif host_machine.system() == 'windows'
-  libgit_sources += 'compat/win32/trace2_win32_process_info.c'
+  compat_sources += 'compat/win32/trace2_win32_process_info.c'
 elif host_machine.system() == 'darwin'
-  libgit_sources += 'compat/darwin/procinfo.c'
+  compat_sources += 'compat/darwin/procinfo.c'
 else
-  libgit_sources += 'compat/stub/procinfo.c'
+  compat_sources += 'compat/stub/procinfo.c'
 endif
 
 if host_machine.system() == 'cygwin' or host_machine.system() == 'windows'
@@ -1325,13 +1330,13 @@
 
 # Configure the simple-ipc subsystem required fro the fsmonitor.
 if host_machine.system() == 'windows'
-  libgit_sources += [
+  compat_sources += [
     'compat/simple-ipc/ipc-shared.c',
     'compat/simple-ipc/ipc-win32.c',
   ]
   libgit_c_args += '-DSUPPORTS_SIMPLE_IPC'
 else
-  libgit_sources += [
+  compat_sources += [
     'compat/simple-ipc/ipc-shared.c',
     'compat/simple-ipc/ipc-unix-socket.c',
   ]
@@ -1349,7 +1354,7 @@
   libgit_c_args += '-DHAVE_FSMONITOR_DAEMON_BACKEND'
   libgit_c_args += '-DHAVE_FSMONITOR_OS_SETTINGS'
 
-  libgit_sources += [
+  compat_sources += [
     'compat/fsmonitor/fsm-health-' + fsmonitor_backend + '.c',
     'compat/fsmonitor/fsm-ipc-' + fsmonitor_backend + '.c',
     'compat/fsmonitor/fsm-listen-' + fsmonitor_backend + '.c',
@@ -1365,7 +1370,7 @@
 
   if compiler.get_define('REG_ENHANCED', prefix: '#include <regex.h>') != ''
     libgit_c_args += '-DUSE_ENHANCED_BASIC_REGULAR_EXPRESSIONS'
-    libgit_sources += 'compat/regcomp_enhanced.c'
+    compat_sources += 'compat/regcomp_enhanced.c'
   endif
 elif not get_option('regex').enabled()
   libgit_c_args += [
@@ -1374,7 +1379,7 @@
     '-DNO_MBSUPPORT',
   ]
   build_options_config.set('NO_REGEX', '1')
-  libgit_sources += 'compat/regex/regex.c'
+  compat_sources += 'compat/regex/regex.c'
   libgit_include_directories += 'compat/regex'
 else
     error('Native regex support requested but not found')
@@ -1424,6 +1429,7 @@
   'initgroups' : [],
   'strtoumax' : ['strtoumax.c', 'strtoimax.c'],
   'pread' : ['pread.c'],
+  'writev' : ['writev.c'],
 }
 
 if host_machine.system() == 'windows'
@@ -1436,9 +1442,9 @@
     'getpagesize' : [],
   }
 
-  if get_option('b_sanitize').contains('address')
+  if get_option('b_sanitize').contains('address') or get_option('b_sanitize').contains('leak')
     libgit_c_args += '-DNO_MMAP'
-    libgit_sources += 'compat/mmap.c'
+    compat_sources += 'compat/mmap.c'
   else
     checkfuncs += { 'mmap': ['mmap.c'] }
   endif
@@ -1448,7 +1454,7 @@
   if not compiler.has_function(func)
     libgit_c_args += '-DNO_' + func.to_upper()
     foreach impl : impls
-      libgit_sources += 'compat/' + impl
+      compat_sources += 'compat/' + impl
     endforeach
   endif
 endforeach
@@ -1459,13 +1465,13 @@
 
 if not compiler.has_function('strdup')
   libgit_c_args += '-DOVERRIDE_STRDUP'
-  libgit_sources += 'compat/strdup.c'
+  compat_sources += 'compat/strdup.c'
 endif
 
 if not compiler.has_function('qsort')
   libgit_c_args += '-DINTERNAL_QSORT'
 endif
-libgit_sources += 'compat/qsort_s.c'
+compat_sources += 'compat/qsort_s.c'
 
 if compiler.has_function('getdelim')
   libgit_c_args += '-DHAVE_GETDELIM'
@@ -1521,7 +1527,7 @@
   }
 ''', name: 'fread reads directories').returncode() == 0
   libgit_c_args += '-DFREAD_READS_DIRECTORIES'
-  libgit_sources += 'compat/fopen.c'
+  compat_sources += 'compat/fopen.c'
 endif
 
 if not meson.is_cross_build() and fs.exists('/dev/tty')
@@ -1755,14 +1761,23 @@
 endif
 
 libgit = declare_dependency(
-  link_with: static_library('git',
-    sources: libgit_sources,
-    c_args: libgit_c_args + [
-      '-DGIT_VERSION_H="' + version_def_h.full_path() + '"',
-    ],
-    dependencies: libgit_dependencies,
-    include_directories: libgit_include_directories,
-  ),
+  link_with: [
+    static_library('compat',
+      sources: compat_sources,
+      c_args: libgit_c_args,
+      dependencies: libgit_dependencies,
+      include_directories: libgit_include_directories,
+    ),
+    static_library('git',
+      sources: libgit_sources,
+      c_args: libgit_c_args + [
+        '-DGIT_VERSION_H="' + version_def_h.full_path() + '"',
+      ],
+      c_pch: 'tools/precompiled.h',
+      dependencies: libgit_dependencies,
+      include_directories: libgit_include_directories,
+    ),
+  ],
   compile_args: libgit_c_args,
   dependencies: libgit_dependencies,
   include_directories: libgit_include_directories,
@@ -1819,6 +1834,7 @@
 
 git_builtin = executable('git',
   sources: builtin_sources + 'git.c',
+  c_pch: 'tools/precompiled.h',
   dependencies: [libgit_commonmain],
   install: true,
   install_dir: git_exec_path,
@@ -1969,7 +1985,7 @@
     output: fs.stem(script),
     command: [
       shell,
-      meson.project_source_root() / 'generate-script.sh',
+      meson.project_source_root() / 'tools/generate-script.sh',
       '@INPUT@',
       '@OUTPUT@',
       meson.project_build_root() / 'GIT-BUILD-OPTIONS',
@@ -2018,7 +2034,7 @@
 
   generate_perl_command = [
     shell,
-    meson.project_source_root() / 'generate-perl.sh',
+    meson.project_source_root() / 'tools/generate-perl.sh',
     meson.project_build_root() / 'GIT-BUILD-OPTIONS',
     git_version_file.full_path(),
     perl_header,
@@ -2067,7 +2083,7 @@
       output: fs.stem(script),
       command: [
         shell,
-        meson.project_source_root() / 'generate-python.sh',
+        meson.project_source_root() / 'tools/generate-python.sh',
         meson.project_build_root() / 'GIT-BUILD-OPTIONS',
         '@INPUT@',
         '@OUTPUT@',
@@ -2159,6 +2175,7 @@
 endif
 
 subdir('contrib')
+subdir('tools')
 
 # Note that the target is intentionally configured after including the
 # 'contrib' directory, as some tool there also have their own manpages.
diff --git a/midx-write.c b/midx-write.c
index 6485cb6..0ff2e45 100644
--- a/midx-write.c
+++ b/midx-write.c
@@ -36,10 +36,13 @@ extern int cmp_idx_or_pack_name(const char *idx_or_pack_name,
 
 static size_t write_midx_header(const struct git_hash_algo *hash_algo,
 				struct hashfile *f, unsigned char num_chunks,
-				uint32_t num_packs)
+				uint32_t num_packs, int version)
 {
+	if (version != MIDX_VERSION_V1 && version != MIDX_VERSION_V2)
+		BUG("unexpected MIDX version: %d", version);
+
 	hashwrite_be32(f, MIDX_SIGNATURE);
-	hashwrite_u8(f, MIDX_VERSION);
+	hashwrite_u8(f, version);
 	hashwrite_u8(f, oid_version(hash_algo));
 	hashwrite_u8(f, num_chunks);
 	hashwrite_u8(f, 0); /* unused */
@@ -105,15 +108,29 @@ struct write_midx_context {
 
 	uint32_t preferred_pack_idx;
 
+	int version; /* must be MIDX_VERSION_V1 or _V2 */
+
 	int incremental;
 	uint32_t num_multi_pack_indexes_before;
 
+	struct multi_pack_index *compact_from;
+	struct multi_pack_index *compact_to;
+	int compact;
+
 	struct string_list *to_include;
 
 	struct repository *repo;
 	struct odb_source *source;
 };
 
+static uint32_t midx_pack_perm(struct write_midx_context *ctx,
+			       uint32_t orig_pack_int_id)
+{
+	if (ctx->compact)
+		orig_pack_int_id -= ctx->compact_from->num_packs_in_base;
+	return ctx->pack_perm[orig_pack_int_id];
+}
+
 static int should_include_pack(const struct write_midx_context *ctx,
 			       const char *file_name)
 {
@@ -257,18 +274,14 @@ static void midx_fanout_sort(struct midx_fanout *fanout)
 	QSORT(fanout->entries, fanout->nr, midx_oid_compare);
 }
 
-static void midx_fanout_add_midx_fanout(struct midx_fanout *fanout,
-					struct multi_pack_index *m,
-					uint32_t cur_fanout,
-					uint32_t preferred_pack)
+static void midx_fanout_add_midx_fanout_1(struct midx_fanout *fanout,
+					  struct multi_pack_index *m,
+					  uint32_t cur_fanout,
+					  uint32_t preferred_pack)
 {
 	uint32_t start = m->num_objects_in_base, end;
 	uint32_t cur_object;
 
-	if (m->base_midx)
-		midx_fanout_add_midx_fanout(fanout, m->base_midx, cur_fanout,
-					    preferred_pack);
-
 	if (cur_fanout)
 		start += ntohl(m->chunk_oid_fanout[cur_fanout - 1]);
 	end = m->num_objects_in_base + ntohl(m->chunk_oid_fanout[cur_fanout]);
@@ -292,6 +305,17 @@ static void midx_fanout_add_midx_fanout(struct midx_fanout *fanout,
 	}
 }
 
+static void midx_fanout_add_midx_fanout(struct midx_fanout *fanout,
+					struct multi_pack_index *m,
+					uint32_t cur_fanout,
+					uint32_t preferred_pack)
+{
+	if (m->base_midx)
+		midx_fanout_add_midx_fanout(fanout, m->base_midx, cur_fanout,
+					    preferred_pack);
+	midx_fanout_add_midx_fanout_1(fanout, m, cur_fanout, preferred_pack);
+}
+
 static void midx_fanout_add_pack_fanout(struct midx_fanout *fanout,
 					struct pack_info *info,
 					uint32_t cur_pack,
@@ -317,6 +341,45 @@ static void midx_fanout_add_pack_fanout(struct midx_fanout *fanout,
 	}
 }
 
+static void midx_fanout_add(struct midx_fanout *fanout,
+			    struct write_midx_context *ctx,
+			    uint32_t start_pack,
+			    uint32_t cur_fanout)
+{
+	uint32_t cur_pack;
+
+	if (ctx->m && !ctx->incremental)
+		midx_fanout_add_midx_fanout(fanout, ctx->m, cur_fanout,
+					    ctx->preferred_pack_idx);
+
+	for (cur_pack = start_pack; cur_pack < ctx->nr; cur_pack++) {
+		int preferred = cur_pack == ctx->preferred_pack_idx;
+		midx_fanout_add_pack_fanout(fanout, ctx->info, cur_pack,
+					    preferred, cur_fanout);
+	}
+
+	if (ctx->preferred_pack_idx != NO_PREFERRED_PACK &&
+	    ctx->preferred_pack_idx < start_pack)
+		midx_fanout_add_pack_fanout(fanout, ctx->info,
+					    ctx->preferred_pack_idx, 1,
+					    cur_fanout);
+}
+
+static void midx_fanout_add_compact(struct midx_fanout *fanout,
+				    struct write_midx_context *ctx,
+				    uint32_t cur_fanout)
+{
+	struct multi_pack_index *m = ctx->compact_to;
+
+	ASSERT(ctx->compact);
+
+	while (m && m != ctx->compact_from->base_midx) {
+		midx_fanout_add_midx_fanout_1(fanout, m, cur_fanout,
+					      NO_PREFERRED_PACK);
+		m = m->base_midx;
+	}
+}
+
 /*
  * It is possible to artificially get into a state where there are many
  * duplicate copies of objects. That can create high memory pressure if
@@ -335,6 +398,9 @@ static void compute_sorted_entries(struct write_midx_context *ctx,
 	size_t alloc_objects, total_objects = 0;
 	struct midx_fanout fanout = { 0 };
 
+	if (ctx->compact)
+		ASSERT(!start_pack);
+
 	for (cur_pack = start_pack; cur_pack < ctx->nr; cur_pack++)
 		total_objects = st_add(total_objects,
 				       ctx->info[cur_pack].p->num_objects);
@@ -353,23 +419,10 @@ static void compute_sorted_entries(struct write_midx_context *ctx,
 	for (cur_fanout = 0; cur_fanout < 256; cur_fanout++) {
 		fanout.nr = 0;
 
-		if (ctx->m && !ctx->incremental)
-			midx_fanout_add_midx_fanout(&fanout, ctx->m, cur_fanout,
-						    ctx->preferred_pack_idx);
-
-		for (cur_pack = start_pack; cur_pack < ctx->nr; cur_pack++) {
-			int preferred = cur_pack == ctx->preferred_pack_idx;
-			midx_fanout_add_pack_fanout(&fanout,
-						    ctx->info, cur_pack,
-						    preferred, cur_fanout);
-		}
-
-		if (ctx->preferred_pack_idx != NO_PREFERRED_PACK &&
-		    ctx->preferred_pack_idx < start_pack)
-			midx_fanout_add_pack_fanout(&fanout, ctx->info,
-						    ctx->preferred_pack_idx, 1,
-						    cur_fanout);
-
+		if (ctx->compact)
+			midx_fanout_add_compact(&fanout, ctx, cur_fanout);
+		else
+			midx_fanout_add(&fanout, ctx, start_pack, cur_fanout);
 		midx_fanout_sort(&fanout);
 
 		/*
@@ -410,7 +463,9 @@ static int write_midx_pack_names(struct hashfile *f, void *data)
 		if (ctx->info[i].expired)
 			continue;
 
-		if (i && strcmp(ctx->info[i].pack_name, ctx->info[i - 1].pack_name) <= 0)
+		if (ctx->version == MIDX_VERSION_V1 &&
+		    i && strcmp(ctx->info[i].pack_name,
+				ctx->info[i - 1].pack_name) <= 0)
 			BUG("incorrect pack-file order: %s before %s",
 			    ctx->info[i - 1].pack_name,
 			    ctx->info[i].pack_name);
@@ -514,12 +569,12 @@ static int write_midx_object_offsets(struct hashfile *f,
 	for (i = 0; i < ctx->entries_nr; i++) {
 		struct pack_midx_entry *obj = list++;
 
-		if (ctx->pack_perm[obj->pack_int_id] == PACK_EXPIRED)
+		if (midx_pack_perm(ctx, obj->pack_int_id) == PACK_EXPIRED)
 			BUG("object %s is in an expired pack with int-id %d",
 			    oid_to_hex(&obj->oid),
 			    obj->pack_int_id);
 
-		hashwrite_be32(f, ctx->pack_perm[obj->pack_int_id]);
+		hashwrite_be32(f, midx_pack_perm(ctx, obj->pack_int_id));
 
 		if (ctx->large_offsets_needed && obj->offset >> 31)
 			hashwrite_be32(f, MIDX_LARGE_OFFSET_NEEDED | nr_large_offset++);
@@ -620,8 +675,8 @@ static uint32_t *midx_pack_order(struct write_midx_context *ctx)
 	for (i = 0; i < ctx->entries_nr; i++) {
 		struct pack_midx_entry *e = &ctx->entries[i];
 		data[i].nr = i;
-		data[i].pack = ctx->pack_perm[e->pack_int_id];
-		if (!e->preferred)
+		data[i].pack = midx_pack_perm(ctx, e->pack_int_id);
+		if (!e->preferred || ctx->compact)
 			data[i].pack |= (1U << 31);
 		data[i].offset = e->offset;
 	}
@@ -630,14 +685,14 @@ static uint32_t *midx_pack_order(struct write_midx_context *ctx)
 
 	for (i = 0; i < ctx->entries_nr; i++) {
 		struct pack_midx_entry *e = &ctx->entries[data[i].nr];
-		struct pack_info *pack = &ctx->info[ctx->pack_perm[e->pack_int_id]];
+		struct pack_info *pack = &ctx->info[midx_pack_perm(ctx, e->pack_int_id)];
 		if (pack->bitmap_pos == BITMAP_POS_UNKNOWN)
 			pack->bitmap_pos = i + base_objects;
 		pack->bitmap_nr++;
 		pack_order[i] = data[i].nr;
 	}
 	for (i = 0; i < ctx->nr; i++) {
-		struct pack_info *pack = &ctx->info[ctx->pack_perm[i]];
+		struct pack_info *pack = &ctx->info[i];
 		if (pack->bitmap_pos == BITMAP_POS_UNKNOWN)
 			pack->bitmap_pos = 0;
 	}
@@ -691,7 +746,7 @@ static void prepare_midx_packing_data(struct packing_data *pdata,
 		struct object_entry *to = packlist_alloc(pdata, &from->oid);
 
 		oe_set_in_pack(pdata, to,
-			       ctx->info[ctx->pack_perm[from->pack_int_id]].p);
+			       ctx->info[midx_pack_perm(ctx, from->pack_int_id)].p);
 	}
 
 	trace2_region_leave("midx", "prepare_midx_packing_data", ctx->repo);
@@ -900,6 +955,21 @@ static int write_midx_bitmap(struct write_midx_context *ctx,
 	return ret;
 }
 
+static int fill_pack_from_midx(struct pack_info *info,
+			       struct multi_pack_index *m,
+			       uint32_t pack_int_id)
+{
+	if (prepare_midx_pack(m, pack_int_id))
+		return error(_("could not load pack %d"), pack_int_id);
+
+	fill_pack_info(info,
+		       m->packs[pack_int_id - m->num_packs_in_base],
+		       m->pack_names[pack_int_id - m->num_packs_in_base],
+		       pack_int_id);
+
+	return 0;
+}
+
 static int fill_packs_from_midx(struct write_midx_context *ctx)
 {
 	struct multi_pack_index *m;
@@ -907,19 +977,88 @@ static int fill_packs_from_midx(struct write_midx_context *ctx)
 	for (m = ctx->m; m; m = m->base_midx) {
 		uint32_t i;
 
-		for (i = 0; i < m->num_packs; i++) {
-			if (prepare_midx_pack(m, m->num_packs_in_base + i))
-				return error(_("could not load pack"));
-
+		for (i = m->num_packs_in_base;
+		     i < m->num_packs_in_base + m->num_packs; i++) {
 			ALLOC_GROW(ctx->info, ctx->nr + 1, ctx->alloc);
-			fill_pack_info(&ctx->info[ctx->nr++], m->packs[i],
-				       m->pack_names[i],
-				       m->num_packs_in_base + i);
+
+			if (fill_pack_from_midx(&ctx->info[ctx->nr], m, i) < 0)
+				return -1;
+
+			ctx->nr++;
 		}
 	}
 	return 0;
 }
 
+static uint32_t compactible_packs_between(const struct multi_pack_index *from,
+					  const struct multi_pack_index *to)
+{
+	uint32_t nr;
+
+	ASSERT(from && to);
+
+	if (unsigned_add_overflows(to->num_packs, to->num_packs_in_base))
+		die(_("too many packs, unable to compact"));
+
+	nr = to->num_packs + to->num_packs_in_base;
+	if (nr < from->num_packs_in_base)
+		BUG("unexpected number of packs in base during compaction: "
+		    "%"PRIu32" < %"PRIu32, nr, from->num_packs_in_base);
+
+	return nr - from->num_packs_in_base;
+}
+
+static int fill_packs_from_midx_range(struct write_midx_context *ctx,
+				      int bitmap_order)
+{
+	struct multi_pack_index *m = ctx->compact_to;
+	uint32_t packs_nr;
+
+	ASSERT(ctx->compact && !ctx->nr);
+	ASSERT(ctx->compact_from);
+	ASSERT(ctx->compact_to);
+
+	packs_nr = compactible_packs_between(ctx->compact_from,
+					     ctx->compact_to);
+
+	ALLOC_GROW(ctx->info, packs_nr, ctx->alloc);
+
+	while (m != ctx->compact_from->base_midx) {
+		uint32_t pack_int_id, preferred_pack_id;
+		uint32_t i;
+
+		if (bitmap_order) {
+			if (midx_preferred_pack(m, &preferred_pack_id) < 0)
+				die(_("could not determine preferred pack"));
+		} else {
+			preferred_pack_id = m->num_packs_in_base;
+		}
+
+		pack_int_id = m->num_packs_in_base - ctx->compact_from->num_packs_in_base;
+
+		if (fill_pack_from_midx(&ctx->info[pack_int_id++], m,
+					preferred_pack_id) < 0)
+			return -1;
+
+		for (i = m->num_packs_in_base;
+		     i < m->num_packs_in_base + m->num_packs; i++) {
+			if (preferred_pack_id == i)
+				continue;
+
+			if (fill_pack_from_midx(&ctx->info[pack_int_id++], m,
+						i) < 0)
+				return -1;
+		}
+
+		ctx->nr += m->num_packs;
+		m = m->base_midx;
+	}
+
+	ASSERT(ctx->nr == packs_nr);
+
+	return 0;
+}
+
 static struct {
 	const char *non_split;
 	const char *split;
@@ -946,7 +1085,7 @@ static int link_midx_to_chain(struct multi_pack_index *m)
 	}
 
 	for (i = 0; i < ARRAY_SIZE(midx_exts); i++) {
-		const unsigned char *hash = get_midx_checksum(m);
+		const unsigned char *hash = midx_get_checksum_hash(m);
 
 		get_midx_filename_ext(m->source, &from,
 				      hash, midx_exts[i].non_split);
@@ -1026,6 +1165,12 @@ static bool midx_needs_update(struct multi_pack_index *midx, struct write_midx_c
 		goto out;
 
 	/*
+	 * If the version differs, we need to update.
+	 */
+	if (midx->version != ctx->version)
+		goto out;
+
+	/*
 	 * Ignore incremental updates for now. The assumption is that any
 	 * incremental update would be either empty (in which case we will bail
 	 * out later) or it would actually cover at least one new pack.
@@ -1033,6 +1178,9 @@ static bool midx_needs_update(struct multi_pack_index *midx, struct write_midx_c
 	if (ctx->incremental)
 		goto out;
 
+	if (ctx->compact)
+		goto out; /* Compaction always requires an update. */
+
 	/*
 	 * Otherwise, we need to verify that the packs covered by the existing
 	 * MIDX match the packs that we already have. The logic to do so is way
@@ -1078,14 +1226,31 @@ static bool midx_needs_update(struct multi_pack_index *midx, struct write_midx_c
 	return needed;
 }
 
-static int write_midx_internal(struct odb_source *source,
-			       struct string_list *packs_to_include,
-			       struct string_list *packs_to_drop,
-			       const char *preferred_pack_name,
-			       const char *refs_snapshot,
-			       unsigned flags)
+static int midx_hashcmp(const struct multi_pack_index *a,
+			const struct multi_pack_index *b,
+			const struct git_hash_algo *algop)
 {
-	struct repository *r = source->odb->repo;
+	return hashcmp(midx_get_checksum_hash(a), midx_get_checksum_hash(b),
+		       algop);
+}
+
+struct write_midx_opts {
+	struct odb_source *source; /* non-optional */
+
+	struct string_list *packs_to_include;
+	struct string_list *packs_to_drop;
+
+	struct multi_pack_index *compact_from;
+	struct multi_pack_index *compact_to;
+
+	const char *preferred_pack_name;
+	const char *refs_snapshot;
+	unsigned flags;
+};
+
+static int write_midx_internal(struct write_midx_opts *opts)
+{
+	struct repository *r = opts->source->odb->repo;
 	struct strbuf midx_name = STRBUF_INIT;
 	unsigned char midx_hash[GIT_MAX_RAWSZ];
 	uint32_t start_pack;
@@ -1094,6 +1259,7 @@ static int write_midx_internal(struct odb_source *source,
 	struct tempfile *incr;
 	struct write_midx_context ctx = {
 		.preferred_pack_idx = NO_PREFERRED_PACK,
+		.version = MIDX_VERSION_V2,
 	 };
 	struct multi_pack_index *midx_to_free = NULL;
 	int bitmapped_packs_concat_len = 0;
@@ -1101,27 +1267,45 @@ static int write_midx_internal(struct odb_source *source,
 	int dropped_packs = 0;
 	int result = -1;
 	const char **keep_hashes = NULL;
+	size_t keep_hashes_nr = 0;
 	struct chunkfile *cf;
 
 	trace2_region_enter("midx", "write_midx_internal", r);
 
 	ctx.repo = r;
-	ctx.source = source;
+	ctx.source = opts->source;
 
-	ctx.incremental = !!(flags & MIDX_WRITE_INCREMENTAL);
+	repo_config_get_int(ctx.repo, "midx.version", &ctx.version);
+	if (ctx.version != MIDX_VERSION_V1 && ctx.version != MIDX_VERSION_V2)
+		die(_("unknown MIDX version: %d"), ctx.version);
+
+	ctx.incremental = !!(opts->flags & MIDX_WRITE_INCREMENTAL);
+	ctx.compact = !!(opts->flags & MIDX_WRITE_COMPACT);
+
+	if (ctx.compact) {
+		if (ctx.version != MIDX_VERSION_V2)
+			die(_("cannot perform MIDX compaction with v1 format"));
+		if (!opts->compact_from)
+			BUG("expected non-NULL 'from' MIDX during compaction");
+		if (!opts->compact_to)
+			BUG("expected non-NULL 'to' MIDX during compaction");
+
+		ctx.compact_from = opts->compact_from;
+		ctx.compact_to = opts->compact_to;
+	}
 
 	if (ctx.incremental)
 		strbuf_addf(&midx_name,
 			    "%s/pack/multi-pack-index.d/tmp_midx_XXXXXX",
-			    source->path);
+			    opts->source->path);
 	else
-		get_midx_filename(source, &midx_name);
+		get_midx_filename(opts->source, &midx_name);
 	if (safe_create_leading_directories(r, midx_name.buf))
 		die_errno(_("unable to create leading directories of %s"),
 			  midx_name.buf);
 
-	if (!packs_to_include || ctx.incremental) {
-		struct multi_pack_index *m = get_multi_pack_index(source);
+	if (!opts->packs_to_include || ctx.incremental) {
+		struct multi_pack_index *m = get_multi_pack_index(opts->source);
 		if (m && !midx_checksum_valid(m)) {
 			warning(_("ignoring existing multi-pack-index; checksum mismatch"));
 			m = NULL;
@@ -1136,11 +1320,18 @@ static int write_midx_internal(struct odb_source *source,
 			 */
 			if (ctx.incremental)
 				ctx.base_midx = m;
-			else if (!packs_to_include)
+			if (!opts->packs_to_include)
 				ctx.m = m;
 		}
 	}
 
+	/*
+	 * If compacting MIDX layer(s) in the range [from, to], then the
+	 * compacted MIDX will share the same base MIDX as 'from'.
+	 */
+	if (ctx.compact)
+		ctx.base_midx = ctx.compact_from->base_midx;
+
 	ctx.nr = 0;
 	ctx.alloc = ctx.m ? ctx.m->num_packs + ctx.m->num_packs_in_base : 16;
 	ctx.info = NULL;
@@ -1149,34 +1340,42 @@ static int write_midx_internal(struct odb_source *source,
 	if (ctx.incremental) {
 		struct multi_pack_index *m = ctx.base_midx;
 		while (m) {
-			if (flags & MIDX_WRITE_BITMAP && load_midx_revindex(m)) {
+			if (opts->flags & MIDX_WRITE_BITMAP && load_midx_revindex(m)) {
 				error(_("could not load reverse index for MIDX %s"),
-				      hash_to_hex_algop(get_midx_checksum(m),
-							m->source->odb->repo->hash_algo));
+				      midx_get_checksum_hex(m));
 				goto cleanup;
 			}
 			ctx.num_multi_pack_indexes_before++;
 			m = m->base_midx;
 		}
-	} else if (ctx.m && fill_packs_from_midx(&ctx)) {
+	} else if (ctx.m && !ctx.compact && fill_packs_from_midx(&ctx)) {
 		goto cleanup;
 	}
 
 	start_pack = ctx.nr;
 
 	ctx.pack_paths_checked = 0;
-	if (flags & MIDX_PROGRESS)
+	if (opts->flags & MIDX_PROGRESS)
 		ctx.progress = start_delayed_progress(r,
 						      _("Adding packfiles to multi-pack-index"), 0);
 	else
 		ctx.progress = NULL;
 
-	ctx.to_include = packs_to_include;
+	if (ctx.compact) {
+		int bitmap_order = 0;
+		if (opts->preferred_pack_name)
+			bitmap_order |= 1;
+		else if (opts->flags & (MIDX_WRITE_REV_INDEX | MIDX_WRITE_BITMAP))
+			bitmap_order |= 1;
 
-	for_each_file_in_pack_dir(source->path, add_pack_to_midx, &ctx);
+		fill_packs_from_midx_range(&ctx, bitmap_order);
+	} else {
+		ctx.to_include = opts->packs_to_include;
+		for_each_file_in_pack_dir(opts->source->path, add_pack_to_midx, &ctx);
+	}
 	stop_progress(&ctx.progress);
 
-	if (!packs_to_drop) {
+	if (!opts->packs_to_drop) {
 		/*
 		 * If there is no MIDX then either it doesn't exist, or we're
 		 * doing a geometric repack. Try to load it from the source to
@@ -1189,7 +1388,7 @@ static int write_midx_internal(struct odb_source *source,
 		if (midx && !midx_needs_update(midx, &ctx)) {
 			struct bitmap_index *bitmap_git;
 			int bitmap_exists;
-			int want_bitmap = flags & MIDX_WRITE_BITMAP;
+			int want_bitmap = opts->flags & MIDX_WRITE_BITMAP;
 
 			bitmap_git = prepare_midx_bitmap_git(midx);
 			bitmap_exists = bitmap_git && bitmap_is_midx(bitmap_git);
@@ -1201,7 +1400,7 @@ static int write_midx_internal(struct odb_source *source,
 				 * corresponding bitmap (or one wasn't requested).
 				 */
 				if (!want_bitmap)
-					clear_midx_files_ext(source, "bitmap", NULL);
+					clear_midx_files_ext(ctx.source, "bitmap", NULL);
 				result = 0;
 				goto cleanup;
 			}
@@ -1216,11 +1415,11 @@ static int write_midx_internal(struct odb_source *source,
 		goto cleanup; /* nothing to do */
 	}
 
-	if (preferred_pack_name) {
+	if (opts->preferred_pack_name) {
 		ctx.preferred_pack_idx = NO_PREFERRED_PACK;
 
 		for (size_t i = 0; i < ctx.nr; i++) {
-			if (!cmp_idx_or_pack_name(preferred_pack_name,
+			if (!cmp_idx_or_pack_name(opts->preferred_pack_name,
 						  ctx.info[i].pack_name)) {
 				ctx.preferred_pack_idx = i;
 				break;
@@ -1229,9 +1428,9 @@ static int write_midx_internal(struct odb_source *source,
 
 		if (ctx.preferred_pack_idx == NO_PREFERRED_PACK)
 			warning(_("unknown preferred pack: '%s'"),
-				preferred_pack_name);
+				opts->preferred_pack_name);
 	} else if (ctx.nr &&
-		   (flags & (MIDX_WRITE_REV_INDEX | MIDX_WRITE_BITMAP))) {
+		   (opts->flags & (MIDX_WRITE_REV_INDEX | MIDX_WRITE_BITMAP))) {
 		struct packed_git *oldest = ctx.info[0].p;
 		ctx.preferred_pack_idx = 0;
 
@@ -1242,7 +1441,7 @@ static int write_midx_internal(struct odb_source *source,
 		 */
 		open_pack_index(oldest);
 
-		if (packs_to_drop && packs_to_drop->nr)
+		if (opts->packs_to_drop && opts->packs_to_drop->nr)
 			BUG("cannot write a MIDX bitmap during expiration");
 
 		/*
@@ -1302,22 +1501,30 @@ static int write_midx_internal(struct odb_source *source,
 			ctx.large_offsets_needed = 1;
 	}
 
-	QSORT(ctx.info, ctx.nr, pack_info_compare);
+	if (ctx.compact) {
+		if (ctx.version != MIDX_VERSION_V2)
+			BUG("performing MIDX compaction with v1 MIDX");
+	} else {
+		QSORT(ctx.info, ctx.nr, pack_info_compare);
+	}
 
-	if (packs_to_drop && packs_to_drop->nr) {
+	if (opts->packs_to_drop && opts->packs_to_drop->nr) {
 		size_t drop_index = 0;
 		int missing_drops = 0;
 
-		for (size_t i = 0; i < ctx.nr && drop_index < packs_to_drop->nr; i++) {
+		ASSERT(!ctx.compact);
+
+		for (size_t i = 0;
+		     i < ctx.nr && drop_index < opts->packs_to_drop->nr; i++) {
 			int cmp = strcmp(ctx.info[i].pack_name,
-					 packs_to_drop->items[drop_index].string);
+					 opts->packs_to_drop->items[drop_index].string);
 
 			if (!cmp) {
 				drop_index++;
 				ctx.info[i].expired = 1;
 			} else if (cmp > 0) {
 				error(_("did not see pack-file %s to drop"),
-				      packs_to_drop->items[drop_index].string);
+				      opts->packs_to_drop->items[drop_index].string);
 				drop_index++;
 				missing_drops++;
 				i--;
@@ -1338,12 +1545,20 @@ static int write_midx_internal(struct odb_source *source,
 	 */
 	ALLOC_ARRAY(ctx.pack_perm, ctx.nr);
 	for (size_t i = 0; i < ctx.nr; i++) {
+		uint32_t from = ctx.info[i].orig_pack_int_id;
+		uint32_t to;
+
 		if (ctx.info[i].expired) {
+			to = PACK_EXPIRED;
 			dropped_packs++;
-			ctx.pack_perm[ctx.info[i].orig_pack_int_id] = PACK_EXPIRED;
 		} else {
-			ctx.pack_perm[ctx.info[i].orig_pack_int_id] = i - dropped_packs;
+			to = i - dropped_packs;
 		}
+
+		if (ctx.compact)
+			from -= ctx.compact_from->num_packs_in_base;
+
+		ctx.pack_perm[from] = to;
 	}
 
 	for (size_t i = 0; i < ctx.nr; i++) {
@@ -1354,16 +1569,16 @@ static int write_midx_internal(struct odb_source *source,
 	}
 
 	/* Check that the preferred pack wasn't expired (if given). */
-	if (preferred_pack_name) {
-		struct pack_info *preferred = bsearch(preferred_pack_name,
+	if (opts->preferred_pack_name) {
+		struct pack_info *preferred = bsearch(opts->preferred_pack_name,
 						      ctx.info, ctx.nr,
 						      sizeof(*ctx.info),
 						      idx_or_pack_name_cmp);
 		if (preferred) {
-			uint32_t perm = ctx.pack_perm[preferred->orig_pack_int_id];
+			uint32_t perm = midx_pack_perm(&ctx, preferred->orig_pack_int_id);
 			if (perm == PACK_EXPIRED)
 				warning(_("preferred pack '%s' is expired"),
-					preferred_pack_name);
+					opts->preferred_pack_name);
 		}
 	}
 
@@ -1377,15 +1592,15 @@ static int write_midx_internal(struct odb_source *source,
 	}
 
 	if (!ctx.entries_nr) {
-		if (flags & MIDX_WRITE_BITMAP)
+		if (opts->flags & MIDX_WRITE_BITMAP)
 			warning(_("refusing to write multi-pack .bitmap without any objects"));
-		flags &= ~(MIDX_WRITE_REV_INDEX | MIDX_WRITE_BITMAP);
+		opts->flags &= ~(MIDX_WRITE_REV_INDEX | MIDX_WRITE_BITMAP);
 	}
 
 	if (ctx.incremental) {
 		struct strbuf lock_name = STRBUF_INIT;
 
-		get_midx_chain_filename(source, &lock_name);
+		get_midx_chain_filename(opts->source, &lock_name);
 		hold_lock_file_for_update(&lk, lock_name.buf, LOCK_DIE_ON_ERROR);
 		strbuf_release(&lock_name);
 
@@ -1428,7 +1643,7 @@ static int write_midx_internal(struct odb_source *source,
 				MIDX_CHUNK_LARGE_OFFSET_WIDTH),
 			write_midx_large_offsets);
 
-	if (flags & (MIDX_WRITE_REV_INDEX | MIDX_WRITE_BITMAP)) {
+	if (opts->flags & (MIDX_WRITE_REV_INDEX | MIDX_WRITE_BITMAP)) {
 		ctx.pack_order = midx_pack_order(&ctx);
 		add_chunk(cf, MIDX_CHUNKID_REVINDEX,
 			  st_mult(ctx.entries_nr, sizeof(uint32_t)),
@@ -1439,18 +1654,18 @@ static int write_midx_internal(struct odb_source *source,
 	}
 
 	write_midx_header(r->hash_algo, f, get_num_chunks(cf),
-			  ctx.nr - dropped_packs);
+			  ctx.nr - dropped_packs, ctx.version);
 	write_chunkfile(cf, &ctx);
 
 	finalize_hashfile(f, midx_hash, FSYNC_COMPONENT_PACK_METADATA,
 			  CSUM_FSYNC | CSUM_HASH_IN_STREAM);
 	free_chunkfile(cf);
 
-	if (flags & MIDX_WRITE_REV_INDEX &&
+	if (opts->flags & MIDX_WRITE_REV_INDEX &&
 	    git_env_bool("GIT_TEST_MIDX_WRITE_REV", 0))
 		write_midx_reverse_index(&ctx, midx_hash);
 
-	if (flags & MIDX_WRITE_BITMAP) {
+	if (opts->flags & MIDX_WRITE_BITMAP) {
 		struct packing_data pdata;
 		struct commit_stack commits = COMMIT_STACK_INIT;
 
@@ -1459,7 +1674,7 @@ static int write_midx_internal(struct odb_source *source,
 
 		prepare_midx_packing_data(&pdata, &ctx);
 
-		find_commits_for_midx_bitmap(&commits, refs_snapshot, &ctx);
+		find_commits_for_midx_bitmap(&commits, opts->refs_snapshot, &ctx);
 
 		/*
 		 * The previous steps translated the information from
@@ -1470,8 +1685,8 @@ static int write_midx_internal(struct odb_source *source,
 		FREE_AND_NULL(ctx.entries);
 		ctx.entries_nr = 0;
 
-		if (write_midx_bitmap(&ctx, midx_hash, &pdata,
-				      commits.items, commits.nr, flags) < 0) {
+		if (write_midx_bitmap(&ctx, midx_hash, &pdata, commits.items,
+				      commits.nr, opts->flags) < 0) {
 			error(_("could not write multi-pack bitmap"));
 			clear_packing_data(&pdata);
 			commit_stack_clear(&commits);
@@ -1489,7 +1704,24 @@ static int write_midx_internal(struct odb_source *source,
 	if (ctx.num_multi_pack_indexes_before == UINT32_MAX)
 		die(_("too many multi-pack-indexes"));
 
-	CALLOC_ARRAY(keep_hashes, ctx.num_multi_pack_indexes_before + 1);
+	if (ctx.compact) {
+		struct multi_pack_index *m;
+
+		/*
+		 * Keep all MIDX layers excluding those in the range [from, to].
+		 */
+		for (m = ctx.base_midx; m; m = m->base_midx)
+			keep_hashes_nr++;
+		for (m = ctx.m;
+		     m && midx_hashcmp(m, ctx.compact_to, r->hash_algo);
+		     m = m->base_midx)
+			keep_hashes_nr++;
+
+		keep_hashes_nr++; /* include the compacted layer */
+	} else {
+		keep_hashes_nr = ctx.num_multi_pack_indexes_before + 1;
+	}
+	CALLOC_ARRAY(keep_hashes, keep_hashes_nr);
 
 	if (ctx.incremental) {
 		FILE *chainf = fdopen_lock_file(&lk, "w");
@@ -1504,7 +1736,7 @@ static int write_midx_internal(struct odb_source *source,
 		if (link_midx_to_chain(ctx.base_midx) < 0)
 			goto cleanup;
 
-		get_split_midx_filename_ext(source, &final_midx_name,
+		get_split_midx_filename_ext(opts->source, &final_midx_name,
 					    midx_hash, MIDX_EXT_MIDX);
 
 		if (rename_tempfile(&incr, final_midx_name.buf) < 0) {
@@ -1514,18 +1746,47 @@ static int write_midx_internal(struct odb_source *source,
 
 		strbuf_release(&final_midx_name);
 
-		keep_hashes[ctx.num_multi_pack_indexes_before] =
-			xstrdup(hash_to_hex_algop(midx_hash, r->hash_algo));
+		if (ctx.compact) {
+			struct multi_pack_index *m;
+			uint32_t num_layers_before_from = 0;
+			uint32_t i;
 
-		for (uint32_t i = 0; i < ctx.num_multi_pack_indexes_before; i++) {
-			uint32_t j = ctx.num_multi_pack_indexes_before - i - 1;
+			for (m = ctx.base_midx; m; m = m->base_midx)
+				num_layers_before_from++;
 
-			keep_hashes[j] = xstrdup(hash_to_hex_algop(get_midx_checksum(m),
+			m = ctx.base_midx;
+			for (i = 0; i < num_layers_before_from; i++) {
+				uint32_t j = num_layers_before_from - i - 1;
+
+				keep_hashes[j] = xstrdup(midx_get_checksum_hex(m));
+				m = m->base_midx;
+			}
+
+			keep_hashes[i] = xstrdup(hash_to_hex_algop(midx_hash,
 								   r->hash_algo));
-			m = m->base_midx;
+
+			i = 0;
+			for (m = ctx.m;
+			     m && midx_hashcmp(m, ctx.compact_to, r->hash_algo);
+			     m = m->base_midx) {
+				keep_hashes[keep_hashes_nr - i - 1] =
+					xstrdup(midx_get_checksum_hex(m));
+				i++;
+			}
+		} else {
+			keep_hashes[ctx.num_multi_pack_indexes_before] =
+				xstrdup(hash_to_hex_algop(midx_hash,
+							  r->hash_algo));
+
+			for (uint32_t i = 0; i < ctx.num_multi_pack_indexes_before; i++) {
+				uint32_t j = ctx.num_multi_pack_indexes_before - i - 1;
+
+				keep_hashes[j] = xstrdup(midx_get_checksum_hex(m));
+				m = m->base_midx;
+			}
 		}
 
-		for (uint32_t i = 0; i <= ctx.num_multi_pack_indexes_before; i++)
+		for (uint32_t i = 0; i < keep_hashes_nr; i++)
 			fprintf(get_lock_file_fp(&lk), "%s\n", keep_hashes[i]);
 	} else {
 		keep_hashes[ctx.num_multi_pack_indexes_before] =
@@ -1538,8 +1799,7 @@ static int write_midx_internal(struct odb_source *source,
 	if (commit_lock_file(&lk) < 0)
 		die_errno(_("could not write multi-pack-index"));
 
-	clear_midx_files(source, keep_hashes,
-			 ctx.num_multi_pack_indexes_before + 1,
+	clear_midx_files(opts->source, keep_hashes, keep_hashes_nr,
 			 ctx.incremental);
 	result = 0;
 
@@ -1557,7 +1817,7 @@ static int write_midx_internal(struct odb_source *source,
 	free(ctx.pack_perm);
 	free(ctx.pack_order);
 	if (keep_hashes) {
-		for (uint32_t i = 0; i <= ctx.num_multi_pack_indexes_before; i++)
+		for (uint32_t i = 0; i < keep_hashes_nr; i++)
 			free((char *)keep_hashes[i]);
 		free(keep_hashes);
 	}
@@ -1573,9 +1833,14 @@ int write_midx_file(struct odb_source *source,
 		    const char *preferred_pack_name,
 		    const char *refs_snapshot, unsigned flags)
 {
-	return write_midx_internal(source, NULL, NULL,
-				   preferred_pack_name, refs_snapshot,
-				   flags);
+	struct write_midx_opts opts = {
+		.source = source,
+		.preferred_pack_name = preferred_pack_name,
+		.refs_snapshot = refs_snapshot,
+		.flags = flags,
+	};
+
+	return write_midx_internal(&opts);
 }
 
 int write_midx_file_only(struct odb_source *source,
@@ -1583,8 +1848,30 @@ int write_midx_file_only(struct odb_source *source,
 			 const char *preferred_pack_name,
 			 const char *refs_snapshot, unsigned flags)
 {
-	return write_midx_internal(source, packs_to_include, NULL,
-				   preferred_pack_name, refs_snapshot, flags);
+	struct write_midx_opts opts = {
+		.source = source,
+		.packs_to_include = packs_to_include,
+		.preferred_pack_name = preferred_pack_name,
+		.refs_snapshot = refs_snapshot,
+		.flags = flags,
+	};
+
+	return write_midx_internal(&opts);
+}
+
+int write_midx_file_compact(struct odb_source *source,
+			    struct multi_pack_index *from,
+			    struct multi_pack_index *to,
+			    unsigned flags)
+{
+	struct write_midx_opts opts = {
+		.source = source,
+		.compact_from = from,
+		.compact_to = to,
+		.flags = flags | MIDX_WRITE_COMPACT,
+	};
+
+	return write_midx_internal(&opts);
 }
 
 int expire_midx_packs(struct odb_source *source, unsigned flags)
@@ -1643,9 +1930,14 @@ int expire_midx_packs(struct odb_source *source, unsigned flags)
 
 	free(count);
 
-	if (packs_to_drop.nr)
-		result = write_midx_internal(source, NULL,
-					     &packs_to_drop, NULL, NULL, flags);
+	if (packs_to_drop.nr) {
+		struct write_midx_opts opts = {
+			.source = source,
+			.packs_to_drop = &packs_to_drop,
+			.flags = flags & MIDX_PROGRESS,
+		};
+		result = write_midx_internal(&opts);
+	}
 
 	string_list_clear(&packs_to_drop, 0);
 
@@ -1778,6 +2070,10 @@ int midx_repack(struct odb_source *source, size_t batch_size, unsigned flags)
 	struct child_process cmd = CHILD_PROCESS_INIT;
 	FILE *cmd_in;
 	struct multi_pack_index *m = get_multi_pack_index(source);
+	struct write_midx_opts opts = {
+		.source = source,
+		.flags = flags,
+	};
 
 	/*
 	 * When updating the default for these configuration
@@ -1852,8 +2148,7 @@ int midx_repack(struct odb_source *source, size_t batch_size, unsigned flags)
 		goto cleanup;
 	}
 
-	result = write_midx_internal(source, NULL, NULL, NULL, NULL,
-				     flags);
+	result = write_midx_internal(&opts);
 
 cleanup:
 	free(include_pack);
diff --git a/midx.c b/midx.c
index a75ea99..81d6ab1 100644
--- a/midx.c
+++ b/midx.c
@@ -24,7 +24,13 @@ void clear_incremental_midx_files_ext(struct odb_source *source, const char *ext
 int cmp_idx_or_pack_name(const char *idx_or_pack_name,
 			 const char *idx_name);
 
-const unsigned char *get_midx_checksum(struct multi_pack_index *m)
+const char *midx_get_checksum_hex(const struct multi_pack_index *m)
+{
+	return hash_to_hex_algop(midx_get_checksum_hash(m),
+				 m->source->odb->repo->hash_algo);
+}
+
+const unsigned char *midx_get_checksum_hash(const struct multi_pack_index *m)
 {
 	return m->data + m->data_len - m->source->odb->repo->hash_algo->rawsz;
 }
@@ -95,8 +101,9 @@ static int midx_read_object_offsets(const unsigned char *chunk_start,
 
 struct multi_pack_index *get_multi_pack_index(struct odb_source *source)
 {
-	packfile_store_prepare(source->packfiles);
-	return source->packfiles->midx;
+	struct odb_source_files *files = odb_source_files_downcast(source);
+	packfile_store_prepare(files->packed);
+	return files->packed->midx;
 }
 
 static struct multi_pack_index *load_multi_pack_index_one(struct odb_source *source,
@@ -143,7 +150,7 @@ static struct multi_pack_index *load_multi_pack_index_one(struct odb_source *sou
 		      m->signature, MIDX_SIGNATURE);
 
 	m->version = m->data[MIDX_BYTE_FILE_VERSION];
-	if (m->version != MIDX_VERSION)
+	if (m->version != MIDX_VERSION_V1 && m->version != MIDX_VERSION_V2)
 		die(_("multi-pack-index version %d not recognized"),
 		      m->version);
 
@@ -204,7 +211,8 @@ static struct multi_pack_index *load_multi_pack_index_one(struct odb_source *sou
 			die(_("multi-pack-index pack-name chunk is too short"));
 		cur_pack_name = end + 1;
 
-		if (i && strcmp(m->pack_names[i], m->pack_names[i - 1]) <= 0)
+		if (m->version == MIDX_VERSION_V1 &&
+		    i && strcmp(m->pack_names[i], m->pack_names[i - 1]) <= 0)
 			die(_("multi-pack-index pack names out of order: '%s' before '%s'"),
 			      m->pack_names[i - 1],
 			      m->pack_names[i]);
@@ -405,6 +413,7 @@ void close_midx(struct multi_pack_index *m)
 	}
 	FREE_AND_NULL(m->packs);
 	FREE_AND_NULL(m->pack_names);
+	FREE_AND_NULL(m->pack_names_sorted);
 	free(m);
 }
 
@@ -447,6 +456,7 @@ static uint32_t midx_for_pack(struct multi_pack_index **_m,
 int prepare_midx_pack(struct multi_pack_index *m,
 		      uint32_t pack_int_id)
 {
+	struct odb_source_files *files = odb_source_files_downcast(m->source);
 	struct strbuf pack_name = STRBUF_INIT;
 	struct packed_git *p;
 
@@ -457,10 +467,10 @@ int prepare_midx_pack(struct multi_pack_index *m,
 	if (m->packs[pack_int_id])
 		return 0;
 
-	strbuf_addf(&pack_name, "%s/pack/%s", m->source->path,
+	strbuf_addf(&pack_name, "%s/pack/%s", files->base.path,
 		    m->pack_names[pack_int_id]);
-	p = packfile_store_load_pack(m->source->packfiles,
-				     pack_name.buf, m->source->local);
+	p = packfile_store_load_pack(files->packed,
+				     pack_name.buf, files->base.local);
 	strbuf_release(&pack_name);
 
 	if (!p) {
@@ -649,17 +659,40 @@ int cmp_idx_or_pack_name(const char *idx_or_pack_name,
 	return strcmp(idx_or_pack_name, idx_name);
 }
 
+
+static int midx_pack_names_cmp(const void *a, const void *b, void *m_)
+{
+	struct multi_pack_index *m = m_;
+	return strcmp(m->pack_names[*(const size_t *)a],
+		      m->pack_names[*(const size_t *)b]);
+}
+
 static int midx_contains_pack_1(struct multi_pack_index *m,
 				const char *idx_or_pack_name)
 {
 	uint32_t first = 0, last = m->num_packs;
 
+	if (m->version == MIDX_VERSION_V2 && !m->pack_names_sorted) {
+		uint32_t i;
+
+		ALLOC_ARRAY(m->pack_names_sorted, m->num_packs);
+
+		for (i = 0; i < m->num_packs; i++)
+			m->pack_names_sorted[i] = i;
+
+		QSORT_S(m->pack_names_sorted, m->num_packs, midx_pack_names_cmp,
+			m);
+	}
+
 	while (first < last) {
 		uint32_t mid = first + (last - first) / 2;
 		const char *current;
 		int cmp;
 
-		current = m->pack_names[mid];
+		if (m->pack_names_sorted)
+			current = m->pack_names[m->pack_names_sorted[mid]];
+		else
+			current = m->pack_names[mid];
 		cmp = cmp_idx_or_pack_name(idx_or_pack_name, current);
 		if (!cmp)
 			return 1;
@@ -703,18 +736,19 @@ int midx_preferred_pack(struct multi_pack_index *m, uint32_t *pack_int_id)
 
 int prepare_multi_pack_index_one(struct odb_source *source)
 {
+	struct odb_source_files *files = odb_source_files_downcast(source);
 	struct repository *r = source->odb->repo;
 
 	prepare_repo_settings(r);
 	if (!r->settings.core_multi_pack_index)
 		return 0;
 
-	if (source->packfiles->midx)
+	if (files->packed->midx)
 		return 1;
 
-	source->packfiles->midx = load_multi_pack_index(source);
+	files->packed->midx = load_multi_pack_index(source);
 
-	return !!source->packfiles->midx;
+	return !!files->packed->midx;
 }
 
 int midx_checksum_valid(struct multi_pack_index *m)
@@ -803,9 +837,10 @@ void clear_midx_file(struct repository *r)
 		struct odb_source *source;
 
 		for (source = r->objects->sources; source; source = source->next) {
-			if (source->packfiles->midx)
-				close_midx(source->packfiles->midx);
-			source->packfiles->midx = NULL;
+			struct odb_source_files *files = odb_source_files_downcast(source);
+			if (files->packed->midx)
+				close_midx(files->packed->midx);
+			files->packed->midx = NULL;
 		}
 	}
 
diff --git a/midx.h b/midx.h
index 6e54d73..08f3728 100644
--- a/midx.h
+++ b/midx.h
@@ -11,7 +11,8 @@ struct git_hash_algo;
 struct odb_source;
 
 #define MIDX_SIGNATURE 0x4d494458 /* "MIDX" */
-#define MIDX_VERSION 1
+#define MIDX_VERSION_V1 1
+#define MIDX_VERSION_V2 2
 #define MIDX_BYTE_FILE_VERSION 4
 #define MIDX_BYTE_HASH_VERSION 5
 #define MIDX_BYTE_NUM_CHUNKS 6
@@ -71,6 +72,7 @@ struct multi_pack_index {
 	uint32_t num_packs_in_base;
 
 	const char **pack_names;
+	size_t *pack_names_sorted;
 	struct packed_git **packs;
 };
 
@@ -80,12 +82,14 @@ struct multi_pack_index {
 #define MIDX_WRITE_BITMAP_HASH_CACHE (1 << 3)
 #define MIDX_WRITE_BITMAP_LOOKUP_TABLE (1 << 4)
 #define MIDX_WRITE_INCREMENTAL (1 << 5)
+#define MIDX_WRITE_COMPACT (1 << 6)
 
 #define MIDX_EXT_REV "rev"
 #define MIDX_EXT_BITMAP "bitmap"
 #define MIDX_EXT_MIDX "midx"
 
-const unsigned char *get_midx_checksum(struct multi_pack_index *m);
+const char *midx_get_checksum_hex(const struct multi_pack_index *m) /* static buffer */;
+const unsigned char *midx_get_checksum_hash(const struct multi_pack_index *m);
 void get_midx_filename(struct odb_source *source, struct strbuf *out);
 void get_midx_filename_ext(struct odb_source *source, struct strbuf *out,
 			   const unsigned char *hash, const char *ext);
@@ -128,6 +132,10 @@ int write_midx_file_only(struct odb_source *source,
 			 struct string_list *packs_to_include,
 			 const char *preferred_pack_name,
 			 const char *refs_snapshot, unsigned flags);
+int write_midx_file_compact(struct odb_source *source,
+			    struct multi_pack_index *from,
+			    struct multi_pack_index *to,
+			    unsigned flags);
 void clear_midx_file(struct repository *r);
 int verify_midx_file(struct odb_source *source, unsigned flags);
 int expire_midx_packs(struct odb_source *source, unsigned flags);
diff --git a/negotiator/default.c b/negotiator/default.c
index 116dedc..3cac047 100644
--- a/negotiator/default.c
+++ b/negotiator/default.c
@@ -57,19 +57,19 @@ static int clear_marks(const struct reference *ref, void *cb_data UNUSED)
 static void mark_common(struct negotiation_state *ns, struct commit *commit,
 		int ancestors_only, int dont_parse)
 {
-	struct prio_queue queue = { NULL };
+	struct commit_stack stack = COMMIT_STACK_INIT;
 
 	if (!commit || (commit->object.flags & COMMON))
 		return;
 
-	prio_queue_put(&queue, commit);
+	commit_stack_push(&stack, commit);
 	if (!ancestors_only) {
 		commit->object.flags |= COMMON;
 
 		if ((commit->object.flags & SEEN) && !(commit->object.flags & POPPED))
 			ns->non_common_revs--;
 	}
-	while ((commit = prio_queue_get(&queue))) {
+	while ((commit = commit_stack_pop(&stack))) {
 		struct object *o = (struct object *)commit;
 
 		if (!(o->flags & SEEN))
@@ -94,12 +94,12 @@ static void mark_common(struct negotiation_state *ns, struct commit *commit,
 				if ((p->object.flags & SEEN) && !(p->object.flags & POPPED))
 					ns->non_common_revs--;
 
-				prio_queue_put(&queue, parents->item);
+				commit_stack_push(&stack, parents->item);
 			}
 		}
 	}
 
-	clear_prio_queue(&queue);
+	commit_stack_clear(&stack);
 }
 
 /*
diff --git a/negotiator/skipping.c b/negotiator/skipping.c
index 0a27213..fe4126c 100644
--- a/negotiator/skipping.c
+++ b/negotiator/skipping.c
@@ -91,15 +91,15 @@ static int clear_marks(const struct reference *ref, void *cb_data UNUSED)
  */
 static void mark_common(struct data *data, struct commit *seen_commit)
 {
-	struct prio_queue queue = { NULL };
+	struct commit_stack stack = COMMIT_STACK_INIT;
 	struct commit *c;
 
 	if (seen_commit->object.flags & COMMON)
 		return;
 
-	prio_queue_put(&queue, seen_commit);
+	commit_stack_push(&stack, seen_commit);
 	seen_commit->object.flags |= COMMON;
-	while ((c = prio_queue_get(&queue))) {
+	while ((c = commit_stack_pop(&stack))) {
 		struct commit_list *p;
 
 		if (!(c->object.flags & POPPED))
@@ -113,11 +113,11 @@ static void mark_common(struct data *data, struct commit *seen_commit)
 				continue;
 
 			p->item->object.flags |= COMMON;
-			prio_queue_put(&queue, p->item);
+			commit_stack_push(&stack, p->item);
 		}
 	}
 
-	clear_prio_queue(&queue);
+	commit_stack_clear(&stack);
 }
 
 /*
diff --git a/object-file.c b/object-file.c
index 3094140..f0b029f 100644
--- a/object-file.c
+++ b/object-file.c
@@ -215,8 +215,9 @@ static void *odb_source_loose_map_object(struct odb_source *source,
 					 const struct object_id *oid,
 					 unsigned long *size)
 {
+	struct odb_source_files *files = odb_source_files_downcast(source);
 	const char *p;
-	int fd = open_loose_object(source->loose, oid, &p);
+	int fd = open_loose_object(files->loose, oid, &p);
 
 	if (fd < 0)
 		return NULL;
@@ -397,6 +398,7 @@ static int read_object_info_from_path(struct odb_source *source,
 				      struct object_info *oi,
 				      enum object_info_flags flags)
 {
+	struct odb_source_files *files = odb_source_files_downcast(source);
 	int ret;
 	int fd;
 	unsigned long mapsize;
@@ -419,7 +421,7 @@ static int read_object_info_from_path(struct odb_source *source,
 		struct stat st;
 
 		if ((!oi || (!oi->disk_sizep && !oi->mtimep)) && (flags & OBJECT_INFO_QUICK)) {
-			ret = quick_has_loose(source->loose, oid) ? 0 : -1;
+			ret = quick_has_loose(files->loose, oid) ? 0 : -1;
 			goto out;
 		}
 
@@ -540,6 +542,16 @@ int odb_source_loose_read_object_info(struct odb_source *source,
 				      enum object_info_flags flags)
 {
 	static struct strbuf buf = STRBUF_INIT;
+
+	/*
+	 * The second read shouldn't cause new loose objects to show up, unless
+	 * there was a race condition with a secondary process. We don't care
+	 * about this case though, so we simply skip reading loose objects a
+	 * second time.
+	 */
+	if (flags & OBJECT_INFO_SECOND_READ)
+		return -1;
+
 	odb_loose_path(source, &buf, oid);
 	return read_object_info_from_path(source, buf.buf, oid, oi, flags);
 }
@@ -1856,6 +1868,64 @@ int odb_source_loose_for_each_object(struct odb_source *source,
 					     NULL, NULL, &data);
 }
 
+static int count_loose_object(const struct object_id *oid UNUSED,
+			      struct object_info *oi UNUSED,
+			      void *payload)
+{
+	unsigned long *count = payload;
+	(*count)++;
+	return 0;
+}
+
+int odb_source_loose_count_objects(struct odb_source *source,
+				   enum odb_count_objects_flags flags,
+				   unsigned long *out)
+{
+	const unsigned hexsz = source->odb->repo->hash_algo->hexsz - 2;
+	char *path = NULL;
+	DIR *dir = NULL;
+	int ret;
+
+	if (flags & ODB_COUNT_OBJECTS_APPROXIMATE) {
+		unsigned long count = 0;
+		struct dirent *ent;
+
+		path = xstrfmt("%s/17", source->path);
+
+		dir = opendir(path);
+		if (!dir) {
+			if (errno == ENOENT) {
+				*out = 0;
+				ret = 0;
+				goto out;
+			}
+
+			ret = error_errno("cannot open object shard '%s'", path);
+			goto out;
+		}
+
+		while ((ent = readdir(dir)) != NULL) {
+			if (strspn(ent->d_name, "0123456789abcdef") != hexsz ||
+			    ent->d_name[hexsz] != '\0')
+				continue;
+			count++;
+		}
+
+		*out = count * 256;
+		ret = 0;
+	} else {
+		*out = 0;
+		ret = odb_source_loose_for_each_object(source, NULL, count_loose_object,
+						       out, 0);
+	}
+
+out:
+	if (dir)
+		closedir(dir);
+	free(path);
+	return ret;
+}
+
 static int append_loose_object(const struct object_id *oid,
 			       const char *path UNUSED,
 			       void *data)
@@ -1867,33 +1937,34 @@ static int append_loose_object(const struct object_id *oid,
 struct oidtree *odb_source_loose_cache(struct odb_source *source,
 				       const struct object_id *oid)
 {
+	struct odb_source_files *files = odb_source_files_downcast(source);
 	int subdir_nr = oid->hash[0];
 	struct strbuf buf = STRBUF_INIT;
-	size_t word_bits = bitsizeof(source->loose->subdir_seen[0]);
+	size_t word_bits = bitsizeof(files->loose->subdir_seen[0]);
 	size_t word_index = subdir_nr / word_bits;
 	size_t mask = (size_t)1u << (subdir_nr % word_bits);
 	uint32_t *bitmap;
 
 	if (subdir_nr < 0 ||
-	    (size_t) subdir_nr >= bitsizeof(source->loose->subdir_seen))
+	    (size_t) subdir_nr >= bitsizeof(files->loose->subdir_seen))
 		BUG("subdir_nr out of range");
 
-	bitmap = &source->loose->subdir_seen[word_index];
+	bitmap = &files->loose->subdir_seen[word_index];
 	if (*bitmap & mask)
-		return source->loose->cache;
-	if (!source->loose->cache) {
-		ALLOC_ARRAY(source->loose->cache, 1);
-		oidtree_init(source->loose->cache);
+		return files->loose->cache;
+	if (!files->loose->cache) {
+		ALLOC_ARRAY(files->loose->cache, 1);
+		oidtree_init(files->loose->cache);
 	}
 	strbuf_addstr(&buf, source->path);
 	for_each_file_in_obj_subdir(subdir_nr, &buf,
 				    source->odb->repo->hash_algo,
 				    append_loose_object,
 				    NULL, NULL,
-				    source->loose->cache);
+				    files->loose->cache);
 	*bitmap |= mask;
 	strbuf_release(&buf);
-	return source->loose->cache;
+	return files->loose->cache;
 }
 
 static void odb_source_loose_clear_cache(struct odb_source_loose *loose)
@@ -1906,7 +1977,8 @@ static void odb_source_loose_clear_cache(struct odb_source_loose *loose)
 
 void odb_source_loose_reprepare(struct odb_source *source)
 {
-	odb_source_loose_clear_cache(source->loose);
+	struct odb_source_files *files = odb_source_files_downcast(source);
+	odb_source_loose_clear_cache(files->loose);
 }
 
 static int check_stream_oid(git_zstream *stream,
@@ -2197,7 +2269,7 @@ int odb_source_loose_read_object_stream(struct odb_read_stream **out,
 	return 0;
 error:
 	git_inflate_end(&st->z);
-	munmap(st->mapped, st->mapsize);
+	munmap(mapped, mapsize);
 	free(st);
 	return -1;
 }
diff --git a/object-file.h b/object-file.h
index ff6da65..f8d8805 100644
--- a/object-file.h
+++ b/object-file.h
@@ -139,6 +139,20 @@ int odb_source_loose_for_each_object(struct odb_source *source,
 				     void *cb_data,
 				     unsigned flags);
 
+/*
+ * Count the number of loose objects in this source.
+ *
+ * The object count is approximated by opening a single sharding directory for
+ * loose objects and scanning its contents. The result is then extrapolated by
+ * 256. This should generally work as a reasonable estimate given that the
+ * object hash is supposed to be indistinguishable from random.
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ */
+int odb_source_loose_count_objects(struct odb_source *source,
+				   enum odb_count_objects_flags flags,
+				   unsigned long *out);
+
 /**
  * format_object_header() is a thin wrapper around s xsnprintf() that
  * writes the initial "<type> <obj-len>" part of the loose object
diff --git a/object-name.c b/object-name.c
index 7b14c3b..84a34b8 100644
--- a/object-name.c
+++ b/object-name.c
@@ -837,7 +837,11 @@ int repo_find_unique_abbrev_r(struct repository *r, char *hex,
 	const unsigned hexsz = algo->hexsz;
 
 	if (len < 0) {
-		unsigned long count = repo_approximate_object_count(r);
+		unsigned long count;
+
+		if (odb_count_objects(r->objects, ODB_COUNT_OBJECTS_APPROXIMATE, &count) < 0)
+			count = 0;
+
 		/*
 		 * Add one because the MSB only tells us the highest bit set,
 		 * not including the value of all the _other_ bits (so "15"
@@ -1660,7 +1664,8 @@ static int interpret_empty_at(const char *name, int namelen, int len, struct str
 
 static int reinterpret(struct repository *r,
 		       const char *name, int namelen, int len,
-		       struct strbuf *buf, unsigned allowed)
+		       struct strbuf *buf,
+		       enum interpret_branch_kind allowed)
 {
 	/* we have extra data, which might need further processing */
 	struct strbuf tmp = STRBUF_INIT;
@@ -1692,7 +1697,8 @@ static void set_shortened_ref(struct repository *r, struct strbuf *buf, const ch
 	free(s);
 }
 
-static int branch_interpret_allowed(const char *refname, unsigned allowed)
+static int branch_interpret_allowed(const char *refname,
+				    enum interpret_branch_kind allowed)
 {
 	if (!allowed)
 		return 1;
diff --git a/object-name.h b/object-name.h
index cda4934..167a915 100644
--- a/object-name.h
+++ b/object-name.h
@@ -101,9 +101,12 @@ int set_disambiguate_hint_config(const char *var, const char *value);
  * If the input was ok but there are not N branch switches in the
  * reflog, it returns 0.
  */
-#define INTERPRET_BRANCH_LOCAL (1<<0)
-#define INTERPRET_BRANCH_REMOTE (1<<1)
-#define INTERPRET_BRANCH_HEAD (1<<2)
+enum interpret_branch_kind {
+	INTERPRET_BRANCH_LOCAL = (1 << 0),
+	INTERPRET_BRANCH_REMOTE = (1 << 1),
+	INTERPRET_BRANCH_HEAD = (1 << 2),
+};
+
 struct interpret_branch_name_options {
 	/*
 	 * If "allowed" is non-zero, it is a treated as a bitfield of allowable
@@ -111,7 +114,7 @@ struct interpret_branch_name_options {
 	 * ("refs/remotes/"), or "HEAD". If no "allowed" bits are set, any expansion is
 	 * allowed, even ones to refs outside of those namespaces.
 	 */
-	unsigned allowed;
+	enum interpret_branch_kind allowed;
 
 	/*
 	 * If ^{upstream} or ^{push} (or equivalent) is requested, and the
diff --git a/odb.c b/odb.c
index 776de53..350e23f 100644
--- a/odb.c
+++ b/odb.c
@@ -1,6 +1,5 @@
 #include "git-compat-util.h"
 #include "abspath.h"
-#include "chdir-notify.h"
 #include "commit-graph.h"
 #include "config.h"
 #include "dir.h"
@@ -132,10 +131,10 @@ static bool odb_is_source_usable(struct object_database *o, const char *path)
 	return usable;
 }
 
-static void parse_alternates(const char *string,
-			     int sep,
-			     const char *relative_base,
-			     struct strvec *out)
+void parse_alternates(const char *string,
+		      int sep,
+		      const char *relative_base,
+		      struct strvec *out)
 {
 	struct strbuf pathbuf = STRBUF_INIT;
 	struct strbuf buf = STRBUF_INIT;
@@ -199,41 +198,6 @@ static void parse_alternates(const char *string,
 	strbuf_release(&buf);
 }
 
-static void odb_source_read_alternates(struct odb_source *source,
-				       struct strvec *out)
-{
-	struct strbuf buf = STRBUF_INIT;
-	char *path;
-
-	path = xstrfmt("%s/info/alternates", source->path);
-	if (strbuf_read_file(&buf, path, 1024) < 0) {
-		warn_on_fopen_errors(path);
-		free(path);
-		return;
-	}
-	parse_alternates(buf.buf, '\n', source->path, out);
-
-	strbuf_release(&buf);
-	free(path);
-}
-
-
-static struct odb_source *odb_source_new(struct object_database *odb,
-					 const char *path,
-					 bool local)
-{
-	struct odb_source *source;
-
-	CALLOC_ARRAY(source, 1);
-	source->odb = odb;
-	source->local = local;
-	source->path = xstrdup(path);
-	source->loose = odb_source_loose_new(source);
-	source->packfiles = packfile_store_new(source);
-
-	return source;
-}
-
 static struct odb_source *odb_add_alternate_recursively(struct object_database *odb,
 							const char *source,
 							int depth)
@@ -272,58 +236,6 @@ static struct odb_source *odb_add_alternate_recursively(struct object_database *
 	return alternate;
 }
 
-static int odb_source_write_alternate(struct odb_source *source,
-				      const char *alternate)
-{
-	struct lock_file lock = LOCK_INIT;
-	char *path = xstrfmt("%s/%s", source->path, "info/alternates");
-	FILE *in, *out;
-	int found = 0;
-	int ret;
-
-	hold_lock_file_for_update(&lock, path, LOCK_DIE_ON_ERROR);
-	out = fdopen_lock_file(&lock, "w");
-	if (!out) {
-		ret = error_errno(_("unable to fdopen alternates lockfile"));
-		goto out;
-	}
-
-	in = fopen(path, "r");
-	if (in) {
-		struct strbuf line = STRBUF_INIT;
-
-		while (strbuf_getline(&line, in) != EOF) {
-			if (!strcmp(alternate, line.buf)) {
-				found = 1;
-				break;
-			}
-			fprintf_or_die(out, "%s\n", line.buf);
-		}
-
-		strbuf_release(&line);
-		fclose(in);
-	} else if (errno != ENOENT) {
-		ret = error_errno(_("unable to read alternates file"));
-		goto out;
-	}
-
-	if (found) {
-		rollback_lock_file(&lock);
-	} else {
-		fprintf_or_die(out, "%s\n", alternate);
-		if (commit_lock_file(&lock)) {
-			ret = error_errno(_("unable to move new alternates file into place"));
-			goto out;
-		}
-	}
-
-	ret = 0;
-
-out:
-	free(path);
-	return ret;
-}
-
 void odb_add_to_alternates_file(struct object_database *odb,
 				const char *dir)
 {
@@ -373,14 +285,6 @@ struct odb_source *odb_set_temporary_primary_source(struct object_database *odb,
 	return source->next;
 }
 
-static void odb_source_free(struct odb_source *source)
-{
-	free(source->path);
-	odb_source_loose_free(source->loose);
-	packfile_store_free(source->packfiles);
-	free(source);
-}
-
 void odb_restore_primary_source(struct object_database *odb,
 				struct odb_source *restore_source,
 				const char *old_path)
@@ -714,18 +618,19 @@ static int do_oid_object_info_extended(struct object_database *odb,
 	while (1) {
 		struct odb_source *source;
 
-		/* Most likely it's a loose object. */
-		for (source = odb->sources; source; source = source->next) {
-			if (!packfile_store_read_object_info(source->packfiles, real, oi, flags) ||
-			    !odb_source_loose_read_object_info(source, real, oi, flags))
+		for (source = odb->sources; source; source = source->next)
+			if (!odb_source_read_object_info(source, real, oi, flags))
 				return 0;
-		}
 
-		/* Not a loose object; someone else may have just packed it. */
+		/*
+		 * When the object hasn't been found we try a second read and
+		 * tell the sources so. This may cause them to invalidate
+		 * caches or reload on-disk state.
+		 */
 		if (!(flags & OBJECT_INFO_QUICK)) {
-			odb_reprepare(odb->repo->objects);
 			for (source = odb->sources; source; source = source->next)
-				if (!packfile_store_read_object_info(source->packfiles, real, oi, flags))
+				if (!odb_source_read_object_info(source, real, oi,
+								 flags | OBJECT_INFO_SECOND_READ))
 					return 0;
 		}
 
@@ -984,16 +889,10 @@ int odb_freshen_object(struct object_database *odb,
 		       const struct object_id *oid)
 {
 	struct odb_source *source;
-
 	odb_prepare_alternates(odb);
-	for (source = odb->sources; source; source = source->next) {
-		if (packfile_store_freshen_object(source->packfiles, oid))
+	for (source = odb->sources; source; source = source->next)
+		if (odb_source_freshen_object(source, oid))
 			return 1;
-
-		if (odb_source_loose_freshen_object(source, oid))
-			return 1;
-	}
-
 	return 0;
 }
 
@@ -1010,15 +909,7 @@ int odb_for_each_object(struct object_database *odb,
 		if (flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY && !source->local)
 			continue;
 
-		if (!(flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY)) {
-			ret = odb_source_loose_for_each_object(source, request,
-							       cb, cb_data, flags);
-			if (ret)
-				return ret;
-		}
-
-		ret = packfile_store_for_each_object(source->packfiles, request,
-						     cb, cb_data, flags);
+		ret = odb_source_for_each_object(source, request, cb, cb_data, flags);
 		if (ret)
 			return ret;
 	}
@@ -1026,6 +917,41 @@ int odb_for_each_object(struct object_database *odb,
 	return 0;
 }
 
+int odb_count_objects(struct object_database *odb,
+		      enum odb_count_objects_flags flags,
+		      unsigned long *out)
+{
+	struct odb_source *source;
+	unsigned long count = 0;
+	int ret;
+
+	if (odb->object_count_valid && odb->object_count_flags == flags) {
+		*out = odb->object_count;
+		return 0;
+	}
+
+	odb_prepare_alternates(odb);
+	for (source = odb->sources; source; source = source->next) {
+		unsigned long c;
+
+		ret = odb_source_count_objects(source, flags, &c);
+		if (ret < 0)
+			goto out;
+
+		count += c;
+	}
+
+	odb->object_count = count;
+	odb->object_count_valid = 1;
+	odb->object_count_flags = flags;
+
+	*out = count;
+	ret = 0;
+
+out:
+	return ret;
+}
+
 void odb_assert_oid_type(struct object_database *odb,
 			 const struct object_id *oid, enum object_type expect)
 {
@@ -1044,47 +970,15 @@ int odb_write_object_ext(struct object_database *odb,
 			 struct object_id *compat_oid,
 			 unsigned flags)
 {
-	return odb_source_loose_write_object(odb->sources, buf, len, type,
-					     oid, compat_oid, flags);
+	return odb_source_write_object(odb->sources, buf, len, type,
+				       oid, compat_oid, flags);
 }
 
 int odb_write_object_stream(struct object_database *odb,
 			    struct odb_write_stream *stream, size_t len,
 			    struct object_id *oid)
 {
-	return odb_source_loose_write_stream(odb->sources, stream, len, oid);
-}
-
-static void odb_update_commondir(const char *name UNUSED,
-				 const char *old_cwd,
-				 const char *new_cwd,
-				 void *cb_data)
-{
-	struct object_database *odb = cb_data;
-	struct tmp_objdir *tmp_objdir;
-	struct odb_source *source;
-
-	tmp_objdir = tmp_objdir_unapply_primary_odb();
-
-	/*
-	 * In theory, we only have to do this for the primary object source, as
-	 * alternates' paths are always resolved to an absolute path.
-	 */
-	for (source = odb->sources; source; source = source->next) {
-		char *path;
-
-		if (is_absolute_path(source->path))
-			continue;
-
-		path = reparent_relative_path(old_cwd, new_cwd,
-					      source->path);
-
-		free(source->path);
-		source->path = path;
-	}
-
-	if (tmp_objdir)
-		tmp_objdir_reapply_primary_odb(tmp_objdir, old_cwd, new_cwd);
+	return odb_source_write_object_stream(odb->sources, stream, len, oid);
 }
 
 struct object_database *odb_new(struct repository *repo,
@@ -1107,8 +1001,6 @@ struct object_database *odb_new(struct repository *repo,
 
 	free(to_free);
 
-	chdir_notify_register(NULL, odb_update_commondir, o);
-
 	return o;
 }
 
@@ -1116,7 +1008,7 @@ void odb_close(struct object_database *o)
 {
 	struct odb_source *source;
 	for (source = o->sources; source; source = source->next)
-		packfile_store_close(source->packfiles);
+		odb_source_close(source);
 	close_commit_graph(o);
 }
 
@@ -1152,8 +1044,6 @@ void odb_free(struct object_database *o)
 
 	string_list_clear(&o->submodule_source_paths, 0);
 
-	chdir_notify_unregister(NULL, odb_update_commondir, o);
-
 	free(o);
 }
 
@@ -1172,12 +1062,10 @@ void odb_reprepare(struct object_database *o)
 	o->loaded_alternates = 0;
 	odb_prepare_alternates(o);
 
-	for (source = o->sources; source; source = source->next) {
-		odb_source_loose_reprepare(source);
-		packfile_store_reprepare(source->packfiles);
-	}
+	for (source = o->sources; source; source = source->next)
+		odb_source_reprepare(source);
 
-	o->approximate_object_count_valid = 0;
+	o->object_count_valid = 0;
 
 	obj_read_unlock();
 }
diff --git a/odb.h b/odb.h
index 68b8ec2..9aee260 100644
--- a/odb.h
+++ b/odb.h
@@ -11,6 +11,7 @@
 struct oidmap;
 struct oidtree;
 struct strbuf;
+struct strvec;
 struct repository;
 struct multi_pack_index;
 
@@ -30,50 +31,6 @@ extern int fetch_if_missing;
  */
 char *compute_alternate_path(const char *path, struct strbuf *err);
 
-/*
- * The source is the part of the object database that stores the actual
- * objects. It thus encapsulates the logic to read and write the specific
- * on-disk format. An object database can have multiple sources:
- *
- *   - The primary source, which is typically located in "$GIT_DIR/objects".
- *     This is where new objects are usually written to.
- *
- *   - Alternate sources, which are configured via "objects/info/alternates" or
- *     via the GIT_ALTERNATE_OBJECT_DIRECTORIES environment variable. These
- *     alternate sources are only used to read objects.
- */
-struct odb_source {
-	struct odb_source *next;
-
-	/* Object database that owns this object source. */
-	struct object_database *odb;
-
-	/* Private state for loose objects. */
-	struct odb_source_loose *loose;
-
-	/* Should only be accessed directly by packfile.c and midx.c. */
-	struct packfile_store *packfiles;
-
-	/*
-	 * Figure out whether this is the local source of the owning
-	 * repository, which would typically be its ".git/objects" directory.
-	 * This local object directory is usually where objects would be
-	 * written to.
-	 */
-	bool local;
-
-	/*
-	 * This object store is ephemeral, so there is no need to fsync.
-	 */
-	int will_destroy;
-
-	/*
-	 * Path to the source. If this is a relative path, it is relative to
-	 * the current working directory.
-	 */
-	char *path;
-};
-
 struct packed_git;
 struct packfile_store;
 struct cached_object_entry;
@@ -153,10 +110,11 @@ struct object_database {
 	/*
 	 * A fast, rough count of the number of objects in the repository.
 	 * These two fields are not meant for direct access. Use
-	 * repo_approximate_object_count() instead.
+	 * odb_count_objects() instead.
 	 */
-	unsigned long approximate_object_count;
-	unsigned approximate_object_count_valid : 1;
+	unsigned long object_count;
+	unsigned object_count_flags;
+	unsigned object_count_valid : 1;
 
 	/*
 	 * Submodule source paths that will be added as additional sources to
@@ -400,6 +358,18 @@ enum object_info_flags {
 	OBJECT_INFO_DIE_IF_CORRUPT = (1 << 3),
 
 	/*
+	 * We have already tried reading the object, but it couldn't be found
+	 * via any of the attached sources, and are now doing a second read.
+	 * This second read asks the individual sources to also evaluate
+	 * whether any on-disk state may have changed that may have caused the
+	 * object to appear.
+	 *
+	 * This flag is for internal use, only. The second read only occurs
+	 * when `OBJECT_INFO_QUICK` was not passed.
+	 */
+	OBJECT_INFO_SECOND_READ = (1 << 4),
+
+	/*
 	 * This is meant for bulk prefetching of missing blobs in a partial
 	 * clone. Implies OBJECT_INFO_SKIP_FETCH_OBJECT and OBJECT_INFO_QUICK.
 	 */
@@ -531,6 +501,27 @@ int odb_for_each_object(struct object_database *odb,
 			void *cb_data,
 			unsigned flags);
 
+enum odb_count_objects_flags {
+	/*
+	 * Instead of providing an accurate count, allow the number of objects
+	 * to be approximated. Details of how this approximation works are
+	 * subject to the specific source's implementation.
+	 */
+	ODB_COUNT_OBJECTS_APPROXIMATE = (1 << 0),
+};
+
+/*
+ * Count the number of objects in the given object database. This object count
+ * may double-count objects that are stored in multiple backends, or which are
+ * stored multiple times in a single backend.
+ *
+ * Returns 0 on success, a negative error code otherwise. The number of objects
+ * will be assigned to the `out` pointer on success.
+ */
+int odb_count_objects(struct object_database *odb,
+		      enum odb_count_objects_flags flags,
+		      unsigned long *out);
+
 enum {
 	/*
 	 * By default, `odb_write_object()` does not actually write anything
@@ -579,4 +570,9 @@ int odb_write_object_stream(struct object_database *odb,
 			    struct odb_write_stream *stream, size_t len,
 			    struct object_id *oid);
 
+void parse_alternates(const char *string,
+		      int sep,
+		      const char *relative_base,
+		      struct strvec *out);
+
 #endif /* ODB_H */
diff --git a/odb/source-files.c b/odb/source-files.c
new file mode 100644
index 0000000..c08d899
--- /dev/null
+++ b/odb/source-files.c
@@ -0,0 +1,269 @@
+#include "git-compat-util.h"
+#include "abspath.h"
+#include "chdir-notify.h"
+#include "gettext.h"
+#include "lockfile.h"
+#include "object-file.h"
+#include "odb.h"
+#include "odb/source.h"
+#include "odb/source-files.h"
+#include "packfile.h"
+#include "strbuf.h"
+#include "write-or-die.h"
+
+static void odb_source_files_reparent(const char *name UNUSED,
+				      const char *old_cwd,
+				      const char *new_cwd,
+				      void *cb_data)
+{
+	struct odb_source_files *files = cb_data;
+	char *path = reparent_relative_path(old_cwd, new_cwd,
+					    files->base.path);
+	free(files->base.path);
+	files->base.path = path;
+}
+
+static void odb_source_files_free(struct odb_source *source)
+{
+	struct odb_source_files *files = odb_source_files_downcast(source);
+	chdir_notify_unregister(NULL, odb_source_files_reparent, files);
+	odb_source_loose_free(files->loose);
+	packfile_store_free(files->packed);
+	odb_source_release(&files->base);
+	free(files);
+}
+
+static void odb_source_files_close(struct odb_source *source)
+{
+	struct odb_source_files *files = odb_source_files_downcast(source);
+	packfile_store_close(files->packed);
+}
+
+static void odb_source_files_reprepare(struct odb_source *source)
+{
+	struct odb_source_files *files = odb_source_files_downcast(source);
+	odb_source_loose_reprepare(&files->base);
+	packfile_store_reprepare(files->packed);
+}
+
+static int odb_source_files_read_object_info(struct odb_source *source,
+					     const struct object_id *oid,
+					     struct object_info *oi,
+					     enum object_info_flags flags)
+{
+	struct odb_source_files *files = odb_source_files_downcast(source);
+
+	if (!packfile_store_read_object_info(files->packed, oid, oi, flags) ||
+	    !odb_source_loose_read_object_info(source, oid, oi, flags))
+		return 0;
+
+	return -1;
+}
+
+static int odb_source_files_read_object_stream(struct odb_read_stream **out,
+					       struct odb_source *source,
+					       const struct object_id *oid)
+{
+	struct odb_source_files *files = odb_source_files_downcast(source);
+	if (!packfile_store_read_object_stream(out, files->packed, oid) ||
+	    !odb_source_loose_read_object_stream(out, source, oid))
+		return 0;
+	return -1;
+}
+
+static int odb_source_files_for_each_object(struct odb_source *source,
+					    const struct object_info *request,
+					    odb_for_each_object_cb cb,
+					    void *cb_data,
+					    unsigned flags)
+{
+	struct odb_source_files *files = odb_source_files_downcast(source);
+	int ret;
+
+	if (!(flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY)) {
+		ret = odb_source_loose_for_each_object(source, request, cb, cb_data, flags);
+		if (ret)
+			return ret;
+	}
+
+	ret = packfile_store_for_each_object(files->packed, request, cb, cb_data, flags);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int odb_source_files_count_objects(struct odb_source *source,
+					  enum odb_count_objects_flags flags,
+					  unsigned long *out)
+{
+	struct odb_source_files *files = odb_source_files_downcast(source);
+	unsigned long count;
+	int ret;
+
+	ret = packfile_store_count_objects(files->packed, flags, &count);
+	if (ret < 0)
+		goto out;
+
+	if (!(flags & ODB_COUNT_OBJECTS_APPROXIMATE)) {
+		unsigned long loose_count;
+
+		ret = odb_source_loose_count_objects(source, flags, &loose_count);
+		if (ret < 0)
+			goto out;
+
+		count += loose_count;
+	}
+
+	*out = count;
+	ret = 0;
+
+out:
+	return ret;
+}
+
+static int odb_source_files_freshen_object(struct odb_source *source,
+					   const struct object_id *oid)
+{
+	struct odb_source_files *files = odb_source_files_downcast(source);
+	if (packfile_store_freshen_object(files->packed, oid) ||
+	    odb_source_loose_freshen_object(source, oid))
+		return 1;
+	return 0;
+}
+
+static int odb_source_files_write_object(struct odb_source *source,
+					 const void *buf, unsigned long len,
+					 enum object_type type,
+					 struct object_id *oid,
+					 struct object_id *compat_oid,
+					 unsigned flags)
+{
+	return odb_source_loose_write_object(source, buf, len, type,
+					     oid, compat_oid, flags);
+}
+
+static int odb_source_files_write_object_stream(struct odb_source *source,
+						struct odb_write_stream *stream,
+						size_t len,
+						struct object_id *oid)
+{
+	return odb_source_loose_write_stream(source, stream, len, oid);
+}
+
+static int odb_source_files_begin_transaction(struct odb_source *source,
+					      struct odb_transaction **out)
+{
+	struct odb_transaction *tx = odb_transaction_files_begin(source);
+	if (!tx)
+		return -1;
+	*out = tx;
+	return 0;
+}
+
+static int odb_source_files_read_alternates(struct odb_source *source,
+					    struct strvec *out)
+{
+	struct strbuf buf = STRBUF_INIT;
+	char *path;
+
+	path = xstrfmt("%s/info/alternates", source->path);
+	if (strbuf_read_file(&buf, path, 1024) < 0) {
+		warn_on_fopen_errors(path);
+		free(path);
+		return 0;
+	}
+	parse_alternates(buf.buf, '\n', source->path, out);
+
+	strbuf_release(&buf);
+	free(path);
+	return 0;
+}
+
+static int odb_source_files_write_alternate(struct odb_source *source,
+					    const char *alternate)
+{
+	struct lock_file lock = LOCK_INIT;
+	char *path = xstrfmt("%s/%s", source->path, "info/alternates");
+	FILE *in, *out;
+	int found = 0;
+	int ret;
+
+	hold_lock_file_for_update(&lock, path, LOCK_DIE_ON_ERROR);
+	out = fdopen_lock_file(&lock, "w");
+	if (!out) {
+		ret = error_errno(_("unable to fdopen alternates lockfile"));
+		goto out;
+	}
+
+	in = fopen(path, "r");
+	if (in) {
+		struct strbuf line = STRBUF_INIT;
+
+		while (strbuf_getline(&line, in) != EOF) {
+			if (!strcmp(alternate, line.buf)) {
+				found = 1;
+				break;
+			}
+			fprintf_or_die(out, "%s\n", line.buf);
+		}
+
+		strbuf_release(&line);
+		fclose(in);
+	} else if (errno != ENOENT) {
+		ret = error_errno(_("unable to read alternates file"));
+		goto out;
+	}
+
+	if (found) {
+		rollback_lock_file(&lock);
+	} else {
+		fprintf_or_die(out, "%s\n", alternate);
+		if (commit_lock_file(&lock)) {
+			ret = error_errno(_("unable to move new alternates file into place"));
+			goto out;
+		}
+	}
+
+	ret = 0;
+
+out:
+	free(path);
+	return ret;
+}
+
+struct odb_source_files *odb_source_files_new(struct object_database *odb,
+					      const char *path,
+					      bool local)
+{
+	struct odb_source_files *files;
+
+	CALLOC_ARRAY(files, 1);
+	odb_source_init(&files->base, odb, ODB_SOURCE_FILES, path, local);
+	files->loose = odb_source_loose_new(&files->base);
+	files->packed = packfile_store_new(&files->base);
+
+	files->base.free = odb_source_files_free;
+	files->base.close = odb_source_files_close;
+	files->base.reprepare = odb_source_files_reprepare;
+	files->base.read_object_info = odb_source_files_read_object_info;
+	files->base.read_object_stream = odb_source_files_read_object_stream;
+	files->base.for_each_object = odb_source_files_for_each_object;
+	files->base.count_objects = odb_source_files_count_objects;
+	files->base.freshen_object = odb_source_files_freshen_object;
+	files->base.write_object = odb_source_files_write_object;
+	files->base.write_object_stream = odb_source_files_write_object_stream;
+	files->base.begin_transaction = odb_source_files_begin_transaction;
+	files->base.read_alternates = odb_source_files_read_alternates;
+	files->base.write_alternate = odb_source_files_write_alternate;
+
+	/*
+	 * Ideally, we would only ever store absolute paths in the source. This
+	 * is not (yet) possible though because we access and assume relative
+	 * paths in the primary ODB source in some user-facing functionality.
+	 */
+	if (!is_absolute_path(path))
+		chdir_notify_register(NULL, odb_source_files_reparent, files);
+
+	return files;
+}
diff --git a/odb/source-files.h b/odb/source-files.h
new file mode 100644
index 0000000..23a3b4e
--- /dev/null
+++ b/odb/source-files.h
@@ -0,0 +1,35 @@
+#ifndef ODB_SOURCE_FILES_H
+#define ODB_SOURCE_FILES_H
+
+#include "odb/source.h"
+
+struct odb_source_loose;
+struct packfile_store;
+
+/*
+ * The files object database source uses a combination of loose objects and
+ * packfiles. It is the default backend used by Git to store objects.
+ */
+struct odb_source_files {
+	struct odb_source base;
+	struct odb_source_loose *loose;
+	struct packfile_store *packed;
+};
+
+/* Allocate and initialize a new object source. */
+struct odb_source_files *odb_source_files_new(struct object_database *odb,
+					      const char *path,
+					      bool local);
+
+/*
+ * Cast the given object database source to the files backend. This will cause
+ * a BUG in case the source doesn't use this backend.
+ */
+static inline struct odb_source_files *odb_source_files_downcast(struct odb_source *source)
+{
+	if (source->type != ODB_SOURCE_FILES)
+		BUG("trying to downcast source of type '%d' to files", source->type);
+	return container_of(source, struct odb_source_files, base);
+}
+
+#endif
diff --git a/odb/source.c b/odb/source.c
new file mode 100644
index 0000000..7993dcb
--- /dev/null
+++ b/odb/source.c
@@ -0,0 +1,38 @@
+#include "git-compat-util.h"
+#include "object-file.h"
+#include "odb/source-files.h"
+#include "odb/source.h"
+#include "packfile.h"
+
+struct odb_source *odb_source_new(struct object_database *odb,
+				  const char *path,
+				  bool local)
+{
+	return &odb_source_files_new(odb, path, local)->base;
+}
+
+void odb_source_init(struct odb_source *source,
+		     struct object_database *odb,
+		     enum odb_source_type type,
+		     const char *path,
+		     bool local)
+{
+	source->odb = odb;
+	source->type = type;
+	source->local = local;
+	source->path = xstrdup(path);
+}
+
+void odb_source_free(struct odb_source *source)
+{
+	if (!source)
+		return;
+	source->free(source);
+}
+
+void odb_source_release(struct odb_source *source)
+{
+	if (!source)
+		return;
+	free(source->path);
+}
diff --git a/odb/source.h b/odb/source.h
new file mode 100644
index 0000000..96c906e
--- /dev/null
+++ b/odb/source.h
@@ -0,0 +1,445 @@
+#ifndef ODB_SOURCE_H
+#define ODB_SOURCE_H
+
+#include "object.h"
+#include "odb.h"
+
+enum odb_source_type {
+	/*
+	 * The "unknown" type, which should never be in use. This type mostly
+	 * exists to catch cases where the type field remains zeroed out.
+	 */
+	ODB_SOURCE_UNKNOWN,
+
+	/* The "files" backend that uses loose objects and packfiles. */
+	ODB_SOURCE_FILES,
+};
+
+struct object_id;
+struct odb_read_stream;
+struct strvec;
+
+/*
+ * The source is the part of the object database that stores the actual
+ * objects. It thus encapsulates the logic to read and write the specific
+ * on-disk format. An object database can have multiple sources:
+ *
+ *   - The primary source, which is typically located in "$GIT_DIR/objects".
+ *     This is where new objects are usually written to.
+ *
+ *   - Alternate sources, which are configured via "objects/info/alternates" or
+ *     via the GIT_ALTERNATE_OBJECT_DIRECTORIES environment variable. These
+ *     alternate sources are only used to read objects.
+ */
+struct odb_source {
+	struct odb_source *next;
+
+	/* Object database that owns this object source. */
+	struct object_database *odb;
+
+	/* The type used by this source. */
+	enum odb_source_type type;
+
+	/*
+	 * Figure out whether this is the local source of the owning
+	 * repository, which would typically be its ".git/objects" directory.
+	 * This local object directory is usually where objects would be
+	 * written to.
+	 */
+	bool local;
+
+	/*
+	 * This object store is ephemeral, so there is no need to fsync.
+	 */
+	int will_destroy;
+
+	/*
+	 * Path to the source. If this is a relative path, it is relative to
+	 * the current working directory.
+	 */
+	char *path;
+
+	/*
+	 * This callback is expected to free the underlying object database source and
+	 * all associated resources. The function will never be called with a NULL pointer.
+	 */
+	void (*free)(struct odb_source *source);
+
+	/*
+	 * This callback is expected to close any open resources, like for
+	 * example file descriptors or connections. The source is expected to
+	 * still be usable after it has been closed. Closed resources may need
+	 * to be reopened in that case.
+	 */
+	void (*close)(struct odb_source *source);
+
+	/*
+	 * This callback is expected to clear underlying caches of the object
+	 * database source. The function is called when the repository has for
+	 * example just been repacked so that new objects will become visible.
+	 */
+	void (*reprepare)(struct odb_source *source);
+
+	/*
+	 * This callback is expected to read object information from the object
+	 * database source. The object info will be partially populated with
+	 * pointers for each bit of information that was requested by the
+	 * caller.
+	 *
+	 * The flags field is a combination of `OBJECT_INFO` flags. Only the
+	 * following fields need to be handled by the backend:
+	 *
+	 *   - `OBJECT_INFO_QUICK` indicates it is fine to use caches without
+	 *     re-verifying the data.
+	 *
+	 *   - `OBJECT_INFO_SECOND_READ` indicates that the initial object
+	 *     lookup has failed and that the object sources should check
+	 *     whether any of its on-disk state has changed that may have
+	 *     caused the object to appear. Sources are free to ignore the
+	 *     second read in case they know that the first read would have
+	 *     already surfaced the object without reloading any on-disk state.
+	 *
+	 * The callback is expected to return a negative error code in case
+	 * reading the object has failed, 0 otherwise.
+	 */
+	int (*read_object_info)(struct odb_source *source,
+				const struct object_id *oid,
+				struct object_info *oi,
+				enum object_info_flags flags);
+
+	/*
+	 * This callback is expected to create a new read stream that can be
+	 * used to stream the object identified by the given ID.
+	 *
+	 * The callback is expected to return a negative error code in case
+	 * creating the object stream has failed, 0 otherwise.
+	 */
+	int (*read_object_stream)(struct odb_read_stream **out,
+				  struct odb_source *source,
+				  const struct object_id *oid);
+
+	/*
+	 * This callback is expected to iterate over all objects stored in this
+	 * source and invoke the callback function for each of them. It is
+	 * valid to yield the same object multiple time. A non-zero exit code
+	 * from the object callback shall abort iteration.
+	 *
+	 * The optional `request` structure should serve as a template for
+	 * looking up object info for every individual iterated object. It
+	 * should not be modified directly and should instead be copied into a
+	 * separate `struct object_info` that gets passed to the callback. If
+	 * the caller passes a `NULL` pointer then the object itself shall not
+	 * be read.
+	 *
+	 * The callback is expected to return a negative error code in case the
+	 * iteration has failed to read all objects, 0 otherwise. When the
+	 * callback function returns a non-zero error code then that error code
+	 * should be returned.
+	 */
+	int (*for_each_object)(struct odb_source *source,
+			       const struct object_info *request,
+			       odb_for_each_object_cb cb,
+			       void *cb_data,
+			       unsigned flags);
+
+	/*
+	 * This callback is expected to count objects in the given object
+	 * database source. The callback function does not have to guarantee
+	 * that only unique objects are counted. The result shall be assigned
+	 * to the `out` pointer.
+	 *
+	 * Accepts `enum odb_count_objects_flag` flags to alter the behaviour.
+	 *
+	 * The callback is expected to return 0 on success, or a negative error
+	 * code otherwise.
+	 */
+	int (*count_objects)(struct odb_source *source,
+			     enum odb_count_objects_flags flags,
+			     unsigned long *out);
+
+	/*
+	 * This callback is expected to freshen the given object so that its
+	 * last access time is set to the current time. This is used to ensure
+	 * that objects that are recent will not get garbage collected even if
+	 * they were unreachable.
+	 *
+	 * Returns 0 in case the object does not exist, 1 in case the object
+	 * has been freshened.
+	 */
+	int (*freshen_object)(struct odb_source *source,
+			      const struct object_id *oid);
+
+	/*
+	 * This callback is expected to persist the given object into the
+	 * object source. In case the object already exists it shall be
+	 * freshened.
+	 *
+	 * The flags field is a combination of `WRITE_OBJECT` flags.
+	 *
+	 * The resulting object ID (and optionally the compatibility object ID)
+	 * shall be written into the out pointers. The callback is expected to
+	 * return 0 on success, a negative error code otherwise.
+	 */
+	int (*write_object)(struct odb_source *source,
+			    const void *buf, unsigned long len,
+			    enum object_type type,
+			    struct object_id *oid,
+			    struct object_id *compat_oid,
+			    unsigned flags);
+
+	/*
+	 * This callback is expected to persist the given object stream into
+	 * the object source.
+	 *
+	 * The resulting object ID shall be written into the out pointer. The
+	 * callback is expected to return 0 on success, a negative error code
+	 * otherwise.
+	 */
+	int (*write_object_stream)(struct odb_source *source,
+				   struct odb_write_stream *stream, size_t len,
+				   struct object_id *oid);
+
+	/*
+	 * This callback is expected to create a new transaction that can be
+	 * used to write objects to. The objects shall only be persisted into
+	 * the object database when the transcation's commit function is
+	 * called. Otherwise, the objects shall be discarded.
+	 *
+	 * Returns 0 on success, in which case the `*out` pointer will have
+	 * been populated with the object database transaction. Returns a
+	 * negative error code otherwise.
+	 */
+	int (*begin_transaction)(struct odb_source *source,
+				 struct odb_transaction **out);
+
+	/*
+	 * This callback is expected to read the list of alternate object
+	 * database sources connected to it and write them into the `strvec`.
+	 *
+	 * The result is expected to be paths to the alternates. All paths must
+	 * be resolved to absolute paths.
+	 *
+	 * The callback is expected to return 0 on success, a negative error
+	 * code otherwise.
+	 */
+	int (*read_alternates)(struct odb_source *source,
+			       struct strvec *out);
+
+	/*
+	 * This callback is expected to persist the singular alternate passed
+	 * to it into its list of alternates. Any pre-existing alternates are
+	 * expected to remain active. Subsequent calls to `read_alternates` are
+	 * thus expected to yield the pre-existing list of alternates plus the
+	 * newly added alternate appended to its end.
+	 *
+	 * The callback is expected to return 0 on success, a negative error
+	 * code otherwise.
+	 */
+	int (*write_alternate)(struct odb_source *source,
+			       const char *alternate);
+};
+
+/*
+ * Allocate and initialize a new source for the given object database located
+ * at `path`. `local` indicates whether or not the source is the local and thus
+ * primary object source of the object database.
+ */
+struct odb_source *odb_source_new(struct object_database *odb,
+				  const char *path,
+				  bool local);
+
+/*
+ * Initialize the source for the given object database located at `path`.
+ * `local` indicates whether or not the source is the local and thus primary
+ * object source of the object database.
+ *
+ * This function is only supposed to be called by specific object source
+ * implementations.
+ */
+void odb_source_init(struct odb_source *source,
+		     struct object_database *odb,
+		     enum odb_source_type type,
+		     const char *path,
+		     bool local);
+
+/*
+ * Free the object database source, releasing all associated resources and
+ * freeing the structure itself.
+ */
+void odb_source_free(struct odb_source *source);
+
+/*
+ * Release the object database source, releasing all associated resources.
+ *
+ * This function is only supposed to be called by specific object source
+ * implementations.
+ */
+void odb_source_release(struct odb_source *source);
+
+/*
+ * Close the object database source without releasing he underlying data. The
+ * source can still be used going forward, but it first needs to be reopened.
+ * This can be useful to reduce resource usage.
+ */
+static inline void odb_source_close(struct odb_source *source)
+{
+	source->close(source);
+}
+
+/*
+ * Reprepare the object database source and clear any caches. Depending on the
+ * backend used this may have the effect that concurrently-written objects
+ * become visible.
+ */
+static inline void odb_source_reprepare(struct odb_source *source)
+{
+	source->reprepare(source);
+}
+
+/*
+ * Read an object from the object database source identified by its object ID.
+ * Returns 0 on success, a negative error code otherwise.
+ */
+static inline int odb_source_read_object_info(struct odb_source *source,
+					      const struct object_id *oid,
+					      struct object_info *oi,
+					      enum object_info_flags flags)
+{
+	return source->read_object_info(source, oid, oi, flags);
+}
+
+/*
+ * Create a new read stream for the given object ID. Returns 0 on success, a
+ * negative error code otherwise.
+ */
+static inline int odb_source_read_object_stream(struct odb_read_stream **out,
+						struct odb_source *source,
+						const struct object_id *oid)
+{
+	return source->read_object_stream(out, source, oid);
+}
+
+/*
+ * Iterate through all objects contained in the given source and invoke the
+ * callback function for each of them. Returning a non-zero code from the
+ * callback function aborts iteration. There is no guarantee that objects
+ * are only iterated over once.
+ *
+ * The optional `request` structure serves as a template for retrieving the
+ * object info for each indvidual iterated object and will be populated as if
+ * `odb_source_read_object_info()` was called on the object. It will not be
+ * modified, the callback will instead be invoked with a separate `struct
+ * object_info` for every object. Object info will not be read when passing a
+ * `NULL` pointer.
+ *
+ * The flags is a bitfield of `ODB_FOR_EACH_OBJECT_*` flags. Not all flags may
+ * apply to a specific backend, so whether or not they are honored is defined
+ * by the implementation.
+ *
+ * Returns 0 when all objects have been iterated over, a negative error code in
+ * case iteration has failed, or a non-zero value returned from the callback.
+ */
+static inline int odb_source_for_each_object(struct odb_source *source,
+					     const struct object_info *request,
+					     odb_for_each_object_cb cb,
+					     void *cb_data,
+					     unsigned flags)
+{
+	return source->for_each_object(source, request, cb, cb_data, flags);
+}
+
+/*
+ * Count the number of objects in the given object database source.
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ */
+static inline int odb_source_count_objects(struct odb_source *source,
+					   enum odb_count_objects_flags flags,
+					   unsigned long *out)
+{
+	return source->count_objects(source, flags, out);
+}
+
+/*
+ * Freshen an object in the object database by updating its timestamp.
+ * Returns 1 in case the object has been freshened, 0 in case the object does
+ * not exist.
+ */
+static inline int odb_source_freshen_object(struct odb_source *source,
+					    const struct object_id *oid)
+{
+	return source->freshen_object(source, oid);
+}
+
+/*
+ * Write an object into the object database source. Returns 0 on success, a
+ * negative error code otherwise. Populates the given out pointers for the
+ * object ID and the compatibility object ID, if non-NULL.
+ */
+static inline int odb_source_write_object(struct odb_source *source,
+					  const void *buf, unsigned long len,
+					  enum object_type type,
+					  struct object_id *oid,
+					  struct object_id *compat_oid,
+					  unsigned flags)
+{
+	return source->write_object(source, buf, len, type, oid,
+				    compat_oid, flags);
+}
+
+/*
+ * Write an object into the object database source via a stream. The overall
+ * length of the object must be known in advance.
+ *
+ * Return 0 on success, a negative error code otherwise. Populates the given
+ * out pointer for the object ID.
+ */
+static inline int odb_source_write_object_stream(struct odb_source *source,
+						 struct odb_write_stream *stream,
+						 size_t len,
+						 struct object_id *oid)
+{
+	return source->write_object_stream(source, stream, len, oid);
+}
+
+/*
+ * Read the list of alternative object database sources from the given backend
+ * and populate the `strvec` with them. The listing is not recursive -- that
+ * is, if any of the yielded alternate sources has alternates itself, those
+ * will not be yielded as part of this function call.
+ *
+ * Return 0 on success, a negative error code otherwise.
+ */
+static inline int odb_source_read_alternates(struct odb_source *source,
+					     struct strvec *out)
+{
+	return source->read_alternates(source, out);
+}
+
+/*
+ * Write and persist a new alternate object database source for the given
+ * source. Any preexisting alternates are expected to stay valid, and the new
+ * alternate shall be appended to the end of the list.
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ */
+static inline int odb_source_write_alternate(struct odb_source *source,
+					      const char *alternate)
+{
+	return source->write_alternate(source, alternate);
+}
+
+/*
+ * Create a new transaction that can be used to write objects into a temporary
+ * staging area. The objects will only be persisted when the transaction is
+ * committed.
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ */
+static inline int odb_source_begin_transaction(struct odb_source *source,
+					       struct odb_transaction **out)
+{
+	return source->begin_transaction(source, out);
+}
+
+#endif
diff --git a/odb/streaming.c b/odb/streaming.c
index 4a4474f..5927a12 100644
--- a/odb/streaming.c
+++ b/odb/streaming.c
@@ -6,11 +6,10 @@
 #include "convert.h"
 #include "environment.h"
 #include "repository.h"
-#include "object-file.h"
 #include "odb.h"
+#include "odb/source.h"
 #include "odb/streaming.h"
 #include "replace-object.h"
-#include "packfile.h"
 
 #define FILTER_BUFFER (1024*16)
 
@@ -186,11 +185,9 @@ static int istream_source(struct odb_read_stream **out,
 	struct odb_source *source;
 
 	odb_prepare_alternates(odb);
-	for (source = odb->sources; source; source = source->next) {
-		if (!packfile_store_read_object_stream(out, source->packfiles, oid) ||
-		    !odb_source_loose_read_object_stream(out, source, oid))
+	for (source = odb->sources; source; source = source->next)
+		if (!odb_source_read_object_stream(out, source, oid))
 			return 0;
-	}
 
 	return open_istream_incore(out, odb, oid);
 }
diff --git a/pack-bitmap.c b/pack-bitmap.c
index 22419bf..f6ec18d 100644
--- a/pack-bitmap.c
+++ b/pack-bitmap.c
@@ -441,11 +441,11 @@ char *midx_bitmap_filename(struct multi_pack_index *midx)
 	struct strbuf buf = STRBUF_INIT;
 	if (midx->has_chain)
 		get_split_midx_filename_ext(midx->source, &buf,
-					    get_midx_checksum(midx),
+					    midx_get_checksum_hash(midx),
 					    MIDX_EXT_BITMAP);
 	else
 		get_midx_filename_ext(midx->source, &buf,
-				      get_midx_checksum(midx),
+				      midx_get_checksum_hash(midx),
 				      MIDX_EXT_BITMAP);
 
 	return strbuf_detach(&buf, NULL);
@@ -502,7 +502,7 @@ static int open_midx_bitmap_1(struct bitmap_index *bitmap_git,
 	if (load_bitmap_header(bitmap_git) < 0)
 		goto cleanup;
 
-	if (!hasheq(get_midx_checksum(bitmap_git->midx), bitmap_git->checksum,
+	if (!hasheq(midx_get_checksum_hash(bitmap_git->midx), bitmap_git->checksum,
 		    bitmap_repo(bitmap_git)->hash_algo)) {
 		error(_("checksum doesn't match in MIDX and bitmap"));
 		goto cleanup;
@@ -2819,8 +2819,7 @@ void test_bitmap_walk(struct rev_info *revs)
 
 		if (bitmap_is_midx(found))
 			fprintf_ln(stderr, "Located via MIDX '%s'.",
-				   hash_to_hex_algop(get_midx_checksum(found->midx),
-						     revs->repo->hash_algo));
+				   midx_get_checksum_hex(found->midx));
 		else
 			fprintf_ln(stderr, "Located via pack '%s'.",
 				   hash_to_hex_algop(found->pack->hash,
diff --git a/pack-revindex.c b/pack-revindex.c
index 56cd803..1b67863 100644
--- a/pack-revindex.c
+++ b/pack-revindex.c
@@ -277,6 +277,10 @@ int load_pack_revindex_from_disk(struct packed_git *p)
 {
 	char *revindex_name;
 	int ret;
+
+	if (p->revindex_data)
+		return 0;
+
 	if (open_pack_index(p))
 		return -1;
 
@@ -390,11 +394,11 @@ int load_midx_revindex(struct multi_pack_index *m)
 
 	if (m->has_chain)
 		get_split_midx_filename_ext(m->source, &revindex_name,
-					    get_midx_checksum(m),
+					    midx_get_checksum_hash(m),
 					    MIDX_EXT_REV);
 	else
 		get_midx_filename_ext(m->source, &revindex_name,
-				      get_midx_checksum(m),
+				      midx_get_checksum_hash(m),
 				      MIDX_EXT_REV);
 
 	ret = load_revindex_from_disk(m->source->odb->repo->hash_algo,
diff --git a/packfile.c b/packfile.c
index 4a6d4a8..d4de9f3 100644
--- a/packfile.c
+++ b/packfile.c
@@ -362,9 +362,11 @@ static int unuse_one_window(struct object_database *odb)
 	struct packed_git *lru_p = NULL;
 	struct pack_window *lru_w = NULL, *lru_l = NULL;
 
-	for (source = odb->sources; source; source = source->next)
-		for (e = source->packfiles->packs.head; e; e = e->next)
+	for (source = odb->sources; source; source = source->next) {
+		struct odb_source_files *files = odb_source_files_downcast(source);
+		for (e = files->packed->packs.head; e; e = e->next)
 			scan_windows(e->pack, &lru_p, &lru_w, &lru_l);
+	}
 
 	if (lru_p) {
 		munmap(lru_w->base, lru_w->len);
@@ -537,7 +539,8 @@ static int close_one_pack(struct repository *r)
 	int accept_windows_inuse = 1;
 
 	for (source = r->objects->sources; source; source = source->next) {
-		for (e = source->packfiles->packs.head; e; e = e->next) {
+		struct odb_source_files *files = odb_source_files_downcast(source);
+		for (e = files->packed->packs.head; e; e = e->next) {
 			if (e->pack->pack_fd == -1)
 				continue;
 			find_lru_pack(e->pack, &lru_p, &mru_w, &accept_windows_inuse);
@@ -987,13 +990,14 @@ static void prepare_pack(const char *full_name, size_t full_name_len,
 			 const char *file_name, void *_data)
 {
 	struct prepare_pack_data *data = (struct prepare_pack_data *)_data;
+	struct odb_source_files *files = odb_source_files_downcast(data->source);
 	size_t base_len = full_name_len;
 
 	if (strip_suffix_mem(full_name, &base_len, ".idx") &&
-	    !(data->source->packfiles->midx &&
-	      midx_contains_pack(data->source->packfiles->midx, file_name))) {
+	    !(files->packed->midx &&
+	      midx_contains_pack(files->packed->midx, file_name))) {
 		char *trimmed_path = xstrndup(full_name, full_name_len);
-		packfile_store_load_pack(data->source->packfiles,
+		packfile_store_load_pack(files->packed,
 					 trimmed_path, data->source->local);
 		free(trimmed_path);
 	}
@@ -1097,37 +1101,35 @@ struct packfile_list_entry *packfile_store_get_packs(struct packfile_store *stor
 	return store->packs.head;
 }
 
-/*
- * Give a fast, rough count of the number of objects in the repository. This
- * ignores loose objects completely. If you have a lot of them, then either
- * you should repack because your performance will be awful, or they are
- * all unreachable objects about to be pruned, in which case they're not really
- * interesting as a measure of repo size in the first place.
- */
-unsigned long repo_approximate_object_count(struct repository *r)
+int packfile_store_count_objects(struct packfile_store *store,
+				 enum odb_count_objects_flags flags UNUSED,
+				 unsigned long *out)
 {
-	if (!r->objects->approximate_object_count_valid) {
-		struct odb_source *source;
-		unsigned long count = 0;
-		struct packed_git *p;
+	struct packfile_list_entry *e;
+	struct multi_pack_index *m;
+	unsigned long count = 0;
+	int ret;
 
-		odb_prepare_alternates(r->objects);
+	m = get_multi_pack_index(store->source);
+	if (m)
+		count += m->num_objects + m->num_objects_in_base;
 
-		for (source = r->objects->sources; source; source = source->next) {
-			struct multi_pack_index *m = get_multi_pack_index(source);
-			if (m)
-				count += m->num_objects + m->num_objects_in_base;
+	for (e = packfile_store_get_packs(store); e; e = e->next) {
+		if (e->pack->multi_pack_index)
+			continue;
+		if (open_pack_index(e->pack)) {
+			ret = -1;
+			goto out;
 		}
 
-		repo_for_each_pack(r, p) {
-			if (p->multi_pack_index || open_pack_index(p))
-				continue;
-			count += p->num_objects;
-		}
-		r->objects->approximate_object_count = count;
-		r->objects->approximate_object_count_valid = 1;
+		count += e->pack->num_objects;
 	}
-	return r->objects->approximate_object_count;
+
+	*out = count;
+	ret = 0;
+
+out:
+	return ret;
 }
 
 unsigned long unpack_object_header_buffer(const unsigned char *buf,
@@ -1247,8 +1249,10 @@ const struct packed_git *has_packed_and_bad(struct repository *r,
 	struct odb_source *source;
 
 	for (source = r->objects->sources; source; source = source->next) {
+		struct odb_source_files *files = odb_source_files_downcast(source);
 		struct packfile_list_entry *e;
-		for (e = source->packfiles->packs.head; e; e = e->next)
+
+		for (e = files->packed->packs.head; e; e = e->next)
 			if (oidset_contains(&e->pack->bad_objects, oid))
 				return e->pack;
 	}
@@ -2175,11 +2179,19 @@ int packfile_store_freshen_object(struct packfile_store *store,
 int packfile_store_read_object_info(struct packfile_store *store,
 				    const struct object_id *oid,
 				    struct object_info *oi,
-				    enum object_info_flags flags UNUSED)
+				    enum object_info_flags flags)
 {
 	struct pack_entry e;
 	int ret;
 
+	/*
+	 * In case the first read didn't surface the object, we have to reload
+	 * packfiles. This may cause us to discover new packfiles that have
+	 * been added since the last time we have prepared the packfile store.
+	 */
+	if (flags & OBJECT_INFO_SECOND_READ)
+		packfile_store_reprepare(store);
+
 	if (!find_pack_entry(store, oid, &e))
 		return 1;
 
@@ -2254,7 +2266,8 @@ int has_object_pack(struct repository *r, const struct object_id *oid)
 
 	odb_prepare_alternates(r->objects);
 	for (source = r->objects->sources; source; source = source->next) {
-		int ret = find_pack_entry(source->packfiles, oid, &e);
+		struct odb_source_files *files = odb_source_files_downcast(source);
+		int ret = find_pack_entry(files->packed, oid, &e);
 		if (ret)
 			return ret;
 	}
@@ -2269,9 +2282,10 @@ int has_object_kept_pack(struct repository *r, const struct object_id *oid,
 	struct pack_entry e;
 
 	for (source = r->objects->sources; source; source = source->next) {
+		struct odb_source_files *files = odb_source_files_downcast(source);
 		struct packed_git **cache;
 
-		cache = packfile_store_get_kept_pack_cache(source->packfiles, flags);
+		cache = packfile_store_get_kept_pack_cache(files->packed, flags);
 
 		for (; *cache; cache++) {
 			struct packed_git *p = *cache;
diff --git a/packfile.h b/packfile.h
index 85ce44f..a16ec39 100644
--- a/packfile.h
+++ b/packfile.h
@@ -4,6 +4,7 @@
 #include "list.h"
 #include "object.h"
 #include "odb.h"
+#include "odb/source-files.h"
 #include "oidset.h"
 #include "repository.h"
 #include "strmap.h"
@@ -192,7 +193,8 @@ static inline struct repo_for_each_pack_data repo_for_eack_pack_data_init(struct
 	odb_prepare_alternates(repo->objects);
 
 	for (struct odb_source *source = repo->objects->sources; source; source = source->next) {
-		struct packfile_list_entry *entry = packfile_store_get_packs(source->packfiles);
+		struct odb_source_files *files = odb_source_files_downcast(source);
+		struct packfile_list_entry *entry = packfile_store_get_packs(files->packed);
 		if (!entry)
 			continue;
 		data.source = source;
@@ -212,7 +214,8 @@ static inline void repo_for_each_pack_data_next(struct repo_for_each_pack_data *
 		return;
 
 	for (source = data->source->next; source; source = source->next) {
-		struct packfile_list_entry *entry = packfile_store_get_packs(source->packfiles);
+		struct odb_source_files *files = odb_source_files_downcast(source);
+		struct packfile_list_entry *entry = packfile_store_get_packs(files->packed);
 		if (!entry)
 			continue;
 		data->source = source;
@@ -266,6 +269,16 @@ enum kept_pack_type {
 };
 
 /*
+ * Count the number objects contained in the given packfile store. If
+ * successful, the number of objects will be written to the `out` pointer.
+ *
+ * Return 0 on success, a negative error code otherwise.
+ */
+int packfile_store_count_objects(struct packfile_store *store,
+				 enum odb_count_objects_flags flags,
+				 unsigned long *out);
+
+/*
  * Retrieve the cache of kept packs from the given packfile store. Accepts a
  * combination of `kept_pack_type` flags. The cache is computed on demand and
  * will be recomputed whenever the flags change.
@@ -362,12 +375,6 @@ int packfile_store_for_each_object(struct packfile_store *store,
 #define PACKDIR_FILE_GARBAGE 4
 extern void (*report_garbage)(unsigned seen_bits, const char *path);
 
-/*
- * Give a rough count of objects in the repository. This sacrifices accuracy
- * for speed.
- */
-unsigned long repo_approximate_object_count(struct repository *r);
-
 void pack_report(struct repository *repo);
 
 /*
diff --git a/patch-ids.c b/patch-ids.c
index a5683b4..1fbc88c 100644
--- a/patch-ids.c
+++ b/patch-ids.c
@@ -41,7 +41,14 @@ static int patch_id_neq(const void *cmpfn_data,
 			const struct hashmap_entry *entry_or_key,
 			const void *keydata UNUSED)
 {
-	/* NEEDSWORK: const correctness? */
+	/*
+	 * We drop the 'const' modifier here intentionally.
+	 *
+	 * Even though eptr and entry_or_key are const, we want to
+	 * lazily compute their .patch_id members; see b3dfeebb (rebase:
+	 * avoid computing unnecessary patch IDs, 2016-07-29). So we cast
+	 * the constness away with container_of().
+	 */
 	struct diff_options *opt = (void *)cmpfn_data;
 	struct patch_id *a, *b;
 
diff --git a/range-diff.c b/range-diff.c
index 57edff4..2712a9a 100644
--- a/range-diff.c
+++ b/range-diff.c
@@ -140,7 +140,7 @@ static int read_patches(const char *range, struct string_list *list,
 			if (eol)
 				*eol = '\n';
 			orig_len = len;
-			len = parse_git_diff_header(&root, &linenr, 0, line,
+			len = parse_git_diff_header(&root, NULL, &linenr, 0, line,
 						    len, size, &patch);
 			if (len < 0) {
 				error(_("could not parse git header '%.*s'"),
diff --git a/refs.c b/refs.c
index 6fb8f9d..685a0c2 100644
--- a/refs.c
+++ b/refs.c
@@ -64,6 +64,9 @@ const char *ref_storage_format_to_name(enum ref_storage_format ref_storage_forma
 	return be->name;
 }
 
+static const char *abort_by_ref_transaction_hook =
+	N_("in '%s' phase, update aborted by the reference-transaction hook");
+
 /*
  * How to handle various characters in refnames:
  * 0: An acceptable character for refs
@@ -740,7 +743,8 @@ static char *substitute_branch_name(struct repository *r,
 	return NULL;
 }
 
-void copy_branchname(struct strbuf *sb, const char *name, unsigned allowed)
+void copy_branchname(struct strbuf *sb, const char *name,
+		     enum interpret_branch_kind allowed)
 {
 	int len = strlen(name);
 	struct interpret_branch_name_options options = {
@@ -2655,6 +2659,13 @@ int ref_transaction_prepare(struct ref_transaction *transaction,
 	if (ref_update_reject_duplicates(&transaction->refnames, err))
 		return REF_TRANSACTION_ERROR_GENERIC;
 
+	/* Preparing checks before locking references */
+	ret = run_transaction_hook(transaction, "preparing");
+	if (ret) {
+		ref_transaction_abort(transaction, err);
+		die(_(abort_by_ref_transaction_hook), "preparing");
+	}
+
 	ret = refs->be->transaction_prepare(refs, transaction, err);
 	if (ret)
 		return ret;
@@ -2662,7 +2673,7 @@ int ref_transaction_prepare(struct ref_transaction *transaction,
 	ret = run_transaction_hook(transaction, "prepared");
 	if (ret) {
 		ref_transaction_abort(transaction, err);
-		die(_("ref updates aborted by hook"));
+		die(_(abort_by_ref_transaction_hook), "prepared");
 	}
 
 	return 0;
diff --git a/refs.h b/refs.h
index d98c1fc..d65de6a 100644
--- a/refs.h
+++ b/refs.h
@@ -1,6 +1,7 @@
 #ifndef REFS_H
 #define REFS_H
 
+#include "object-name.h"
 #include "commit.h"
 #include "repository.h"
 #include "repo-settings.h"
@@ -225,7 +226,7 @@ char *repo_default_branch_name(struct repository *r, int quiet);
  * repo_interpret_branch_name() for details.
  */
 void copy_branchname(struct strbuf *sb, const char *name,
-		       unsigned allowed);
+		     enum interpret_branch_kind allowed);
 
 /*
  * Like copy_branchname() above, but confirm that the result is
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 7ce0d57..0537a72 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1813,7 +1813,7 @@ static int commit_ref(struct ref_lock *lock)
 		size_t len = strlen(path);
 		struct strbuf sb_path = STRBUF_INIT;
 
-		strbuf_attach(&sb_path, path, len, len);
+		strbuf_attach(&sb_path, path, len, len + 1);
 
 		/*
 		 * If this fails, commit_lock_file() will also fail
diff --git a/refspec.c b/refspec.c
index 0775358..fb89bce 100644
--- a/refspec.c
+++ b/refspec.c
@@ -85,7 +85,7 @@ static int parse_refspec(struct refspec_item *item, const char *refspec, int fet
 		if (!*item->src)
 			return 0; /* negative refspecs must not be empty */
 		else if (llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))
-			return 0; /* negative refpsecs cannot be exact sha1 */
+			return 0; /* negative refspecs cannot be exact sha1 */
 		else if (!check_refname_format(item->src, flags))
 			; /* valid looking ref is ok */
 		else
diff --git a/remote-curl.c b/remote-curl.c
index 92e40bb..aba60d5 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -529,6 +529,17 @@ static struct discovery *discover_refs(const char *service, int for_push)
 		show_http_message(&type, &charset, &buffer);
 		die(_("unable to access '%s' with http.pinnedPubkey configuration: %s"),
 		    transport_anonymize_url(url.buf), curl_errorstr);
+	case HTTP_RATE_LIMITED:
+		if (http_options.retry_after > 0) {
+			show_http_message(&type, &charset, &buffer);
+			die(_("rate limited by '%s', please try again in %ld seconds"),
+				transport_anonymize_url(url.buf),
+				http_options.retry_after);
+		} else {
+			show_http_message(&type, &charset, &buffer);
+			die(_("rate limited by '%s', please try again later"),
+				transport_anonymize_url(url.buf));
+		}
 	default:
 		show_http_message(&type, &charset, &buffer);
 		die(_("unable to access '%s': %s"),
@@ -1552,6 +1563,13 @@ int cmd_main(int argc, const char **argv)
 		goto cleanup;
 	}
 
+	/*
+	 * yuck, see 9e89dcb66a (builtin/ls-remote: fall back to SHA1 outside
+	 * of a repo, 2024-08-02)
+	 */
+	if (nongit)
+		repo_set_hash_algo(the_repository, GIT_HASH_DEFAULT);
+
 	options.verbosity = 1;
 	options.progress = !!isatty(2);
 	options.thin = 1;
diff --git a/remote.c b/remote.c
index f6980dc..7ca2a65 100644
--- a/remote.c
+++ b/remote.c
@@ -29,6 +29,12 @@
 
 enum map_direction { FROM_SRC, FROM_DST };
 
+enum {
+	ENABLE_ADVICE_PULL       = (1 << 0),
+	ENABLE_ADVICE_PUSH       = (1 << 1),
+	ENABLE_ADVICE_DIVERGENCE = (1 << 2),
+};
+
 struct counted_string {
 	size_t len;
 	const char *s;
@@ -2234,43 +2240,49 @@ int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs,
 	return stat_branch_pair(branch->refname, base, num_ours, num_theirs, abf);
 }
 
-/*
- * Return true when there is anything to report, otherwise false.
- */
-int format_tracking_info(struct branch *branch, struct strbuf *sb,
-			 enum ahead_behind_flags abf,
-			 int show_divergence_advice)
+static char *resolve_compare_branch(struct branch *branch, const char *name)
 {
-	int ours, theirs, sti;
-	const char *full_base;
-	char *base;
-	int upstream_is_gone = 0;
+	const char *resolved = NULL;
 
-	sti = stat_tracking_info(branch, &ours, &theirs, &full_base, 0, abf);
-	if (sti < 0) {
-		if (!full_base)
-			return 0;
-		upstream_is_gone = 1;
+	if (!branch || !name)
+		return NULL;
+
+	if (!strcasecmp(name, "@{upstream}")) {
+		resolved = branch_get_upstream(branch, NULL);
+	} else if (!strcasecmp(name, "@{push}")) {
+		resolved = branch_get_push(branch, NULL);
+	} else {
+		warning(_("ignoring value '%s' for status.compareBranches, "
+			  "only @{upstream} and @{push} are supported"),
+			name);
+		return NULL;
 	}
 
-	base = refs_shorten_unambiguous_ref(get_main_ref_store(the_repository),
-					    full_base, 0);
-	if (upstream_is_gone) {
-		strbuf_addf(sb,
-			_("Your branch is based on '%s', but the upstream is gone.\n"),
-			base);
-		if (advice_enabled(ADVICE_STATUS_HINTS))
-			strbuf_addstr(sb,
-				_("  (use \"git branch --unset-upstream\" to fixup)\n"));
-	} else if (!sti) {
+	if (resolved)
+		return xstrdup(resolved);
+	return NULL;
+}
+
+static void format_branch_comparison(struct strbuf *sb,
+				     bool up_to_date,
+				     int ours, int theirs,
+				     const char *branch_name,
+				     enum ahead_behind_flags abf,
+				     unsigned flags)
+{
+	bool use_push_advice = (flags & ENABLE_ADVICE_PUSH);
+	bool use_pull_advice = (flags & ENABLE_ADVICE_PULL);
+	bool use_divergence_advice = (flags & ENABLE_ADVICE_DIVERGENCE);
+
+	if (up_to_date) {
 		strbuf_addf(sb,
 			_("Your branch is up to date with '%s'.\n"),
-			base);
+			branch_name);
 	} else if (abf == AHEAD_BEHIND_QUICK) {
 		strbuf_addf(sb,
 			    _("Your branch and '%s' refer to different commits.\n"),
-			    base);
-		if (advice_enabled(ADVICE_STATUS_HINTS))
+			    branch_name);
+		if (use_push_advice && advice_enabled(ADVICE_STATUS_HINTS))
 			strbuf_addf(sb, _("  (use \"%s\" for details)\n"),
 				    "git status --ahead-behind");
 	} else if (!theirs) {
@@ -2278,8 +2290,8 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb,
 			Q_("Your branch is ahead of '%s' by %d commit.\n",
 			   "Your branch is ahead of '%s' by %d commits.\n",
 			   ours),
-			base, ours);
-		if (advice_enabled(ADVICE_STATUS_HINTS))
+			branch_name, ours);
+		if (use_push_advice && advice_enabled(ADVICE_STATUS_HINTS))
 			strbuf_addstr(sb,
 				_("  (use \"git push\" to publish your local commits)\n"));
 	} else if (!ours) {
@@ -2289,8 +2301,8 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb,
 			   "Your branch is behind '%s' by %d commits, "
 			       "and can be fast-forwarded.\n",
 			   theirs),
-			base, theirs);
-		if (advice_enabled(ADVICE_STATUS_HINTS))
+			branch_name, theirs);
+		if (use_pull_advice && advice_enabled(ADVICE_STATUS_HINTS))
 			strbuf_addstr(sb,
 				_("  (use \"git pull\" to update your local branch)\n"));
 	} else {
@@ -2302,14 +2314,106 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb,
 			       "and have %d and %d different commits each, "
 			       "respectively.\n",
 			   ours + theirs),
-			base, ours, theirs);
-		if (show_divergence_advice &&
-		    advice_enabled(ADVICE_STATUS_HINTS))
+			branch_name, ours, theirs);
+		if (use_divergence_advice && advice_enabled(ADVICE_STATUS_HINTS))
 			strbuf_addstr(sb,
 				_("  (use \"git pull\" if you want to integrate the remote branch with yours)\n"));
 	}
-	free(base);
-	return 1;
+}
+
+/*
+ * Return true when there is anything to report, otherwise false.
+ */
+int format_tracking_info(struct branch *branch, struct strbuf *sb,
+			 enum ahead_behind_flags abf,
+			 int show_divergence_advice)
+{
+	char *compare_branches = NULL;
+	struct string_list branches = STRING_LIST_INIT_DUP;
+	struct strset processed_refs = STRSET_INIT;
+	int reported = 0;
+	size_t i;
+	const char *upstream_ref;
+	const char *push_ref;
+
+	repo_config_get_string(the_repository, "status.comparebranches",
+			       &compare_branches);
+
+	if (compare_branches) {
+		string_list_split(&branches, compare_branches, " ", -1);
+		string_list_remove_empty_items(&branches, 0);
+	} else {
+		string_list_append(&branches, "@{upstream}");
+	}
+
+	upstream_ref = branch_get_upstream(branch, NULL);
+	push_ref = branch_get_push(branch, NULL);
+
+	for (i = 0; i < branches.nr; i++) {
+		char *full_ref;
+		char *short_ref;
+		int ours, theirs, cmp;
+		int is_upstream, is_push;
+		unsigned flags = 0;
+
+		full_ref = resolve_compare_branch(branch,
+						  branches.items[i].string);
+		if (!full_ref)
+			continue;
+
+		if (!strset_add(&processed_refs, full_ref)) {
+			free(full_ref);
+			continue;
+		}
+
+		short_ref = refs_shorten_unambiguous_ref(
+			get_main_ref_store(the_repository), full_ref, 0);
+
+		is_upstream = upstream_ref && !strcmp(full_ref, upstream_ref);
+		is_push = push_ref && !strcmp(full_ref, push_ref);
+
+		if (is_upstream && (!push_ref || !strcmp(upstream_ref, push_ref)))
+			is_push = 1;
+
+		cmp = stat_branch_pair(branch->refname, full_ref,
+				       &ours, &theirs, abf);
+
+		if (cmp < 0) {
+			if (is_upstream) {
+				strbuf_addf(sb,
+					_("Your branch is based on '%s', but the upstream is gone.\n"),
+					short_ref);
+				if (advice_enabled(ADVICE_STATUS_HINTS))
+					strbuf_addstr(sb,
+						_("  (use \"git branch --unset-upstream\" to fixup)\n"));
+				reported = 1;
+			}
+			free(full_ref);
+			free(short_ref);
+			continue;
+		}
+
+		if (reported)
+			strbuf_addstr(sb, "\n");
+
+		if (is_upstream)
+			flags |= ENABLE_ADVICE_PULL;
+		if (is_push)
+			flags |= ENABLE_ADVICE_PUSH;
+		if (show_divergence_advice && is_upstream)
+			flags |= ENABLE_ADVICE_DIVERGENCE;
+		format_branch_comparison(sb, !cmp, ours, theirs, short_ref,
+					 abf, flags);
+		reported = 1;
+
+		free(full_ref);
+		free(short_ref);
+	}
+
+	string_list_clear(&branches, 0);
+	strset_clear(&processed_refs);
+	free(compare_branches);
+	return reported;
 }
 
 static int one_local_ref(const struct reference *ref, void *cb_data)
diff --git a/repository.c b/repository.c
index 0b8f7ec..9e5537f 100644
--- a/repository.c
+++ b/repository.c
@@ -3,6 +3,7 @@
 #include "repository.h"
 #include "hook.h"
 #include "odb.h"
+#include "odb/source.h"
 #include "config.h"
 #include "gettext.h"
 #include "object.h"
diff --git a/rerere.c b/rerere.c
index 6ec5596..0296700 100644
--- a/rerere.c
+++ b/rerere.c
@@ -403,12 +403,8 @@ static int handle_conflict(struct strbuf *out, struct rerere_io *io,
 			strbuf_addbuf(out, &two);
 			rerere_strbuf_putconflict(out, '>', marker_size);
 			if (ctx) {
-				git_hash_update(ctx, one.buf ?
-						one.buf : "",
-						one.len + 1);
-				git_hash_update(ctx, two.buf ?
-						two.buf : "",
-						two.len + 1);
+				git_hash_update(ctx, one.buf, one.len + 1);
+				git_hash_update(ctx, two.buf, two.len + 1);
 			}
 			break;
 		} else if (hunk == RR_SIDE_1)
diff --git a/run-command.c b/run-command.c
index b27064e..32c290e 100644
--- a/run-command.c
+++ b/run-command.c
@@ -1,4 +1,3 @@
-#define USE_THE_REPOSITORY_VARIABLE
 #define DISABLE_SIGN_COMPARE_WARNINGS
 
 #include "git-compat-util.h"
@@ -742,8 +741,8 @@ int start_command(struct child_process *cmd)
 
 	fflush(NULL);
 
-	if (cmd->close_object_store)
-		odb_close(the_repository->objects);
+	if (cmd->odb_to_close)
+		odb_close(cmd->odb_to_close);
 
 #ifndef GIT_WINDOWS_NATIVE
 {
@@ -1937,11 +1936,12 @@ void run_processes_parallel(const struct run_process_parallel_opts *opts)
 		trace2_region_leave(tr2_category, tr2_label, NULL);
 }
 
-int prepare_auto_maintenance(int quiet, struct child_process *maint)
+int prepare_auto_maintenance(struct repository *r, int quiet,
+			     struct child_process *maint)
 {
 	int enabled, auto_detach;
 
-	if (!repo_config_get_bool(the_repository, "maintenance.auto", &enabled) &&
+	if (!repo_config_get_bool(r, "maintenance.auto", &enabled) &&
 	    !enabled)
 		return 0;
 
@@ -1950,12 +1950,12 @@ int prepare_auto_maintenance(int quiet, struct child_process *maint)
 	 * honoring `gc.autoDetach`. This is somewhat weird, but required to
 	 * retain behaviour from when we used to run git-gc(1) here.
 	 */
-	if (repo_config_get_bool(the_repository, "maintenance.autodetach", &auto_detach) &&
-	    repo_config_get_bool(the_repository, "gc.autodetach", &auto_detach))
+	if (repo_config_get_bool(r, "maintenance.autodetach", &auto_detach) &&
+	    repo_config_get_bool(r, "gc.autodetach", &auto_detach))
 		auto_detach = git_env_bool("GIT_TEST_MAINT_AUTO_DETACH", true);
 
 	maint->git_cmd = 1;
-	maint->close_object_store = 1;
+	maint->odb_to_close = r->objects;
 	strvec_pushl(&maint->args, "maintenance", "run", "--auto", NULL);
 	strvec_push(&maint->args, quiet ? "--quiet" : "--no-quiet");
 	strvec_push(&maint->args, auto_detach ? "--detach" : "--no-detach");
@@ -1963,15 +1963,15 @@ int prepare_auto_maintenance(int quiet, struct child_process *maint)
 	return 1;
 }
 
-int run_auto_maintenance(int quiet)
+int run_auto_maintenance(struct repository *r, int quiet)
 {
 	struct child_process maint = CHILD_PROCESS_INIT;
-	if (!prepare_auto_maintenance(quiet, &maint))
+	if (!prepare_auto_maintenance(r, quiet, &maint))
 		return 0;
 	return run_command(&maint);
 }
 
-void prepare_other_repo_env(struct strvec *env, const char *new_git_dir)
+void sanitize_repo_env(struct strvec *env)
 {
 	const char * const *var;
 
@@ -1980,6 +1980,11 @@ void prepare_other_repo_env(struct strvec *env, const char *new_git_dir)
 		    strcmp(*var, CONFIG_COUNT_ENVIRONMENT))
 			strvec_push(env, *var);
 	}
+}
+
+void prepare_other_repo_env(struct strvec *env, const char *new_git_dir)
+{
+	sanitize_repo_env(env);
 	strvec_pushf(env, "%s=%s", GIT_DIR_ENVIRONMENT, new_git_dir);
 }
 
diff --git a/run-command.h b/run-command.h
index e1ca965..8ca496d 100644
--- a/run-command.h
+++ b/run-command.h
@@ -5,6 +5,8 @@
 
 #include "strvec.h"
 
+struct repository;
+
 /**
  * The run-command API offers a versatile tool to run sub-processes with
  * redirected input and output as well as with a modified environment
@@ -136,7 +138,7 @@ struct child_process {
 	 * want to repack because that would delete `.pack` files (and on
 	 * Windows, you cannot delete files that are still in use).
 	 */
-	unsigned close_object_store:1;
+	struct object_database *odb_to_close;
 
 	unsigned stdout_to_stderr:1;
 	unsigned clean_on_exit:1;
@@ -227,12 +229,13 @@ int run_command(struct child_process *);
  * process has been prepared and is ready to run, or 0 in case auto-maintenance
  * should be skipped.
  */
-int prepare_auto_maintenance(int quiet, struct child_process *maint);
+int prepare_auto_maintenance(struct repository *r, int quiet,
+			     struct child_process *maint);
 
 /*
  * Trigger an auto-gc
  */
-int run_auto_maintenance(int quiet);
+int run_auto_maintenance(struct repository *r, int quiet);
 
 /**
  * Execute the given command, sending "in" to its stdin, and capturing its
@@ -531,12 +534,17 @@ struct run_process_parallel_opts
 void run_processes_parallel(const struct run_process_parallel_opts *opts);
 
 /**
+ * Unset all local-repo GIT_* variables in env; see local_repo_env in
+ * environment.h. GIT_CONFIG_PARAMETERS and GIT_CONFIG_COUNT are preserved
+ * to pass -c and --config-env options from the parent process.
+ */
+void sanitize_repo_env(struct strvec *env);
+
+/**
  * Convenience function which prepares env for a command to be run in a
- * new repo. This adds all GIT_* environment variables to env with the
- * exception of GIT_CONFIG_PARAMETERS and GIT_CONFIG_COUNT (which cause the
- * corresponding environment variables to be unset in the subprocess) and adds
- * an environment variable pointing to new_git_dir. See local_repo_env in
- * environment.h for more information.
+ * new repo. This removes variables pointing to the local repository (using
+ * sanitize_repo_env() above), and adds an environment variable pointing to
+ * new_git_dir.
  */
 void prepare_other_repo_env(struct strvec *env, const char *new_git_dir);
 
diff --git a/send-pack.c b/send-pack.c
index 67d6987..07ecfae 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -391,7 +391,7 @@ static int generate_push_cert(struct strbuf *req_buf,
 	if (!update_seen)
 		goto free_return;
 
-	if (sign_buffer(&cert, &cert, signing_key))
+	if (sign_buffer(&cert, &cert, signing_key, 0))
 		die(_("failed to sign the push certificate"));
 
 	packet_buf_write(req_buf, "push-cert%c%s", 0, cap_string);
diff --git a/sequencer.c b/sequencer.c
index aafd0bc..e5af49c 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -209,6 +209,7 @@ static GIT_PATH_FUNC(rebase_path_reschedule_failed_exec, "rebase-merge/reschedul
 static GIT_PATH_FUNC(rebase_path_no_reschedule_failed_exec, "rebase-merge/no-reschedule-failed-exec")
 static GIT_PATH_FUNC(rebase_path_drop_redundant_commits, "rebase-merge/drop_redundant_commits")
 static GIT_PATH_FUNC(rebase_path_keep_redundant_commits, "rebase-merge/keep_redundant_commits")
+static GIT_PATH_FUNC(rebase_path_trailer, "rebase-merge/trailer")
 
 /*
  * A 'struct replay_ctx' represents the private state of the sequencer.
@@ -420,6 +421,7 @@ void replay_opts_release(struct replay_opts *opts)
 	if (opts->revs)
 		release_revisions(opts->revs);
 	free(opts->revs);
+	strvec_clear(&opts->trailer_args);
 	replay_ctx_release(ctx);
 	free(opts->ctx);
 }
@@ -2027,12 +2029,15 @@ static int append_squash_message(struct strbuf *buf, const char *body,
 	if (is_fixup_flag(command, flag) && !seen_squash(ctx)) {
 		/*
 		 * We're replacing the commit message so we need to
-		 * append the Signed-off-by: trailer if the user
-		 * requested '--signoff'.
+		 * append any trailers if the user requested
+		 * '--signoff' or '--trailer'.
 		 */
 		if (opts->signoff)
 			append_signoff(buf, 0, 0);
 
+		if (opts->trailer_args.nr)
+			amend_strbuf_with_trailers(buf, &opts->trailer_args);
+
 		if ((command == TODO_FIXUP) &&
 		    (flag & TODO_REPLACE_FIXUP_MSG) &&
 		    (file_exists(rebase_path_fixup_msg()) ||
@@ -2451,6 +2456,9 @@ static int do_pick_commit(struct repository *r,
 	if (opts->signoff && !is_fixup(command))
 		append_signoff(&ctx->message, 0, 0);
 
+	if (opts->trailer_args.nr && !is_fixup(command))
+		amend_strbuf_with_trailers(&ctx->message, &opts->trailer_args);
+
 	if (is_rebase_i(opts) && write_author_script(msg.message) < 0)
 		res = -1;
 	else if (!opts->strategy ||
@@ -3180,6 +3188,33 @@ static void read_strategy_opts(struct replay_opts *opts, struct strbuf *buf)
 	parse_strategy_opts(opts, buf->buf);
 }
 
+static int read_trailers(struct replay_opts *opts, struct strbuf *buf)
+{
+	ssize_t len;
+
+	strbuf_reset(buf);
+	len = strbuf_read_file(buf, rebase_path_trailer(), 0);
+	if (len > 0) {
+		char *p = buf->buf, *nl;
+
+		trailer_config_init();
+
+		while ((nl = strchr(p, '\n'))) {
+			*nl = '\0';
+			if (!*p)
+				return error(_("trailers file contains empty line"));
+			strvec_push(&opts->trailer_args, p);
+			p = nl + 1;
+		}
+	} else if (!len) {
+		return error(_("trailers file is empty"));
+	} else if (errno != ENOENT) {
+		return error(_("cannot read trailers files"));
+	}
+
+	return 0;
+}
+
 static int read_populate_opts(struct replay_opts *opts)
 {
 	struct replay_ctx *ctx = opts->ctx;
@@ -3241,6 +3276,11 @@ static int read_populate_opts(struct replay_opts *opts)
 			opts->keep_redundant_commits = 1;
 
 		read_strategy_opts(opts, &buf);
+
+		if (read_trailers(opts, &buf)) {
+			ret = -1;
+			goto done_rebase_i;
+		}
 		strbuf_reset(&buf);
 
 		if (read_oneliner(&ctx->current_fixups,
@@ -3336,6 +3376,14 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
 		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
 	else
 		write_file(rebase_path_no_reschedule_failed_exec(), "%s", "");
+	if (opts->trailer_args.nr) {
+		struct strbuf buf = STRBUF_INIT;
+
+		for (size_t i = 0; i < opts->trailer_args.nr; i++)
+			strbuf_addf(&buf, "%s\n", opts->trailer_args.v[i]);
+		write_file(rebase_path_trailer(), "%s", buf.buf);
+		strbuf_release(&buf);
+	}
 
 	return 0;
 }
diff --git a/sequencer.h b/sequencer.h
index 719684c..bea20da 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -57,6 +57,8 @@ struct replay_opts {
 	int ignore_date;
 	int commit_use_reference;
 
+	struct strvec trailer_args;
+
 	int mainline;
 
 	char *gpg_sign;
@@ -84,6 +86,7 @@ struct replay_opts {
 #define REPLAY_OPTS_INIT {			\
 	.edit = -1,				\
 	.action = -1,				\
+	.trailer_args = STRVEC_INIT,		\
 	.xopts = STRVEC_INIT,			\
 	.ctx = replay_ctx_new(),		\
 }
diff --git a/setup.c b/setup.c
index 393b970..7ec4427 100644
--- a/setup.c
+++ b/setup.c
@@ -920,8 +920,10 @@ int verify_repository_format(const struct repository_format *format,
 void read_gitfile_error_die(int error_code, const char *path, const char *dir)
 {
 	switch (error_code) {
-	case READ_GITFILE_ERR_STAT_FAILED:
 	case READ_GITFILE_ERR_NOT_A_FILE:
+	case READ_GITFILE_ERR_STAT_FAILED:
+	case READ_GITFILE_ERR_MISSING:
+	case READ_GITFILE_ERR_IS_A_DIR:
 		/* non-fatal; follow return path */
 		break;
 	case READ_GITFILE_ERR_OPEN_FAILED:
@@ -964,8 +966,14 @@ const char *read_gitfile_gently(const char *path, int *return_error_code)
 	static struct strbuf realpath = STRBUF_INIT;
 
 	if (stat(path, &st)) {
-		/* NEEDSWORK: discern between ENOENT vs other errors */
-		error_code = READ_GITFILE_ERR_STAT_FAILED;
+		if (errno == ENOENT || errno == ENOTDIR)
+			error_code = READ_GITFILE_ERR_MISSING;
+		else
+			error_code = READ_GITFILE_ERR_STAT_FAILED;
+		goto cleanup_return;
+	}
+	if (S_ISDIR(st.st_mode)) {
+		error_code = READ_GITFILE_ERR_IS_A_DIR;
 		goto cleanup_return;
 	}
 	if (!S_ISREG(st.st_mode)) {
@@ -1601,20 +1609,37 @@ static enum discovery_result setup_git_directory_gently_1(struct strbuf *dir,
 		if (offset > min_offset)
 			strbuf_addch(dir, '/');
 		strbuf_addstr(dir, DEFAULT_GIT_DIR_ENVIRONMENT);
-		gitdirenv = read_gitfile_gently(dir->buf, die_on_error ?
-						NULL : &error_code);
+		gitdirenv = read_gitfile_gently(dir->buf, &error_code);
 		if (!gitdirenv) {
-			if (die_on_error ||
-			    error_code == READ_GITFILE_ERR_NOT_A_FILE) {
-				/* NEEDSWORK: fail if .git is not file nor dir */
+			switch (error_code) {
+			case READ_GITFILE_ERR_MISSING:
+				/* no .git in this directory, move on */
+				break;
+			case READ_GITFILE_ERR_IS_A_DIR:
 				if (is_git_directory(dir->buf)) {
 					gitdirenv = DEFAULT_GIT_DIR_ENVIRONMENT;
 					gitdir_path = xstrdup(dir->buf);
 				}
-			} else if (error_code != READ_GITFILE_ERR_STAT_FAILED)
-				return GIT_DIR_INVALID_GITFILE;
-		} else
+				break;
+			case READ_GITFILE_ERR_STAT_FAILED:
+				if (die_on_error)
+					die(_("error reading '%s'"), dir->buf);
+				else
+					return GIT_DIR_INVALID_GITFILE;
+			case READ_GITFILE_ERR_NOT_A_FILE:
+				if (die_on_error)
+					die(_("not a regular file: '%s'"), dir->buf);
+				else
+					return GIT_DIR_INVALID_GITFILE;
+			default:
+				if (die_on_error)
+					read_gitfile_error_die(error_code, dir->buf, NULL);
+				else
+					return GIT_DIR_INVALID_GITFILE;
+			}
+		} else {
 			gitfile = xstrdup(dir->buf);
+		}
 		/*
 		 * Earlier, we tentatively added DEFAULT_GIT_DIR_ENVIRONMENT
 		 * to check that directory for a repository.
diff --git a/setup.h b/setup.h
index bcb16b0..80bc6e5 100644
--- a/setup.h
+++ b/setup.h
@@ -36,6 +36,8 @@ int is_nonbare_repository_dir(struct strbuf *path);
 #define READ_GITFILE_ERR_NO_PATH 6
 #define READ_GITFILE_ERR_NOT_A_REPO 7
 #define READ_GITFILE_ERR_TOO_LARGE 8
+#define READ_GITFILE_ERR_MISSING 9
+#define READ_GITFILE_ERR_IS_A_DIR 10
 void read_gitfile_error_die(int error_code, const char *path, const char *dir);
 const char *read_gitfile_gently(const char *path, int *return_error_code);
 #define read_gitfile(path) read_gitfile_gently((path), NULL)
diff --git a/sideband.c b/sideband.c
index ea7c252..1ed6614 100644
--- a/sideband.c
+++ b/sideband.c
@@ -264,6 +264,7 @@ void send_sideband(int fd, int band, const char *data, ssize_t sz, int packet_ma
 	const char *p = data;
 
 	while (sz) {
+		struct iovec iov[2];
 		unsigned n;
 		char hdr[5];
 
@@ -273,12 +274,19 @@ void send_sideband(int fd, int band, const char *data, ssize_t sz, int packet_ma
 		if (0 <= band) {
 			xsnprintf(hdr, sizeof(hdr), "%04x", n + 5);
 			hdr[4] = band;
-			write_or_die(fd, hdr, 5);
+			iov[0].iov_base = hdr;
+			iov[0].iov_len = 5;
 		} else {
 			xsnprintf(hdr, sizeof(hdr), "%04x", n + 4);
-			write_or_die(fd, hdr, 4);
+			iov[0].iov_base = hdr;
+			iov[0].iov_len = 4;
 		}
-		write_or_die(fd, p, n);
+
+		iov[1].iov_base = (void *) p;
+		iov[1].iov_len = n;
+
+		writev_or_die(fd, iov, ARRAY_SIZE(iov));
+
 		p += n;
 		sz -= n;
 	}
diff --git a/split-index.c b/split-index.c
index 4c74c4a..6ba2107 100644
--- a/split-index.c
+++ b/split-index.c
@@ -1,4 +1,3 @@
-#define USE_THE_REPOSITORY_VARIABLE
 #define DISABLE_SIGN_COMPARE_WARNINGS
 
 #include "git-compat-util.h"
@@ -6,6 +5,7 @@
 #include "hash.h"
 #include "mem-pool.h"
 #include "read-cache-ll.h"
+#include "repository.h"
 #include "split-index.h"
 #include "strbuf.h"
 #include "ewah/ewok.h"
@@ -25,16 +25,17 @@ struct split_index *init_split_index(struct index_state *istate)
 int read_link_extension(struct index_state *istate,
 			 const void *data_, unsigned long sz)
 {
+	const struct git_hash_algo *algo = istate->repo->hash_algo;
 	const unsigned char *data = data_;
 	struct split_index *si;
 	int ret;
 
-	if (sz < the_hash_algo->rawsz)
+	if (sz < algo->rawsz)
 		return error("corrupt link extension (too short)");
 	si = init_split_index(istate);
-	oidread(&si->base_oid, data, the_repository->hash_algo);
-	data += the_hash_algo->rawsz;
-	sz -= the_hash_algo->rawsz;
+	oidread(&si->base_oid, data, algo);
+	data += algo->rawsz;
+	sz -= algo->rawsz;
 	if (!sz)
 		return 0;
 	si->delete_bitmap = ewah_new();
@@ -56,7 +57,7 @@ int write_link_extension(struct strbuf *sb,
 			 struct index_state *istate)
 {
 	struct split_index *si = istate->split_index;
-	strbuf_add(sb, si->base_oid.hash, the_hash_algo->rawsz);
+	strbuf_add(sb, si->base_oid.hash, istate->repo->hash_algo->rawsz);
 	if (!si->delete_bitmap && !si->replace_bitmap)
 		return 0;
 	ewah_serialize_strbuf(si->delete_bitmap, sb);
diff --git a/strbuf.c b/strbuf.c
index 3939863..3e04add 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -168,7 +168,7 @@ int strbuf_reencode(struct strbuf *sb, const char *from, const char *to)
 	if (!out)
 		return -1;
 
-	strbuf_attach(sb, out, len, len);
+	strbuf_attach(sb, out, len, len + 1);
 	return 0;
 }
 
diff --git a/submodule-config.c b/submodule-config.c
index 1f19fe2..72a46b7 100644
--- a/submodule-config.c
+++ b/submodule-config.c
@@ -14,6 +14,7 @@
 #include "strbuf.h"
 #include "object-name.h"
 #include "odb.h"
+#include "odb/source.h"
 #include "parse-options.h"
 #include "thread-utils.h"
 #include "tree-walk.h"
diff --git a/submodule.c b/submodule.c
index 4f9aaa2..b1a0363 100644
--- a/submodule.c
+++ b/submodule.c
@@ -1708,6 +1708,8 @@ static int get_next_submodule(struct child_process *cp, struct strbuf *err,
 	if (spf->oid_fetch_tasks_nr) {
 		struct fetch_task *task =
 			spf->oid_fetch_tasks[spf->oid_fetch_tasks_nr - 1];
+		struct child_process cp_remote = CHILD_PROCESS_INIT;
+		struct strbuf remote_name = STRBUF_INIT;
 		spf->oid_fetch_tasks_nr--;
 
 		child_process_init(cp);
@@ -1721,8 +1723,19 @@ static int get_next_submodule(struct child_process *cp, struct strbuf *err,
 		strvec_pushf(&cp->args, "--submodule-prefix=%s%s/",
 			     spf->prefix, task->sub->path);
 
-		/* NEEDSWORK: have get_default_remote from submodule--helper */
-		strvec_push(&cp->args, "origin");
+		cp_remote.git_cmd = 1;
+		strvec_pushl(&cp_remote.args, "submodule--helper",
+			     "get-default-remote", task->sub->path, NULL);
+
+		if (!capture_command(&cp_remote, &remote_name, 0)) {
+			strbuf_trim_trailing_newline(&remote_name);
+			strvec_push(&cp->args, remote_name.buf);
+		} else {
+			/* Fallback to "origin" if the helper fails */
+			strvec_push(&cp->args, "origin");
+		}
+		strbuf_release(&remote_name);
+
 		oid_array_for_each_unique(task->commits,
 					  append_oid_to_argv, &cp->args);
 
@@ -1815,7 +1828,6 @@ int fetch_submodules(struct repository *r,
 		     int default_option,
 		     int quiet, int max_parallel_jobs)
 {
-	int i;
 	struct submodule_parallel_fetch spf = SPF_INIT;
 	const struct run_process_parallel_opts opts = {
 		.tr2_category = "submodule",
@@ -1842,8 +1854,7 @@ int fetch_submodules(struct repository *r,
 		die(_("index file corrupt"));
 
 	strvec_push(&spf.args, "fetch");
-	for (i = 0; i < options->nr; i++)
-		strvec_push(&spf.args, options->v[i]);
+	strvec_pushv(&spf.args, options->v);
 	strvec_push(&spf.args, "--recurse-submodules-default");
 	/* default value, "--submodule-prefix" and its value are added later */
 
@@ -2559,7 +2570,7 @@ void absorb_git_dir_into_superproject(const char *path,
 		const struct submodule *sub;
 		struct strbuf sub_gitdir = STRBUF_INIT;
 
-		if (err_code == READ_GITFILE_ERR_STAT_FAILED) {
+		if (err_code == READ_GITFILE_ERR_MISSING) {
 			/* unpopulated as expected */
 			strbuf_release(&gitdir);
 			return;
diff --git a/t/check-non-portable-shell.pl b/t/check-non-portable-shell.pl
index 6ee7700..18d944b 100755
--- a/t/check-non-portable-shell.pl
+++ b/t/check-non-portable-shell.pl
@@ -36,7 +36,7 @@
 
 	$_ = $line;
 	/\bcp\s+-a/ and err 'cp -a is not portable';
-	/\bsed\s+-[^efn]\s+/ and err 'sed option not portable (use only -n, -e, -f)';
+	/\bsed\s+-[^Eefn]\s+/ and err 'sed option not portable (use only -E, -n, -e, -f)';
 	/\becho\s+-[neE]/ and err 'echo with option is not portable (use printf)';
 	/^\s*declare\s+/ and err 'arrays/declare not portable';
 	/^\s*[^#]\s*which\s/ and err 'which is not portable (use type)';
diff --git a/t/helper/test-example-tap.c b/t/helper/test-example-tap.c
index 229d495..998a1f0 100644
--- a/t/helper/test-example-tap.c
+++ b/t/helper/test-example-tap.c
@@ -63,6 +63,8 @@ static void t_messages(void)
 	check_str("NULL", NULL);
 	check_char('a', ==, '\n');
 	check_char('\\', ==, '\'');
+	check_char('\a', ==, '\v');
+	check_char('\x00', ==, '\x01');
 }
 
 static void t_empty(void)
@@ -123,6 +125,8 @@ int cmd__example_tap(int argc UNUSED, const char **argv UNUSED)
 		check_str("NULL", NULL);
 		check_char('a', ==, '\n');
 		check_char('\\', ==, '\'');
+		check_char('\a', ==, '\v');
+		check_char('\x00', ==, '\x01');
 	}
 	if_test ("if_test test with no checks")
 		; /* nothing */
diff --git a/t/helper/test-read-midx.c b/t/helper/test-read-midx.c
index 6de5d16..388d29e 100644
--- a/t/helper/test-read-midx.c
+++ b/t/helper/test-read-midx.c
@@ -26,18 +26,22 @@ static int read_midx_file(const char *object_dir, const char *checksum,
 			  int show_objects)
 {
 	uint32_t i;
-	struct multi_pack_index *m;
+	struct multi_pack_index *m, *tip;
+	int ret = 0;
 
-	m = setup_midx(object_dir);
+	m = tip = setup_midx(object_dir);
 
 	if (!m)
 		return 1;
 
 	if (checksum) {
-		while (m && strcmp(hash_to_hex(get_midx_checksum(m)), checksum))
+		while (m && strcmp(midx_get_checksum_hex(m), checksum))
 			m = m->base_midx;
-		if (!m)
-			return 1;
+		if (!m) {
+			ret = error(_("could not find MIDX with checksum %s"),
+				    checksum);
+			goto out;
+		}
 	}
 
 	printf("header: %08x %d %d %d %d\n",
@@ -82,9 +86,10 @@ static int read_midx_file(const char *object_dir, const char *checksum,
 		}
 	}
 
-	close_midx(m);
+out:
+	close_midx(tip);
 
-	return 0;
+	return ret;
 }
 
 static int read_midx_checksum(const char *object_dir)
@@ -94,7 +99,7 @@ static int read_midx_checksum(const char *object_dir)
 	m = setup_midx(object_dir);
 	if (!m)
 		return 1;
-	printf("%s\n", hash_to_hex(get_midx_checksum(m)));
+	printf("%s\n", midx_get_checksum_hex(m));
 
 	close_midx(m);
 	return 0;
diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh
index 5f42c31..4c76e81 100644
--- a/t/lib-httpd.sh
+++ b/t/lib-httpd.sh
@@ -167,6 +167,7 @@
 	install_script error.sh
 	install_script apply-one-time-script.sh
 	install_script nph-custom-auth.sh
+	install_script http-429.sh
 
 	ln -s "$LIB_HTTPD_MODULE_PATH" "$HTTPD_ROOT_PATH/modules"
 
diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf
index 6b8c50a..40a690b 100644
--- a/t/lib-httpd/apache.conf
+++ b/t/lib-httpd/apache.conf
@@ -139,6 +139,10 @@
 	SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}
 	SetEnv GIT_HTTP_EXPORT_ALL
 </LocationMatch>
+<LocationMatch /http_429/>
+	SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}
+	SetEnv GIT_HTTP_EXPORT_ALL
+</LocationMatch>
 <LocationMatch /smart_v0/>
 	SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}
 	SetEnv GIT_HTTP_EXPORT_ALL
@@ -160,6 +164,7 @@
 ScriptAlias /error_smart/ error-smart-http.sh/
 ScriptAlias /error/ error.sh/
 ScriptAliasMatch /one_time_script/(.*) apply-one-time-script.sh/$1
+ScriptAliasMatch /http_429/(.*) http-429.sh/$1
 ScriptAliasMatch /custom_auth/(.*) nph-custom-auth.sh/$1
 <Directory ${GIT_EXEC_PATH}>
 	Options FollowSymlinks
@@ -185,6 +190,9 @@
 <Files apply-one-time-script.sh>
 	Options ExecCGI
 </Files>
+<Files http-429.sh>
+	Options ExecCGI
+</Files>
 <Files ${GIT_EXEC_PATH}/git-http-backend>
 	Options ExecCGI
 </Files>
diff --git a/t/lib-httpd/http-429.sh b/t/lib-httpd/http-429.sh
new file mode 100644
index 0000000..c97b161
--- /dev/null
+++ b/t/lib-httpd/http-429.sh
@@ -0,0 +1,98 @@
+#!/bin/sh
+
+# Script to return HTTP 429 Too Many Requests responses for testing retry logic.
+# Usage: /http_429/<test-context>/<retry-after-value>/<repo-path>
+#
+# The test-context is a unique identifier for each test to isolate state files.
+# The retry-after-value can be:
+#   - A number (e.g., "1", "2", "100") - sets Retry-After header to that many seconds
+#   - "none" - no Retry-After header
+#   - "invalid" - invalid Retry-After format
+#   - "permanent" - always return 429 (never succeed)
+#   - An HTTP-date string (RFC 2822 format) - sets Retry-After to that date
+#
+# On first call, returns 429. On subsequent calls (after retry), forwards to git-http-backend
+# unless retry-after-value is "permanent".
+
+# Extract test context, retry-after value and repo path from PATH_INFO
+# PATH_INFO format: /<test-context>/<retry-after-value>/<repo-path>
+path_info="${PATH_INFO#/}"  # Remove leading slash
+test_context="${path_info%%/*}"  # Get first component (test context)
+remaining="${path_info#*/}"  # Get rest
+retry_after="${remaining%%/*}"  # Get second component (retry-after value)
+repo_path="${remaining#*/}"  # Get rest (repo path)
+
+# Extract repository name from repo_path (e.g., "repo.git" from "repo.git/info/refs")
+# The repo name is the first component before any "/"
+repo_name="${repo_path%%/*}"
+
+# Use current directory (HTTPD_ROOT_PATH) for state file
+# Create a safe filename from test_context, retry_after and repo_name
+# This ensures all requests for the same test context share the same state file
+safe_name=$(echo "${test_context}-${retry_after}-${repo_name}" | tr '/' '_' | tr -cd 'a-zA-Z0-9_-')
+state_file="http-429-state-${safe_name}"
+
+# Check if this is the first call (no state file exists)
+if test -f "$state_file"
+then
+	# Already returned 429 once, forward to git-http-backend
+	# Set PATH_INFO to just the repo path (without retry-after value)
+	# Set GIT_PROJECT_ROOT so git-http-backend can find the repository
+	# Use exec to replace this process so git-http-backend gets the updated environment
+	PATH_INFO="/$repo_path"
+	export PATH_INFO
+	# GIT_PROJECT_ROOT points to the document root where repositories are stored
+	# The script runs from HTTPD_ROOT_PATH, and www/ is the document root
+	if test -z "$GIT_PROJECT_ROOT"
+	then
+		# Construct path: current directory (HTTPD_ROOT_PATH) + /www
+		GIT_PROJECT_ROOT="$(pwd)/www"
+		export GIT_PROJECT_ROOT
+	fi
+	exec "$GIT_EXEC_PATH/git-http-backend"
+fi
+
+# Mark that we've returned 429
+touch "$state_file"
+
+# Output HTTP 429 response
+printf "Status: 429 Too Many Requests\r\n"
+
+# Set Retry-After header based on retry_after value
+case "$retry_after" in
+	none)
+		# No Retry-After header
+		;;
+	invalid)
+		printf "Retry-After: invalid-format-123abc\r\n"
+		;;
+	permanent)
+		# Always return 429, don't set state file for success
+		rm -f "$state_file"
+		printf "Retry-After: 1\r\n"
+		printf "Content-Type: text/plain\r\n"
+		printf "\r\n"
+		printf "Permanently rate limited\n"
+		exit 0
+		;;
+	*)
+		# Check if it's a number
+		case "$retry_after" in
+			[0-9]*)
+				# Numeric value
+				printf "Retry-After: %s\r\n" "$retry_after"
+				;;
+			*)
+				# Assume it's an HTTP-date format (passed as-is, URL decoded)
+				# Apache may URL-encode the path, so decode common URL-encoded characters
+				# %20 = space, %2C = comma, %3A = colon
+				retry_value=$(echo "$retry_after" | sed -e 's/%20/ /g' -e 's/%2C/,/g' -e 's/%3A/:/g')
+				printf "Retry-After: %s\r\n" "$retry_value"
+				;;
+		esac
+		;;
+esac
+
+printf "Content-Type: text/plain\r\n"
+printf "\r\n"
+printf "Rate limited\n"
diff --git a/t/meson.build b/t/meson.build
index f66a73f..7528e5c 100644
--- a/t/meson.build
+++ b/t/meson.build
@@ -81,6 +81,7 @@
   't0006-date.sh',
   't0007-git-var.sh',
   't0008-ignores.sh',
+  't0009-git-dir-validation.sh',
   't0010-racy-git.sh',
   't0012-help.sh',
   't0013-sha1dc.sh',
@@ -392,8 +393,10 @@
   't3436-rebase-more-options.sh',
   't3437-rebase-fixup-options.sh',
   't3438-rebase-broken-files.sh',
+  't3440-rebase-trailer.sh',
   't3450-history.sh',
   't3451-history-reword.sh',
+  't3452-history-split.sh',
   't3500-cherry.sh',
   't3501-revert-cherry-pick.sh',
   't3502-cherry-pick-merge.sh',
@@ -506,6 +509,7 @@
   't4071-diff-minimal.sh',
   't4072-diff-max-depth.sh',
   't4073-diff-stat-name-width.sh',
+  't4074-diff-shifted-matched-group.sh',
   't4100-apply-stat.sh',
   't4101-apply-nonl.sh',
   't4102-apply-rename.sh',
@@ -622,6 +626,7 @@
   't5332-multi-pack-reuse.sh',
   't5333-pseudo-merge-bitmaps.sh',
   't5334-incremental-multi-pack-index.sh',
+  't5335-compact-multi-pack-index.sh',
   't5351-unpack-large-objects.sh',
   't5400-send-pack.sh',
   't5401-update-hooks.sh',
@@ -708,6 +713,7 @@
   't5581-http-curl-verbose.sh',
   't5582-fetch-negative-refspec.sh',
   't5583-push-branches.sh',
+  't5584-http-429-retry.sh',
   't5600-clone-fail-cleanup.sh',
   't5601-clone.sh',
   't5602-clone-remote-exec.sh',
@@ -896,6 +902,7 @@
   't7423-submodule-symlinks.sh',
   't7424-submodule-mixed-ref-formats.sh',
   't7425-submodule-gitdir-path-extension.sh',
+  't7426-submodule-get-default-remote.sh',
   't7450-bad-git-dotfiles.sh',
   't7500-commit-template-squash-signoff.sh',
   't7501-commit-basic-functionality.sh',
diff --git a/t/pack-refs-tests.sh b/t/pack-refs-tests.sh
index 2fdaccb..d76b087 100644
--- a/t/pack-refs-tests.sh
+++ b/t/pack-refs-tests.sh
@@ -61,13 +61,13 @@
 test_expect_success 'see if git ${pack_refs} --prune remove ref files' '
 	git branch f &&
 	git ${pack_refs} --all --prune &&
-	! test -f .git/refs/heads/f
+	test_path_is_missing .git/refs/heads/f
 '
 
 test_expect_success 'see if git ${pack_refs} --prune removes empty dirs' '
 	git branch r/s/t &&
 	git ${pack_refs} --all --prune &&
-	! test -e .git/refs/heads/r
+	test_path_is_missing .git/refs/heads/r
 '
 
 test_expect_success 'git branch g should work when git branch g/h has been deleted' '
@@ -111,43 +111,43 @@
 	git branch dont_pack2 &&
 	git branch pack_this &&
 	git ${pack_refs} --all --exclude "refs/heads/dont_pack*" &&
-	test -f .git/refs/heads/dont_pack1 &&
-	test -f .git/refs/heads/dont_pack2 &&
-	! test -f .git/refs/heads/pack_this'
+	test_path_is_file .git/refs/heads/dont_pack1 &&
+	test_path_is_file .git/refs/heads/dont_pack2 &&
+	test_path_is_missing .git/refs/heads/pack_this'
 
 test_expect_success 'test --no-exclude refs clears excluded refs' '
 	git branch dont_pack3 &&
 	git branch dont_pack4 &&
 	git ${pack_refs} --all --exclude "refs/heads/dont_pack*" --no-exclude &&
-	! test -f .git/refs/heads/dont_pack3 &&
-	! test -f .git/refs/heads/dont_pack4'
+	test_path_is_missing .git/refs/heads/dont_pack3 &&
+	test_path_is_missing .git/refs/heads/dont_pack4'
 
 test_expect_success 'test only included refs are packed' '
 	git branch pack_this1 &&
 	git branch pack_this2 &&
 	git tag dont_pack5 &&
 	git ${pack_refs} --include "refs/heads/pack_this*" &&
-	test -f .git/refs/tags/dont_pack5 &&
-	! test -f .git/refs/heads/pack_this1 &&
-	! test -f .git/refs/heads/pack_this2'
+	test_path_is_file .git/refs/tags/dont_pack5 &&
+	test_path_is_missing .git/refs/heads/pack_this1 &&
+	test_path_is_missing .git/refs/heads/pack_this2'
 
 test_expect_success 'test --no-include refs clears included refs' '
 	git branch pack1 &&
 	git branch pack2 &&
 	git ${pack_refs} --include "refs/heads/pack*" --no-include &&
-	test -f .git/refs/heads/pack1 &&
-	test -f .git/refs/heads/pack2'
+	test_path_is_file .git/refs/heads/pack1 &&
+	test_path_is_file .git/refs/heads/pack2'
 
 test_expect_success 'test --exclude takes precedence over --include' '
 	git branch dont_pack5 &&
 	git ${pack_refs} --include "refs/heads/pack*" --exclude "refs/heads/pack*" &&
-	test -f .git/refs/heads/dont_pack5'
+	test_path_is_file .git/refs/heads/dont_pack5'
 
 test_expect_success 'see if up-to-date packed refs are preserved' '
 	git branch q &&
 	git ${pack_refs} --all --prune &&
 	git update-ref refs/heads/q refs/heads/q &&
-	! test -f .git/refs/heads/q
+	test_path_is_missing .git/refs/heads/q
 '
 
 test_expect_success 'pack, prune and repack' '
diff --git a/t/t0008-ignores.sh b/t/t0008-ignores.sh
index db8bde2..e716b5c 100755
--- a/t/t0008-ignores.sh
+++ b/t/t0008-ignores.sh
@@ -946,7 +946,7 @@
 '
 
 test_expect_success SYMLINKS 'symlinks not respected in-tree' '
-	test_when_finished "rm .gitignore" &&
+	test_when_finished "rm -rf subdir .gitignore err actual" &&
 	ln -s ignore .gitignore &&
 	mkdir subdir &&
 	ln -s ignore subdir/.gitignore &&
@@ -957,6 +957,7 @@
 
 test_expect_success EXPENSIVE 'large exclude file ignored in tree' '
 	test_when_finished "rm .gitignore" &&
+	find . -name .gitignore -exec rm "{}" ";" &&
 	dd if=/dev/zero of=.gitignore bs=101M count=1 &&
 	git ls-files -o --exclude-standard 2>err &&
 	echo "warning: ignoring excessively large pattern file: .gitignore" >expect &&
diff --git a/t/t0009-git-dir-validation.sh b/t/t0009-git-dir-validation.sh
new file mode 100755
index 0000000..33d21ed
--- /dev/null
+++ b/t/t0009-git-dir-validation.sh
@@ -0,0 +1,77 @@
+#!/bin/sh
+
+test_description='setup: validation of .git file/directory types
+
+Verify that setup_git_directory() correctly handles:
+1. Valid .git directories (including symlinks to them).
+2. Invalid .git files (FIFOs, sockets) by erroring out.
+3. Invalid .git files (garbage) by erroring out.
+'
+
+. ./test-lib.sh
+
+test_expect_success 'setup: create parent git repository' '
+	git init parent &&
+	test_commit -C parent "root-commit"
+'
+
+test_expect_success SYMLINKS 'setup: .git as a symlink to a directory is valid' '
+	test_when_finished "rm -rf parent/link-to-dir" &&
+	mkdir -p parent/link-to-dir &&
+	(
+		cd parent/link-to-dir &&
+		git init real-repo &&
+		ln -s real-repo/.git .git &&
+		git rev-parse --git-dir >actual &&
+		echo .git >expect &&
+		test_cmp expect actual
+	)
+'
+
+test_expect_success PIPE 'setup: .git as a FIFO (named pipe) is rejected' '
+	test_when_finished "rm -rf parent/fifo-trap" &&
+	mkdir -p parent/fifo-trap &&
+	(
+		cd parent/fifo-trap &&
+		mkfifo .git &&
+		test_must_fail git rev-parse --git-dir 2>stderr &&
+		grep "not a regular file" stderr
+	)
+'
+
+test_expect_success SYMLINKS,PIPE 'setup: .git as a symlink to a FIFO is rejected' '
+	test_when_finished "rm -rf parent/symlink-fifo-trap" &&
+	mkdir -p parent/symlink-fifo-trap &&
+	(
+		cd parent/symlink-fifo-trap &&
+		mkfifo target-fifo &&
+		ln -s target-fifo .git &&
+		test_must_fail git rev-parse --git-dir 2>stderr &&
+		grep "not a regular file" stderr
+	)
+'
+
+test_expect_success 'setup: .git with garbage content is rejected' '
+	test_when_finished "rm -rf parent/garbage-trap" &&
+	mkdir -p parent/garbage-trap &&
+	(
+		cd parent/garbage-trap &&
+		echo "garbage" >.git &&
+		test_must_fail git rev-parse --git-dir 2>stderr &&
+		grep "invalid gitfile format" stderr
+	)
+'
+
+test_expect_success 'setup: .git as an empty directory is ignored' '
+	test_when_finished "rm -rf parent/empty-dir" &&
+	mkdir -p parent/empty-dir &&
+	(
+		cd parent/empty-dir &&
+		git rev-parse --git-dir >expect &&
+		mkdir .git &&
+		git rev-parse --git-dir >actual &&
+		test_cmp expect actual
+	)
+'
+
+test_done
diff --git a/t/t0012-help.sh b/t/t0012-help.sh
index d3a0967..c33501b 100755
--- a/t/t0012-help.sh
+++ b/t/t0012-help.sh
@@ -141,20 +141,23 @@
 
 	'\''git help config'\'' for more information
 	EOF
-	grep -v -E \
-		-e "^[^.]+\.[^.]+$" \
-		-e "^[^.]+\.[^.]+\.[^.]+$" \
-		help.output >actual &&
+	sed -E -e "
+		/^[^.]+\.[^.]+$/d
+		/^[^.]+\.[^.]+\.[^.]+$/d
+	" help.output >actual &&
 	test_cmp expect actual
 '
 
 test_expect_success 'git help --config-for-completion' '
 	git help -c >human &&
-	grep -E \
-	     -e "^[^.]+\.[^.]+$" \
-	     -e "^[^.]+\.[^.]+\.[^.]+$" human |
-	     sed -e "s/\*.*//" -e "s/<.*//" |
-	     sort -u >human.munged &&
+	sed -E -e "
+		/^[^.]+\.[^.]+$/b out
+		/^[^.]+\.[^.]+\.[^.]+$/b out
+		d
+		: out
+		s/\*.*//
+		s/<.*//
+	" human | sort -u >human.munged &&
 
 	git help --config-for-completion >vars &&
 	test_cmp human.munged vars
@@ -162,14 +165,16 @@
 
 test_expect_success 'git help --config-sections-for-completion' '
 	git help -c >human &&
-	grep -E \
-	     -e "^[^.]+\.[^.]+$" \
-	     -e "^[^.]+\.[^.]+\.[^.]+$" human |
-	     sed -e "s/\..*//" |
-	     sort -u >human.munged &&
+	sed -E -e "
+		/^[^.]+\.[^.]+$/b out
+		/^[^.]+\.[^.]+\.[^.]+$/b out
+		d
+		: out
+		s/\..*//
+	" human | sort -u >expect &&
 
-	git help --config-sections-for-completion >sections &&
-	test_cmp human.munged sections
+	git help --config-sections-for-completion >actual &&
+	test_cmp expect actual
 '
 
 test_section_spacing () {
diff --git a/t/t0061-run-command.sh b/t/t0061-run-command.sh
index 2f77fde..60cfe65 100755
--- a/t/t0061-run-command.sh
+++ b/t/t0061-run-command.sh
@@ -287,16 +287,8 @@
 	rm -f out &&
 	echo "echo %* >>out" >"$bat" &&
 
-	# Ask git to invoke .bat; clone will fail due to fake SSH helper
-	test_must_fail env GIT_SSH="$bat" git clone myhost:src ssh-clone &&
-
-	# Spawning .bat can fail if there are two quoted cmd.exe arguments.
-	# .bat itself is first (due to spaces in name), so just one more is
-	# needed to verify. GIT_SSH will invoke .bat multiple times:
-	# 1) -G myhost
-	# 2) myhost "git-upload-pack src"
-	# First invocation will always succeed. Test the second one.
-	grep "git-upload-pack" out
+	test-tool run-command run-command "$bat" "arg with spaces" &&
+	test_grep "arg with spaces" out
 '
 
 test_done
diff --git a/t/t0068-for-each-repo.sh b/t/t0068-for-each-repo.sh
index f2f3e50..80b163e 100755
--- a/t/t0068-for-each-repo.sh
+++ b/t/t0068-for-each-repo.sh
@@ -2,17 +2,23 @@
 
 test_description='git for-each-repo builtin'
 
+# We need to test running 'git for-each-repo' outside of a repo context.
+TEST_NO_CREATE_REPO=1
+
 . ./test-lib.sh
 
 test_expect_success 'run based on configured value' '
-	git init one &&
-	git init two &&
-	git init three &&
-	git init ~/four &&
+	git init --initial-branch=one one &&
+	git init --initial-branch=two two &&
+	git -C two worktree add --orphan ../three &&
+	git -C three checkout -b three &&
+	git init --initial-branch=four ~/four &&
+
 	git -C two commit --allow-empty -m "DID NOT RUN" &&
-	git config run.key "$TRASH_DIRECTORY/one" &&
-	git config --add run.key "$TRASH_DIRECTORY/three" &&
-	git config --add run.key "~/four" &&
+	git config --global run.key "$TRASH_DIRECTORY/one" &&
+	git config --global --add run.key "$TRASH_DIRECTORY/three" &&
+	git config --global --add run.key "~/four" &&
+
 	git for-each-repo --config=run.key commit --allow-empty -m "ran" &&
 	git -C one log -1 --pretty=format:%s >message &&
 	grep ran message &&
@@ -22,6 +28,7 @@
 	grep ran message &&
 	git -C ~/four log -1 --pretty=format:%s >message &&
 	grep ran message &&
+
 	git for-each-repo --config=run.key -- commit --allow-empty -m "ran again" &&
 	git -C one log -1 --pretty=format:%s >message &&
 	grep again message &&
@@ -30,7 +37,43 @@
 	git -C three log -1 --pretty=format:%s >message &&
 	grep again message &&
 	git -C ~/four log -1 --pretty=format:%s >message &&
-	grep again message
+	grep again message &&
+
+	git -C three for-each-repo --config=run.key -- \
+		commit --allow-empty -m "ran from worktree" &&
+	git -C one log -1 --pretty=format:%s >message &&
+	test_grep "ran from worktree" message &&
+	git -C two log -1 --pretty=format:%s >message &&
+	test_grep ! "ran from worktree" message &&
+	git -C three log -1 --pretty=format:%s >message &&
+	test_grep "ran from worktree" message &&
+	git -C ~/four log -1 --pretty=format:%s >message &&
+	test_grep "ran from worktree" message &&
+
+	# Test running with config values set by environment
+	cat >expect <<-EOF &&
+	ran from worktree (HEAD -> refs/heads/one)
+	ran from worktree (HEAD -> refs/heads/three)
+	ran from worktree (HEAD -> refs/heads/four)
+	EOF
+
+	GIT_CONFIG_PARAMETERS="${SQ}log.decorate=full${SQ}" \
+		git -C three for-each-repo --config=run.key -- log --format="%s%d" -1 >out &&
+	test_cmp expect out &&
+
+	cat >test-config <<-EOF &&
+	[run]
+		key = $(pwd)/one
+		key = $(pwd)/three
+		key = $(pwd)/four
+
+	[log]
+		decorate = full
+	EOF
+
+	GIT_CONFIG_GLOBAL="$(pwd)/test-config" \
+		git -C three for-each-repo --config=run.key -- log --format="%s%d" -1 >out &&
+	test_cmp expect out
 '
 
 test_expect_success 'do nothing on empty config' '
@@ -46,7 +89,7 @@
 '
 
 test_expect_success 'error on NULL value for config keys' '
-	cat >>.git/config <<-\EOF &&
+	cat >>.gitconfig <<-\EOF &&
 	[empty]
 		key
 	EOF
@@ -59,8 +102,8 @@
 '
 
 test_expect_success '--keep-going' '
-	git config keep.going non-existing &&
-	git config --add keep.going . &&
+	git config --global keep.going non-existing &&
+	git config --global --add keep.going one &&
 
 	test_must_fail git for-each-repo --config=keep.going \
 		-- branch >out 2>err &&
@@ -70,7 +113,7 @@
 	test_must_fail git for-each-repo --config=keep.going --keep-going \
 		-- branch >out 2>err &&
 	test_grep "cannot change to .*non-existing" err &&
-	git branch >expect &&
+	git -C one branch >expect &&
 	test_cmp expect out
 '
 
diff --git a/t/t0080-unit-test-output.sh b/t/t0080-unit-test-output.sh
index 3db10f0..66838a0 100755
--- a/t/t0080-unit-test-output.sh
+++ b/t/t0080-unit-test-output.sh
@@ -6,10 +6,10 @@
 
 test_expect_success 'TAP output from unit tests' - <<\EOT
 	cat >expect <<-EOF &&
-	# BUG: check outside of test at t/helper/test-example-tap.c:75
+	# BUG: check outside of test at t/helper/test-example-tap.c:77
 	ok 1 - passing test
 	ok 2 - passing test and assertion return 1
-	# check "1 == 2" failed at t/helper/test-example-tap.c:79
+	# check "1 == 2" failed at t/helper/test-example-tap.c:81
 	#    left: 1
 	#   right: 2
 	not ok 3 - failing test
@@ -34,53 +34,65 @@
 	not ok 15 - failing check after TEST_TODO()
 	ok 16 - failing check after TEST_TODO() returns 0
 	# check "!strcmp("\thello\\\\", "there\"\n")" failed at t/helper/test-example-tap.c:62
-	#    left: "\011hello\\\\"
-	#   right: "there\"\012"
+	#    left: "\thello\\\\"
+	#   right: "there\"\n"
 	# check "!strcmp("NULL", NULL)" failed at t/helper/test-example-tap.c:63
 	#    left: "NULL"
 	#   right: NULL
 	# check "'a' == '\n'" failed at t/helper/test-example-tap.c:64
 	#    left: 'a'
-	#   right: '\012'
+	#   right: '\n'
 	# check "'\\\\' == '\\''" failed at t/helper/test-example-tap.c:65
 	#    left: '\\\\'
 	#   right: '\\''
+	# check "'\a' == '\v'" failed at t/helper/test-example-tap.c:66
+	#    left: '\a'
+	#   right: '\v'
+	# check "'\x00' == '\x01'" failed at t/helper/test-example-tap.c:67
+	#    left: '\000'
+	#   right: '\001'
 	not ok 17 - messages from failing string and char comparison
-	# BUG: test has no checks at t/helper/test-example-tap.c:94
+	# BUG: test has no checks at t/helper/test-example-tap.c:96
 	not ok 18 - test with no checks
 	ok 19 - test with no checks returns 0
 	ok 20 - if_test passing test
-	# check "1 == 2" failed at t/helper/test-example-tap.c:100
+	# check "1 == 2" failed at t/helper/test-example-tap.c:102
 	#    left: 1
 	#   right: 2
 	not ok 21 - if_test failing test
 	not ok 22 - if_test passing TEST_TODO() # TODO
-	# todo check 'check(1)' succeeded at t/helper/test-example-tap.c:104
+	# todo check 'check(1)' succeeded at t/helper/test-example-tap.c:106
 	not ok 23 - if_test failing TEST_TODO()
-	# check "0" failed at t/helper/test-example-tap.c:106
+	# check "0" failed at t/helper/test-example-tap.c:108
 	# skipping test - missing prerequisite
-	# skipping check '1' at t/helper/test-example-tap.c:108
+	# skipping check '1' at t/helper/test-example-tap.c:110
 	ok 24 - if_test test_skip() # SKIP
 	# skipping test - missing prerequisite
 	ok 25 - if_test test_skip() inside TEST_TODO() # SKIP
-	# check "0" failed at t/helper/test-example-tap.c:113
+	# check "0" failed at t/helper/test-example-tap.c:115
 	not ok 26 - if_test TEST_TODO() after failing check
-	# check "0" failed at t/helper/test-example-tap.c:119
+	# check "0" failed at t/helper/test-example-tap.c:121
 	not ok 27 - if_test failing check after TEST_TODO()
-	# check "!strcmp("\thello\\\\", "there\"\n")" failed at t/helper/test-example-tap.c:122
-	#    left: "\011hello\\\\"
-	#   right: "there\"\012"
-	# check "!strcmp("NULL", NULL)" failed at t/helper/test-example-tap.c:123
+	# check "!strcmp("\thello\\\\", "there\"\n")" failed at t/helper/test-example-tap.c:124
+	#    left: "\thello\\\\"
+	#   right: "there\"\n"
+	# check "!strcmp("NULL", NULL)" failed at t/helper/test-example-tap.c:125
 	#    left: "NULL"
 	#   right: NULL
-	# check "'a' == '\n'" failed at t/helper/test-example-tap.c:124
+	# check "'a' == '\n'" failed at t/helper/test-example-tap.c:126
 	#    left: 'a'
-	#   right: '\012'
-	# check "'\\\\' == '\\''" failed at t/helper/test-example-tap.c:125
+	#   right: '\n'
+	# check "'\\\\' == '\\''" failed at t/helper/test-example-tap.c:127
 	#    left: '\\\\'
 	#   right: '\\''
+	# check "'\a' == '\v'" failed at t/helper/test-example-tap.c:128
+	#    left: '\a'
+	#   right: '\v'
+	# check "'\x00' == '\x01'" failed at t/helper/test-example-tap.c:129
+	#    left: '\000'
+	#   right: '\001'
 	not ok 28 - if_test messages from failing string and char comparison
-	# BUG: test has no checks at t/helper/test-example-tap.c:127
+	# BUG: test has no checks at t/helper/test-example-tap.c:131
 	not ok 29 - if_test test with no checks
 	1..29
 	EOF
diff --git a/t/t0410-partial-clone.sh b/t/t0410-partial-clone.sh
index 2a5bdbe..52e1972 100755
--- a/t/t0410-partial-clone.sh
+++ b/t/t0410-partial-clone.sh
@@ -11,7 +11,10 @@
 GIT_TEST_COMMIT_GRAPH=0
 
 delete_object () {
-	rm $1/.git/objects/$(echo $2 | sed -e 's|^..|&/|')
+	local repo="$1"
+	local obj="$2"
+	local path="$repo/.git/objects/$(test_oid_to_path "$obj")" &&
+	rm "$path"
 }
 
 pack_as_from_promisor () {
diff --git a/t/t0450/adoc-help-mismatches b/t/t0450/adoc-help-mismatches
index 8ee2d3f..e8d6c13 100644
--- a/t/t0450/adoc-help-mismatches
+++ b/t/t0450/adoc-help-mismatches
@@ -33,7 +33,6 @@
 merge-file
 merge-index
 merge-one-file
-multi-pack-index
 name-rev
 notes
 push
diff --git a/t/t1416-ref-transaction-hooks.sh b/t/t1416-ref-transaction-hooks.sh
index d91dd3a..4fe9d9b 100755
--- a/t/t1416-ref-transaction-hooks.sh
+++ b/t/t1416-ref-transaction-hooks.sh
@@ -20,6 +20,7 @@
 		echo "$*" >>actual
 	EOF
 	cat >expect <<-EOF &&
+		preparing
 		prepared
 		committed
 	EOF
@@ -27,6 +28,18 @@
 	test_cmp expect actual
 '
 
+test_expect_success 'hook aborts updating ref in preparing state' '
+	git reset --hard PRE &&
+	test_hook reference-transaction <<-\EOF &&
+		if test "$1" = preparing
+		then
+			exit 1
+		fi
+	EOF
+	test_must_fail git update-ref HEAD POST 2>err &&
+	test_grep "in '\''preparing'\'' phase, update aborted by the reference-transaction hook" err
+'
+
 test_expect_success 'hook aborts updating ref in prepared state' '
 	git reset --hard PRE &&
 	test_hook reference-transaction <<-\EOF &&
@@ -36,7 +49,7 @@
 		fi
 	EOF
 	test_must_fail git update-ref HEAD POST 2>err &&
-	test_grep "ref updates aborted by hook" err
+	test_grep "in '\''prepared'\'' phase, update aborted by the reference-transaction hook" err
 '
 
 test_expect_success 'hook gets all queued updates in prepared state' '
@@ -121,6 +134,7 @@
 	cat >expect <<-EOF &&
 		hooks/update refs/tags/PRE $ZERO_OID $PRE_OID
 		hooks/update refs/tags/POST $ZERO_OID $POST_OID
+		hooks/reference-transaction preparing
 		hooks/reference-transaction prepared
 		hooks/reference-transaction committed
 	EOF
@@ -143,6 +157,8 @@
 	git symbolic-ref refs/heads/symref refs/heads/main &&
 
 	cat >expect <<-EOF &&
+	preparing
+	$ZERO_OID ref:refs/heads/main refs/heads/symref
 	prepared
 	$ZERO_OID ref:refs/heads/main refs/heads/symref
 	committed
@@ -171,14 +187,20 @@
 	# In the files backend, "delete" also triggers an additional transaction
 	# update on the packed-refs backend, which constitutes additional reflog
 	# entries.
+	cat >expect <<-EOF &&
+	preparing
+	ref:refs/heads/main $ZERO_OID refs/heads/symref
+	ref:refs/heads/main $ZERO_OID refs/heads/symrefd
+	$ZERO_OID ref:refs/heads/main refs/heads/symrefc
+	ref:refs/heads/main ref:refs/heads/branch refs/heads/symrefu
+	EOF
+
 	if test_have_prereq REFFILES
 	then
-		cat >expect <<-EOF
+		cat >>expect <<-EOF
 		aborted
 		$ZERO_OID $ZERO_OID refs/heads/symrefd
 		EOF
-	else
-		>expect
 	fi &&
 
 	cat >>expect <<-EOF &&
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index a9eb07a..39bb77d 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -149,4 +149,10 @@
 	test_cmp expect actual
 '
 
+test_expect_success 'git repo info -h shows only repo info usage' '
+	test_must_fail git repo info -h >actual &&
+	test_grep "git repo info" actual &&
+	test_grep ! "git repo structure" actual
+'
+
 test_done
diff --git a/t/t1901-repo-structure.sh b/t/t1901-repo-structure.sh
index a67b38a..10050ab 100755
--- a/t/t1901-repo-structure.sh
+++ b/t/t1901-repo-structure.sh
@@ -27,31 +27,43 @@
 	(
 		cd repo &&
 		cat >expect <<-\EOF &&
-		| Repository structure | Value  |
-		| -------------------- | ------ |
-		| * References         |        |
-		|   * Count            |    0   |
-		|     * Branches       |    0   |
-		|     * Tags           |    0   |
-		|     * Remotes        |    0   |
-		|     * Others         |    0   |
-		|                      |        |
-		| * Reachable objects  |        |
-		|   * Count            |    0   |
-		|     * Commits        |    0   |
-		|     * Trees          |    0   |
-		|     * Blobs          |    0   |
-		|     * Tags           |    0   |
-		|   * Inflated size    |    0 B |
-		|     * Commits        |    0 B |
-		|     * Trees          |    0 B |
-		|     * Blobs          |    0 B |
-		|     * Tags           |    0 B |
-		|   * Disk size        |    0 B |
-		|     * Commits        |    0 B |
-		|     * Trees          |    0 B |
-		|     * Blobs          |    0 B |
-		|     * Tags           |    0 B |
+		| Repository structure      | Value  |
+		| ------------------------- | ------ |
+		| * References              |        |
+		|   * Count                 |    0   |
+		|     * Branches            |    0   |
+		|     * Tags                |    0   |
+		|     * Remotes             |    0   |
+		|     * Others              |    0   |
+		|                           |        |
+		| * Reachable objects       |        |
+		|   * Count                 |    0   |
+		|     * Commits             |    0   |
+		|     * Trees               |    0   |
+		|     * Blobs               |    0   |
+		|     * Tags                |    0   |
+		|   * Inflated size         |    0 B |
+		|     * Commits             |    0 B |
+		|     * Trees               |    0 B |
+		|     * Blobs               |    0 B |
+		|     * Tags                |    0 B |
+		|   * Disk size             |    0 B |
+		|     * Commits             |    0 B |
+		|     * Trees               |    0 B |
+		|     * Blobs               |    0 B |
+		|     * Tags                |    0 B |
+		|                           |        |
+		| * Largest objects         |        |
+		|   * Commits               |        |
+		|     * Maximum size        |    0 B |
+		|     * Maximum parents     |    0   |
+		|   * Trees                 |        |
+		|     * Maximum size        |    0 B |
+		|     * Maximum entries     |    0   |
+		|   * Blobs                 |        |
+		|     * Maximum size        |    0 B |
+		|   * Tags                  |        |
+		|     * Maximum size        |    0 B |
 		EOF
 
 		git repo structure >out 2>err &&
@@ -79,31 +91,50 @@
 		# git-rev-list(1) --disk-usage=human option printing the full
 		# "byte/bytes" unit string instead of just "B".
 		cat >expect <<-EOF &&
-		| Repository structure | Value      |
-		| -------------------- | ---------- |
-		| * References         |            |
-		|   * Count            |      4     |
-		|     * Branches       |      1     |
-		|     * Tags           |      1     |
-		|     * Remotes        |      1     |
-		|     * Others         |      1     |
-		|                      |            |
-		| * Reachable objects  |            |
-		|   * Count            |   3.02 k   |
-		|     * Commits        |   1.01 k   |
-		|     * Trees          |   1.01 k   |
-		|     * Blobs          |   1.01 k   |
-		|     * Tags           |      1     |
-		|   * Inflated size    |  16.03 MiB |
-		|     * Commits        | 217.92 KiB |
-		|     * Trees          |  15.81 MiB |
-		|     * Blobs          |  11.68 KiB |
-		|     * Tags           |    132 B   |
-		|   * Disk size        | $(object_type_disk_usage all true) |
-		|     * Commits        | $(object_type_disk_usage commit true) |
-		|     * Trees          | $(object_type_disk_usage tree true) |
-		|     * Blobs          |  $(object_type_disk_usage blob true) |
-		|     * Tags           |    $(object_type_disk_usage tag) B   |
+		| Repository structure      | Value      |
+		| ------------------------- | ---------- |
+		| * References              |            |
+		|   * Count                 |      4     |
+		|     * Branches            |      1     |
+		|     * Tags                |      1     |
+		|     * Remotes             |      1     |
+		|     * Others              |      1     |
+		|                           |            |
+		| * Reachable objects       |            |
+		|   * Count                 |   3.02 k   |
+		|     * Commits             |   1.01 k   |
+		|     * Trees               |   1.01 k   |
+		|     * Blobs               |   1.01 k   |
+		|     * Tags                |      1     |
+		|   * Inflated size         |  16.03 MiB |
+		|     * Commits             | 217.92 KiB |
+		|     * Trees               |  15.81 MiB |
+		|     * Blobs               |  11.68 KiB |
+		|     * Tags                |    132 B   |
+		|   * Disk size             | $(object_type_disk_usage all true) |
+		|     * Commits             | $(object_type_disk_usage commit true) |
+		|     * Trees               | $(object_type_disk_usage tree true) |
+		|     * Blobs               |  $(object_type_disk_usage blob true) |
+		|     * Tags                |    $(object_type_disk_usage tag) B   |
+		|                           |            |
+		| * Largest objects         |            |
+		|   * Commits               |            |
+		|     * Maximum size    [1] |    223 B   |
+		|     * Maximum parents [2] |      1     |
+		|   * Trees                 |            |
+		|     * Maximum size    [3] |  32.29 KiB |
+		|     * Maximum entries [4] |   1.01 k   |
+		|   * Blobs                 |            |
+		|     * Maximum size    [5] |     13 B   |
+		|   * Tags                  |            |
+		|     * Maximum size    [6] |    132 B   |
+
+		[1] 0dc91eb18580102a3a216c8bfecedeba2b9f9b9a
+		[2] 0dc91eb18580102a3a216c8bfecedeba2b9f9b9a
+		[3] 60665251ab71dbd8c18d9bf2174f4ee0d58aa06c
+		[4] 60665251ab71dbd8c18d9bf2174f4ee0d58aa06c
+		[5] 97d808e45116bf02103490294d3d46dad7a2ac62
+		[6] 4dae4f5954f5e6feb3577cfb1b181daa3fd3afd2
 		EOF
 
 		git repo structure >out 2>err &&
@@ -138,6 +169,18 @@
 		objects.trees.disk_size=$(object_type_disk_usage tree)
 		objects.blobs.disk_size=$(object_type_disk_usage blob)
 		objects.tags.disk_size=$(object_type_disk_usage tag)
+		objects.commits.max_size=221
+		objects.commits.max_size_oid=de3508174b5c2ace6993da67cae9be9069e2df39
+		objects.trees.max_size=1335
+		objects.trees.max_size_oid=09931deea9d81ec21300d3e13c74412f32eacec5
+		objects.blobs.max_size=11
+		objects.blobs.max_size_oid=eaeeedced46482bd4281fda5a5f05ce24854151f
+		objects.tags.max_size=132
+		objects.tags.max_size_oid=1ee0f2b16ea37d895dbe9dbd76cd2ac70446176c
+		objects.commits.max_parents=1
+		objects.commits.max_parents_oid=de3508174b5c2ace6993da67cae9be9069e2df39
+		objects.trees.max_entries=42
+		objects.trees.max_entries_oid=09931deea9d81ec21300d3e13c74412f32eacec5
 		EOF
 
 		git repo structure --format=lines >out 2>err &&
@@ -181,4 +224,10 @@
 	)
 '
 
+test_expect_success 'git repo structure -h shows only repo structure usage' '
+	test_must_fail git repo structure -h >actual &&
+	test_grep "git repo structure" actual &&
+	test_grep ! "git repo info" actual
+'
+
 test_done
diff --git a/t/t2107-update-index-basic.sh b/t/t2107-update-index-basic.sh
index cc72ead..3bffe5d 100755
--- a/t/t2107-update-index-basic.sh
+++ b/t/t2107-update-index-basic.sh
@@ -86,7 +86,7 @@
 	# the_index.cache_changed is zero, rollback_lock_file fails
 	git update-index --refresh --verbose >out &&
 	test_must_be_empty out &&
-	! test -f .git/index.lock
+	test_path_is_missing .git/index.lock
 	)
 '
 
diff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh
index 192ad14..44c1936 100755
--- a/t/t2203-add-intent.sh
+++ b/t/t2203-add-intent.sh
@@ -16,7 +16,8 @@
 '
 
 test_expect_success 'git status' '
-	git status --porcelain | grep -v actual >actual &&
+	git status --porcelain >actual.raw &&
+	grep -v actual actual.raw >actual &&
 	cat >expect <<-\EOF &&
 	DA 1.t
 	A  elif
@@ -26,7 +27,8 @@
 '
 
 test_expect_success 'git status with porcelain v2' '
-	git status --porcelain=v2 | grep -v "^?" >actual &&
+	git status --porcelain=v2 >actual.raw &&
+	grep -v "^?" actual.raw >actual &&
 	nam1=$(echo 1 | git hash-object --stdin) &&
 	nam2=$(git hash-object elif) &&
 	cat >expect <<-EOF &&
@@ -171,17 +173,20 @@
 		mv first third &&
 		git add -N third &&
 
-		git status | grep -v "^?" >actual.1 &&
+		git status >actual.raw.1 &&
+		grep -v "^?" actual.raw.1 >actual.1 &&
 		test_grep "renamed: *first -> third" actual.1 &&
 
-		git status --porcelain | grep -v "^?" >actual.2 &&
+		git status --porcelain >actual.raw.2 &&
+		grep -v "^?" actual.raw.2 >actual.2 &&
 		cat >expected.2 <<-\EOF &&
 		 R first -> third
 		EOF
 		test_cmp expected.2 actual.2 &&
 
 		hash=$(git hash-object third) &&
-		git status --porcelain=v2 | grep -v "^?" >actual.3 &&
+		git status --porcelain=v2 >actual.raw.3 &&
+		grep -v "^?" actual.raw.3 >actual.3 &&
 		cat >expected.3 <<-EOF &&
 		2 .R N... 100644 100644 100644 $hash $hash R100 third	first
 		EOF
@@ -211,11 +216,13 @@
 		mv second third &&
 		git add -N third &&
 
-		git status | grep -v "^?" >actual.1 &&
+		git status >actual.raw.1 &&
+		grep -v "^?" actual.raw.1 >actual.1 &&
 		test_grep "renamed: *first -> second" actual.1 &&
 		test_grep "renamed: *second -> third" actual.1 &&
 
-		git status --porcelain | grep -v "^?" >actual.2 &&
+		git status --porcelain >actual.raw.2 &&
+		grep -v "^?" actual.raw.2 >actual.2 &&
 		cat >expected.2 <<-\EOF &&
 		R  first -> second
 		 R second -> third
@@ -223,7 +230,8 @@
 		test_cmp expected.2 actual.2 &&
 
 		hash=$(git hash-object third) &&
-		git status --porcelain=v2 | grep -v "^?" >actual.3 &&
+		git status --porcelain=v2 >actual.raw.3 &&
+		grep -v "^?" actual.raw.3 >actual.3 &&
 		cat >expected.3 <<-EOF &&
 		2 R. N... 100644 100644 100644 $hash $hash R100 second	first
 		2 .R N... 100644 100644 100644 $hash $hash R100 third	second
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index c58e505..e7829c2 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -1494,7 +1494,8 @@
 '
 
 test_expect_success '--merged catches invalid object names' '
-	test_must_fail git branch --merged 0000000000000000000000000000000000000000
+	test_must_fail git branch --merged $ZERO_OID 2>err &&
+	test_grep "must point to a commit" err
 '
 
 test_expect_success '--list during rebase' '
diff --git a/t/t3310-notes-merge-manual-resolve.sh b/t/t3310-notes-merge-manual-resolve.sh
index f0054b0..0bb366f 100755
--- a/t/t3310-notes-merge-manual-resolve.sh
+++ b/t/t3310-notes-merge-manual-resolve.sh
@@ -227,7 +227,8 @@
 	# Verify that current notes tree (pre-merge) has not changed (m == y)
 	verify_notes y &&
 	verify_notes m &&
-	test "$(git rev-parse refs/notes/m)" = "$(cat pre_merge_y)"
+	git rev-parse refs/notes/m >actual &&
+	test_cmp pre_merge_y actual
 '
 
 cat <<EOF | sort >expect_notes_z
@@ -375,8 +376,10 @@
 	git notes merge --commit &&
 	notes_merge_files_gone &&
 	# Merge commit has pre-merge y and pre-merge z as parents
-	test "$(git rev-parse refs/notes/m^1)" = "$(cat pre_merge_y)" &&
-	test "$(git rev-parse refs/notes/m^2)" = "$(cat pre_merge_z)" &&
+	git rev-parse refs/notes/m^1 >actual &&
+	test_cmp pre_merge_y actual &&
+	git rev-parse refs/notes/m^2 >actual &&
+	test_cmp pre_merge_z actual &&
 	# Merge commit mentions the notes refs merged
 	git log -1 --format=%B refs/notes/m > merge_commit_msg &&
 	grep -q refs/notes/m merge_commit_msg &&
@@ -428,14 +431,16 @@
 	# Verify that current notes tree (pre-merge) has not changed (m == y)
 	verify_notes y &&
 	verify_notes m &&
-	test "$(git rev-parse refs/notes/m)" = "$(cat pre_merge_y)"
+	git rev-parse refs/notes/m >actual &&
+	test_cmp pre_merge_y actual
 '
 
 test_expect_success 'abort notes merge' '
 	git notes merge --abort &&
 	notes_merge_files_gone &&
 	# m has not moved (still == y)
-	test "$(git rev-parse refs/notes/m)" = "$(cat pre_merge_y)" &&
+	git rev-parse refs/notes/m >actual &&
+	test_cmp pre_merge_y actual &&
 	# Verify that other notes refs has not changed (w, x, y and z)
 	verify_notes w &&
 	verify_notes x &&
@@ -460,7 +465,8 @@
 	# Verify that current notes tree (pre-merge) has not changed (m == y)
 	verify_notes y &&
 	verify_notes m &&
-	test "$(git rev-parse refs/notes/m)" = "$(cat pre_merge_y)"
+	git rev-parse refs/notes/m >actual &&
+	test_cmp pre_merge_y actual
 '
 
 cat <<EOF | sort >expect_notes_m
@@ -500,8 +506,10 @@
 	git notes merge --commit &&
 	notes_merge_files_gone &&
 	# Merge commit has pre-merge y and pre-merge z as parents
-	test "$(git rev-parse refs/notes/m^1)" = "$(cat pre_merge_y)" &&
-	test "$(git rev-parse refs/notes/m^2)" = "$(cat pre_merge_z)" &&
+	git rev-parse refs/notes/m^1 >actual &&
+	test_cmp pre_merge_y actual &&
+	git rev-parse refs/notes/m^2 >actual &&
+	test_cmp pre_merge_z actual &&
 	# Merge commit mentions the notes refs merged
 	git log -1 --format=%B refs/notes/m > merge_commit_msg &&
 	grep -q refs/notes/m merge_commit_msg &&
@@ -539,7 +547,8 @@
 	# Verify that current notes tree (pre-merge) has not changed (m == y)
 	verify_notes y &&
 	verify_notes m &&
-	test "$(git rev-parse refs/notes/m)" = "$(cat pre_merge_y)"
+	git rev-parse refs/notes/m >actual &&
+	test_cmp pre_merge_y actual
 '
 
 cp expect_notes_w expect_notes_m
@@ -548,7 +557,7 @@
 test_expect_success 'reset notes ref m to somewhere else (w)' '
 	git update-ref refs/notes/m refs/notes/w &&
 	verify_notes m &&
-	test "$(git rev-parse refs/notes/m)" = "$(git rev-parse refs/notes/w)"
+	test_cmp_rev refs/notes/m refs/notes/w
 '
 
 test_expect_success 'fail to finalize conflicting merge if underlying ref has moved in the meantime (m != NOTES_MERGE_PARTIAL^1)' '
@@ -569,13 +578,15 @@
 	test_path_is_file .git/NOTES_MERGE_WORKTREE/$commit_sha3 &&
 	test_path_is_file .git/NOTES_MERGE_WORKTREE/$commit_sha4 &&
 	# Refs are unchanged
-	test "$(git rev-parse refs/notes/m)" = "$(git rev-parse refs/notes/w)" &&
-	test "$(git rev-parse refs/notes/y)" = "$(git rev-parse NOTES_MERGE_PARTIAL^1)" &&
-	test "$(git rev-parse refs/notes/m)" != "$(git rev-parse NOTES_MERGE_PARTIAL^1)" &&
+	test_cmp_rev refs/notes/m refs/notes/w &&
+	test_cmp_rev refs/notes/y NOTES_MERGE_PARTIAL^1 &&
+	test_cmp_rev ! refs/notes/m NOTES_MERGE_PARTIAL^1 &&
 	# Mention refs/notes/m, and its current and expected value in output
 	test_grep -q "refs/notes/m" output &&
-	test_grep -q "$(git rev-parse refs/notes/m)" output &&
-	test_grep -q "$(git rev-parse NOTES_MERGE_PARTIAL^1)" output &&
+	oid=$(git rev-parse refs/notes/m) &&
+	test_grep -q "$oid" output &&
+	oid=$(git rev-parse NOTES_MERGE_PARTIAL^1) &&
+	test_grep -q "$oid" output &&
 	# Verify that other notes refs has not changed (w, x, y and z)
 	verify_notes w &&
 	verify_notes x &&
@@ -587,7 +598,7 @@
 	git notes merge --abort &&
 	notes_merge_files_gone &&
 	# m has not moved (still == w)
-	test "$(git rev-parse refs/notes/m)" = "$(git rev-parse refs/notes/w)" &&
+	test_cmp_rev refs/notes/m refs/notes/w &&
 	# Verify that other notes refs has not changed (w, x, y and z)
 	verify_notes w &&
 	verify_notes x &&
@@ -606,8 +617,8 @@
 	test_must_fail git notes merge refs/notes/other &&
 	(
 		cd .git/NOTES_MERGE_WORKTREE &&
-		echo "foo" > $(git rev-parse HEAD) &&
-		echo "bar" >> $(git rev-parse HEAD) &&
+		oid=$(git rev-parse HEAD) &&
+		test_write_lines foo bar >"$oid" &&
 		git notes merge --commit
 	) &&
 	git notes show HEAD > actual_notes &&
diff --git a/t/t3440-rebase-trailer.sh b/t/t3440-rebase-trailer.sh
new file mode 100755
index 0000000..8b47579
--- /dev/null
+++ b/t/t3440-rebase-trailer.sh
@@ -0,0 +1,147 @@
+#!/bin/sh
+#
+
+test_description='git rebase --trailer integration tests
+We verify that --trailer works with the merge backend,
+and that it is rejected early when the apply backend is requested.'
+
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-rebase.sh # test_commit_message, helpers
+
+REVIEWED_BY_TRAILER="Reviewed-by: Dev <dev@example.com>"
+SP=" "
+
+test_expect_success 'setup repo with a small history' '
+	git commit --allow-empty -m "Initial empty commit" &&
+	test_commit first file a &&
+	test_commit second file &&
+	git checkout -b conflict-branch first &&
+	test_commit file-2 file-2 &&
+	test_commit conflict file &&
+	test_commit third file &&
+	git checkout main
+'
+
+test_expect_success 'apply backend is rejected with --trailer' '
+	git checkout -B apply-backend third &&
+	test_expect_code 128 \
+		git rebase --apply --trailer "$REVIEWED_BY_TRAILER" HEAD^ 2>err &&
+	test_grep "fatal: --trailer requires the merge backend" err
+'
+
+test_expect_success 'reject empty --trailer argument' '
+	git checkout -B empty-trailer third &&
+	test_expect_code 128 git rebase --trailer "" HEAD^ 2>err &&
+	test_grep "empty --trailer" err
+'
+
+test_expect_success 'reject trailer with missing key before separator' '
+	git checkout -B missing-key third &&
+	test_expect_code 128 git rebase --trailer ": no-key" HEAD^ 2>err &&
+	test_grep "missing key before separator" err
+'
+
+test_expect_success 'allow trailer with missing value after separator' '
+	git checkout -B missing-value third &&
+	git rebase --trailer "Acked-by:" HEAD^ &&
+	test_commit_message HEAD <<-EOF
+	third
+
+	Acked-by:${SP}
+	EOF
+'
+
+test_expect_success 'CLI trailer duplicates allowed; replace policy keeps last' '
+	git checkout -B replace-policy third &&
+	git -c trailer.Bug.ifexists=replace -c trailer.Bug.ifmissing=add \
+		rebase --trailer "Bug: 123" --trailer "Bug: 456" HEAD^ &&
+	test_commit_message HEAD <<-EOF
+	third
+
+	Bug: 456
+	EOF
+'
+
+test_expect_success 'multiple Signed-off-by trailers all preserved' '
+	git checkout -B multiple-signoff third &&
+	git rebase --trailer "Signed-off-by: Dev A <a@example.com>" \
+		--trailer "Signed-off-by: Dev B <b@example.com>" HEAD^ &&
+	test_commit_message HEAD <<-EOF
+	third
+
+	Signed-off-by: Dev A <a@example.com>
+	Signed-off-by: Dev B <b@example.com>
+	EOF
+'
+
+test_expect_success 'rebase --trailer adds trailer after conflicts' '
+	git checkout -B trailer-conflict third &&
+	test_commit fourth file &&
+	test_must_fail git rebase --trailer "$REVIEWED_BY_TRAILER" second &&
+	git checkout --theirs file &&
+	git add file &&
+	git rebase --continue &&
+	test_commit_message HEAD <<-EOF &&
+	fourth
+
+	$REVIEWED_BY_TRAILER
+	EOF
+	test_commit_message HEAD^ <<-EOF
+	third
+
+	$REVIEWED_BY_TRAILER
+	EOF
+'
+
+test_expect_success '--trailer handles fixup commands in todo list' '
+	git checkout -B fixup-trailer third &&
+	test_commit fixup-base base &&
+	test_commit fixup-second second &&
+	cat >todo <<-\EOF &&
+	pick fixup-base fixup-base
+	fixup fixup-second fixup-second
+	EOF
+	(
+		set_replace_editor todo &&
+		git rebase -i --trailer "$REVIEWED_BY_TRAILER" HEAD~2
+	) &&
+	test_commit_message HEAD <<-EOF &&
+	fixup-base
+
+	$REVIEWED_BY_TRAILER
+	EOF
+	git reset --hard fixup-second &&
+	cat >todo <<-\EOF &&
+	pick fixup-base fixup-base
+	fixup -C fixup-second fixup-second
+	EOF
+	(
+		set_replace_editor todo &&
+		git rebase -i --trailer "$REVIEWED_BY_TRAILER" HEAD~2
+	) &&
+	test_commit_message HEAD <<-EOF
+	fixup-second
+
+	$REVIEWED_BY_TRAILER
+	EOF
+'
+
+test_expect_success 'rebase --root honors trailer.<name>.key' '
+	git checkout -B root-trailer first &&
+	git -c trailer.review.key=Reviewed-by rebase --root \
+		--trailer=review="Dev <dev@example.com>" &&
+	test_commit_message HEAD <<-EOF &&
+	first
+
+	Reviewed-by: Dev <dev@example.com>
+	EOF
+	test_commit_message HEAD^ <<-EOF
+	Initial empty commit
+
+	Reviewed-by: Dev <dev@example.com>
+	EOF
+'
+test_done
diff --git a/t/t3452-history-split.sh b/t/t3452-history-split.sh
new file mode 100755
index 0000000..8ed0ceb
--- /dev/null
+++ b/t/t3452-history-split.sh
@@ -0,0 +1,757 @@
+#!/bin/sh
+
+test_description='tests for git-history split subcommand'
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY/lib-log-graph.sh"
+
+# The fake editor takes multiple arguments, each of which represents a commit
+# message. Subsequent invocations of the editor will then yield those messages
+# in order.
+#
+set_fake_editor () {
+	printf "%s\n" "$@" >fake-input &&
+	write_script fake-editor.sh <<-\EOF &&
+	head -n1 fake-input >"$1"
+	sed 1d fake-input >fake-input.trimmed &&
+	mv fake-input.trimmed fake-input
+	EOF
+	test_set_editor "$(pwd)"/fake-editor.sh
+}
+
+expect_graph () {
+	cat >expect &&
+	lib_test_cmp_graph --graph --format=%s "$@"
+}
+
+expect_log () {
+	git log --format="%s" >actual &&
+	cat >expect &&
+	test_cmp expect actual
+}
+
+expect_tree_entries () {
+	git ls-tree --name-only "$1" >actual &&
+	cat >expect &&
+	test_cmp expect actual
+}
+
+test_expect_success 'refuses to work with merge commits' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		test_commit base &&
+		git branch branch &&
+		test_commit ours &&
+		git switch branch &&
+		test_commit theirs &&
+		git switch - &&
+		git merge theirs &&
+		test_must_fail git history split HEAD 2>err &&
+		test_grep "cannot split up merge commit" err &&
+		test_must_fail git history split HEAD~ 2>err &&
+		test_grep "replaying merge commits is not supported yet" err
+	)
+'
+
+test_expect_success 'errors on missing commit argument' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		test_commit initial &&
+		test_must_fail git history split 2>err &&
+		test_grep "command expects a committish" err
+	)
+'
+
+test_expect_success 'errors on unknown revision' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		test_commit initial &&
+		test_must_fail git history split does-not-exist 2>err &&
+		test_grep "commit cannot be found" err
+	)
+'
+
+test_expect_success '--dry-run does not modify any refs' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		test_commit base &&
+		touch bar foo &&
+		git add . &&
+		git commit -m split-me &&
+
+		git refs list --include-root-refs >before &&
+
+		set_fake_editor "first" "second" &&
+		git history split --dry-run HEAD <<-EOF &&
+		y
+		n
+		EOF
+
+		git refs list --include-root-refs >after &&
+		test_cmp before after
+	)
+'
+
+test_expect_success 'can split up tip commit' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		test_commit initial &&
+		touch bar foo &&
+		git add . &&
+		git commit -m split-me &&
+
+		git symbolic-ref HEAD >expect &&
+		set_fake_editor "first" "second" &&
+		git history split HEAD <<-EOF &&
+		y
+		n
+		EOF
+		git symbolic-ref HEAD >actual &&
+		test_cmp expect actual &&
+
+		expect_log <<-EOF &&
+		second
+		first
+		initial
+		EOF
+
+		expect_tree_entries HEAD~ <<-EOF &&
+		bar
+		initial.t
+		EOF
+
+		expect_tree_entries HEAD <<-EOF &&
+		bar
+		foo
+		initial.t
+		EOF
+
+		git reflog >reflog &&
+		test_grep "split: updating HEAD" reflog
+	)
+'
+
+test_expect_success 'can split up root commit' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		touch bar foo &&
+		git add . &&
+		git commit -m root &&
+		test_commit tip &&
+
+		set_fake_editor "first" "second" &&
+		git history split HEAD~ <<-EOF &&
+		y
+		n
+		EOF
+
+		expect_log <<-EOF &&
+		tip
+		second
+		first
+		EOF
+
+		expect_tree_entries HEAD~2 <<-EOF &&
+		bar
+		EOF
+
+		expect_tree_entries HEAD~ <<-EOF &&
+		bar
+		foo
+		EOF
+
+		expect_tree_entries HEAD <<-EOF
+		bar
+		foo
+		tip.t
+		EOF
+	)
+'
+
+test_expect_success 'can split up in-between commit' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		test_commit initial &&
+		touch bar foo &&
+		git add . &&
+		git commit -m split-me &&
+		test_commit tip &&
+
+		set_fake_editor "first" "second" &&
+		git history split HEAD~ <<-EOF &&
+		y
+		n
+		EOF
+
+		expect_log <<-EOF &&
+		tip
+		second
+		first
+		initial
+		EOF
+
+		expect_tree_entries HEAD~2 <<-EOF &&
+		bar
+		initial.t
+		EOF
+
+		expect_tree_entries HEAD~ <<-EOF &&
+		bar
+		foo
+		initial.t
+		EOF
+
+		expect_tree_entries HEAD <<-EOF
+		bar
+		foo
+		initial.t
+		tip.t
+		EOF
+	)
+'
+
+test_expect_success 'can split HEAD only' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		test_commit base &&
+		touch a b &&
+		git add . &&
+		git commit -m split-me &&
+		git branch unrelated &&
+
+		set_fake_editor "ours-a" "ours-b" &&
+		git history split --update-refs=head HEAD <<-EOF &&
+		y
+		n
+		EOF
+		expect_graph --branches <<-EOF
+		* ours-b
+		* ours-a
+		| * split-me
+		|/
+		* base
+		EOF
+	)
+'
+
+test_expect_success 'can split detached HEAD' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		test_commit initial &&
+		touch bar foo &&
+		git add . &&
+		git commit -m split-me &&
+		git checkout --detach HEAD &&
+
+		set_fake_editor "first" "second" &&
+		git history split --update-refs=head HEAD <<-EOF &&
+		y
+		n
+		EOF
+
+		# HEAD should be detached and updated.
+		test_must_fail git symbolic-ref HEAD &&
+
+		expect_log <<-EOF
+		second
+		first
+		initial
+		EOF
+	)
+'
+
+test_expect_success 'can split commit in unrelated branch' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		test_commit base &&
+		git branch ours &&
+		git switch --create theirs &&
+		touch theirs-a theirs-b &&
+		git add . &&
+		git commit -m theirs &&
+		git switch ours &&
+		test_commit ours &&
+
+		# With --update-refs=head it is not possible to split up a
+		# commit that is unrelated to HEAD.
+		test_must_fail git history split --update-refs=head theirs 2>err &&
+		test_grep "rewritten commit must be an ancestor of HEAD" err &&
+
+		set_fake_editor "theirs-rewritten-a" "theirs-rewritten-b" &&
+		git history split theirs <<-EOF &&
+		y
+		n
+		EOF
+		expect_graph --branches <<-EOF &&
+		* ours
+		| * theirs-rewritten-b
+		| * theirs-rewritten-a
+		|/
+		* base
+		EOF
+
+		expect_tree_entries theirs~ <<-EOF &&
+		base.t
+		theirs-a
+		EOF
+
+		expect_tree_entries theirs <<-EOF
+		base.t
+		theirs-a
+		theirs-b
+		EOF
+	)
+'
+
+test_expect_success 'updates multiple descendant branches' '
+	test_when_finished "rm -rf repo" &&
+	git init repo --initial-branch=main &&
+	(
+		cd repo &&
+		test_commit base &&
+		touch file-a file-b &&
+		git add . &&
+		git commit -m split-me &&
+		git branch branch &&
+		test_commit on-main &&
+		git switch branch &&
+		test_commit on-branch &&
+		git switch main &&
+
+		set_fake_editor "split-a" "split-b" &&
+		git history split HEAD~ <<-EOF &&
+		y
+		n
+		EOF
+
+		# Both branches should now descend from the split commits.
+		expect_graph --branches <<-EOF
+		* on-branch
+		| * on-main
+		|/
+		* split-b
+		* split-a
+		* base
+		EOF
+	)
+'
+
+test_expect_success 'can pick multiple hunks' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		touch bar baz foo qux &&
+		git add . &&
+		git commit -m split-me &&
+
+		set_fake_editor "first" "second" &&
+		git history split HEAD <<-EOF &&
+		y
+		n
+		y
+		n
+		EOF
+
+		expect_tree_entries HEAD~ <<-EOF &&
+		bar
+		foo
+		EOF
+
+		expect_tree_entries HEAD <<-EOF
+		bar
+		baz
+		foo
+		qux
+		EOF
+	)
+'
+
+test_expect_success 'can use only last hunk' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		touch bar foo &&
+		git add . &&
+		git commit -m split-me &&
+
+		set_fake_editor "first" "second" &&
+		git history split HEAD <<-EOF &&
+		n
+		y
+		EOF
+
+		expect_log <<-EOF &&
+		second
+		first
+		EOF
+
+		expect_tree_entries HEAD~ <<-EOF &&
+		foo
+		EOF
+
+		expect_tree_entries HEAD <<-EOF
+		bar
+		foo
+		EOF
+	)
+'
+
+test_expect_success 'can split commit with file deletions' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		echo a >a &&
+		echo b >b &&
+		echo c >c &&
+		git add . &&
+		git commit -m base &&
+		git rm a b &&
+		git commit -m delete-both &&
+
+		set_fake_editor "delete-a" "delete-b" &&
+		git history split HEAD <<-EOF &&
+		y
+		n
+		EOF
+
+		expect_log <<-EOF &&
+		delete-b
+		delete-a
+		base
+		EOF
+
+		expect_tree_entries HEAD~ <<-EOF &&
+		b
+		c
+		EOF
+
+		expect_tree_entries HEAD <<-EOF
+		c
+		EOF
+	)
+'
+
+test_expect_success 'preserves original authorship' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		test_commit initial &&
+		touch bar foo &&
+		git add . &&
+		GIT_AUTHOR_NAME="Other Author" \
+		GIT_AUTHOR_EMAIL="other@example.com" \
+		git commit -m split-me &&
+
+		set_fake_editor "first" "second" &&
+		git history split HEAD <<-EOF &&
+		y
+		n
+		EOF
+
+		git log -1 --format="%an <%ae>" HEAD~ >actual &&
+		echo "Other Author <other@example.com>" >expect &&
+		test_cmp expect actual &&
+
+		git log -1 --format="%an <%ae>" HEAD >actual &&
+		test_cmp expect actual
+	)
+'
+
+test_expect_success 'aborts with empty commit message' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		touch bar foo &&
+		git add . &&
+		git commit -m split-me &&
+
+		set_fake_editor "" &&
+		test_must_fail git history split HEAD <<-EOF 2>err &&
+		y
+		n
+		EOF
+		test_grep "Aborting commit due to empty commit message." err
+	)
+'
+
+test_expect_success 'commit message editor sees split-out changes' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		touch bar foo &&
+		git add . &&
+		git commit -m split-me &&
+
+		write_script fake-editor.sh <<-\EOF &&
+		cat "$1" >>MESSAGES &&
+		echo "some commit message" >"$1"
+		EOF
+		test_set_editor "$(pwd)"/fake-editor.sh &&
+
+		git history split HEAD <<-EOF &&
+		y
+		n
+		EOF
+
+		# Note that we expect to see the messages twice, once for each
+		# of the commits. The committed files are different though.
+		cat >expect <<-EOF &&
+		split-me
+
+		# Please enter the commit message for the split-out changes. Lines starting
+		# with ${SQ}#${SQ} will be ignored, and an empty message aborts the commit.
+		# Changes to be committed:
+		#	new file:   bar
+		#
+		split-me
+
+		# Please enter the commit message for the split-out changes. Lines starting
+		# with ${SQ}#${SQ} will be ignored, and an empty message aborts the commit.
+		# Changes to be committed:
+		#	new file:   foo
+		#
+		EOF
+		test_cmp expect MESSAGES &&
+
+		expect_log <<-EOF
+		some commit message
+		some commit message
+		EOF
+	)
+'
+
+test_expect_success 'can use pathspec to limit what gets split' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		touch bar foo &&
+		git add . &&
+		git commit -m split-me &&
+
+		set_fake_editor "first" "second" &&
+		git history split HEAD -- foo <<-EOF &&
+		y
+		EOF
+
+		expect_tree_entries HEAD~ <<-EOF &&
+		foo
+		EOF
+
+		expect_tree_entries HEAD <<-EOF
+		bar
+		foo
+		EOF
+	)
+'
+
+test_expect_success 'pathspec matching no files produces empty split error' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		test_commit initial &&
+		touch bar foo &&
+		git add . &&
+		git commit -m split-me &&
+
+		set_fake_editor "first" "second" &&
+		test_must_fail git history split HEAD -- nonexistent 2>err &&
+		test_grep "split commit is empty" err
+	)
+'
+
+test_expect_success 'split with multiple pathspecs' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		test_commit initial &&
+		touch a b c d &&
+		git add . &&
+		git commit -m split-me &&
+
+		# Only a and c should be offered for splitting.
+		set_fake_editor "split-ac" "remainder" &&
+		git history split HEAD -- a c <<-EOF &&
+		y
+		y
+		EOF
+
+		expect_tree_entries HEAD~ <<-EOF &&
+		a
+		c
+		initial.t
+		EOF
+
+		expect_tree_entries HEAD <<-EOF
+		a
+		b
+		c
+		d
+		initial.t
+		EOF
+	)
+'
+
+test_expect_success 'split with file mode change' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		echo content >script &&
+		git add . &&
+		git commit -m base &&
+		test_chmod +x script &&
+		echo change >script &&
+		git commit -a -m "mode and content change" &&
+
+		set_fake_editor "mode-change" "content-change" &&
+		git history split HEAD <<-EOF &&
+		y
+		n
+		EOF
+
+		expect_log <<-EOF
+		content-change
+		mode-change
+		base
+		EOF
+	)
+'
+
+test_expect_success 'refuses to create empty split-out commit' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		test_commit base &&
+		touch bar foo &&
+		git add . &&
+		git commit -m split-me &&
+
+		test_must_fail git history split HEAD 2>err <<-EOF &&
+		n
+		n
+		EOF
+		test_grep "split commit is empty" err
+	)
+'
+
+test_expect_success 'hooks are not executed for rewritten commits' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		touch bar foo &&
+		git add . &&
+		git commit -m split-me &&
+		old_head=$(git rev-parse HEAD) &&
+
+		ORIG_PATH="$(pwd)" &&
+		export ORIG_PATH &&
+		for hook in prepare-commit-msg pre-commit post-commit post-rewrite commit-msg
+		do
+			write_script .git/hooks/$hook <<-\EOF || exit 1
+			touch "$ORIG_PATH"/hooks.log
+			EOF
+		done &&
+
+		set_fake_editor "first" "second" &&
+		git history split HEAD <<-EOF &&
+		y
+		n
+		EOF
+
+		expect_log <<-EOF &&
+		second
+		first
+		EOF
+
+		test_path_is_missing hooks.log
+	)
+'
+
+test_expect_success 'refuses to create empty original commit' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		touch bar foo &&
+		git add . &&
+		git commit -m split-me &&
+
+		test_must_fail git history split HEAD 2>err <<-EOF &&
+		y
+		y
+		EOF
+		test_grep "split commit tree matches original commit" err
+	)
+'
+
+test_expect_success 'retains changes in the worktree and index' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		echo a >a &&
+		echo b >b &&
+		git add . &&
+		git commit -m "initial commit" &&
+		echo a-modified >a &&
+		echo b-modified >b &&
+		git add b &&
+		set_fake_editor "a-only" "remainder" &&
+		git history split HEAD <<-EOF &&
+		y
+		n
+		EOF
+
+		expect_tree_entries HEAD~ <<-EOF &&
+		a
+		EOF
+		expect_tree_entries HEAD <<-EOF &&
+		a
+		b
+		EOF
+
+		cat >expect <<-\EOF &&
+		 M a
+		M  b
+		?? actual
+		?? expect
+		?? fake-editor.sh
+		?? fake-input
+		EOF
+		git status --porcelain >actual &&
+		test_cmp expect actual
+	)
+'
+
+test_done
diff --git a/t/t4012-diff-binary.sh b/t/t4012-diff-binary.sh
index d1d30ac..97b5ac0 100755
--- a/t/t4012-diff-binary.sh
+++ b/t/t4012-diff-binary.sh
@@ -68,7 +68,7 @@
 	sed -e "s/-CIT/xCIT/" <output >broken &&
 	test_must_fail git apply --stat --summary broken 2>detected &&
 	detected=$(cat detected) &&
-	detected=$(expr "$detected" : "error.*at line \\([0-9]*\\)\$") &&
+	detected=$(expr "$detected" : "error.*broken:\\([0-9]*\\)\$") &&
 	detected=$(sed -ne "${detected}p" broken) &&
 	test "$detected" = xCIT
 '
@@ -77,7 +77,7 @@
 	git diff --binary | sed -e "s/-CIT/xCIT/" >broken &&
 	test_must_fail git apply --stat --summary broken 2>detected &&
 	detected=$(cat detected) &&
-	detected=$(expr "$detected" : "error.*at line \\([0-9]*\\)\$") &&
+	detected=$(expr "$detected" : "error.*broken:\\([0-9]*\\)\$") &&
 	detected=$(sed -ne "${detected}p" broken) &&
 	test "$detected" = xCIT
 '
diff --git a/t/t4074-diff-shifted-matched-group.sh b/t/t4074-diff-shifted-matched-group.sh
new file mode 100755
index 0000000..d77fa3b
--- /dev/null
+++ b/t/t4074-diff-shifted-matched-group.sh
@@ -0,0 +1,164 @@
+#!/bin/sh
+
+test_description='shifted diff groups re-diffing during histogram diff'
+
+. ./test-lib.sh
+
+test_expect_success 'shifted/merged diff group should re-diff to minimize patch' '
+	test_write_lines A x A A A x A A A >file1 &&
+	test_write_lines A x A Z A x A A A >file2 &&
+
+	file1_h=$(git rev-parse --short $(git hash-object file1)) &&
+	file2_h=$(git rev-parse --short $(git hash-object file2)) &&
+
+	cat >expect <<-EOF &&
+	diff --git a/file1 b/file2
+	index $file1_h..$file2_h 100644
+	--- a/file1
+	+++ b/file2
+	@@ -1,7 +1,7 @@
+	 A
+	 x
+	 A
+	-A
+	+Z
+	 A
+	 x
+	 A
+	EOF
+
+	test_expect_code 1 git diff --no-index --histogram file1 file2 >output &&
+	test_cmp expect output
+'
+
+test_expect_success 'merged diff group with no shift' '
+	test_write_lines A Z B x >file1 &&
+	test_write_lines C D x Z E x >file2 &&
+
+	file1_h=$(git rev-parse --short $(git hash-object file1)) &&
+	file2_h=$(git rev-parse --short $(git hash-object file2)) &&
+
+	cat >expect <<-EOF &&
+	diff --git a/file1 b/file2
+	index $file1_h..$file2_h 100644
+	--- a/file1
+	+++ b/file2
+	@@ -1,4 +1,6 @@
+	-A
+	+C
+	+D
+	+x
+	 Z
+	-B
+	+E
+	 x
+	EOF
+
+	test_expect_code 1 git diff --no-index --histogram file1 file2 >output &&
+	test_cmp expect output
+'
+
+test_expect_success 're-diff should preserve diff flags' '
+	test_write_lines a b c a b c >file1 &&
+	test_write_lines x " b" z a b c >file2 &&
+
+	file1_h=$(git rev-parse --short $(git hash-object file1)) &&
+	file2_h=$(git rev-parse --short $(git hash-object file2)) &&
+
+	cat >expect <<-EOF &&
+	diff --git a/file1 b/file2
+	index $file1_h..$file2_h 100644
+	--- a/file1
+	+++ b/file2
+	@@ -1,6 +1,6 @@
+	-a
+	-b
+	-c
+	+x
+	+ b
+	+z
+	 a
+	 b
+	 c
+	EOF
+
+	test_expect_code 1 git diff --no-index --histogram file1 file2 >output &&
+	test_cmp expect output &&
+
+	cat >expect_iwhite <<-EOF &&
+	diff --git a/file1 b/file2
+	index $file1_h..$file2_h 100644
+	--- a/file1
+	+++ b/file2
+	@@ -1,6 +1,6 @@
+	-a
+	+x
+	  b
+	-c
+	+z
+	 a
+	 b
+	 c
+	EOF
+
+	test_expect_code 1 git diff --no-index --histogram --ignore-all-space file1 file2 >output_iwhite &&
+	test_cmp expect_iwhite output_iwhite
+'
+
+test_expect_success 'shifting on either side should trigger re-diff properly' '
+	test_write_lines a b c a b c a b c >file1 &&
+	test_write_lines a b c a1 a2 a3 b c1 a b c >file2 &&
+
+	file1_h=$(git rev-parse --short $(git hash-object file1)) &&
+	file2_h=$(git rev-parse --short $(git hash-object file2)) &&
+
+	cat >expect1 <<-EOF &&
+	diff --git a/file1 b/file2
+	index $file1_h..$file2_h 100644
+	--- a/file1
+	+++ b/file2
+	@@ -1,9 +1,11 @@
+	 a
+	 b
+	 c
+	-a
+	+a1
+	+a2
+	+a3
+	 b
+	-c
+	+c1
+	 a
+	 b
+	 c
+	EOF
+
+	test_expect_code 1 git diff --no-index --histogram file1 file2 >output1 &&
+	test_cmp expect1 output1 &&
+
+	cat >expect2 <<-EOF &&
+	diff --git a/file2 b/file1
+	index $file2_h..$file1_h 100644
+	--- a/file2
+	+++ b/file1
+	@@ -1,11 +1,9 @@
+	 a
+	 b
+	 c
+	-a1
+	-a2
+	-a3
+	+a
+	 b
+	-c1
+	+c
+	 a
+	 b
+	 c
+	EOF
+
+	test_expect_code 1 git diff --no-index --histogram file2 file1 >output2 &&
+	test_cmp expect2 output2
+'
+
+test_done
diff --git a/t/t4100-apply-stat.sh b/t/t4100-apply-stat.sh
index a5664f3..8393076 100755
--- a/t/t4100-apply-stat.sh
+++ b/t/t4100-apply-stat.sh
@@ -48,7 +48,93 @@
 	+b
 	EOF
 	test_must_fail git apply patch 2>err &&
-	echo "error: corrupt patch at line 4" >expect &&
+	echo "error: corrupt patch at patch:4" >expect &&
+	test_cmp expect err
+'
+
+test_expect_success 'applying a hunk header which overflows from stdin fails' '
+	cat >patch <<-\EOF &&
+	diff -u a/file b/file
+	--- a/file
+	+++ b/file
+	@@ -98765432109876543210 +98765432109876543210 @@
+	-a
+	+b
+	EOF
+	test_must_fail git apply <patch 2>err &&
+	echo "error: corrupt patch at <stdin>:4" >expect &&
+	test_cmp expect err
+'
+
+test_expect_success 'applying multiple patches reports the corrupted input' '
+	cat >good.patch <<-\EOF &&
+	diff -u a/file b/file
+	--- a/file
+	+++ b/file
+	@@ -1 +1 @@
+	-a
+	+b
+	EOF
+	cat >bad.patch <<-\EOF &&
+	diff -u a/file b/file
+	--- a/file
+	+++ b/file
+	@@ -98765432109876543210 +98765432109876543210 @@
+	-a
+	+b
+	EOF
+	test_must_fail git apply --stat --summary good.patch bad.patch 2>err &&
+	echo "error: corrupt patch at bad.patch:4" >expect &&
+	test_cmp expect err
+'
+
+test_expect_success 'applying a patch without a header reports the input' '
+	cat >fragment.patch <<-\EOF &&
+	@@ -1 +1 @@
+	-a
+	+b
+	EOF
+	test_must_fail git apply fragment.patch 2>err &&
+	echo "error: patch fragment without header at fragment.patch:1: @@ -1 +1 @@" >expect &&
+	test_cmp expect err
+'
+
+test_expect_success 'applying a patch with a missing filename reports the input' '
+	cat >missing.patch <<-\EOF &&
+	diff --git a/f b/f
+	index 7898192..6178079 100644
+	--- a/f
+	@@ -1 +1 @@
+	-a
+	+b
+	EOF
+	test_must_fail git apply missing.patch 2>err &&
+	echo "error: git diff header lacks filename information at missing.patch:4" >expect &&
+	test_cmp expect err
+'
+
+test_expect_success 'applying a patch with an invalid mode reports the input' '
+	cat >mode.patch <<-\EOF &&
+	diff --git a/f b/f
+	old mode 10x644
+	EOF
+	test_must_fail git apply mode.patch 2>err &&
+	cat >expect <<-\EOF &&
+	error: invalid mode at mode.patch:2: 10x644
+
+	EOF
+	test_cmp expect err
+'
+
+test_expect_success 'applying a patch with only garbage reports the input' '
+	cat >garbage.patch <<-\EOF &&
+	diff --git a/f b/f
+	--- a/f
+	+++ b/f
+	this is garbage
+	EOF
+	test_must_fail git apply garbage.patch 2>err &&
+	echo "error: patch with only garbage at garbage.patch:4" >expect &&
 	test_cmp expect err
 '
 test_done
diff --git a/t/t4103-apply-binary.sh b/t/t4103-apply-binary.sh
index 8e302a5..f2d41e0 100755
--- a/t/t4103-apply-binary.sh
+++ b/t/t4103-apply-binary.sh
@@ -179,6 +179,24 @@
 	" <patch >patch.trunc &&
 
 	do_reset &&
-	test_must_fail git apply patch.trunc
+	test_must_fail git apply patch.trunc 2>err &&
+	line=$(awk "END { print NR + 1 }" patch.trunc) &&
+	grep "error: corrupt binary patch at patch.trunc:$line: " err
+'
+
+test_expect_success 'reject unrecognized binary diff' '
+	cat >patch.bad <<-\EOF &&
+	diff --git a/f b/f
+	new file mode 100644
+	index 0000000..7898192
+	GIT binary patch
+	bogus
+	EOF
+	test_must_fail git apply patch.bad 2>err &&
+	cat >expect <<-\EOF &&
+	error: unrecognized binary patch at patch.bad:4
+	error: No valid patches in input (allow with "--allow-empty")
+	EOF
+	test_cmp expect err
 '
 test_done
diff --git a/t/t4120-apply-popt.sh b/t/t4120-apply-popt.sh
index 697e86c..c960fdf 100755
--- a/t/t4120-apply-popt.sh
+++ b/t/t4120-apply-popt.sh
@@ -23,6 +23,47 @@
 	rmdir süb
 '
 
+test_expect_success 'git apply -p 1 patch' '
+	cat >patch <<-\EOF &&
+	From 90ad11d5b2d437e82d4d992f72fb44c2227798b5 Mon Sep 17 00:00:00 2001
+	From: Mroik <mroik@delayed.space>
+	Date: Mon, 9 Mar 2026 23:25:00 +0100
+	Subject: [PATCH] Test
+
+	---
+	 t/test/test | 0
+	 1 file changed, 0 insertions(+), 0 deletions(-)
+	 create mode 100644 t/test/test
+
+	diff --git a/t/test/test b/t/test/test
+	new file mode 100644
+	index 0000000000..e69de29bb2
+	--
+	2.53.0.851.ga537e3e6e9
+	EOF
+	test_when_finished "rm -rf t" &&
+	git apply -p 1 patch &&
+	test_path_is_dir t
+'
+
+test_expect_success 'apply fails due to non-num -p' '
+	test_when_finished "rm -rf t test err" &&
+	test_must_fail git apply -p malformed patch 2>err &&
+	test_grep "option -p expects a non-negative integer" err
+'
+
+test_expect_success 'apply fails due to trailing non-digit in -p' '
+	test_when_finished "rm -rf t test err" &&
+	test_must_fail git apply -p 2q patch 2>err &&
+	test_grep "option -p expects a non-negative integer" err
+'
+
+test_expect_success 'apply fails due to negative number in -p' '
+	test_when_finished "rm -rf t test err patch" &&
+	test_must_fail git apply -p -1 patch 2> err &&
+	test_grep "option -p expects a non-negative integer" err
+'
+
 test_expect_success 'apply git diff with -p2' '
 	cp file1.saved file1 &&
 	git apply -p2 patch.file
diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh
index 204325f..1717f40 100755
--- a/t/t4200-rerere.sh
+++ b/t/t4200-rerere.sh
@@ -72,7 +72,7 @@
 	rm -rf .git/rr-cache &&
 	git config rerere.enabled false &&
 	test_must_fail git merge first &&
-	! test -d .git/rr-cache
+	test_path_is_missing .git/rr-cache
 '
 
 test_expect_success 'activate rerere, old style (conflicting merge)' '
@@ -84,8 +84,8 @@
 	sha1=$(sed "s/	.*//" .git/MERGE_RR) &&
 	rr=.git/rr-cache/$sha1 &&
 	grep "^=======\$" $rr/preimage &&
-	! test -f $rr/postimage &&
-	! test -f $rr/thisimage
+	test_path_is_missing $rr/postimage &&
+	test_path_is_missing $rr/thisimage
 '
 
 test_expect_success 'rerere.enabled works, too' '
@@ -110,8 +110,8 @@
 
 test_expect_success 'rr-cache looks sane' '
 	# no postimage or thisimage yet
-	! test -f $rr/postimage &&
-	! test -f $rr/thisimage &&
+	test_path_is_missing $rr/postimage &&
+	test_path_is_missing $rr/thisimage &&
 
 	# preimage has right number of lines
 	cnt=$(sed -ne "/^<<<<<<</,/^>>>>>>>/p" $rr/preimage | wc -l) &&
@@ -167,7 +167,7 @@
 	git show first:a1 | sed "s/To die: t/To die! T/" >expect &&
 
 	git commit -q -a -m "prefer first over second" &&
-	test -f $rr/postimage &&
+	test_path_is_file $rr/postimage &&
 
 	oldmtimepost=$(test-tool chmtime --get -60 $rr/postimage) &&
 
@@ -190,14 +190,14 @@
 	mv $rr/postimage .git/post-saved &&
 	echo "$sha1	a1" | tr "\012" "\000" >.git/MERGE_RR &&
 	git rerere clear &&
-	! test -d $rr
+	test_path_is_missing $rr
 '
 
 test_expect_success 'leftover directory' '
 	git reset --hard &&
 	mkdir -p $rr &&
 	test_must_fail git merge first &&
-	test -f $rr/preimage
+	test_path_is_file $rr/preimage
 '
 
 test_expect_success 'missing preimage' '
@@ -205,7 +205,7 @@
 	mkdir -p $rr &&
 	cp .git/post-saved $rr/postimage &&
 	test_must_fail git merge first &&
-	test -f $rr/preimage
+	test_path_is_file $rr/preimage
 '
 
 test_expect_success 'set up for garbage collection tests' '
@@ -230,16 +230,16 @@
 
 test_expect_success 'gc preserves young or recently used records' '
 	git rerere gc &&
-	test -f $rr/preimage &&
-	test -f $rr2/preimage
+	test_path_is_file $rr/preimage &&
+	test_path_is_file $rr2/preimage
 '
 
 test_expect_success 'old records rest in peace' '
 	test-tool chmtime =$just_over_60_days_ago $rr/postimage &&
 	test-tool chmtime =$just_over_15_days_ago $rr2/preimage &&
 	git rerere gc &&
-	! test -f $rr/preimage &&
-	! test -f $rr2/preimage
+	test_path_is_missing $rr/preimage &&
+	test_path_is_missing $rr2/preimage
 '
 
 rerere_gc_custom_expiry_test () {
diff --git a/t/t4254-am-corrupt.sh b/t/t4254-am-corrupt.sh
index ae0a56c..96ddf3c 100755
--- a/t/t4254-am-corrupt.sh
+++ b/t/t4254-am-corrupt.sh
@@ -65,9 +65,8 @@
 test_expect_success 'try to apply corrupted patch' '
 	test_when_finished "git am --abort" &&
 	test_must_fail git -c advice.amWorkDir=false -c advice.mergeConflict=false am bad-patch.diff 2>actual &&
-	echo "error: git diff header lacks filename information (line 4)" >expected &&
 	test_path_is_file f &&
-	test_cmp expected actual
+	test_grep "error: git diff header lacks filename information at .*rebase-apply/patch:4" actual
 '
 
 test_expect_success "NUL in commit message's body" '
diff --git a/t/t5315-pack-objects-compression.sh b/t/t5315-pack-objects-compression.sh
index 8bacd96..d0feab1 100755
--- a/t/t5315-pack-objects-compression.sh
+++ b/t/t5315-pack-objects-compression.sh
@@ -10,7 +10,7 @@
 	# make sure it resulted in a loose object
 	ob=$(sed -e "s/\(..\).*/\1/" object-name) &&
 	ject=$(sed -e "s/..\(.*\)/\1/" object-name) &&
-	test -f .git/objects/$ob/$ject
+	test_path_is_file .git/objects/$ob/$ject
 '
 
 while read expect config
diff --git a/t/t5319-multi-pack-index.sh b/t/t5319-multi-pack-index.sh
index a7c7922..58e0b68 100755
--- a/t/t5319-multi-pack-index.sh
+++ b/t/t5319-multi-pack-index.sh
@@ -21,7 +21,7 @@
 	EXTRA_CHUNKS="$5"
 	{
 		cat <<-EOF &&
-		header: 4d494458 1 $HASH_LEN $NUM_CHUNKS $NUM_PACKS
+		header: 4d494458 2 $HASH_LEN $NUM_CHUNKS $NUM_PACKS
 		chunks: pack-names oid-fanout oid-lookup object-offsets$EXTRA_CHUNKS
 		num_objects: $NUM_OBJECTS
 		packs:
@@ -512,12 +512,7 @@
 		"improper chunk offset(s)"
 '
 
-test_expect_success 'verify packnames out of order' '
-	corrupt_midx_and_verify $MIDX_BYTE_PACKNAME_ORDER "z" $objdir \
-		"pack names out of order"
-'
-
-test_expect_success 'verify packnames out of order' '
+test_expect_success 'verify missing pack' '
 	corrupt_midx_and_verify $MIDX_BYTE_PACKNAME_ORDER "a" $objdir \
 		"failed to load pack"
 '
@@ -578,6 +573,15 @@
 		$objdir "incorrect checksum"
 '
 
+test_expect_success 'setup for v1-specific fsck tests' '
+	git -c midx.version=1 multi-pack-index write
+'
+
+test_expect_success 'verify packnames out of order (v1)' '
+	corrupt_midx_and_verify $MIDX_BYTE_PACKNAME_ORDER "z" $objdir \
+		"pack names out of order"
+'
+
 test_expect_success 'repack progress off for redirected stderr' '
 	GIT_PROGRESS_DELAY=0 git multi-pack-index --object-dir=$objdir repack 2>err &&
 	test_line_count = 0 err
diff --git a/t/t5335-compact-multi-pack-index.sh b/t/t5335-compact-multi-pack-index.sh
new file mode 100755
index 0000000..40f3844
--- /dev/null
+++ b/t/t5335-compact-multi-pack-index.sh
@@ -0,0 +1,293 @@
+#!/bin/sh
+
+test_description='multi-pack-index compaction'
+
+. ./test-lib.sh
+
+GIT_TEST_MULTI_PACK_INDEX=0
+GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0
+GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL=0
+
+objdir=.git/objects
+packdir=$objdir/pack
+midxdir=$packdir/multi-pack-index.d
+midx_chain=$midxdir/multi-pack-index-chain
+
+nth_line() {
+	local n="$1"
+	shift
+	awk "NR==$n" "$@"
+}
+
+write_packs () {
+	for c in "$@"
+	do
+		test_commit "$c" &&
+
+		git pack-objects --all --unpacked $packdir/pack-$c &&
+		git prune-packed &&
+
+		git multi-pack-index write --incremental --bitmap || return 1
+	done
+}
+
+test_midx_layer_packs () {
+	local checksum="$1" &&
+	shift &&
+
+	test-tool read-midx $objdir "$checksum" >out &&
+
+	printf "%s\n" "$@" >expect &&
+	# NOTE: do *not* pipe through sort here, we want to ensure the
+	# order of packs is preserved during compaction.
+	grep "^pack-" out | cut -d"-" -f2 >actual &&
+
+	test_cmp expect actual
+}
+
+test_midx_layer_object_uniqueness () {
+	: >objs.all
+	while read layer
+	do
+		test-tool read-midx --show-objects $objdir "$layer" >out &&
+		grep "\.pack$" out | cut -d" " -f1 | sort >objs.layer &&
+		test_stdout_line_count = 0 comm -12 objs.all objs.layer &&
+		cat objs.all objs.layer | sort >objs.tmp &&
+		mv objs.tmp objs.all || return 1
+	done <$midx_chain
+}
+
+test_expect_success 'MIDX compaction with lex-ordered pack names' '
+	git init midx-compact-lex-order &&
+	(
+		cd midx-compact-lex-order &&
+
+		git config maintenance.auto false &&
+
+		write_packs A B C D E &&
+		test_line_count = 5 $midx_chain &&
+
+		git multi-pack-index compact --incremental --bitmap \
+			"$(nth_line 2 "$midx_chain")" \
+			"$(nth_line 4 "$midx_chain")" &&
+		test_line_count = 3 $midx_chain &&
+
+		test_midx_layer_packs "$(nth_line 1 "$midx_chain")" A &&
+		test_midx_layer_packs "$(nth_line 2 "$midx_chain")" B C D &&
+		test_midx_layer_packs "$(nth_line 3 "$midx_chain")" E &&
+
+		test_midx_layer_object_uniqueness
+	)
+'
+
+test_expect_success 'MIDX compaction with non-lex-ordered pack names' '
+	git init midx-compact-non-lex-order &&
+	(
+		cd midx-compact-non-lex-order &&
+
+		git config maintenance.auto false &&
+
+		write_packs D C A B E &&
+		test_line_count = 5 $midx_chain &&
+
+		git multi-pack-index compact --incremental --bitmap \
+			"$(nth_line 2 "$midx_chain")" \
+			"$(nth_line 4 "$midx_chain")" &&
+		test_line_count = 3 $midx_chain &&
+
+		test_midx_layer_packs "$(nth_line 1 "$midx_chain")" D &&
+		test_midx_layer_packs "$(nth_line 2 "$midx_chain")" C A B &&
+		test_midx_layer_packs "$(nth_line 3 "$midx_chain")" E &&
+
+		test_midx_layer_object_uniqueness
+	)
+'
+
+test_expect_success 'setup for bogus MIDX compaction scenarios' '
+	git init midx-compact-bogus &&
+	(
+		cd midx-compact-bogus &&
+
+		git config maintenance.auto false &&
+
+		write_packs A B C
+	)
+'
+
+test_expect_success 'MIDX compaction with missing endpoints' '
+	(
+		cd midx-compact-bogus &&
+
+		test_must_fail git multi-pack-index compact --incremental \
+			"<missing>" "<missing>" 2>err &&
+		test_grep "could not find MIDX: <missing>" err &&
+
+		test_must_fail git multi-pack-index compact --incremental \
+			"<missing>" "$(nth_line 2 "$midx_chain")" 2>err &&
+		test_grep "could not find MIDX: <missing>" err &&
+
+		test_must_fail git multi-pack-index compact --incremental \
+			"$(nth_line 2 "$midx_chain")" "<missing>" 2>err &&
+		test_grep "could not find MIDX: <missing>" err
+	)
+'
+
+test_expect_success 'MIDX compaction with reversed endpoints' '
+	(
+		cd midx-compact-bogus &&
+
+		from="$(nth_line 3 "$midx_chain")" &&
+		to="$(nth_line 1 "$midx_chain")" &&
+
+		test_must_fail git multi-pack-index compact --incremental \
+			"$from" "$to" 2>err &&
+
+		test_grep "MIDX $from must be an ancestor of $to" err
+	)
+'
+
+test_expect_success 'MIDX compaction with identical endpoints' '
+	(
+		cd midx-compact-bogus &&
+
+		from="$(nth_line 3 "$midx_chain")" &&
+		to="$(nth_line 3 "$midx_chain")" &&
+
+		test_must_fail git multi-pack-index compact --incremental \
+			"$from" "$to" 2>err &&
+
+		test_grep "MIDX compaction endpoints must be unique" err
+	)
+'
+
+test_expect_success 'MIDX compaction with midx.version=1' '
+	(
+		cd midx-compact-bogus &&
+
+		test_must_fail git -c midx.version=1 multi-pack-index compact \
+			"$(nth_line 1 "$midx_chain")" \
+			"$(nth_line 2 "$midx_chain")" 2>err &&
+
+		test_grep "fatal: cannot perform MIDX compaction with v1 format" err
+	)
+'
+
+midx_objs_by_pack () {
+	awk '/\.pack$/ { split($3, a, "-"); print a[2], $1 }' | sort
+}
+
+tag_objs_from_pack () {
+	objs="$(git rev-list --objects --no-object-names "$2")" &&
+	printf "$1 %s\n" $objs | sort
+}
+
+test_expect_success 'MIDX compaction preserves pack object selection' '
+	git init midx-compact-preserve-selection &&
+	(
+		cd midx-compact-preserve-selection &&
+
+		git config maintenance.auto false &&
+
+		test_commit A &&
+		test_commit B &&
+
+		# Create two packs, one containing just the objects from
+		# A, and another containing all objects from the
+		# repository.
+		p1="$(echo A | git pack-objects --revs --delta-base-offset \
+			$packdir/pack-1)" &&
+		p0="$(echo B | git pack-objects --revs --delta-base-offset \
+			$packdir/pack-0)" &&
+
+		echo "pack-1-$p1.idx" | git multi-pack-index write \
+			--incremental --bitmap --stdin-packs &&
+		echo "pack-0-$p0.idx" | git multi-pack-index write \
+			--incremental --bitmap --stdin-packs &&
+
+		write_packs C &&
+
+		git multi-pack-index compact --incremental --bitmap \
+			"$(nth_line 1 "$midx_chain")" \
+			"$(nth_line 2 "$midx_chain")" &&
+
+
+		test-tool read-midx --show-objects $objdir \
+			"$(nth_line 1 "$midx_chain")" >AB.info &&
+		test-tool read-midx --show-objects $objdir \
+			"$(nth_line 2 "$midx_chain")" >C.info &&
+
+		midx_objs_by_pack <AB.info >AB.actual &&
+		midx_objs_by_pack <C.info >C.actual &&
+
+		{
+			tag_objs_from_pack 1 A &&
+			tag_objs_from_pack 0 A..B
+		} | sort >AB.expect &&
+		tag_objs_from_pack C B..C >C.expect &&
+
+		test_cmp AB.expect AB.actual &&
+		test_cmp C.expect C.actual
+	)
+'
+
+test_expect_success 'MIDX compaction with bitmaps' '
+	git init midx-compact-with-bitmaps &&
+	(
+		cd midx-compact-with-bitmaps &&
+
+		git config maintenance.auto false &&
+
+		write_packs foo bar baz quux woot &&
+
+		test-tool read-midx --bitmap $objdir >bitmap.expect &&
+		git multi-pack-index compact --incremental --bitmap \
+			"$(nth_line 2 "$midx_chain")" \
+			"$(nth_line 4 "$midx_chain")" &&
+		test-tool read-midx --bitmap $objdir >bitmap.actual &&
+
+		test_cmp bitmap.expect bitmap.actual &&
+
+		true
+	)
+'
+
+test_expect_success 'MIDX compaction with bitmaps (non-trivial)' '
+	git init midx-compact-with-bitmaps-non-trivial &&
+	(
+		cd midx-compact-with-bitmaps-non-trivial &&
+
+		git config maintenance.auto false &&
+
+		git branch -m main &&
+
+		#               D(4)
+		#              /
+		# A(1) --- B(2) --- C(3) --- G(7)
+		#              \
+		#               E(5) --- F(6)
+		write_packs A B C &&
+		git checkout -b side &&
+		write_packs D &&
+		git checkout -b other B &&
+		write_packs E F &&
+		git checkout main &&
+		write_packs G &&
+
+		# Compact layers 2-4, leaving us with:
+		#
+		#  [A, [B, C, D], E, F, G]
+		git multi-pack-index compact --incremental --bitmap \
+			"$(nth_line 2 "$midx_chain")" \
+			"$(nth_line 4 "$midx_chain")" &&
+
+		# Then compact the top two layers, condensing the above
+		# such that the new 4th layer contains F and G.
+		#
+		#  [A, [B, C, D], E, [F, G]]
+		git multi-pack-index compact --incremental --bitmap \
+			"$(nth_line 4 "$midx_chain")" \
+			"$(nth_line 5 "$midx_chain")"
+	)
+'
+
+test_done
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index 5dcb4b5..6fe21e2 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -469,12 +469,17 @@
 	head_oid=$(git rev-parse HEAD) &&
 
 	cat >expected <<-EOF &&
+		preparing
+		$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-1
+		$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-2
 		prepared
 		$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-1
 		$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-2
 		committed
 		$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-1
 		$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-2
+		preparing
+		$ZERO_OID ref:refs/remotes/origin/main refs/remotes/origin/HEAD
 	EOF
 
 	rm -f atomic/actual &&
@@ -497,7 +502,7 @@
 	head_oid=$(git rev-parse HEAD) &&
 
 	cat >expected <<-EOF &&
-		prepared
+		preparing
 		$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-1
 		$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-2
 		$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-3
diff --git a/t/t5526-fetch-submodules.sh b/t/t5526-fetch-submodules.sh
index 5e56620..1242ee9 100755
--- a/t/t5526-fetch-submodules.sh
+++ b/t/t5526-fetch-submodules.sh
@@ -834,11 +834,18 @@
 	git commit -m "updated submodules outside of refs/heads" &&
 	E=$(git rev-parse HEAD) &&
 	git update-ref refs/changes/3 $E &&
+	FETCH_TRACE="$(pwd)/trace.out" &&
+	test_when_finished "rm -f \"$FETCH_TRACE\"" &&
 	(
 		cd downstream &&
-		git fetch --recurse-submodules origin refs/changes/3:refs/heads/my_branch &&
+		GIT_TRACE="$FETCH_TRACE" git fetch --recurse-submodules origin \
+			refs/changes/3:refs/heads/my_branch &&
 		git -C submodule cat-file -t $C &&
 		git -C sub1 cat-file -t $D &&
+		test_grep "trace: built-in: git submodule--helper get-default-remote sub1" \
+			"$FETCH_TRACE" &&
+		test_grep "trace: built-in: git fetch .* --submodule-prefix=sub1/ origin" \
+			"$FETCH_TRACE" &&
 		git checkout --recurse-submodules FETCH_HEAD
 	)
 '
@@ -929,6 +936,68 @@
 	)
 '
 
+test_expect_success 'fetch new submodule commits on-demand outside standard refspec with custom remote name' '
+	# depends on the previous test for setup
+
+	# Rename the remote in sub1 from "origin" to "custom_remote"
+	git -C downstream/sub1 remote rename origin custom_remote &&
+
+	# Create new commits in the original submodules
+	C=$(git -C submodule commit-tree \
+		-m "change outside refs/heads for custom remote" HEAD^{tree}) &&
+	git -C submodule update-ref refs/changes/custom1 $C &&
+	git update-index --cacheinfo 160000 $C submodule &&
+	test_tick &&
+
+	D=$(git -C sub1 commit-tree \
+		-m "change outside refs/heads for custom remote" HEAD^{tree}) &&
+	git -C sub1 update-ref refs/changes/custom2 $D &&
+	git update-index --cacheinfo 160000 $D sub1 &&
+
+	git commit \
+		-m "updated submodules outside of refs/heads for custom remote" &&
+	E=$(git rev-parse HEAD) &&
+	git update-ref refs/changes/custom3 $E &&
+	FETCH_TRACE="$(pwd)/trace.out" &&
+	test_when_finished "rm -f \"$FETCH_TRACE\"" &&
+	(
+		cd downstream &&
+		GIT_TRACE="$FETCH_TRACE" git fetch --recurse-submodules origin \
+			refs/changes/custom3:refs/heads/my_other_branch &&
+		git -C submodule cat-file -t $C &&
+		git -C sub1 cat-file -t $D &&
+		test_grep "trace: built-in: git submodule--helper get-default-remote sub1" \
+			"$FETCH_TRACE" &&
+		test_grep "trace: built-in: git fetch .* --submodule-prefix=sub1/ custom_remote $D" \
+			"$FETCH_TRACE" &&
+		git checkout --recurse-submodules FETCH_HEAD
+	)
+'
+
+test_expect_success 'fetch new submodule commit on-demand in FETCH_HEAD from custom remote' '
+	# depends on the previous test for setup
+
+	C=$(git -C submodule commit-tree -m "another change outside refs/heads for custom remote" HEAD^{tree}) &&
+	git -C submodule update-ref refs/changes/custom4 $C &&
+	git update-index --cacheinfo 160000 $C submodule &&
+	test_tick &&
+
+	D=$(git -C sub1 commit-tree -m "another change outside refs/heads for custom remote" HEAD^{tree}) &&
+	git -C sub1 update-ref refs/changes/custom5 $D &&
+	git update-index --cacheinfo 160000 $D sub1 &&
+
+	git commit -m "updated submodules outside of refs/heads" &&
+	E=$(git rev-parse HEAD) &&
+	git update-ref refs/changes/custom6 $E &&
+	(
+		cd downstream &&
+		git fetch --recurse-submodules origin refs/changes/custom6 &&
+		git -C submodule cat-file -t $C &&
+		git -C sub1 cat-file -t $D &&
+		git checkout --recurse-submodules FETCH_HEAD
+	)
+'
+
 add_commit_push () {
 	dir="$1" &&
 	msg="$2" &&
diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh
index 73cf531..a26b6c2 100755
--- a/t/t5551-http-fetch-smart.sh
+++ b/t/t5551-http-fetch-smart.sh
@@ -782,4 +782,11 @@
 	test_cmp expect actual
 '
 
+test_expect_success 'ls-remote outside repo does not segfault with fetch refspec' '
+	nongit git \
+		-c remote.origin.url="$HTTPD_URL/smart/repo.git" \
+		-c remote.origin.fetch=anything \
+		ls-remote origin
+'
+
 test_done
diff --git a/t/t5572-pull-submodule.sh b/t/t5572-pull-submodule.sh
index 45f384d..42d1432 100755
--- a/t/t5572-pull-submodule.sh
+++ b/t/t5572-pull-submodule.sh
@@ -257,7 +257,26 @@
 	git -C a-submodule reset --hard HEAD^^ &&
 
 	git -C child pull --no-recurse-submodules &&
-	git -C child submodule update
+	git -C child submodule update &&
+	test_path_is_file child/a-submodule/moreecho.t
+'
+
+test_expect_success 'fetch non-origin submodule remote named different from superproject' '
+	git -C child/a-submodule remote rename origin o2 &&
+
+	# Create commit that is unreachable from current master branch
+	# newmain is already reset in the previous test
+	test_commit -C a-submodule echo_o2 &&
+	test_commit -C a-submodule moreecho_o2 &&
+	subc=$(git -C a-submodule rev-parse --short HEAD) &&
+
+	git -C parent/a-submodule fetch &&
+	git -C parent/a-submodule checkout "$subc" &&
+	git -C parent commit -m "update submodule o2" a-submodule &&
+	git -C a-submodule reset --hard HEAD^^ &&
+
+	git -C child pull --recurse-submodules &&
+	test_path_is_file child/a-submodule/moreecho_o2.t
 '
 
 test_done
diff --git a/t/t5584-http-429-retry.sh b/t/t5584-http-429-retry.sh
new file mode 100755
index 0000000..a22007b
--- /dev/null
+++ b/t/t5584-http-429-retry.sh
@@ -0,0 +1,266 @@
+#!/bin/sh
+
+test_description='test HTTP 429 Too Many Requests retry logic'
+
+. ./test-lib.sh
+
+. "$TEST_DIRECTORY"/lib-httpd.sh
+
+start_httpd
+
+test_expect_success 'setup test repository' '
+	test_commit initial &&
+	git clone --bare . "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+	git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/repo.git" config http.receivepack true
+'
+
+# This test suite uses a special HTTP 429 endpoint at /http_429/ that simulates
+# rate limiting. The endpoint format is:
+#   /http_429/<test-context>/<retry-after-value>/<repo-path>
+# The http-429.sh script (in t/lib-httpd) returns a 429 response with the
+# specified Retry-After header on the first request for each test context,
+# then forwards subsequent requests to git-http-backend. Each test context
+# is isolated, allowing multiple tests to run independently.
+
+test_expect_success 'HTTP 429 with retries disabled (maxRetries=0) fails immediately' '
+	# Set maxRetries to 0 (disabled)
+	test_config http.maxRetries 0 &&
+	test_config http.retryAfter 1 &&
+
+	# Should fail immediately without any retry attempt
+	test_must_fail git ls-remote "$HTTPD_URL/http_429/retries-disabled/1/repo.git" 2>err &&
+
+	# Verify no retry happened (no "waiting" message in stderr)
+	test_grep ! -i "waiting.*retry" err
+'
+
+test_expect_success 'HTTP 429 permanent should fail after max retries' '
+	# Enable retries with a limit
+	test_config http.maxRetries 2 &&
+
+	# Git should retry but eventually fail when 429 persists
+	test_must_fail git ls-remote "$HTTPD_URL/http_429/permanent-fail/permanent/repo.git" 2>err
+'
+
+test_expect_success 'HTTP 429 with Retry-After is retried and succeeds' '
+	# Enable retries
+	test_config http.maxRetries 3 &&
+
+	# Git should retry after receiving 429 and eventually succeed
+	git ls-remote "$HTTPD_URL/http_429/retry-succeeds/1/repo.git" >output 2>err &&
+	test_grep "refs/heads/" output
+'
+
+test_expect_success 'HTTP 429 without Retry-After uses configured default' '
+	# Enable retries and configure default delay
+	test_config http.maxRetries 3 &&
+	test_config http.retryAfter 1 &&
+
+	# Git should retry using configured default and succeed
+	git ls-remote "$HTTPD_URL/http_429/no-retry-after-header/none/repo.git" >output 2>err &&
+	test_grep "refs/heads/" output
+'
+
+test_expect_success 'HTTP 429 retry delays are respected' '
+	# Enable retries
+	test_config http.maxRetries 3 &&
+
+	# Time the operation - it should take at least 2 seconds due to retry delay
+	start=$(test-tool date getnanos) &&
+	git ls-remote "$HTTPD_URL/http_429/retry-delays-respected/2/repo.git" >output 2>err &&
+	duration=$(test-tool date getnanos $start) &&
+
+	# Verify it took at least 2 seconds (allowing some tolerance)
+	duration_int=${duration%.*} &&
+	test "$duration_int" -ge 1 &&
+	test_grep "refs/heads/" output
+'
+
+test_expect_success 'HTTP 429 fails immediately if Retry-After exceeds http.maxRetryTime' '
+	# Configure max retry time to 3 seconds (much less than requested 100)
+	test_config http.maxRetries 3 &&
+	test_config http.maxRetryTime 3 &&
+
+	# Should fail immediately without waiting
+	start=$(test-tool date getnanos) &&
+	test_must_fail git ls-remote "$HTTPD_URL/http_429/retry-after-exceeds-max-time/100/repo.git" 2>err &&
+	duration=$(test-tool date getnanos $start) &&
+
+	# Should fail quickly (no 100 second wait)
+	duration_int=${duration%.*} &&
+	test "$duration_int" -lt 99 &&
+	test_grep "greater than http.maxRetryTime" err
+'
+
+test_expect_success 'HTTP 429 fails if configured http.retryAfter exceeds http.maxRetryTime' '
+	# Test misconfiguration: retryAfter > maxRetryTime
+	# Configure retryAfter larger than maxRetryTime
+	test_config http.maxRetries 3 &&
+	test_config http.retryAfter 100 &&
+	test_config http.maxRetryTime 5 &&
+
+	# Should fail immediately with configuration error
+	start=$(test-tool date getnanos) &&
+	test_must_fail git ls-remote "$HTTPD_URL/http_429/config-retry-after-exceeds-max-time/none/repo.git" 2>err &&
+	duration=$(test-tool date getnanos $start) &&
+
+	# Should fail quickly (no 100 second wait)
+	duration_int=${duration%.*} &&
+	test "$duration_int" -lt 99 &&
+	test_grep "configured http.retryAfter.*exceeds.*http.maxRetryTime" err
+'
+
+test_expect_success 'HTTP 429 with Retry-After HTTP-date format' '
+	# Test HTTP-date format (RFC 2822) in Retry-After header
+	raw=$(test-tool date timestamp now) &&
+	now="${raw#* -> }" &&
+	future_time=$((now + 2)) &&
+	raw=$(test-tool date show:rfc2822 $future_time) &&
+	future_date="${raw#* -> }" &&
+	future_date_encoded=$(echo "$future_date" | sed "s/ /%20/g") &&
+
+	# Enable retries
+	test_config http.maxRetries 3 &&
+
+	# Git should parse the HTTP-date and retry after the delay
+	start=$(test-tool date getnanos) &&
+	git ls-remote "$HTTPD_URL/http_429/http-date-format/$future_date_encoded/repo.git" >output 2>err &&
+	duration=$(test-tool date getnanos $start) &&
+
+	# Should take at least 1 second (allowing tolerance for processing time)
+	duration_int=${duration%.*} &&
+	test "$duration_int" -ge 1 &&
+	test_grep "refs/heads/" output
+'
+
+test_expect_success 'HTTP 429 with HTTP-date exceeding maxRetryTime fails immediately' '
+	raw=$(test-tool date timestamp now) &&
+	now="${raw#* -> }" &&
+	future_time=$((now + 200)) &&
+	raw=$(test-tool date show:rfc2822 $future_time) &&
+	future_date="${raw#* -> }" &&
+	future_date_encoded=$(echo "$future_date" | sed "s/ /%20/g") &&
+
+	# Configure max retry time much less than the 200 second delay
+	test_config http.maxRetries 3 &&
+	test_config http.maxRetryTime 10 &&
+
+	# Should fail immediately without waiting 200 seconds
+	start=$(test-tool date getnanos) &&
+	test_must_fail git ls-remote "$HTTPD_URL/http_429/http-date-exceeds-max-time/$future_date_encoded/repo.git" 2>err &&
+	duration=$(test-tool date getnanos $start) &&
+
+	# Should fail quickly (not wait 200 seconds)
+	duration_int=${duration%.*} &&
+	test "$duration_int" -lt 199 &&
+	test_grep "http.maxRetryTime" err
+'
+
+test_expect_success 'HTTP 429 with past HTTP-date should not wait' '
+	raw=$(test-tool date timestamp now) &&
+	now="${raw#* -> }" &&
+	past_time=$((now - 10)) &&
+	raw=$(test-tool date show:rfc2822 $past_time) &&
+	past_date="${raw#* -> }" &&
+	past_date_encoded=$(echo "$past_date" | sed "s/ /%20/g") &&
+
+	# Enable retries
+	test_config http.maxRetries 3 &&
+
+	# Git should retry immediately without waiting
+	start=$(test-tool date getnanos) &&
+	git ls-remote "$HTTPD_URL/http_429/past-http-date/$past_date_encoded/repo.git" >output 2>err &&
+	duration=$(test-tool date getnanos $start) &&
+
+	# Should complete quickly (no wait for a past-date Retry-After)
+	duration_int=${duration%.*} &&
+	test "$duration_int" -lt 5 &&
+	test_grep "refs/heads/" output
+'
+
+test_expect_success 'HTTP 429 with invalid Retry-After format uses configured default' '
+	# Configure default retry-after
+	test_config http.maxRetries 3 &&
+	test_config http.retryAfter 1 &&
+
+	# Should use configured default (1 second) since header is invalid
+	start=$(test-tool date getnanos) &&
+	git ls-remote "$HTTPD_URL/http_429/invalid-retry-after-format/invalid/repo.git" >output 2>err &&
+	duration=$(test-tool date getnanos $start) &&
+
+	# Should take at least 1 second (the configured default)
+	duration_int=${duration%.*} &&
+	test "$duration_int" -ge 1 &&
+	test_grep "refs/heads/" output &&
+	test_grep "waiting.*retry" err
+'
+
+test_expect_success 'HTTP 429 will not be retried without config' '
+	# Default config means http.maxRetries=0 (retries disabled)
+	# When 429 is received, it should fail immediately without retry
+	# Do NOT configure anything - use defaults (http.maxRetries defaults to 0)
+
+	# Should fail immediately without retry
+	test_must_fail git ls-remote "$HTTPD_URL/http_429/no-retry-without-config/1/repo.git" 2>err &&
+
+	# Verify no retry happened (no "waiting" message)
+	test_grep ! -i "waiting.*retry" err &&
+
+	# Should get 429 error
+	test_grep "429" err
+'
+
+test_expect_success 'GIT_HTTP_RETRY_AFTER overrides http.retryAfter config' '
+	# Configure retryAfter to 10 seconds
+	test_config http.maxRetries 3 &&
+	test_config http.retryAfter 10 &&
+
+	# Override with environment variable to 1 second
+	start=$(test-tool date getnanos) &&
+	GIT_HTTP_RETRY_AFTER=1 git ls-remote "$HTTPD_URL/http_429/env-retry-after-override/none/repo.git" >output 2>err &&
+	duration=$(test-tool date getnanos $start) &&
+
+	# Should use env var (1 second), not config (10 seconds)
+	duration_int=${duration%.*} &&
+	test "$duration_int" -ge 1 &&
+	test "$duration_int" -lt 5 &&
+	test_grep "refs/heads/" output &&
+	test_grep "waiting.*retry" err
+'
+
+test_expect_success 'GIT_HTTP_MAX_RETRIES overrides http.maxRetries config' '
+	# Configure maxRetries to 0 (disabled)
+	test_config http.maxRetries 0 &&
+	test_config http.retryAfter 1 &&
+
+	# Override with environment variable to enable retries
+	GIT_HTTP_MAX_RETRIES=3 git ls-remote "$HTTPD_URL/http_429/env-max-retries-override/1/repo.git" >output 2>err &&
+
+	# Should retry (env var enables it despite config saying disabled)
+	test_grep "refs/heads/" output &&
+	test_grep "waiting.*retry" err
+'
+
+test_expect_success 'GIT_HTTP_MAX_RETRY_TIME overrides http.maxRetryTime config' '
+	# Configure maxRetryTime to 100 seconds (would accept 50 second delay)
+	test_config http.maxRetries 3 &&
+	test_config http.maxRetryTime 100 &&
+
+	# Override with environment variable to 10 seconds (should reject 50 second delay)
+	start=$(test-tool date getnanos) &&
+	test_must_fail env GIT_HTTP_MAX_RETRY_TIME=10 \
+		git ls-remote "$HTTPD_URL/http_429/env-max-retry-time-override/50/repo.git" 2>err &&
+	duration=$(test-tool date getnanos $start) &&
+
+	# Should fail quickly (not wait 50 seconds) because env var limits to 10
+	duration_int=${duration%.*} &&
+	test "$duration_int" -lt 49 &&
+	test_grep "greater than http.maxRetryTime" err
+'
+
+test_expect_success 'verify normal repository access still works' '
+	git ls-remote "$HTTPD_URL/smart/repo.git" >output &&
+	test_grep "refs/heads/" output
+'
+
+test_done
diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh
index cdc0270..1ba9ca2 100755
--- a/t/t6030-bisect-porcelain.sh
+++ b/t/t6030-bisect-porcelain.sh
@@ -402,7 +402,7 @@
 	git bisect good $HASH1 &&
 	git bisect bad $HASH4 &&
 	! git bisect run ./fail.sh 2>err &&
-	sed -En 's/.*(bisect.*code) (-?[0-9]+) (from.*)/\1 -1 \3/p' err >actual &&
+	sed -E -n 's/.*(bisect.*code) (-?[0-9]+) (from.*)/\1 -1 \3/p' err >actual &&
 	test_cmp expect actual
 "
 
diff --git a/t/t6040-tracking-info.sh b/t/t6040-tracking-info.sh
index 0b719bb..0242b5b 100755
--- a/t/t6040-tracking-info.sh
+++ b/t/t6040-tracking-info.sh
@@ -292,4 +292,358 @@
 	test_cmp expect actual
 '
 
+test_expect_success 'status tracking origin/main shows only main' '
+	git -C test checkout b4 &&
+	git -C test status >actual &&
+	cat >expect <<-EOF &&
+	On branch b4
+	Your branch is ahead of ${SQ}origin/main${SQ} by 2 commits.
+	  (use "git push" to publish your local commits)
+
+	nothing to commit, working tree clean
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'status --no-ahead-behind tracking origin/main shows only main' '
+	git -C test checkout b4 &&
+	git -C test status --no-ahead-behind >actual &&
+	cat >expect <<-EOF &&
+	On branch b4
+	Your branch and ${SQ}origin/main${SQ} refer to different commits.
+	  (use "git status --ahead-behind" for details)
+
+	nothing to commit, working tree clean
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'status.compareBranches deduplicates when upstream and push are the same' '
+	test_config -C test status.compareBranches "@{upstream} @{push}" &&
+	git -C test checkout main &&
+	git -C test status >actual &&
+	cat >expect <<-EOF &&
+	On branch main
+	Your branch is up to date with ${SQ}origin/main${SQ}.
+
+	nothing to commit, working tree clean
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'status.compareBranches with only upstream shows only upstream' '
+	test_config -C test status.compareBranches "@{upstream}" &&
+	git -C test checkout main &&
+	git -C test status >actual &&
+	cat >expect <<-EOF &&
+	On branch main
+	Your branch is up to date with ${SQ}origin/main${SQ}.
+
+	nothing to commit, working tree clean
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'status.compareBranches with only push shows only push' '
+	test_config -C test push.default current &&
+	test_config -C test status.compareBranches "@{push}" &&
+	git -C test checkout -b feature2 origin/main &&
+	git -C test push origin HEAD &&
+	(cd test && advance work) &&
+	git -C test status >actual &&
+	cat >expect <<-EOF &&
+	On branch feature2
+	Your branch is ahead of ${SQ}origin/feature2${SQ} by 1 commit.
+	  (use "git push" to publish your local commits)
+
+	nothing to commit, working tree clean
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'status.compareBranches shows ahead of both upstream and push branch' '
+	test_config -C test push.default current &&
+	test_config -C test status.compareBranches "@{upstream} @{push}" &&
+	git -C test checkout -b feature3 origin/main &&
+	git -C test push origin HEAD &&
+	(cd test && advance work) &&
+	git -C test status >actual &&
+	cat >expect <<-EOF &&
+	On branch feature3
+	Your branch is ahead of ${SQ}origin/main${SQ} by 1 commit.
+
+	Your branch is ahead of ${SQ}origin/feature3${SQ} by 1 commit.
+	  (use "git push" to publish your local commits)
+
+	nothing to commit, working tree clean
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'checkout with status.compareBranches shows both branches' '
+	test_config -C test push.default current &&
+	test_config -C test status.compareBranches "@{upstream} @{push}" &&
+	git -C test checkout feature3 >actual &&
+	cat >expect <<-EOF &&
+	Your branch is ahead of ${SQ}origin/main${SQ} by 1 commit.
+
+	Your branch is ahead of ${SQ}origin/feature3${SQ} by 1 commit.
+	  (use "git push" to publish your local commits)
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'setup for ahead of tracked but diverged from main' '
+	(
+		cd test &&
+		git checkout -b feature4 origin/main &&
+		advance work1 &&
+		git checkout origin/main &&
+		advance work2 &&
+		git push origin HEAD:main &&
+		git checkout feature4 &&
+		advance work3
+	)
+'
+
+test_expect_success 'status.compareBranches shows diverged and ahead' '
+	test_config -C test push.default current &&
+	test_config -C test status.compareBranches "@{upstream} @{push}" &&
+	git -C test checkout feature4 &&
+	git -C test branch --set-upstream-to origin/main &&
+	git -C test push origin HEAD &&
+	(cd test && advance work) &&
+	git -C test status >actual &&
+	cat >expect <<-EOF &&
+	On branch feature4
+	Your branch and ${SQ}origin/main${SQ} have diverged,
+	and have 3 and 1 different commits each, respectively.
+	  (use "git pull" if you want to integrate the remote branch with yours)
+
+	Your branch is ahead of ${SQ}origin/feature4${SQ} by 1 commit.
+	  (use "git push" to publish your local commits)
+
+	nothing to commit, working tree clean
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'status --no-ahead-behind with status.compareBranches' '
+	test_config -C test push.default current &&
+	test_config -C test status.compareBranches "@{upstream} @{push}" &&
+	git -C test checkout feature4 &&
+	git -C test status --no-ahead-behind >actual &&
+	cat >expect <<-EOF &&
+	On branch feature4
+	Your branch and ${SQ}origin/main${SQ} refer to different commits.
+
+	Your branch and ${SQ}origin/feature4${SQ} refer to different commits.
+	  (use "git status --ahead-behind" for details)
+
+	nothing to commit, working tree clean
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'setup upstream remote' '
+	(
+		cd test &&
+		git remote add upstream ../. &&
+		git fetch upstream
+	)
+'
+
+test_expect_success 'status.compareBranches with upstream and origin remotes' '
+	test_config -C test push.default current &&
+	test_config -C test remote.pushDefault origin &&
+	test_config -C test status.compareBranches "@{upstream} @{push}" &&
+	git -C test checkout -b feature5 upstream/main &&
+	git -C test push origin &&
+	(cd test && advance work) &&
+	git -C test status >actual &&
+	cat >expect <<-EOF &&
+	On branch feature5
+	Your branch is ahead of ${SQ}upstream/main${SQ} by 1 commit.
+
+	Your branch is ahead of ${SQ}origin/feature5${SQ} by 1 commit.
+	  (use "git push" to publish your local commits)
+
+	nothing to commit, working tree clean
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'status.compareBranches supports ordered upstream/push entries' '
+	test_config -C test push.default current &&
+	test_config -C test remote.pushDefault origin &&
+	test_config -C test status.compareBranches "@{push} @{upstream}" &&
+	git -C test checkout -b feature6 upstream/main &&
+	git -C test push origin &&
+	(cd test && advance work) &&
+	git -C test status >actual &&
+	cat >expect <<-EOF &&
+	On branch feature6
+	Your branch is ahead of ${SQ}origin/feature6${SQ} by 1 commit.
+	  (use "git push" to publish your local commits)
+
+	Your branch is ahead of ${SQ}upstream/main${SQ} by 1 commit.
+
+	nothing to commit, working tree clean
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'status.compareBranches deduplicates repeated specifiers' '
+	test_config -C test push.default current &&
+	test_config -C test remote.pushDefault origin &&
+	test_config -C test status.compareBranches "@{push} @{upstream} @{push}" &&
+	git -C test checkout -b feature7 upstream/main &&
+	git -C test push origin &&
+	(cd test && advance work) &&
+	git -C test status >actual &&
+	cat >expect <<-EOF &&
+	On branch feature7
+	Your branch is ahead of ${SQ}origin/feature7${SQ} by 1 commit.
+	  (use "git push" to publish your local commits)
+
+	Your branch is ahead of ${SQ}upstream/main${SQ} by 1 commit.
+
+	nothing to commit, working tree clean
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'status.compareBranches with diverged push branch' '
+	test_config -C test push.default current &&
+	test_config -C test remote.pushDefault origin &&
+	test_config -C test status.compareBranches "@{upstream} @{push}" &&
+	git -C test checkout -b feature8 upstream/main &&
+	(cd test && advance work81) &&
+	git -C test push origin &&
+	git -C test reset --hard upstream/main &&
+	(cd test && advance work82) &&
+	git -C test status >actual &&
+	cat >expect <<-EOF &&
+	On branch feature8
+	Your branch is ahead of ${SQ}upstream/main${SQ} by 1 commit.
+
+	Your branch and ${SQ}origin/feature8${SQ} have diverged,
+	and have 1 and 1 different commits each, respectively.
+
+	nothing to commit, working tree clean
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'status.compareBranches shows up to date branches' '
+	test_config -C test push.default current &&
+	test_config -C test remote.pushDefault origin &&
+	test_config -C test status.compareBranches "@{upstream} @{push}" &&
+	git -C test checkout -b feature9 upstream/main &&
+	git -C test push origin &&
+	git -C test status >actual &&
+	cat >expect <<-EOF &&
+	On branch feature9
+	Your branch is up to date with ${SQ}upstream/main${SQ}.
+
+	Your branch is up to date with ${SQ}origin/feature9${SQ}.
+
+	nothing to commit, working tree clean
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'status --no-ahead-behind with status.compareBranches up to date' '
+	test_config -C test push.default current &&
+	test_config -C test remote.pushDefault origin &&
+	test_config -C test status.compareBranches "@{upstream} @{push}" &&
+	git -C test checkout feature9 >actual &&
+	git -C test push origin &&
+	git -C test status --no-ahead-behind >actual &&
+	cat >expect <<-EOF &&
+	On branch feature9
+	Your branch is up to date with ${SQ}upstream/main${SQ}.
+
+	Your branch is up to date with ${SQ}origin/feature9${SQ}.
+
+	nothing to commit, working tree clean
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'checkout with status.compareBranches shows up to date' '
+	test_config -C test push.default current &&
+	test_config -C test remote.pushDefault origin &&
+	test_config -C test status.compareBranches "@{upstream} @{push}" &&
+	git -C test checkout feature9 >actual &&
+	cat >expect <<-EOF &&
+	Your branch is up to date with ${SQ}upstream/main${SQ}.
+
+	Your branch is up to date with ${SQ}origin/feature9${SQ}.
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'status.compareBranches with upstream behind and push up to date' '
+	test_config -C test push.default current &&
+	test_config -C test remote.pushDefault origin &&
+	test_config -C test status.compareBranches "@{upstream} @{push}" &&
+	git -C test checkout -b ahead upstream/main &&
+	(cd test && advance work) &&
+	git -C test push upstream HEAD &&
+	git -C test checkout -b feature10 upstream/main &&
+	git -C test push origin &&
+	git -C test branch --set-upstream-to upstream/ahead &&
+	git -C test status >actual &&
+	cat >expect <<-EOF &&
+	On branch feature10
+	Your branch is behind ${SQ}upstream/ahead${SQ} by 1 commit, and can be fast-forwarded.
+	  (use "git pull" to update your local branch)
+
+	Your branch is up to date with ${SQ}origin/feature10${SQ}.
+
+	nothing to commit, working tree clean
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'status.compareBranches with remapped push refspec' '
+	test_config -C test remote.origin.push refs/heads/feature11:refs/heads/remapped &&
+	test_config -C test status.compareBranches "@{upstream} @{push}" &&
+	git -C test checkout -b feature11 origin/main &&
+	git -C test push &&
+	(cd test && advance work) &&
+	git -C test status >actual &&
+	cat >expect <<-EOF &&
+	On branch feature11
+	Your branch is ahead of ${SQ}origin/main${SQ} by 1 commit.
+
+	Your branch is ahead of ${SQ}origin/remapped${SQ} by 1 commit.
+	  (use "git push" to publish your local commits)
+
+	nothing to commit, working tree clean
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'status.compareBranches with remapped push and upstream remote' '
+	test_config -C test remote.pushDefault origin &&
+	test_config -C test remote.origin.push refs/heads/feature12:refs/heads/remapped &&
+	test_config -C test status.compareBranches "@{upstream} @{push}" &&
+	git -C test checkout -b feature12 upstream/main &&
+	git -C test push origin &&
+	(cd test && advance work) &&
+	git -C test status >actual &&
+	cat >expect <<-EOF &&
+	On branch feature12
+	Your branch is ahead of ${SQ}upstream/main${SQ} by 1 commit.
+
+	Your branch is ahead of ${SQ}origin/remapped${SQ} by 1 commit.
+	  (use "git push" to publish your local commits)
+
+	nothing to commit, working tree clean
+	EOF
+	test_cmp expect actual
+'
+
 test_done
diff --git a/t/t6112-rev-list-filters-objects.sh b/t/t6112-rev-list-filters-objects.sh
index 0387f35..39211ef 100755
--- a/t/t6112-rev-list-filters-objects.sh
+++ b/t/t6112-rev-list-filters-objects.sh
@@ -483,10 +483,6 @@
 		"must escape char in sub-filter-spec: .\~."
 '
 
-test_expect_success 'validate err msg for "combine:<valid-filter>+"' '
-	expect_invalid_filter_spec combine:tree:2+ "expected .tree:<depth>."
-'
-
 test_expect_success 'combine:... with edge-case hex digits: Ff Aa 0 9' '
 	git -C r3 rev-list --objects --filter="combine:tree:2+bl%6Fb:n%6fne" \
 		HEAD >actual &&
diff --git a/t/t6403-merge-file.sh b/t/t6403-merge-file.sh
index 4d6e748..801284c 100755
--- a/t/t6403-merge-file.sh
+++ b/t/t6403-merge-file.sh
@@ -542,6 +542,15 @@
 	grep "not a git repository" err
 '
 
+test_expect_success 'run in a linked worktree with --object-id' '
+	empty="$(test_oid empty_blob)" &&
+	git worktree add work &&
+	git -C work merge-file --object-id $empty $empty $empty >actual &&
+	git worktree remove work &&
+	git merge-file --object-id $empty $empty $empty >expected &&
+	test_cmp actual expected
+'
+
 test_expect_success 'merging C files with "myers" diff algorithm creates some spurious conflicts' '
 	cat >expect.c <<-\EOF &&
 	int g(size_t u)
diff --git a/t/t7426-submodule-get-default-remote.sh b/t/t7426-submodule-get-default-remote.sh
new file mode 100755
index 0000000..b842af9
--- /dev/null
+++ b/t/t7426-submodule-get-default-remote.sh
@@ -0,0 +1,186 @@
+#!/bin/sh
+
+test_description='git submodule--helper get-default-remote'
+
+TEST_NO_CREATE_REPO=1
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+	git config --global protocol.file.allow always
+'
+
+test_expect_success 'setup repositories' '
+	# Create a repository to be used as submodule
+	git init sub &&
+	test_commit --no-tag -C sub "initial commit in sub" file.txt "sub content" &&
+
+	# Create main repository
+	git init super &&
+	(
+		cd super &&
+		mkdir subdir &&
+		test_commit --no-tag -C subdir "initial commit in super" main.txt "super content" &&
+		git submodule add ../sub subpath &&
+		git commit -m "add submodule 'sub' at subpath"
+	)
+'
+
+test_expect_success 'get-default-remote returns origin for initialized submodule' '
+	(
+		cd super &&
+		git submodule update --init &&
+		echo "origin" >expect &&
+		git submodule--helper get-default-remote subpath >actual &&
+		test_cmp expect actual
+	)
+'
+
+test_expect_success 'get-default-remote works from subdirectory' '
+	(
+		cd super/subdir &&
+		echo "origin" >expect &&
+		git submodule--helper get-default-remote ../subpath >actual &&
+		test_cmp expect actual
+	)
+'
+
+test_expect_success 'get-default-remote fails with non-existent path' '
+	(
+		cd super &&
+		test_must_fail git submodule--helper get-default-remote nonexistent 2>err &&
+		test_grep "could not get a repository handle" err
+	)
+'
+
+test_expect_success 'get-default-remote fails with non-submodule path' '
+	(
+		cd super &&
+		test_must_fail git submodule--helper get-default-remote subdir 2>err &&
+		test_grep "could not get a repository handle" err
+	)
+'
+
+test_expect_success 'get-default-remote fails without path argument' '
+	(
+		cd super &&
+		test_must_fail git submodule--helper get-default-remote 2>err &&
+		test_grep "usage:" err
+	)
+'
+
+test_expect_success 'get-default-remote fails with too many arguments' '
+	(
+		cd super &&
+		test_must_fail git submodule--helper get-default-remote subpath subdir 2>err &&
+		test_grep "usage:" err
+	)
+'
+
+test_expect_success 'setup submodule with non-origin default remote name' '
+	# Create another submodule path with a different remote name
+	(
+		cd super &&
+		git submodule add ../sub upstream-subpath &&
+		git commit -m "add second submodule in upstream-subpath" &&
+		git submodule update --init upstream-subpath &&
+
+		# Change the remote name in the submodule
+		cd upstream-subpath &&
+		git remote rename origin upstream
+	)
+'
+
+test_expect_success 'get-default-remote returns non-origin remote name' '
+	(
+		cd super &&
+		echo "upstream" >expect &&
+		git submodule--helper get-default-remote upstream-subpath >actual &&
+		test_cmp expect actual
+	)
+'
+
+test_expect_success 'get-default-remote handles submodule with multiple remotes' '
+	(
+		cd super/subpath &&
+		git remote add other-upstream ../../sub &&
+		git remote add myfork ../../sub
+	) &&
+
+	(
+		cd super &&
+		echo "origin" >expect &&
+		git submodule--helper get-default-remote subpath >actual &&
+		test_cmp expect actual
+	)
+'
+
+test_expect_success 'get-default-remote handles submodule with multiple remotes and none are origin' '
+	(
+		cd super/upstream-subpath &&
+		git remote add yet-another-upstream ../../sub &&
+		git remote add yourfork ../../sub
+	) &&
+
+	(
+		cd super &&
+		echo "upstream" >expect &&
+		git submodule--helper get-default-remote upstream-subpath >actual &&
+		test_cmp expect actual
+	)
+'
+
+test_expect_success 'setup nested submodule with non-origin remote' '
+	git init innersub &&
+	test_commit --no-tag -C innersub "initial commit in innersub" inner.txt "innersub content" &&
+
+	(
+		cd sub &&
+		git submodule add ../innersub innersubpath &&
+		git commit -m "add nested submodule at innersubpath"
+	) &&
+
+	(
+		cd super/upstream-subpath &&
+		git pull upstream &&
+		git submodule update --init --recursive . &&
+		(
+			cd innersubpath &&
+			git remote rename origin another_upstream
+		)
+	)
+'
+
+test_expect_success 'get-default-remote works with nested submodule' '
+	(
+		cd super &&
+		echo "another_upstream" >expect &&
+		git submodule--helper get-default-remote upstream-subpath/innersubpath >actual &&
+		test_cmp expect actual
+	)
+'
+
+test_expect_success 'get-default-remote works with submodule that has no remotes' '
+	# Create a submodule directory manually without remotes
+	(
+		cd super &&
+		git init no-remote-sub &&
+		test_commit --no-tag -C no-remote-sub "local commit" local.txt "local content"
+	) &&
+
+	# Add it as a submodule
+	(
+		cd super &&
+		git submodule add ./no-remote-sub &&
+		git commit -m "add local submodule 'no-remote-sub'"
+	) &&
+
+	(
+		cd super &&
+		# Should fall back to "origin" remote name when no remotes exist
+		echo "origin" >expect &&
+		git submodule--helper get-default-remote no-remote-sub >actual &&
+		test_cmp expect actual
+	)
+'
+
+test_done
diff --git a/t/t7605-merge-resolve.sh b/t/t7605-merge-resolve.sh
index 5d56c38..44de97a 100755
--- a/t/t7605-merge-resolve.sh
+++ b/t/t7605-merge-resolve.sh
@@ -34,9 +34,9 @@
 	test "$(git rev-parse c1)" = "$(git rev-parse HEAD^1)" &&
 	test "$(git rev-parse c2)" = "$(git rev-parse HEAD^2)" &&
 	git diff --exit-code &&
-	test -f c0.c &&
-	test -f c1.c &&
-	test -f c2.c &&
+	test_path_is_file c0.c &&
+	test_path_is_file c1.c &&
+	test_path_is_file c2.c &&
 	test 3 = $(git ls-tree -r HEAD | wc -l) &&
 	test 3 = $(git ls-files | wc -l)
 '
diff --git a/t/t9200-git-cvsexportcommit.sh b/t/t9200-git-cvsexportcommit.sh
index a44eabf..14cbe96 100755
--- a/t/t9200-git-cvsexportcommit.sh
+++ b/t/t9200-git-cvsexportcommit.sh
@@ -30,13 +30,17 @@
 
 rm -rf "$CVSROOT" "$CVSWORK"
 
-cvs init &&
-test -d "$CVSROOT" &&
-cvs -Q co -d "$CVSWORK" . &&
-echo >empty &&
-git add empty &&
-git commit -q -a -m "Initial" 2>/dev/null ||
-exit 1
+if ! cvs init || ! test -d "$CVSROOT" || ! cvs -Q co -d "$CVSWORK" .
+then
+	skip_all="cvs repository set-up fails"
+	test_done
+fi
+
+test_expect_success 'git setup' '
+	echo >empty &&
+	git add empty &&
+	git commit -q -a -m Initial
+'
 
 check_entries () {
 	# $1 == directory, $2 == expected
@@ -303,7 +307,7 @@
 	git commit -m "Added attic_gremlin" &&
 	git cvsexportcommit -w "$CVSWORK" -c HEAD &&
 	(cd "$CVSWORK" && cvs -Q update -d) &&
-	test -f "$CVSWORK/attic_gremlin"
+	test_path_is_file "$CVSWORK/attic_gremlin"
 '
 
 # the state of the CVS sandbox may be indeterminate for ' space'
diff --git a/t/t9305-fast-import-signatures.sh b/t/t9305-fast-import-signatures.sh
index a540679..18707b3 100755
--- a/t/t9305-fast-import-signatures.sh
+++ b/t/t9305-fast-import-signatures.sh
@@ -103,71 +103,111 @@
 	test_line_count = 2 out
 '
 
-test_expect_success GPG 'import commit with no signature with --signed-commits=strip-if-invalid' '
-	git fast-export main >output &&
-	git -C new fast-import --quiet --signed-commits=strip-if-invalid <output >log 2>&1 &&
-	test_must_be_empty log
-'
+for mode in strip-if-invalid sign-if-invalid
+do
+	test_expect_success GPG "import commit with no signature with --signed-commits=$mode" '
+		git fast-export main >output &&
+		git -C new fast-import --quiet --signed-commits=$mode <output >log 2>&1 &&
+		test_must_be_empty log
+	'
 
-test_expect_success GPG 'keep valid OpenPGP signature with --signed-commits=strip-if-invalid' '
+	test_expect_success GPG "keep valid OpenPGP signature with --signed-commits=$mode" '
+		rm -rf new &&
+		git init new &&
+
+		git fast-export --signed-commits=verbatim openpgp-signing >output &&
+		git -C new fast-import --quiet --signed-commits=$mode <output >log 2>&1 &&
+		IMPORTED=$(git -C new rev-parse --verify refs/heads/openpgp-signing) &&
+		test $OPENPGP_SIGNING = $IMPORTED &&
+		git -C new cat-file commit "$IMPORTED" >actual &&
+		test_grep -E "^gpgsig(-sha256)? " actual &&
+		test_must_be_empty log
+	'
+
+	test_expect_success GPG "handle signature invalidated by message change with --signed-commits=$mode" '
+		rm -rf new &&
+		git init new &&
+
+		git fast-export --signed-commits=verbatim openpgp-signing >output &&
+
+		# Change the commit message, which invalidates the signature.
+		# The commit message length should not change though, otherwise the
+		# corresponding `data <length>` command would have to be changed too.
+		sed "s/OpenPGP signed commit/OpenPGP forged commit/" output >modified &&
+
+		git -C new fast-import --quiet --signed-commits=$mode <modified >log 2>&1 &&
+
+		IMPORTED=$(git -C new rev-parse --verify refs/heads/openpgp-signing) &&
+		test $OPENPGP_SIGNING != $IMPORTED &&
+		git -C new cat-file commit "$IMPORTED" >actual &&
+
+		if test "$mode" = strip-if-invalid
+		then
+			test_grep "stripping invalid signature" log &&
+			test_grep ! -E "^gpgsig" actual
+		else
+			test_grep "replacing invalid signature" log &&
+			test_grep -E "^gpgsig(-sha256)? " actual &&
+			git -C new verify-commit "$IMPORTED"
+		fi
+	'
+
+	test_expect_success GPGSM "keep valid X.509 signature with --signed-commits=$mode" '
+		rm -rf new &&
+		git init new &&
+
+		git fast-export --signed-commits=verbatim x509-signing >output &&
+		git -C new fast-import --quiet --signed-commits=$mode <output >log 2>&1 &&
+		IMPORTED=$(git -C new rev-parse --verify refs/heads/x509-signing) &&
+		test $X509_SIGNING = $IMPORTED &&
+		git -C new cat-file commit "$IMPORTED" >actual &&
+		test_grep -E "^gpgsig(-sha256)? " actual &&
+		test_must_be_empty log
+	'
+
+	test_expect_success GPGSSH "keep valid SSH signature with --signed-commits=$mode" '
+		rm -rf new &&
+		git init new &&
+
+		test_config -C new gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+
+		git fast-export --signed-commits=verbatim ssh-signing >output &&
+		git -C new fast-import --quiet --signed-commits=$mode <output >log 2>&1 &&
+		IMPORTED=$(git -C new rev-parse --verify refs/heads/ssh-signing) &&
+		test $SSH_SIGNING = $IMPORTED &&
+		git -C new cat-file commit "$IMPORTED" >actual &&
+		test_grep -E "^gpgsig(-sha256)? " actual &&
+		test_must_be_empty log
+	'
+done
+
+test_expect_success GPGSSH "sign invalid commit with explicit keyid" '
 	rm -rf new &&
 	git init new &&
 
-	git fast-export --signed-commits=verbatim openpgp-signing >output &&
-	git -C new fast-import --quiet --signed-commits=strip-if-invalid <output >log 2>&1 &&
-	IMPORTED=$(git -C new rev-parse --verify refs/heads/openpgp-signing) &&
-	test $OPENPGP_SIGNING = $IMPORTED &&
-	git -C new cat-file commit "$IMPORTED" >actual &&
-	test_grep -E "^gpgsig(-sha256)? " actual &&
-	test_must_be_empty log
-'
-
-test_expect_success GPG 'strip signature invalidated by message change with --signed-commits=strip-if-invalid' '
-	rm -rf new &&
-	git init new &&
-
-	git fast-export --signed-commits=verbatim openpgp-signing >output &&
+	git fast-export --signed-commits=verbatim ssh-signing >output &&
 
 	# Change the commit message, which invalidates the signature.
 	# The commit message length should not change though, otherwise the
 	# corresponding `data <length>` command would have to be changed too.
-	sed "s/OpenPGP signed commit/OpenPGP forged commit/" output >modified &&
+	sed "s/SSH signed commit/SSH forged commit/" output >modified &&
 
-	git -C new fast-import --quiet --signed-commits=strip-if-invalid <modified >log 2>&1 &&
-
-	IMPORTED=$(git -C new rev-parse --verify refs/heads/openpgp-signing) &&
-	test $OPENPGP_SIGNING != $IMPORTED &&
-	git -C new cat-file commit "$IMPORTED" >actual &&
-	test_grep ! -E "^gpgsig" actual &&
-	test_grep "stripping invalid signature" log
-'
-
-test_expect_success GPGSM 'keep valid X.509 signature with --signed-commits=strip-if-invalid' '
-	rm -rf new &&
-	git init new &&
-
-	git fast-export --signed-commits=verbatim x509-signing >output &&
-	git -C new fast-import --quiet --signed-commits=strip-if-invalid <output >log 2>&1 &&
-	IMPORTED=$(git -C new rev-parse --verify refs/heads/x509-signing) &&
-	test $X509_SIGNING = $IMPORTED &&
-	git -C new cat-file commit "$IMPORTED" >actual &&
-	test_grep -E "^gpgsig(-sha256)? " actual &&
-	test_must_be_empty log
-'
-
-test_expect_success GPGSSH 'keep valid SSH signature with --signed-commits=strip-if-invalid' '
-	rm -rf new &&
-	git init new &&
-
+	# Configure the target repository with an invalid default signing key.
+	test_config -C new user.signingkey "not-a-real-key-id" &&
+	test_config -C new gpg.format ssh &&
 	test_config -C new gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+	test_must_fail git -C new fast-import --quiet \
+		--signed-commits=sign-if-invalid <modified >/dev/null 2>&1 &&
 
-	git fast-export --signed-commits=verbatim ssh-signing >output &&
-	git -C new fast-import --quiet --signed-commits=strip-if-invalid <output >log 2>&1 &&
+	# Import using explicitly provided signing key.
+	git -C new fast-import --quiet \
+		--signed-commits=sign-if-invalid="${GPGSSH_KEY_PRIMARY}" <modified &&
+
 	IMPORTED=$(git -C new rev-parse --verify refs/heads/ssh-signing) &&
-	test $SSH_SIGNING = $IMPORTED &&
+	test $SSH_SIGNING != $IMPORTED &&
 	git -C new cat-file commit "$IMPORTED" >actual &&
 	test_grep -E "^gpgsig(-sha256)? " actual &&
-	test_must_be_empty log
+	git -C new verify-commit "$IMPORTED"
 '
 
 test_done
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 14e238d..f3af10f 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -48,6 +48,9 @@
 			if (n == 2) return "FAINT";
 			if (n == 3) return "ITALIC";
 			if (n == 7) return "REVERSE";
+			if (n == 22) return "NORMAL_INTENSITY";
+			if (n == 23) return "NOITALIC";
+			if (n == 27) return "NOREVERSE";
 			if (n == 30) return "BLACK";
 			if (n == 31) return "RED";
 			if (n == 32) return "GREEN";
diff --git a/t/unit-tests/clar/clar.h b/t/unit-tests/clar/clar.h
index f7e4363..9ea91d3 100644
--- a/t/unit-tests/clar/clar.h
+++ b/t/unit-tests/clar/clar.h
@@ -15,8 +15,10 @@
 # define CLAR_MAX_PATH 4096
 #elif defined(_WIN32)
 # define CLAR_MAX_PATH MAX_PATH
-#else
+#elif defined(PATH_MAX)
 # define CLAR_MAX_PATH PATH_MAX
+#else
+# define CLAR_MAX_PATH 4096
 #endif
 
 #ifndef CLAR_SELFTEST
diff --git a/t/unit-tests/clar/generate.py b/t/unit-tests/clar/generate.py
index fd2f0ee..2357b2d 100755
--- a/t/unit-tests/clar/generate.py
+++ b/t/unit-tests/clar/generate.py
@@ -8,7 +8,7 @@
 
 from __future__ import with_statement
 from string import Template
-import re, fnmatch, os, sys, codecs, pickle
+import re, fnmatch, os, sys, codecs, pickle, io
 
 class Module(object):
     class Template(object):
@@ -147,7 +147,7 @@ def __init__(self, path, output):
         self.path = path
         self.output = output
 
-    def should_generate(self, path):
+    def maybe_generate(self, path):
         if not os.path.isfile(path):
             return True
 
@@ -223,34 +223,85 @@ def callback_count(self):
         return sum(len(module.callbacks) for module in self.modules.values())
 
     def write(self):
-        output = os.path.join(self.output, 'clar.suite')
-        os.makedirs(self.output, exist_ok=True)
+        if not os.path.exists(self.output):
+            os.makedirs(self.output)
 
-        if not self.should_generate(output):
+        wrote_suite = self.write_suite()
+        wrote_header = self.write_header()
+
+        if wrote_suite or wrote_header:
+            self.save_cache()
+            return True
+
+        return False
+
+    def write_output(self, fn, data):
+        if not self.maybe_generate(fn):
             return False
 
-        with open(output, 'w') as data:
+        current = None
+
+        try:
+            with open(fn, 'r') as input:
+                current = input.read()
+        except OSError:
+            pass
+        except IOError:
+            pass
+
+        if current == data:
+            return False
+
+        with open(fn, 'w') as output:
+            output.write(data)
+
+        return True
+
+    def write_suite(self):
+        suite_fn = os.path.join(self.output, 'clar.suite')
+
+        with io.StringIO() as suite_file:
             modules = sorted(self.modules.values(), key=lambda module: module.name)
 
             for module in modules:
                 t = Module.DeclarationTemplate(module)
-                data.write(t.render())
+                suite_file.write(t.render())
 
             for module in modules:
                 t = Module.CallbacksTemplate(module)
-                data.write(t.render())
+                suite_file.write(t.render())
 
             suites = "static struct clar_suite _clar_suites[] = {" + ','.join(
                 Module.InfoTemplate(module).render() for module in modules
             ) + "\n};\n"
 
-            data.write(suites)
+            suite_file.write(suites)
 
-            data.write("static const size_t _clar_suite_count = %d;\n" % self.suite_count())
-            data.write("static const size_t _clar_callback_count = %d;\n" % self.callback_count())
+            suite_file.write(u"static const size_t _clar_suite_count = %d;\n" % self.suite_count())
+            suite_file.write(u"static const size_t _clar_callback_count = %d;\n" % self.callback_count())
 
-        self.save_cache()
-        return True
+            return self.write_output(suite_fn, suite_file.getvalue())
+
+        return False
+
+    def write_header(self):
+        header_fn = os.path.join(self.output, 'clar_suite.h')
+
+        with io.StringIO() as header_file:
+            header_file.write(u"#ifndef _____clar_suite_h_____\n")
+            header_file.write(u"#define _____clar_suite_h_____\n")
+
+            modules = sorted(self.modules.values(), key=lambda module: module.name)
+
+            for module in modules:
+                t = Module.DeclarationTemplate(module)
+                header_file.write(t.render())
+
+            header_file.write(u"#endif\n")
+
+            return self.write_output(header_fn, header_file.getvalue())
+
+        return False
 
 if __name__ == '__main__':
     from optparse import OptionParser
@@ -275,4 +326,4 @@ def write(self):
     suite.load(options.force)
     suite.disable(options.excluded)
     if suite.write():
-        print("Written `clar.suite` (%d tests in %d suites)" % (suite.callback_count(), suite.suite_count()))
+        print("Written `clar.suite`, `clar_suite.h` (%d tests in %d suites)" % (suite.callback_count(), suite.suite_count()))
diff --git a/t/unit-tests/test-lib.c b/t/unit-tests/test-lib.c
index 87e1f5c..72ee20a 100644
--- a/t/unit-tests/test-lib.c
+++ b/t/unit-tests/test-lib.c
@@ -396,8 +396,23 @@ int check_uint_loc(const char *loc, const char *check, int ok,
 static void print_one_char(char ch, char quote)
 {
 	if ((unsigned char)ch < 0x20u || ch == 0x7f) {
-		/* TODO: improve handling of \a, \b, \f ... */
-		printf("\\%03o", (unsigned char)ch);
+		char esc;
+		switch (ch) {
+		case '\a': esc = 'a'; break;
+		case '\b': esc = 'b'; break;
+		case '\t': esc = 't'; break;
+		case '\n': esc = 'n'; break;
+		case '\v': esc = 'v'; break;
+		case '\f': esc = 'f'; break;
+		case '\r': esc = 'r'; break;
+		default: esc = 0; break;
+		}
+		if (esc) {
+			putc('\\', stdout);
+			putc(esc, stdout);
+		} else {
+			printf("\\%03o", (unsigned char)ch);
+		}
 	} else {
 		if (ch == '\\' || ch == quote)
 			putc('\\', stdout);
diff --git a/tmp-objdir.c b/tmp-objdir.c
index 9f5a178..d199d39 100644
--- a/tmp-objdir.c
+++ b/tmp-objdir.c
@@ -11,6 +11,7 @@
 #include "strvec.h"
 #include "quote.h"
 #include "odb.h"
+#include "odb/source.h"
 #include "repository.h"
 
 struct tmp_objdir {
@@ -36,6 +37,21 @@ static void tmp_objdir_free(struct tmp_objdir *t)
 	free(t);
 }
 
+static void tmp_objdir_reparent(const char *name UNUSED,
+				const char *old_cwd,
+				const char *new_cwd,
+				void *cb_data)
+{
+	struct tmp_objdir *t = cb_data;
+	char *path;
+
+	path = reparent_relative_path(old_cwd, new_cwd,
+				      t->path.buf);
+	strbuf_reset(&t->path);
+	strbuf_addstr(&t->path, path);
+	free(path);
+}
+
 int tmp_objdir_destroy(struct tmp_objdir *t)
 {
 	int err;
@@ -51,6 +67,7 @@ int tmp_objdir_destroy(struct tmp_objdir *t)
 
 	err = remove_dir_recursively(&t->path, 0);
 
+	chdir_notify_unregister(NULL, tmp_objdir_reparent, t);
 	tmp_objdir_free(t);
 
 	return err;
@@ -137,6 +154,9 @@ struct tmp_objdir *tmp_objdir_create(struct repository *r,
 	strbuf_addf(&t->path, "%s/tmp_objdir-%s-XXXXXX",
 		    repo_get_object_directory(r), prefix);
 
+	if (!is_absolute_path(t->path.buf))
+		chdir_notify_register(NULL, tmp_objdir_reparent, t);
+
 	if (!mkdtemp(t->path.buf)) {
 		/* free, not destroy, as we never touched the filesystem */
 		tmp_objdir_free(t);
@@ -315,26 +335,3 @@ void tmp_objdir_replace_primary_odb(struct tmp_objdir *t, int will_destroy)
 							  t->path.buf, will_destroy);
 	t->will_destroy = will_destroy;
 }
-
-struct tmp_objdir *tmp_objdir_unapply_primary_odb(void)
-{
-	if (!the_tmp_objdir || !the_tmp_objdir->prev_source)
-		return NULL;
-
-	odb_restore_primary_source(the_tmp_objdir->repo->objects,
-				   the_tmp_objdir->prev_source, the_tmp_objdir->path.buf);
-	the_tmp_objdir->prev_source = NULL;
-	return the_tmp_objdir;
-}
-
-void tmp_objdir_reapply_primary_odb(struct tmp_objdir *t, const char *old_cwd,
-		const char *new_cwd)
-{
-	char *path;
-
-	path = reparent_relative_path(old_cwd, new_cwd, t->path.buf);
-	strbuf_reset(&t->path);
-	strbuf_addstr(&t->path, path);
-	free(path);
-	tmp_objdir_replace_primary_odb(t, t->will_destroy);
-}
diff --git a/tmp-objdir.h b/tmp-objdir.h
index fceda14..ccf800f 100644
--- a/tmp-objdir.h
+++ b/tmp-objdir.h
@@ -68,19 +68,4 @@ void tmp_objdir_add_as_alternate(const struct tmp_objdir *);
  */
 void tmp_objdir_replace_primary_odb(struct tmp_objdir *, int will_destroy);
 
-/*
- * If the primary object database was replaced by a temporary object directory,
- * restore it to its original value while keeping the directory contents around.
- * Returns NULL if the primary object database was not replaced.
- */
-struct tmp_objdir *tmp_objdir_unapply_primary_odb(void);
-
-/*
- * Reapplies the former primary temporary object database, after potentially
- * changing its relative path.
- */
-void tmp_objdir_reapply_primary_odb(struct tmp_objdir *, const char *old_cwd,
-		const char *new_cwd);
-
-
 #endif /* TMP_OBJDIR_H */
diff --git a/tools/README.md b/tools/README.md
new file mode 100644
index 0000000..d732997
--- /dev/null
+++ b/tools/README.md
@@ -0,0 +1,7 @@
+Developer Tooling
+-----------------
+
+This directory is expected to contain all sorts of tooling that
+relates to our build infrastructure. This includes scripts and
+inputs required by our build systems, but also scripts that
+developers are expected to run manually.
diff --git a/check-builtins.sh b/tools/check-builtins.sh
similarity index 100%
rename from check-builtins.sh
rename to tools/check-builtins.sh
diff --git a/contrib/coccinelle/.gitignore b/tools/coccinelle/.gitignore
similarity index 100%
rename from contrib/coccinelle/.gitignore
rename to tools/coccinelle/.gitignore
diff --git a/contrib/coccinelle/README b/tools/coccinelle/README
similarity index 98%
rename from contrib/coccinelle/README
rename to tools/coccinelle/README
index 055ad0e..fd0a543 100644
--- a/contrib/coccinelle/README
+++ b/tools/coccinelle/README
@@ -38,7 +38,7 @@
    So to aid these large scale refactorings, semantic patches can be used.
    However we do not want to store them in the same place as the checks for
    bad patterns, as then automated builds would fail.
-   That is why semantic patches 'contrib/coccinelle/*.pending.cocci'
+   That is why semantic patches 'tools/coccinelle/*.pending.cocci'
    are ignored for checks, and can be applied using 'make coccicheck-pending'.
 
    This allows to expose plans of pending large scale refactorings without
diff --git a/contrib/coccinelle/array.cocci b/tools/coccinelle/array.cocci
similarity index 100%
rename from contrib/coccinelle/array.cocci
rename to tools/coccinelle/array.cocci
diff --git a/contrib/coccinelle/commit.cocci b/tools/coccinelle/commit.cocci
similarity index 100%
rename from contrib/coccinelle/commit.cocci
rename to tools/coccinelle/commit.cocci
diff --git a/contrib/coccinelle/config_fn_ctx.pending.cocci b/tools/coccinelle/config_fn_ctx.pending.cocci
similarity index 100%
rename from contrib/coccinelle/config_fn_ctx.pending.cocci
rename to tools/coccinelle/config_fn_ctx.pending.cocci
diff --git a/contrib/coccinelle/equals-null.cocci b/tools/coccinelle/equals-null.cocci
similarity index 100%
rename from contrib/coccinelle/equals-null.cocci
rename to tools/coccinelle/equals-null.cocci
diff --git a/contrib/coccinelle/flex_alloc.cocci b/tools/coccinelle/flex_alloc.cocci
similarity index 100%
rename from contrib/coccinelle/flex_alloc.cocci
rename to tools/coccinelle/flex_alloc.cocci
diff --git a/contrib/coccinelle/free.cocci b/tools/coccinelle/free.cocci
similarity index 100%
rename from contrib/coccinelle/free.cocci
rename to tools/coccinelle/free.cocci
diff --git a/contrib/coccinelle/git_config_number.cocci b/tools/coccinelle/git_config_number.cocci
similarity index 100%
rename from contrib/coccinelle/git_config_number.cocci
rename to tools/coccinelle/git_config_number.cocci
diff --git a/contrib/coccinelle/hashmap.cocci b/tools/coccinelle/hashmap.cocci
similarity index 100%
rename from contrib/coccinelle/hashmap.cocci
rename to tools/coccinelle/hashmap.cocci
diff --git a/contrib/coccinelle/index-compatibility.cocci b/tools/coccinelle/index-compatibility.cocci
similarity index 100%
rename from contrib/coccinelle/index-compatibility.cocci
rename to tools/coccinelle/index-compatibility.cocci
diff --git a/contrib/coccinelle/meson.build b/tools/coccinelle/meson.build
similarity index 100%
rename from contrib/coccinelle/meson.build
rename to tools/coccinelle/meson.build
diff --git a/contrib/coccinelle/object_id.cocci b/tools/coccinelle/object_id.cocci
similarity index 100%
rename from contrib/coccinelle/object_id.cocci
rename to tools/coccinelle/object_id.cocci
diff --git a/contrib/coccinelle/preincr.cocci b/tools/coccinelle/preincr.cocci
similarity index 100%
rename from contrib/coccinelle/preincr.cocci
rename to tools/coccinelle/preincr.cocci
diff --git a/contrib/coccinelle/qsort.cocci b/tools/coccinelle/qsort.cocci
similarity index 100%
rename from contrib/coccinelle/qsort.cocci
rename to tools/coccinelle/qsort.cocci
diff --git a/contrib/coccinelle/refs.cocci b/tools/coccinelle/refs.cocci
similarity index 100%
rename from contrib/coccinelle/refs.cocci
rename to tools/coccinelle/refs.cocci
diff --git a/contrib/coccinelle/spatchcache b/tools/coccinelle/spatchcache
similarity index 96%
rename from contrib/coccinelle/spatchcache
rename to tools/coccinelle/spatchcache
index 29e9352..efbcbc3 100755
--- a/contrib/coccinelle/spatchcache
+++ b/tools/coccinelle/spatchcache
@@ -30,7 +30,7 @@
 #	   out of control.
 #
 # This along with the general incremental "make" support for
-# "contrib/coccinelle" makes it viable to (re-)run coccicheck
+# "tools/coccinelle" makes it viable to (re-)run coccicheck
 # e.g. when merging integration branches.
 #
 # Note that the "--very-quiet" flag is currently critical. The cache
@@ -42,7 +42,7 @@
 # to change, so just supply "--very-quiet" for now.
 #
 # To use this, simply set SPATCH to
-# contrib/coccinelle/spatchcache. Then optionally set:
+# tools/coccinelle/spatchcache. Then optionally set:
 #
 #	[spatchCache]
 #		# Optional: path to a custom spatch
@@ -65,7 +65,7 @@
 #
 #	redis-cli FLUSHALL
 #	<make && make coccicheck, as above>
-#	grep -hore HIT -e MISS -e SET -e NOCACHE -e CANTCACHE .build/contrib/coccinelle | sort | uniq -c
+#	grep -hore HIT -e MISS -e SET -e NOCACHE -e CANTCACHE .build/tools/coccinelle | sort | uniq -c
 #	    600 CANTCACHE
 #	   7365 MISS
 #	   7365 SET
diff --git a/contrib/coccinelle/strbuf.cocci b/tools/coccinelle/strbuf.cocci
similarity index 78%
rename from contrib/coccinelle/strbuf.cocci
rename to tools/coccinelle/strbuf.cocci
index 5f06105..f586128 100644
--- a/contrib/coccinelle/strbuf.cocci
+++ b/tools/coccinelle/strbuf.cocci
@@ -60,3 +60,21 @@
 @@
 - strbuf_addstr(E1, real_path(E2));
 + strbuf_add_real_path(E1, E2);
+
+@@
+identifier fn, param;
+@@
+  fn(...,
+- struct strbuf param
++ struct strbuf *param
+  ,...)
+  {
+  ...
+  }
+
+// In modern codebase, .buf member of an empty strbuf is not NULL.
+@@
+struct strbuf SB;
+@@
+- SB.buf ? SB.buf : ""
++ SB.buf
diff --git a/tools/coccinelle/strvec.cocci b/tools/coccinelle/strvec.cocci
new file mode 100644
index 0000000..64edb09
--- /dev/null
+++ b/tools/coccinelle/strvec.cocci
@@ -0,0 +1,46 @@
+@@
+type T;
+identifier i;
+expression dst;
+struct strvec *src_ptr;
+struct strvec src_arr;
+@@
+(
+- for (T i = 0; i < src_ptr->nr; i++) { strvec_push(dst, src_ptr->v[i]); }
++ strvec_pushv(dst, src_ptr->v);
+|
+- for (T i = 0; i < src_arr.nr; i++) { strvec_push(dst, src_arr.v[i]); }
++ strvec_pushv(dst, src_arr.v);
+)
+
+@ separate_loop_index @
+type T;
+identifier i;
+expression dst;
+struct strvec *src_ptr;
+struct strvec src_arr;
+@@
+  T i;
+  ...
+(
+- for (i = 0; i < src_ptr->nr; i++) { strvec_push(dst, src_ptr->v[i]); }
++ strvec_pushv(dst, src_ptr->v);
+|
+- for (i = 0; i < src_arr.nr; i++) { strvec_push(dst, src_arr.v[i]); }
++ strvec_pushv(dst, src_arr.v);
+)
+
+@ unused_loop_index extends separate_loop_index @
+@@
+  {
+  ...
+- T i;
+  ... when != i
+  }
+
+@ depends on unused_loop_index @
+@@
+  if (...)
+- {
+  strvec_pushv(...);
+- }
diff --git a/contrib/coccinelle/swap.cocci b/tools/coccinelle/swap.cocci
similarity index 100%
rename from contrib/coccinelle/swap.cocci
rename to tools/coccinelle/swap.cocci
diff --git a/contrib/coccinelle/tests/free.c b/tools/coccinelle/tests/free.c
similarity index 100%
rename from contrib/coccinelle/tests/free.c
rename to tools/coccinelle/tests/free.c
diff --git a/contrib/coccinelle/tests/free.res b/tools/coccinelle/tests/free.res
similarity index 100%
rename from contrib/coccinelle/tests/free.res
rename to tools/coccinelle/tests/free.res
diff --git a/contrib/coccinelle/the_repository.cocci b/tools/coccinelle/the_repository.cocci
similarity index 100%
rename from contrib/coccinelle/the_repository.cocci
rename to tools/coccinelle/the_repository.cocci
diff --git a/contrib/coccinelle/xcalloc.cocci b/tools/coccinelle/xcalloc.cocci
similarity index 100%
rename from contrib/coccinelle/xcalloc.cocci
rename to tools/coccinelle/xcalloc.cocci
diff --git a/contrib/coccinelle/xopen.cocci b/tools/coccinelle/xopen.cocci
similarity index 100%
rename from contrib/coccinelle/xopen.cocci
rename to tools/coccinelle/xopen.cocci
diff --git a/contrib/coccinelle/xstrdup_or_null.cocci b/tools/coccinelle/xstrdup_or_null.cocci
similarity index 100%
rename from contrib/coccinelle/xstrdup_or_null.cocci
rename to tools/coccinelle/xstrdup_or_null.cocci
diff --git a/contrib/coccinelle/xstrncmpz.cocci b/tools/coccinelle/xstrncmpz.cocci
similarity index 100%
rename from contrib/coccinelle/xstrncmpz.cocci
rename to tools/coccinelle/xstrncmpz.cocci
diff --git a/contrib/coverage-diff.sh b/tools/coverage-diff.sh
similarity index 100%
rename from contrib/coverage-diff.sh
rename to tools/coverage-diff.sh
diff --git a/detect-compiler b/tools/detect-compiler
similarity index 100%
rename from detect-compiler
rename to tools/detect-compiler
diff --git a/generate-cmdlist.sh b/tools/generate-cmdlist.sh
similarity index 100%
rename from generate-cmdlist.sh
rename to tools/generate-cmdlist.sh
diff --git a/generate-configlist.sh b/tools/generate-configlist.sh
similarity index 100%
rename from generate-configlist.sh
rename to tools/generate-configlist.sh
diff --git a/generate-hooklist.sh b/tools/generate-hooklist.sh
similarity index 100%
rename from generate-hooklist.sh
rename to tools/generate-hooklist.sh
diff --git a/generate-perl.sh b/tools/generate-perl.sh
similarity index 100%
rename from generate-perl.sh
rename to tools/generate-perl.sh
diff --git a/generate-python.sh b/tools/generate-python.sh
similarity index 100%
rename from generate-python.sh
rename to tools/generate-python.sh
diff --git a/generate-script.sh b/tools/generate-script.sh
similarity index 100%
rename from generate-script.sh
rename to tools/generate-script.sh
diff --git a/tools/meson.build b/tools/meson.build
new file mode 100644
index 0000000..f731f74
--- /dev/null
+++ b/tools/meson.build
@@ -0,0 +1 @@
+subdir('coccinelle')
diff --git a/tools/precompiled.h b/tools/precompiled.h
new file mode 100644
index 0000000..b2bec0d
--- /dev/null
+++ b/tools/precompiled.h
@@ -0,0 +1 @@
+#include "git-compat-util.h"
diff --git a/contrib/update-unicode/.gitignore b/tools/update-unicode/.gitignore
similarity index 100%
rename from contrib/update-unicode/.gitignore
rename to tools/update-unicode/.gitignore
diff --git a/contrib/update-unicode/README b/tools/update-unicode/README
similarity index 100%
rename from contrib/update-unicode/README
rename to tools/update-unicode/README
diff --git a/contrib/update-unicode/update_unicode.sh b/tools/update-unicode/update_unicode.sh
similarity index 100%
rename from contrib/update-unicode/update_unicode.sh
rename to tools/update-unicode/update_unicode.sh
diff --git a/trailer.c b/trailer.c
index 911a81e..470f86a 100644
--- a/trailer.c
+++ b/trailer.c
@@ -7,8 +7,11 @@
 #include "string-list.h"
 #include "run-command.h"
 #include "commit.h"
+#include "strvec.h"
 #include "trailer.h"
 #include "list.h"
+#include "tempfile.h"
+
 /*
  * Copyright (c) 2013, 2014 Christian Couder <chriscool@tuxfamily.org>
  */
@@ -772,6 +775,35 @@ void parse_trailers_from_command_line_args(struct list_head *arg_head,
 	free(cl_separators);
 }
 
+int validate_trailer_args(const struct strvec *cli_args)
+{
+	char *cl_separators;
+	int ret = 0;
+
+	trailer_config_init();
+
+	cl_separators = xstrfmt("=%s", separators);
+
+	for (size_t i = 0; i < cli_args->nr; i++) {
+		const char *txt = cli_args->v[i];
+		ssize_t separator_pos;
+
+		if (!*txt) {
+			ret = error(_("empty --trailer argument"));
+			goto out;
+		}
+		separator_pos = find_separator(txt, cl_separators);
+		if (separator_pos == 0) {
+			ret = error(_("invalid trailer '%s': missing key before separator"),
+				    txt);
+			goto out;
+		}
+	}
+out:
+	free(cl_separators);
+	return ret;
+}
+
 static const char *next_line(const char *str)
 {
 	const char *nl = strchrnul(str, '\n');
@@ -1009,7 +1041,7 @@ static struct trailer_block *trailer_block_get(const struct process_trailer_opti
 	for (ptr = trailer_lines; *ptr; ptr++) {
 		if (last && isspace((*ptr)->buf[0])) {
 			struct strbuf sb = STRBUF_INIT;
-			strbuf_attach(&sb, *last, strlen(*last), strlen(*last));
+			strbuf_attach(&sb, *last, strlen(*last), strlen(*last) + 1);
 			strbuf_addbuf(&sb, *ptr);
 			*last = strbuf_detach(&sb, NULL);
 			continue;
@@ -1224,14 +1256,146 @@ void trailer_iterator_release(struct trailer_iterator *iter)
 	strbuf_release(&iter->key);
 }
 
-int amend_file_with_trailers(const char *path, const struct strvec *trailer_args)
+struct tempfile *trailer_create_in_place_tempfile(const char *file)
 {
-	struct child_process run_trailer = CHILD_PROCESS_INIT;
+	struct tempfile *tempfile = NULL;
+	struct stat st;
+	struct strbuf filename_template = STRBUF_INIT;
+	const char *tail;
 
-	run_trailer.git_cmd = 1;
-	strvec_pushl(&run_trailer.args, "interpret-trailers",
-		     "--in-place", "--no-divider",
-		     path, NULL);
-	strvec_pushv(&run_trailer.args, trailer_args->v);
-	return run_command(&run_trailer);
+	if (stat(file, &st)) {
+		error_errno(_("could not stat %s"), file);
+		return NULL;
+	}
+	if (!S_ISREG(st.st_mode)) {
+		error(_("file %s is not a regular file"), file);
+		return NULL;
+	}
+	if (!(st.st_mode & S_IWUSR)) {
+		error(_("file %s is not writable by user"), file);
+		return NULL;
+	}
+	/* Create temporary file in the same directory as the original */
+	tail = find_last_dir_sep(file);
+	if (tail)
+		strbuf_add(&filename_template, file, tail - file + 1);
+	strbuf_addstr(&filename_template, "git-interpret-trailers-XXXXXX");
+
+	tempfile = mks_tempfile_m(filename_template.buf, st.st_mode);
+
+	strbuf_release(&filename_template);
+
+	return tempfile;
+}
+
+int amend_strbuf_with_trailers(struct strbuf *buf,
+				const struct strvec *trailer_args)
+{
+	struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT;
+	LIST_HEAD(new_trailer_head);
+	struct strbuf out = STRBUF_INIT;
+	size_t i;
+	int ret = 0;
+
+	opts.no_divider = 1;
+
+	for (i = 0; i < trailer_args->nr; i++) {
+		const char *text = trailer_args->v[i];
+		struct new_trailer_item *item;
+
+		if (!*text) {
+			ret = error(_("empty --trailer argument"));
+			goto out;
+		}
+		item = xcalloc(1, sizeof(*item));
+		item->text = xstrdup(text);
+		list_add_tail(&item->list, &new_trailer_head);
+	}
+
+	process_trailers(&opts, &new_trailer_head, buf, &out);
+
+	strbuf_swap(buf, &out);
+out:
+	strbuf_release(&out);
+	free_trailers(&new_trailer_head);
+
+	return ret;
+}
+
+static int write_file_in_place(const char *path, const struct strbuf *buf)
+{
+	struct tempfile *tempfile = trailer_create_in_place_tempfile(path);
+	if (!tempfile)
+		return -1;
+
+	if (write_in_full(tempfile->fd, buf->buf, buf->len) < 0)
+		return error_errno(_("could not write to temporary file"));
+
+	if (rename_tempfile(&tempfile, path))
+		return error_errno(_("could not rename temporary file to %s"), path);
+
+	return 0;
+}
+
+int amend_file_with_trailers(const char *path,
+			     const struct strvec *trailer_args)
+{
+	struct strbuf buf = STRBUF_INIT;
+	int ret = 0;
+
+	if (!trailer_args)
+		BUG("amend_file_with_trailers called with NULL trailer_args");
+	if (!trailer_args->nr)
+		return 0;
+
+	if (validate_trailer_args(trailer_args)) {
+		ret = -1;
+		goto out;
+	}
+	if (strbuf_read_file(&buf, path, 0) < 0)
+		ret = error_errno(_("could not read '%s'"), path);
+	else
+		amend_strbuf_with_trailers(&buf, trailer_args);
+
+	if (!ret)
+		ret = write_file_in_place(path, &buf);
+out:
+	strbuf_release(&buf);
+	return ret;
+}
+
+void process_trailers(const struct process_trailer_options *opts,
+		      struct list_head *new_trailer_head,
+		      struct strbuf *input, struct strbuf *out)
+{
+	LIST_HEAD(head);
+	struct trailer_block *trailer_block;
+
+	trailer_block = parse_trailers(opts, input->buf, &head);
+
+	/* Print the lines before the trailer block */
+	if (!opts->only_trailers)
+		strbuf_add(out, input->buf, trailer_block_start(trailer_block));
+
+	if (!opts->only_trailers && !blank_line_before_trailer_block(trailer_block))
+		strbuf_addch(out, '\n');
+
+	if (!opts->only_input) {
+		LIST_HEAD(config_head);
+		LIST_HEAD(arg_head);
+		parse_trailers_from_config(&config_head);
+		parse_trailers_from_command_line_args(&arg_head, new_trailer_head);
+		list_splice(&config_head, &arg_head);
+		process_trailers_lists(&head, &arg_head);
+	}
+
+	/* Print trailer block. */
+	format_trailers(opts, &head, out);
+	free_trailers(&head);
+
+	/* Print the lines after the trailer block as is. */
+	if (!opts->only_trailers)
+		strbuf_add(out, input->buf + trailer_block_end(trailer_block),
+			   input->len - trailer_block_end(trailer_block));
+	trailer_block_release(trailer_block);
 }
diff --git a/trailer.h b/trailer.h
index 4740549..b493388 100644
--- a/trailer.h
+++ b/trailer.h
@@ -68,6 +68,8 @@ void parse_trailers_from_config(struct list_head *config_head);
 void parse_trailers_from_command_line_args(struct list_head *arg_head,
 					   struct list_head *new_trailer_head);
 
+int validate_trailer_args(const struct strvec *cli_args);
+
 void process_trailers_lists(struct list_head *head,
 			    struct list_head *arg_head);
 
@@ -196,10 +198,38 @@ int trailer_iterator_advance(struct trailer_iterator *iter);
 void trailer_iterator_release(struct trailer_iterator *iter);
 
 /*
- * Augment a file to add trailers to it by running git-interpret-trailers.
- * This calls run_command() and its return value is the same (i.e. 0 for
- * success, various non-zero for other errors). See run-command.h.
+ * Append trailers specified in trailer_args to buf in-place.
+ *
+ * Each element of trailer_args should be in the same format as the value
+ * accepted by --trailer=<trailer> (i.e., without the --trailer= prefix).
+ */
+int amend_strbuf_with_trailers(struct strbuf *buf,
+				const struct strvec *trailer_args);
+
+/*
+ * Augment a file by appending trailers specified in trailer_args.
+ *
+ * Each element of trailer_args should be in the same format as the value
+ * accepted by --trailer=<trailer> (i.e., without the --trailer= prefix).
+ *
+ * Returns 0 on success or a non-zero error code on failure.
  */
 int amend_file_with_trailers(const char *path, const struct strvec *trailer_args);
 
+/*
+ * Create a tempfile ""git-interpret-trailers-XXXXXX" in the same
+ * directory as file.
+ */
+struct tempfile *trailer_create_in_place_tempfile(const char *file);
+
+/*
+ * Rewrite the contents of input by processing its trailer block according to
+ * opts and (optionally) appending trailers from new_trailer_head.
+ *
+ * The rewritten message is appended to out (callers should strbuf_reset()
+ * first if needed).
+ */
+void process_trailers(const struct process_trailer_options *opts,
+		      struct list_head *new_trailer_head,
+		      struct strbuf *input, struct strbuf *out);
 #endif /* TRAILER_H */
diff --git a/transport.c b/transport.c
index 107f4fa..cb1befb 100644
--- a/transport.c
+++ b/transport.c
@@ -47,21 +47,21 @@ static int transport_color_config(void)
 		"color.transport.reset",
 		"color.transport.rejected"
 	}, *key = "color.transport";
-	char *value;
+	const char *value;
 	static int initialized;
 
 	if (initialized)
 		return 0;
 	initialized = 1;
 
-	if (!repo_config_get_string(the_repository, key, &value))
+	if (!repo_config_get_string_tmp(the_repository, key, &value))
 		transport_use_color = git_config_colorbool(key, value);
 
 	if (!want_color_stderr(transport_use_color))
 		return 0;
 
 	for (size_t i = 0; i < ARRAY_SIZE(keys); i++)
-		if (!repo_config_get_string(the_repository, keys[i], &value)) {
+		if (!repo_config_get_string_tmp(the_repository, keys[i], &value)) {
 			if (!value)
 				return config_error_nonbool(keys[i]);
 			if (color_parse(value, transport_colors[i]) < 0)
diff --git a/upload-pack.c b/upload-pack.c
index e8c5cce..9f6d6fe 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -29,6 +29,7 @@
 #include "commit-graph.h"
 #include "commit-reach.h"
 #include "shallow.h"
+#include "trace.h"
 #include "write-or-die.h"
 #include "json-writer.h"
 #include "strmap.h"
@@ -218,7 +219,8 @@ struct output_state {
 };
 
 static int relay_pack_data(int pack_objects_out, struct output_state *os,
-			   int use_sideband, int write_packfile_line)
+			   int use_sideband, int write_packfile_line,
+			   bool *did_send_data)
 {
 	/*
 	 * We keep the last byte to ourselves
@@ -232,6 +234,8 @@ static int relay_pack_data(int pack_objects_out, struct output_state *os,
 	 */
 	ssize_t readsz;
 
+	*did_send_data = false;
+
 	readsz = xread(pack_objects_out, os->buffer + os->used,
 		       sizeof(os->buffer) - os->used);
 	if (readsz < 0) {
@@ -247,6 +251,7 @@ static int relay_pack_data(int pack_objects_out, struct output_state *os,
 				if (os->packfile_uris_started)
 					packet_delim(1);
 				packet_write_fmt(1, "\1packfile\n");
+				*did_send_data = true;
 			}
 			break;
 		}
@@ -259,6 +264,7 @@ static int relay_pack_data(int pack_objects_out, struct output_state *os,
 			}
 			*p = '\0';
 			packet_write_fmt(1, "\1%s\n", os->buffer);
+			*did_send_data = true;
 
 			os->used -= p - os->buffer + 1;
 			memmove(os->buffer, p + 1, os->used);
@@ -270,6 +276,13 @@ static int relay_pack_data(int pack_objects_out, struct output_state *os,
 		}
 	}
 
+	/*
+	 * Make sure that we buffer some data before sending it to the client.
+	 * This significantly reduces the number of write(3p) syscalls.
+	 */
+	if (readsz && os->used < (sizeof(os->buffer) * 2 / 3))
+		return readsz;
+
 	if (os->used > 1) {
 		send_client_data(1, os->buffer, os->used - 1, use_sideband);
 		os->buffer[0] = os->buffer[os->used - 1];
@@ -279,6 +292,7 @@ static int relay_pack_data(int pack_objects_out, struct output_state *os,
 		os->used = 0;
 	}
 
+	*did_send_data = true;
 	return readsz;
 }
 
@@ -290,6 +304,7 @@ static void create_pack_file(struct upload_pack_data *pack_data,
 	char progress[128];
 	char abort_msg[] = "aborting due to possible repository "
 		"corruption on the remote side.";
+	uint64_t last_sent_ms = 0;
 	ssize_t sz;
 	int i;
 	FILE *pipe_fd;
@@ -365,10 +380,14 @@ static void create_pack_file(struct upload_pack_data *pack_data,
 	 */
 
 	while (1) {
+		uint64_t now_ms = getnanotime() / 1000000;
 		struct pollfd pfd[2];
-		int pe, pu, pollsize, polltimeout;
+		int pe, pu, pollsize, polltimeout_ms;
 		int ret;
 
+		if (!last_sent_ms)
+			last_sent_ms = now_ms;
+
 		reset_timeout(pack_data->timeout);
 
 		pollsize = 0;
@@ -390,11 +409,21 @@ static void create_pack_file(struct upload_pack_data *pack_data,
 		if (!pollsize)
 			break;
 
-		polltimeout = pack_data->keepalive < 0
-			? -1
-			: 1000 * pack_data->keepalive;
+		if (pack_data->keepalive < 0) {
+			polltimeout_ms = -1;
+		} else {
+			/*
+			 * The polling timeout needs to be adjusted based on
+			 * the time we have sent our last package. The longer
+			 * it's been in the past, the shorter the timeout
+			 * becomes until we eventually don't block at all.
+			 */
+			polltimeout_ms = 1000 * pack_data->keepalive - (now_ms - last_sent_ms);
+			if (polltimeout_ms < 0)
+				polltimeout_ms = 0;
+		}
 
-		ret = poll(pfd, pollsize, polltimeout);
+		ret = poll(pfd, pollsize, polltimeout_ms);
 
 		if (ret < 0) {
 			if (errno != EINTR) {
@@ -403,16 +432,18 @@ static void create_pack_file(struct upload_pack_data *pack_data,
 			}
 			continue;
 		}
+
 		if (0 <= pe && (pfd[pe].revents & (POLLIN|POLLHUP))) {
 			/* Status ready; we ship that in the side-band
 			 * or dump to the standard error.
 			 */
 			sz = xread(pack_objects.err, progress,
 				  sizeof(progress));
-			if (0 < sz)
+			if (0 < sz) {
 				send_client_data(2, progress, sz,
 						 pack_data->use_sideband);
-			else if (sz == 0) {
+				last_sent_ms = now_ms;
+			} else if (sz == 0) {
 				close(pack_objects.err);
 				pack_objects.err = -1;
 			}
@@ -421,11 +452,14 @@ static void create_pack_file(struct upload_pack_data *pack_data,
 			/* give priority to status messages */
 			continue;
 		}
+
 		if (0 <= pu && (pfd[pu].revents & (POLLIN|POLLHUP))) {
+			bool did_send_data;
 			int result = relay_pack_data(pack_objects.out,
 						     output_state,
 						     pack_data->use_sideband,
-						     !!uri_protocols);
+						     !!uri_protocols,
+						     &did_send_data);
 
 			if (result == 0) {
 				close(pack_objects.out);
@@ -433,21 +467,34 @@ static void create_pack_file(struct upload_pack_data *pack_data,
 			} else if (result < 0) {
 				goto fail;
 			}
+
+			if (did_send_data)
+				last_sent_ms = now_ms;
 		}
 
 		/*
-		 * We hit the keepalive timeout without saying anything; send
-		 * an empty message on the data sideband just to let the other
-		 * side know we're still working on it, but don't have any data
-		 * yet.
+		 * We hit the keepalive timeout without saying anything. If we
+		 * have pending data we flush it out to the caller now.
+		 * Otherwise, we send an empty message on the data sideband
+		 * just to let the other side know we're still working on it,
+		 * but don't have any data yet.
 		 *
 		 * If we don't have a sideband channel, there's no room in the
 		 * protocol to say anything, so those clients are just out of
 		 * luck.
 		 */
 		if (!ret && pack_data->use_sideband) {
-			static const char buf[] = "0005\1";
-			write_or_die(1, buf, 5);
+			if (output_state->packfile_started && output_state->used > 1) {
+				send_client_data(1, output_state->buffer, output_state->used - 1,
+						 pack_data->use_sideband);
+				output_state->buffer[0] = output_state->buffer[output_state->used - 1];
+				output_state->used = 1;
+			} else {
+				static const char buf[] = "0005\1";
+				write_or_die(1, buf, 5);
+			}
+
+			last_sent_ms = now_ms;
 		}
 	}
 
@@ -457,11 +504,9 @@ static void create_pack_file(struct upload_pack_data *pack_data,
 	}
 
 	/* flush the data */
-	if (output_state->used > 0) {
+	if (output_state->used > 0)
 		send_client_data(1, output_state->buffer, output_state->used,
 				 pack_data->use_sideband);
-		fprintf(stderr, "flushed.\n");
-	}
 	free(output_state);
 	if (pack_data->use_sideband)
 		packet_flush(1);
diff --git a/worktree.c b/worktree.c
index e9ff6e6..56732f8 100644
--- a/worktree.c
+++ b/worktree.c
@@ -445,7 +445,7 @@ void update_worktree_location(struct worktree *wt, const char *path_,
 	strbuf_realpath(&path, path_, 1);
 	strbuf_addf(&dotgit, "%s/.git", path.buf);
 	if (fspathcmp(wt->path, path.buf)) {
-		write_worktree_linking_files(dotgit, gitdir, use_relative_paths);
+		write_worktree_linking_files(dotgit.buf, gitdir.buf, use_relative_paths);
 
 		free(wt->path);
 		wt->path = strbuf_detach(&path, NULL);
@@ -673,7 +673,8 @@ static void repair_gitfile(struct worktree *wt,
 		}
 	}
 
-	if (err == READ_GITFILE_ERR_NOT_A_FILE)
+	if (err == READ_GITFILE_ERR_NOT_A_FILE ||
+		err == READ_GITFILE_ERR_IS_A_DIR)
 		fn(1, wt->path, _(".git is not a file"), cb_data);
 	else if (err)
 		repair = _(".git file broken");
@@ -684,7 +685,7 @@ static void repair_gitfile(struct worktree *wt,
 
 	if (repair) {
 		fn(0, wt->path, repair, cb_data);
-		write_worktree_linking_files(dotgit, gitdir, use_relative_paths);
+		write_worktree_linking_files(dotgit.buf, gitdir.buf, use_relative_paths);
 	}
 
 done:
@@ -742,7 +743,7 @@ void repair_worktree_after_gitdir_move(struct worktree *wt, const char *old_path
 	if (!file_exists(dotgit.buf))
 		goto done;
 
-	write_worktree_linking_files(dotgit, gitdir, is_relative_path);
+	write_worktree_linking_files(dotgit.buf, gitdir.buf, is_relative_path);
 done:
 	strbuf_release(&gitdir);
 	strbuf_release(&dotgit);
@@ -853,7 +854,8 @@ void repair_worktree_at_path(const char *path,
 			strbuf_addstr(&backlink, dotgit_contents);
 			strbuf_realpath_forgiving(&backlink, backlink.buf, 0);
 		}
-	} else if (err == READ_GITFILE_ERR_NOT_A_FILE) {
+	} else if (err == READ_GITFILE_ERR_NOT_A_FILE ||
+			err == READ_GITFILE_ERR_IS_A_DIR) {
 		fn(1, dotgit.buf, _("unable to locate repository; .git is not a file"), cb_data);
 		goto done;
 	} else if (err == READ_GITFILE_ERR_NOT_A_REPO) {
@@ -913,7 +915,7 @@ void repair_worktree_at_path(const char *path,
 
 	if (repair) {
 		fn(0, gitdir.buf, repair, cb_data);
-		write_worktree_linking_files(dotgit, gitdir, use_relative_paths);
+		write_worktree_linking_files(dotgit.buf, gitdir.buf, use_relative_paths);
 	}
 done:
 	free(dotgit_contents);
@@ -1087,17 +1089,17 @@ int init_worktree_config(struct repository *r)
 	return res;
 }
 
-void write_worktree_linking_files(struct strbuf dotgit, struct strbuf gitdir,
+void write_worktree_linking_files(const char *dotgit, const char *gitdir,
 				  int use_relative_paths)
 {
 	struct strbuf path = STRBUF_INIT;
 	struct strbuf repo = STRBUF_INIT;
 	struct strbuf tmp = STRBUF_INIT;
 
-	strbuf_addbuf(&path, &dotgit);
+	strbuf_addstr(&path, dotgit);
 	strbuf_strip_suffix(&path, "/.git");
 	strbuf_realpath(&path, path.buf, 1);
-	strbuf_addbuf(&repo, &gitdir);
+	strbuf_addstr(&repo, gitdir);
 	strbuf_strip_suffix(&repo, "/gitdir");
 	strbuf_realpath(&repo, repo.buf, 1);
 
@@ -1110,11 +1112,11 @@ void write_worktree_linking_files(struct strbuf dotgit, struct strbuf gitdir,
 	}
 
 	if (use_relative_paths) {
-		write_file(gitdir.buf, "%s/.git", relative_path(path.buf, repo.buf, &tmp));
-		write_file(dotgit.buf, "gitdir: %s", relative_path(repo.buf, path.buf, &tmp));
+		write_file(gitdir, "%s/.git", relative_path(path.buf, repo.buf, &tmp));
+		write_file(dotgit, "gitdir: %s", relative_path(repo.buf, path.buf, &tmp));
 	} else {
-		write_file(gitdir.buf, "%s/.git", path.buf);
-		write_file(dotgit.buf, "gitdir: %s", repo.buf);
+		write_file(gitdir, "%s/.git", path.buf);
+		write_file(dotgit, "gitdir: %s", repo.buf);
 	}
 
 	strbuf_release(&path);
diff --git a/worktree.h b/worktree.h
index e450d1a..026ef30 100644
--- a/worktree.h
+++ b/worktree.h
@@ -240,7 +240,7 @@ int init_worktree_config(struct repository *r);
  *  dotgit: "/path/to/foo/.git"
  *  gitdir: "/path/to/repo/worktrees/foo/gitdir"
  */
-void write_worktree_linking_files(struct strbuf dotgit, struct strbuf gitdir,
+void write_worktree_linking_files(const char *dotgit, const char *gitdir,
 				  int use_relative_paths);
 
 #endif
diff --git a/wrapper.c b/wrapper.c
index 16f5a63..be8fa57 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -323,6 +323,47 @@ ssize_t write_in_full(int fd, const void *buf, size_t count)
 	return total;
 }
 
+ssize_t writev_in_full(int fd, struct iovec *iov, int iovcnt)
+{
+	ssize_t total_written = 0;
+
+	while (iovcnt) {
+		ssize_t bytes_written = writev(fd, iov, iovcnt);
+		if (bytes_written < 0) {
+			if (errno == EINTR || errno == EAGAIN)
+				continue;
+			return -1;
+		}
+		if (!bytes_written) {
+			errno = ENOSPC;
+			return -1;
+		}
+
+		total_written += bytes_written;
+
+		/*
+		 * We first need to discard any iovec entities that have been
+		 * fully written.
+		 */
+		while (iovcnt && (size_t)bytes_written >= iov->iov_len) {
+			bytes_written -= iov->iov_len;
+			iov++;
+			iovcnt--;
+		}
+
+		/*
+		 * Finally, we need to adjust the last iovec in case we have
+		 * performed a partial write.
+		 */
+		if (iovcnt && bytes_written) {
+			iov->iov_base = (char *) iov->iov_base + bytes_written;
+			iov->iov_len -= bytes_written;
+		}
+	}
+
+	return total_written;
+}
+
 ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset)
 {
 	char *p = buf;
diff --git a/wrapper.h b/wrapper.h
index 15ac3ba..27519b3 100644
--- a/wrapper.h
+++ b/wrapper.h
@@ -47,6 +47,15 @@ ssize_t read_in_full(int fd, void *buf, size_t count);
 ssize_t write_in_full(int fd, const void *buf, size_t count);
 ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset);
 
+/*
+ * Try to write all iovecs. Returns -1 in case an error occurred with a proper
+ * errno set, the number of bytes written otherwise.
+ *
+ * Note that the iovec will be modified as a result of this call to adjust for
+ * partial writes!
+ */
+ssize_t writev_in_full(int fd, struct iovec *iov, int iovcnt);
+
 static inline ssize_t write_str_in_full(int fd, const char *str)
 {
 	return write_in_full(fd, str, strlen(str));
diff --git a/write-or-die.c b/write-or-die.c
index 01a9a51..5f522fb 100644
--- a/write-or-die.c
+++ b/write-or-die.c
@@ -96,6 +96,14 @@ void write_or_die(int fd, const void *buf, size_t count)
 	}
 }
 
+void writev_or_die(int fd, struct iovec *iov, int iovlen)
+{
+	if (writev_in_full(fd, iov, iovlen) < 0) {
+		check_pipe(errno);
+		die_errno("writev error");
+	}
+}
+
 void fwrite_or_die(FILE *f, const void *buf, size_t count)
 {
 	if (fwrite(buf, 1, count, f) != count)
diff --git a/write-or-die.h b/write-or-die.h
index ff0408b..a045bdf 100644
--- a/write-or-die.h
+++ b/write-or-die.h
@@ -7,6 +7,7 @@ void fprintf_or_die(FILE *, const char *fmt, ...);
 void fwrite_or_die(FILE *f, const void *buf, size_t count);
 void fflush_or_die(FILE *f);
 void write_or_die(int fd, const void *buf, size_t count);
+void writev_or_die(int fd, struct iovec *iov, int iovlen);
 
 /*
  * These values are used to help identify parts of a repository to fsync.
diff --git a/wt-status.c b/wt-status.c
index 5430003..479ccc3 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -150,11 +150,11 @@ void wt_status_prepare(struct repository *r, struct wt_status *s)
 	s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
 	s->use_color = GIT_COLOR_UNKNOWN;
 	s->relative_paths = 1;
-	s->branch = refs_resolve_refdup(get_main_ref_store(the_repository),
+	s->branch = refs_resolve_refdup(get_main_ref_store(r),
 					"HEAD", 0, NULL, NULL);
 	s->reference = "HEAD";
 	s->fp = stdout;
-	s->index_file = repo_get_index_file(the_repository);
+	s->index_file = repo_get_index_file(r);
 	s->change.strdup_strings = 1;
 	s->untracked.strdup_strings = 1;
 	s->ignored.strdup_strings = 1;
@@ -670,7 +670,7 @@ static void wt_status_collect_changes_index(struct wt_status *s)
 
 	repo_init_revisions(s->repo, &rev, NULL);
 	memset(&opt, 0, sizeof(opt));
-	opt.def = s->is_initial ? empty_tree_oid_hex(the_repository->hash_algo) : s->reference;
+	opt.def = s->is_initial ? empty_tree_oid_hex(s->repo->hash_algo) : s->reference;
 	setup_revisions(0, NULL, &rev, &opt);
 
 	rev.diffopt.flags.override_submodule_config = 1;
@@ -1008,17 +1008,17 @@ static int stash_count_refs(const char *refname UNUSED,
 	return 0;
 }
 
-static int count_stash_entries(void)
+static int count_stash_entries(struct repository *r)
 {
 	int n = 0;
-	refs_for_each_reflog_ent(get_main_ref_store(the_repository),
+	refs_for_each_reflog_ent(get_main_ref_store(r),
 				 "refs/stash", stash_count_refs, &n);
 	return n;
 }
 
 static void wt_longstatus_print_stash_summary(struct wt_status *s)
 {
-	int stash_count = count_stash_entries();
+	int stash_count = count_stash_entries(s->repo);
 
 	if (stash_count > 0)
 		status_printf_ln(s, GIT_COLOR_NORMAL,
@@ -1170,7 +1170,7 @@ static void wt_longstatus_print_verbose(struct wt_status *s)
 	rev.diffopt.ita_invisible_in_index = 1;
 
 	memset(&opt, 0, sizeof(opt));
-	opt.def = s->is_initial ? empty_tree_oid_hex(the_repository->hash_algo) : s->reference;
+	opt.def = s->is_initial ? empty_tree_oid_hex(s->repo->hash_algo) : s->reference;
 	setup_revisions(0, NULL, &rev, &opt);
 
 	rev.diffopt.output_format |= DIFF_FORMAT_PATCH;
@@ -1311,10 +1311,10 @@ static void show_am_in_progress(struct wt_status *s,
 	wt_longstatus_print_trailer(s);
 }
 
-static char *read_line_from_git_path(const char *filename)
+static char *read_line_from_git_path(struct repository *r, const char *filename)
 {
 	struct strbuf buf = STRBUF_INIT;
-	FILE *fp = fopen_or_warn(repo_git_path_append(the_repository, &buf,
+	FILE *fp = fopen_or_warn(repo_git_path_append(r, &buf,
 						      "%s", filename), "r");
 
 	if (!fp) {
@@ -1341,16 +1341,16 @@ static int split_commit_in_progress(struct wt_status *s)
 	    !s->branch || strcmp(s->branch, "HEAD"))
 		return 0;
 
-	if (refs_read_ref_full(get_main_ref_store(the_repository), "HEAD", RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
+	if (refs_read_ref_full(get_main_ref_store(s->repo), "HEAD", RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
 			       &head_oid, &head_flags) ||
-	    refs_read_ref_full(get_main_ref_store(the_repository), "ORIG_HEAD", RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
+	    refs_read_ref_full(get_main_ref_store(s->repo), "ORIG_HEAD", RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
 			       &orig_head_oid, &orig_head_flags))
 		return 0;
 	if (head_flags & REF_ISSYMREF || orig_head_flags & REF_ISSYMREF)
 		return 0;
 
-	rebase_amend = read_line_from_git_path("rebase-merge/amend");
-	rebase_orig_head = read_line_from_git_path("rebase-merge/orig-head");
+	rebase_amend = read_line_from_git_path(s->repo, "rebase-merge/amend");
+	rebase_orig_head = read_line_from_git_path(s->repo, "rebase-merge/orig-head");
 
 	if (!rebase_amend || !rebase_orig_head)
 		; /* fall through, no split in progress */
@@ -1374,7 +1374,7 @@ static int split_commit_in_progress(struct wt_status *s)
  * The function assumes that the line does not contain useless spaces
  * before or after the command.
  */
-static void abbrev_oid_in_line(struct strbuf *line)
+static void abbrev_oid_in_line(struct repository *r, struct strbuf *line)
 {
 	struct string_list split = STRING_LIST_INIT_DUP;
 	struct object_id oid;
@@ -1386,7 +1386,7 @@ static void abbrev_oid_in_line(struct strbuf *line)
 		return;
 
 	if ((2 <= string_list_split(&split, line->buf, " ", 2)) &&
-	    !repo_get_oid(the_repository, split.items[1].string, &oid)) {
+	    !repo_get_oid(r, split.items[1].string, &oid)) {
 		strbuf_reset(line);
 		strbuf_addf(line, "%s ", split.items[0].string);
 		strbuf_add_unique_abbrev(line, &oid, DEFAULT_ABBREV);
@@ -1396,10 +1396,10 @@ static void abbrev_oid_in_line(struct strbuf *line)
 	string_list_clear(&split, 0);
 }
 
-static int read_rebase_todolist(const char *fname, struct string_list *lines)
+static int read_rebase_todolist(struct repository *r, const char *fname, struct string_list *lines)
 {
 	struct strbuf buf = STRBUF_INIT;
-	FILE *f = fopen(repo_git_path_append(the_repository, &buf, "%s", fname), "r");
+	FILE *f = fopen(repo_git_path_append(r, &buf, "%s", fname), "r");
 	int ret;
 
 	if (!f) {
@@ -1408,7 +1408,7 @@ static int read_rebase_todolist(const char *fname, struct string_list *lines)
 			goto out;
 		}
 		die_errno("Could not open file %s for reading",
-			  repo_git_path_replace(the_repository, &buf, "%s", fname));
+			  repo_git_path_replace(r, &buf, "%s", fname));
 	}
 	while (!strbuf_getline_lf(&buf, f)) {
 		if (starts_with(buf.buf, comment_line_str))
@@ -1416,7 +1416,7 @@ static int read_rebase_todolist(const char *fname, struct string_list *lines)
 		strbuf_trim(&buf);
 		if (!buf.len)
 			continue;
-		abbrev_oid_in_line(&buf);
+		abbrev_oid_in_line(r, &buf);
 		string_list_append(lines, buf.buf);
 	}
 	fclose(f);
@@ -1437,8 +1437,8 @@ static void show_rebase_information(struct wt_status *s,
 		struct string_list have_done = STRING_LIST_INIT_DUP;
 		struct string_list yet_to_do = STRING_LIST_INIT_DUP;
 
-		read_rebase_todolist("rebase-merge/done", &have_done);
-		if (read_rebase_todolist("rebase-merge/git-rebase-todo",
+		read_rebase_todolist(s->repo, "rebase-merge/done", &have_done);
+		if (read_rebase_todolist(s->repo, "rebase-merge/git-rebase-todo",
 					 &yet_to_do))
 			status_printf_ln(s, color,
 				_("git-rebase-todo is missing."));
@@ -1456,7 +1456,7 @@ static void show_rebase_information(struct wt_status *s,
 				i++)
 				status_printf_ln(s, color, "   %s", have_done.items[i].string);
 			if (have_done.nr > nr_lines_to_show && s->hints) {
-				char *path = repo_git_path(the_repository, "rebase-merge/done");
+				char *path = repo_git_path(s->repo, "rebase-merge/done");
 				status_printf_ln(s, color,
 					_("  (see more in file %s)"), path);
 				free(path);
@@ -1558,7 +1558,7 @@ static void show_cherry_pick_in_progress(struct wt_status *s,
 	else
 		status_printf_ln(s, color,
 			_("You are currently cherry-picking commit %s."),
-			repo_find_unique_abbrev(the_repository, &s->state.cherry_pick_head_oid,
+			repo_find_unique_abbrev(s->repo, &s->state.cherry_pick_head_oid,
 						DEFAULT_ABBREV));
 
 	if (s->hints) {
@@ -1588,7 +1588,7 @@ static void show_revert_in_progress(struct wt_status *s,
 	else
 		status_printf_ln(s, color,
 			_("You are currently reverting commit %s."),
-			repo_find_unique_abbrev(the_repository, &s->state.revert_head_oid,
+			repo_find_unique_abbrev(s->repo, &s->state.revert_head_oid,
 						DEFAULT_ABBREV));
 	if (s->hints) {
 		if (has_unmerged(s))
@@ -1715,7 +1715,7 @@ static void wt_status_get_detached_from(struct repository *r,
 	char *ref = NULL;
 
 	strbuf_init(&cb.buf, 0);
-	if (refs_for_each_reflog_ent_reverse(get_main_ref_store(the_repository), "HEAD", grab_1st_switch, &cb) <= 0) {
+	if (refs_for_each_reflog_ent_reverse(get_main_ref_store(r), "HEAD", grab_1st_switch, &cb) <= 0) {
 		strbuf_release(&cb.buf);
 		return;
 	}
@@ -1848,10 +1848,10 @@ void wt_status_get_state(struct repository *r,
 	if (!sequencer_get_last_command(r, &action)) {
 		if (action == REPLAY_PICK && !state->cherry_pick_in_progress) {
 			state->cherry_pick_in_progress = 1;
-			oidcpy(&state->cherry_pick_head_oid, null_oid(the_hash_algo));
+			oidcpy(&state->cherry_pick_head_oid, null_oid(r->hash_algo));
 		} else if (action == REPLAY_REVERT && !state->revert_in_progress) {
 			state->revert_in_progress = 1;
-			oidcpy(&state->revert_head_oid, null_oid(the_hash_algo));
+			oidcpy(&state->revert_head_oid, null_oid(r->hash_algo));
 		}
 	}
 	if (get_detached_from)
@@ -2134,7 +2134,7 @@ static void wt_shortstatus_print_tracking(struct wt_status *s)
 		upstream_is_gone = 1;
 	}
 
-	short_base = refs_shorten_unambiguous_ref(get_main_ref_store(the_repository),
+	short_base = refs_shorten_unambiguous_ref(get_main_ref_store(s->repo),
 						  base, 0);
 	color_fprintf(s->fp, header_color, "...");
 	color_fprintf(s->fp, branch_color_remote, "%s", short_base);
@@ -2268,7 +2268,7 @@ static void wt_porcelain_v2_print_tracking(struct wt_status *s)
 		ab_info = stat_tracking_info(branch, &nr_ahead, &nr_behind,
 					     &base, 0, s->ahead_behind_flags);
 		if (base) {
-			base = refs_shorten_unambiguous_ref(get_main_ref_store(the_repository),
+			base = refs_shorten_unambiguous_ref(get_main_ref_store(s->repo),
 							    base, 0);
 			fprintf(s->fp, "# branch.upstream %s%c", base, eol);
 			free((char *)base);
@@ -2294,7 +2294,7 @@ static void wt_porcelain_v2_print_tracking(struct wt_status *s)
  */
 static void wt_porcelain_v2_print_stash(struct wt_status *s)
 {
-	int stash_count = count_stash_entries();
+	int stash_count = count_stash_entries(s->repo);
 	char eol = s->null_termination ? '\0' : '\n';
 
 	if (stash_count > 0)
@@ -2665,7 +2665,7 @@ int has_uncommitted_changes(struct repository *r,
 		 * We have no head (or it's corrupt); use the empty tree,
 		 * which will complain if the index is non-empty.
 		 */
-		struct tree *tree = lookup_tree(r, the_hash_algo->empty_tree);
+		struct tree *tree = lookup_tree(r, r->hash_algo->empty_tree);
 		add_pending_object(&rev_info, &tree->object, "");
 	}
 
diff --git a/xdiff/xdiffi.c b/xdiff/xdiffi.c
index 4376f94..5455b46 100644
--- a/xdiff/xdiffi.c
+++ b/xdiff/xdiffi.c
@@ -792,6 +792,7 @@ static int group_slide_up(xdfile_t *xdf, struct xdlgroup *g)
  */
 int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo, long flags) {
 	struct xdlgroup g, go;
+	struct xdlgroup g_orig;
 	long earliest_end, end_matching_other;
 	long groupsize;
 
@@ -805,10 +806,12 @@ int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo, long flags) {
 		if (g.end == g.start)
 			goto next;
 
+		g_orig = g;
+
 		/*
 		 * Now shift the change up and then down as far as possible in
 		 * each direction. If it bumps into any other changes, merge
-		 * them.
+		 * them and restart the process.
 		 */
 		do {
 			groupsize = g.end - g.start;
@@ -861,7 +864,8 @@ int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo, long flags) {
 			/*
 			 * Move the possibly merged group of changes back to
 			 * line up with the last group of changes from the
-			 * other file that it can align with.
+			 * other file that it can align with. This avoids breaking
+			 * a single change into a separate addition/deletion.
 			 */
 			while (go.end == go.start) {
 				if (group_slide_up(xdf, &g))
@@ -914,6 +918,45 @@ int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo, long flags) {
 			}
 		}
 
+		/*
+		 * If we merged change groups during shifting, the new
+		 * combined group could now have matching lines in both files,
+		 * even if the original separate groups did not. Re-diff the
+		 * new group to find these matching lines to mark them as
+		 * unchanged.
+		 *
+		 * Only do this if the corresponding group in the other file is
+		 * non-empty, as it's trivial otherwise.
+		 *
+		 * Only do this for histogram diff as its LCS algorithm allows
+		 * for this scenario. In contrast, patience diff finds LCS
+		 * of unique lines that groups cannot be shifted across.
+		 * Myer's diff (standalone or used as fall-back in patience
+		 * diff) already finds minimal edits so it is not possible for
+		 * shifted groups to result in a smaller diff. (Without
+		 * XDF_NEED_MINIMAL, Myer's isn't technically guaranteed to be
+		 * minimal, but it should be so most of the time)
+		 */
+		if (go.end != go.start &&
+				XDF_DIFF_ALG(flags) == XDF_HISTOGRAM_DIFF &&
+				(g.start != g_orig.start ||
+				 g.end != g_orig.end)) {
+			xpparam_t xpp;
+			xdfenv_t xe;
+
+			memset(&xpp, 0, sizeof(xpp));
+			xpp.flags = flags & ~XDF_DIFF_ALGORITHM_MASK;
+
+			xe.xdf1 = *xdf;
+			xe.xdf2 = *xdfo;
+
+			if (xdl_fall_back_diff(&xe, &xpp,
+					       g.start + 1, g.end - g.start,
+					       go.start + 1, go.end - go.start)) {
+				return -1;
+			}
+		}
+
 	next:
 		/* Move past the just-processed group: */
 		if (group_next(xdf, &g))