aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/RelNotes/2.40.0.txt18
-rw-r--r--Documentation/git-apply.txt2
-rw-r--r--Documentation/git-checkout.txt14
-rw-r--r--Documentation/git-credential-cache.txt11
-rw-r--r--Documentation/git-ls-files.txt79
-rw-r--r--Documentation/git-read-tree.txt2
-rw-r--r--Documentation/git-rebase.txt77
-rw-r--r--Documentation/git.txt2
-rw-r--r--Documentation/gitformat-signature.txt2
-rw-r--r--Documentation/pretty-formats.txt32
-rw-r--r--Documentation/technical/hash-function-transition.txt2
-rw-r--r--Documentation/technical/rerere.txt2
-rw-r--r--attr.h2
-rw-r--r--builtin/rebase.c79
-rw-r--r--fsck.c94
-rw-r--r--fsck.h8
-rwxr-xr-xgit-request-pull.sh2
-rw-r--r--gpg-interface.c6
-rw-r--r--object-file.c55
-rwxr-xr-xt/t0003-attributes.sh4
-rwxr-xr-xt/t1006-cat-file.sh6
-rwxr-xr-xt/t1007-hash-object.sh29
-rwxr-xr-xt/t1450-fsck.sh28
-rwxr-xr-xt/t1451-fsck-buffer.sh140
-rwxr-xr-xt/t3422-rebase-incompatible-options.sh71
-rwxr-xr-xt/t4054-diff-bogus-tree.sh2
-rwxr-xr-xt/t4058-diff-duplicates.sh2
-rwxr-xr-xt/t4205-log-pretty-formats.sh27
-rwxr-xr-xt/t4212-log-corrupt.sh4
-rwxr-xr-xt/t5302-pack-index.sh2
-rwxr-xr-xt/t5504-fetch-receive-strict.sh2
-rwxr-xr-xt/t5702-protocol-v2.sh2
-rwxr-xr-xt/t6300-for-each-ref.sh2
-rwxr-xr-xt/t7030-verify-tag.sh2
-rwxr-xr-xt/t7031-verify-tag-signed-ssh.sh2
-rwxr-xr-xt/t7509-commit-authorship.sh2
-rwxr-xr-xt/t7510-signed-commit.sh2
-rwxr-xr-xt/t7528-signed-commit-ssh.sh2
-rwxr-xr-xt/t8003-blame-corner-cases.sh2
-rwxr-xr-xt/t9350-fast-export.sh2
40 files changed, 605 insertions, 219 deletions
diff --git a/Documentation/RelNotes/2.40.0.txt b/Documentation/RelNotes/2.40.0.txt
index 01f539ec0b..7ddfafc2e1 100644
--- a/Documentation/RelNotes/2.40.0.txt
+++ b/Documentation/RelNotes/2.40.0.txt
@@ -43,6 +43,9 @@ UI, Workflows & Features
* "grep -P" learned to use Unicode Character Property to grok
character classes when processing \b and \w etc.
+ * "git rebase" often ignored incompatible options instead of
+ complaining, which has been corrected.
+
Performance, Internal Implementation, Development Support etc.
@@ -189,6 +192,18 @@ Fixes since v2.39
enabled, which has been corrected.
(merge 06a668cb90 cw/fetch-remote-group-with-duplication later to maint).
+ * Clarify how "checkout -b/-B" and "git branch [-f]" are similar but
+ different in the documentation.
+ (merge fedb8ea2df jc/doc-checkout-b later to maint).
+
+ * "git hash-object" now checks that the resulting object is well
+ formed with the same code as "git fsck".
+ (merge 8e4309038f jk/hash-object-fsck later to maint).
+
+ * Improve the error message given when private key is not loaded in
+ the ssh agent in the codepath to sign with an ssh key.
+ (merge dce7b31126 as/ssh-signing-improve-key-missing-error later to maint).
+
* Other code cleanup, docfix, build fix, etc.
(merge 77e04b2ed4 rs/t4205-do-not-exit-in-test-script later to maint).
(merge faebba436e rs/plug-pattern-list-leak-in-lof later to maint).
@@ -219,3 +234,6 @@ Fixes since v2.39
(merge dcb47e52b0 en/t6426-todo-cleanup later to maint).
(merge 5b8db44bdd jc/format-patch-v-unleak later to maint).
(merge 590b636737 jk/hash-object-literally-fd-leak later to maint).
+ (merge 5458ba0a4d tb/t0003-invoke-dd-more-portably later to maint).
+ (merge 70661d288b ar/markup-em-dash later to maint).
+ (merge e750951e74 en/ls-files-doc-update later to maint).
diff --git a/Documentation/git-apply.txt b/Documentation/git-apply.txt
index 1d478cbe9b..5e16e6db7e 100644
--- a/Documentation/git-apply.txt
+++ b/Documentation/git-apply.txt
@@ -208,7 +208,7 @@ behavior:
* `warn` outputs warnings for a few such errors, but applies the
patch as-is (default).
* `fix` outputs warnings for a few such errors, and applies the
- patch after fixing them (`strip` is a synonym --- the tool
+ patch after fixing them (`strip` is a synonym -- the tool
used to consider only trailing whitespace characters as errors, and the
fix involved 'stripping' them, but modern Gits do more).
* `error` outputs warnings for a few such errors, and refuses
diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index 9f116acdbd..6bb32ab460 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -146,14 +146,16 @@ on your side branch as `theirs` (i.e. "one contributor's work on top
of it").
-b <new-branch>::
- Create a new branch named `<new-branch>` and start it at
- `<start-point>`; see linkgit:git-branch[1] for details.
+ Create a new branch named `<new-branch>`, start it at
+ `<start-point>`, and check the resulting branch out;
+ see linkgit:git-branch[1] for details.
-B <new-branch>::
- Creates the branch `<new-branch>` and start it at `<start-point>`;
- if it already exists, then reset it to `<start-point>`. This is
- equivalent to running "git branch" with "-f"; see
- linkgit:git-branch[1] for details.
+ Creates the branch `<new-branch>`, start it at `<start-point>`;
+ if it already exists, then reset it to `<start-point>`. And then
+ check the resulting branch out. This is equivalent to running
+ "git branch" with "-f" followed by "git checkout" of that branch;
+ see linkgit:git-branch[1] for details.
-t::
--track[=(direct|inherit)]::
diff --git a/Documentation/git-credential-cache.txt b/Documentation/git-credential-cache.txt
index 432e159d95..f473994a86 100644
--- a/Documentation/git-credential-cache.txt
+++ b/Documentation/git-credential-cache.txt
@@ -14,10 +14,13 @@ git config credential.helper 'cache [<options>]'
DESCRIPTION
-----------
-This command caches credentials in memory for use by future Git
-programs. The stored credentials never touch the disk, and are forgotten
-after a configurable timeout. The cache is accessible over a Unix
-domain socket, restricted to the current user by filesystem permissions.
+This command caches credentials for use by future Git programs.
+The stored credentials are kept in memory of the cache-daemon
+process (instead of written to a file) and are forgotten after a
+configurable timeout. Credentials are forgotten sooner if the
+cache-daemon dies, for example if the system restarts. The cache
+is accessible over a Unix domain socket, restricted to the current
+user by filesystem permissions.
You probably don't want to invoke this command directly; it is meant to
be used as a credential helper by other parts of Git. See
diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt
index 440043cdb8..1abdd3c21c 100644
--- a/Documentation/git-ls-files.txt
+++ b/Documentation/git-ls-files.txt
@@ -12,6 +12,7 @@ SYNOPSIS
'git ls-files' [-z] [-t] [-v] [-f]
[-c|--cached] [-d|--deleted] [-o|--others] [-i|--ignored]
[-s|--stage] [-u|--unmerged] [-k|--killed] [-m|--modified]
+ [--resolve-undo]
[--directory [--no-empty-directory]] [--eol]
[--deduplicate]
[-x <pattern>|--exclude=<pattern>]
@@ -28,21 +29,26 @@ This merges the file listing in the index with the actual working
directory list, and shows different combinations of the two.
One or more of the options below may be used to determine the files
-shown:
+shown, and each file may be printed multiple times if there are
+multiple entries in the index or multiple statuses are applicable for
+the relevant file selection options.
OPTIONS
-------
-c::
--cached::
- Show cached files in the output (default)
+ Show all files cached in Git's index, i.e. all tracked files.
+ (This is the default if no -c/-s/-d/-o/-u/-k/-m/--resolve-undo
+ options are specified.)
-d::
--deleted::
- Show deleted files in the output
+ Show files with an unstaged deletion
-m::
--modified::
- Show modified files in the output
+ Show files with an unstaged modification (note that an unstaged
+ deletion also counts as an unstaged modification)
-o::
--others::
@@ -50,11 +56,14 @@ OPTIONS
-i::
--ignored::
- Show only ignored files in the output. When showing files in the
- index, print only those matched by an exclude pattern. When
- showing "other" files, show only those matched by an exclude
- pattern. Standard ignore rules are not automatically activated,
- therefore at least one of the `--exclude*` options is required.
+ Show only ignored files in the output. Must be used with
+ either an explicit '-c' or '-o'. When showing files in the
+ index (i.e. when used with '-c'), print only those files
+ matching an exclude pattern. When showing "other" files
+ (i.e. when used with '-o'), show only those matched by an
+ exclude pattern. Standard ignore rules are not automatically
+ activated, therefore at least one of the `--exclude*` options
+ is required.
-s::
--stage::
@@ -63,19 +72,29 @@ OPTIONS
--directory::
If a whole directory is classified as "other", show just its
name (with a trailing slash) and not its whole contents.
+ Has no effect without -o/--others.
--no-empty-directory::
Do not list empty directories. Has no effect without --directory.
-u::
--unmerged::
- Show unmerged files in the output (forces --stage)
+ Show information about unmerged files in the output, but do
+ not show any other tracked files (forces --stage, overrides
+ --cached).
-k::
--killed::
- Show files on the filesystem that need to be removed due
- to file/directory conflicts for checkout-index to
- succeed.
+ Show untracked files on the filesystem that need to be removed
+ due to file/directory conflicts for tracked files to be able to
+ be written to the filesystem.
+
+--resolve-undo::
+ Show files having resolve-undo information in the index
+ together with their resolve-undo information. (resolve-undo
+ information is what is used to implement "git checkout -m
+ $PATH", i.e. to recreate merge conflicts that were
+ accidentally resolved)
-z::
\0 line termination on output and do not quote filenames.
@@ -100,7 +119,8 @@ OPTIONS
--exclude-per-directory=<file>::
Read additional exclude patterns that apply only to the
- directory and its subdirectories in <file>.
+ directory and its subdirectories in <file>. Deprecated; use
+ --exclude-standard instead.
--exclude-standard::
Add the standard Git exclusions: .git/info/exclude, .gitignore
@@ -118,24 +138,27 @@ OPTIONS
with `-s` or `-u` options does not make any sense.
-t::
- This feature is semi-deprecated. For scripting purpose,
- linkgit:git-status[1] `--porcelain` and
+ Show status tags together with filenames. Note that for
+ scripting purposes, linkgit:git-status[1] `--porcelain` and
linkgit:git-diff-files[1] `--name-status` are almost always
superior alternatives, and users should look at
linkgit:git-status[1] `--short` or linkgit:git-diff[1]
`--name-status` for more user-friendly alternatives.
+
--
-This option identifies the file status with the following tags (followed by
-a space) at the start of each line:
-
- H:: cached
- S:: skip-worktree
- M:: unmerged
- R:: removed/deleted
- C:: modified/changed
- K:: to be killed
- ?:: other
+This option provides a reason for showing each filename, in the form
+of a status tag (which is followed by a space and then the filename).
+The status tags are all single characters from the following list:
+
+ H:: tracked file that is not either unmerged or skip-worktree
+ S:: tracked file that is skip-worktree
+ M:: tracked file that is unmerged
+ R:: tracked file with unstaged removal/deletion
+ C:: tracked file with unstaged modification/change
+ K:: untracked paths which are part of file/directory conflicts
+ which prevent checking out tracked files
+ ?:: untracked file
+ U:: file with resolve-undo information
--
-v::
@@ -269,7 +292,9 @@ traversing the directory tree and finding files to show when the
flags --others or --ignored are specified. linkgit:gitignore[5]
specifies the format of exclude patterns.
-These exclude patterns come from these places, in order:
+Generally, you should just use --exclude-standard, but for historical
+reasons the exclude patterns can be specified from the following
+places, in order:
1. The command-line flag --exclude=<pattern> specifies a
single pattern. Patterns are ordered in the same order
diff --git a/Documentation/git-read-tree.txt b/Documentation/git-read-tree.txt
index 7567955bad..b09707474d 100644
--- a/Documentation/git-read-tree.txt
+++ b/Documentation/git-read-tree.txt
@@ -219,7 +219,7 @@ see which of the "local changes" that you made were carried forward by running
`git diff-index --cached $M`. Note that this does not
necessarily match what `git diff-index --cached $H` would have
produced before such a two tree merge. This is because of cases
-18 and 19 --- if you already had the changes in $M (e.g. maybe
+18 and 19 -- if you already had the changes in $M (e.g. maybe
you picked it up via e-mail in a patch form), `git diff-index
--cached $H` would have told you about the change before this
merge, but it would not show in `git diff-index --cached $M`
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index d811c1cf44..9a295bcee4 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -208,6 +208,39 @@ Alternatively, you can undo the 'git rebase' with
git rebase --abort
+MODE OPTIONS
+------------
+
+The options in this section cannot be used with any other option,
+including not with each other:
+
+--continue::
+ Restart the rebasing process after having resolved a merge conflict.
+
+--skip::
+ Restart the rebasing process by skipping the current patch.
+
+--abort::
+ Abort the rebase operation and reset HEAD to the original
+ branch. If `<branch>` was provided when the rebase operation was
+ started, then `HEAD` will be reset to `<branch>`. Otherwise `HEAD`
+ will be reset to where it was when the rebase operation was
+ started.
+
+--quit::
+ Abort the rebase operation but `HEAD` is not reset back to the
+ original branch. The index and working tree are also left
+ unchanged as a result. If a temporary stash entry was created
+ using `--autostash`, it will be saved to the stash list.
+
+--edit-todo::
+ Edit the todo list during an interactive rebase.
+
+--show-current-patch::
+ Show the current patch in an interactive rebase or when rebase
+ is stopped because of conflicts. This is the equivalent of
+ `git show REBASE_HEAD`.
+
OPTIONS
-------
--onto <newbase>::
@@ -249,22 +282,6 @@ See also INCOMPATIBLE OPTIONS below.
<branch>::
Working branch; defaults to `HEAD`.
---continue::
- Restart the rebasing process after having resolved a merge conflict.
-
---abort::
- Abort the rebase operation and reset HEAD to the original
- branch. If `<branch>` was provided when the rebase operation was
- started, then `HEAD` will be reset to `<branch>`. Otherwise `HEAD`
- will be reset to where it was when the rebase operation was
- started.
-
---quit::
- Abort the rebase operation but `HEAD` is not reset back to the
- original branch. The index and working tree are also left
- unchanged as a result. If a temporary stash entry was created
- using `--autostash`, it will be saved to the stash list.
-
--apply::
Use applying strategies to rebase (calling `git-am`
internally). This option may become a no-op in the future
@@ -321,7 +338,6 @@ See also INCOMPATIBLE OPTIONS below.
upstream changes, the behavior towards them is controlled by
the `--empty` flag.)
+
-
In the absence of `--keep-base` (or if `--no-reapply-cherry-picks` is
given), these commits will be automatically dropped. Because this
necessitates reading all upstream commits, this can be expensive in
@@ -330,7 +346,6 @@ read. When using the 'merge' backend, warnings will be issued for each
dropped commit (unless `--quiet` is given). Advice will also be issued
unless `advice.skippedCherryPicks` is set to false (see
linkgit:git-config[1]).
-
+
`--reapply-cherry-picks` allows rebase to forgo reading all upstream
commits, potentially improving performance.
@@ -345,17 +360,6 @@ See also INCOMPATIBLE OPTIONS below.
+
See also INCOMPATIBLE OPTIONS below.
---skip::
- Restart the rebasing process by skipping the current patch.
-
---edit-todo::
- Edit the todo list during an interactive rebase.
-
---show-current-patch::
- Show the current patch in an interactive rebase or when rebase
- is stopped because of conflicts. This is the equivalent of
- `git show REBASE_HEAD`.
-
-m::
--merge::
Using merging strategies to rebase (default).
@@ -574,10 +578,7 @@ See also INCOMPATIBLE OPTIONS below.
--root::
Rebase all commits reachable from `<branch>`, instead of
limiting them with an `<upstream>`. This allows you to rebase
- the root commit(s) on a branch. When used with `--onto`, it
- will skip changes already contained in `<newbase>` (instead of
- `<upstream>`) whereas without `--onto` it will operate on every
- change.
+ the root commit(s) on a branch.
+
See also INCOMPATIBLE OPTIONS below.
@@ -630,6 +631,8 @@ start would be overridden by the presence of
+
If the configuration variable `rebase.updateRefs` is set, then this option
can be used to override and disable this setting.
++
+See also INCOMPATIBLE OPTIONS below.
INCOMPATIBLE OPTIONS
--------------------
@@ -645,17 +648,15 @@ are incompatible with the following options:
* --merge
* --strategy
* --strategy-option
- * --allow-empty-message
- * --[no-]autosquash
+ * --autosquash
* --rebase-merges
* --interactive
* --exec
* --no-keep-empty
* --empty=
- * --reapply-cherry-picks
- * --edit-todo
+ * --[no-]reapply-cherry-picks when used without --keep-base
* --update-refs
- * --root when used in combination with --onto
+ * --root when used without --onto
In addition, the following pairs of options are incompatible:
diff --git a/Documentation/git.txt b/Documentation/git.txt
index f9a7a4554c..74973d3cc4 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -613,7 +613,7 @@ The file parameters can point at the user's working file
(e.g. `new-file` in "git-diff-files"), `/dev/null` (e.g. `old-file`
when a new file is added), or a temporary file (e.g. `old-file` in the
index). `GIT_EXTERNAL_DIFF` should not worry about unlinking the
-temporary file --- it is removed when `GIT_EXTERNAL_DIFF` exits.
+temporary file -- it is removed when `GIT_EXTERNAL_DIFF` exits.
+
For a path that is unmerged, `GIT_EXTERNAL_DIFF` is called with 1
parameter, <path>.
diff --git a/Documentation/gitformat-signature.txt b/Documentation/gitformat-signature.txt
index a249869faf..d8e3eb1bac 100644
--- a/Documentation/gitformat-signature.txt
+++ b/Documentation/gitformat-signature.txt
@@ -37,7 +37,7 @@ line.
This is even true for an originally empty line. In the following
examples, the end of line that ends with a whitespace letter is
highlighted with a `$` sign; if you are trying to recreate these
-example by hand, do not cut and paste them---they are there
+example by hand, do not cut and paste them--they are there
primarily to highlight extra whitespace at the end of some lines.
The signed payload and the way the signature is embedded depends
diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt
index 0b4c1c8d98..3b71334459 100644
--- a/Documentation/pretty-formats.txt
+++ b/Documentation/pretty-formats.txt
@@ -146,24 +146,34 @@ The placeholders are:
'%m':: left (`<`), right (`>`) or boundary (`-`) mark
'%w([<w>[,<i1>[,<i2>]]])':: switch line wrapping, like the -w option of
linkgit:git-shortlog[1].
-'%<(<N>[,trunc|ltrunc|mtrunc])':: make the next placeholder take at
- least N columns, padding spaces on
+'%<( <N> [,trunc|ltrunc|mtrunc])':: make the next placeholder take at
+ least N column widths, padding spaces on
the right if necessary. Optionally
- truncate at the beginning (ltrunc),
- the middle (mtrunc) or the end
- (trunc) if the output is longer than
- N columns. Note that truncating
+ truncate (with ellipsis '..') at the left (ltrunc) `..ft`,
+ the middle (mtrunc) `mi..le`, or the end
+ (trunc) `rig..`, if the output is longer than
+ N columns.
+ Note 1: that truncating
only works correctly with N >= 2.
-'%<|(<N>)':: make the next placeholder take at least until Nth
- columns, padding spaces on the right if necessary
-'%>(<N>)', '%>|(<N>)':: similar to '%<(<N>)', '%<|(<N>)' respectively,
+ Note 2: spaces around the N and M (see below)
+ values are optional.
+ Note 3: Emojis and other wide characters
+ will take two display columns, which may
+ over-run column boundaries.
+ Note 4: decomposed character combining marks
+ may be misplaced at padding boundaries.
+'%<|( <M> )':: make the next placeholder take at least until Mth
+ display column, padding spaces on the right if necessary.
+ Use negative M values for column positions measured
+ from the right hand edge of the terminal window.
+'%>( <N> )', '%>|( <M> )':: similar to '%<( <N> )', '%<|( <M> )' respectively,
but padding spaces on the left
-'%>>(<N>)', '%>>|(<N>)':: similar to '%>(<N>)', '%>|(<N>)'
+'%>>( <N> )', '%>>|( <M> )':: similar to '%>( <N> )', '%>|( <M> )'
respectively, except that if the next
placeholder takes more spaces than given and
there are spaces on its left, use those
spaces
-'%><(<N>)', '%><|(<N>)':: similar to '%<(<N>)', '%<|(<N>)'
+'%><( <N> )', '%><|( <M> )':: similar to '%<( <N> )', '%<|( <M> )'
respectively, but padding both sides
(i.e. the text is centered)
diff --git a/Documentation/technical/hash-function-transition.txt b/Documentation/technical/hash-function-transition.txt
index e2ac36dd21..ed57481089 100644
--- a/Documentation/technical/hash-function-transition.txt
+++ b/Documentation/technical/hash-function-transition.txt
@@ -562,7 +562,7 @@ hash re-encode during clone and to encourage peers to modernize.
The design described here allows fetches by SHA-1 clients of a
personal SHA-256 repository because it's not much more difficult than
allowing pushes from that repository. This support needs to be guarded
-by a configuration option --- servers like git.kernel.org that serve a
+by a configuration option -- servers like git.kernel.org that serve a
large number of clients would not be expected to bear that cost.
Meaning of signatures
diff --git a/Documentation/technical/rerere.txt b/Documentation/technical/rerere.txt
index 35d4541433..be58f1bee3 100644
--- a/Documentation/technical/rerere.txt
+++ b/Documentation/technical/rerere.txt
@@ -99,7 +99,7 @@ conflict to leave line D means that the user declares:
compatible with what AB and AC wanted to do.
So the conflict we would see when merging AB into ACAB should be
-resolved the same way---it is the resolution that is in line with that
+resolved the same way--it is the resolution that is in line with that
declaration.
Imagine that similarly previously a branch XYXZ was forked from XY,
diff --git a/attr.h b/attr.h
index 58a2bc1344..9884ea2bc6 100644
--- a/attr.h
+++ b/attr.h
@@ -45,7 +45,7 @@
* const char *path;
*
* setup_check();
- * git_check_attr(path, check);
+ * git_check_attr(&the_index, tree_oid, path, check);
* ------------
*
* - Act on `.value` member of the result, left in `check->items[]`:
diff --git a/builtin/rebase.c b/builtin/rebase.c
index a26cc0cfdb..7171be40ee 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -122,6 +122,8 @@ struct rebase_options {
int reapply_cherry_picks;
int fork_point;
int update_refs;
+ int config_autosquash;
+ int config_update_refs;
};
#define REBASE_OPTIONS_INIT { \
@@ -134,6 +136,12 @@ struct rebase_options {
.exec = STRING_LIST_INIT_NODUP, \
.git_format_patch_opt = STRBUF_INIT, \
.fork_point = -1, \
+ .reapply_cherry_picks = -1, \
+ .allow_empty_message = 1, \
+ .autosquash = -1, \
+ .config_autosquash = -1, \
+ .update_refs = -1, \
+ .config_update_refs = -1, \
}
static struct replay_opts get_replay_opts(const struct rebase_options *opts)
@@ -776,7 +784,7 @@ static int rebase_config(const char *var, const char *value, void *data)
}
if (!strcmp(var, "rebase.autosquash")) {
- opts->autosquash = git_config_bool(var, value);
+ opts->config_autosquash = git_config_bool(var, value);
return 0;
}
@@ -793,7 +801,7 @@ static int rebase_config(const char *var, const char *value, void *data)
}
if (!strcmp(var, "rebase.updaterefs")) {
- opts->update_refs = git_config_bool(var, value);
+ opts->config_update_refs = git_config_bool(var, value);
return 0;
}
@@ -907,6 +915,9 @@ static int parse_opt_am(const struct option *opt, const char *arg, int unset)
BUG_ON_OPT_NEG(unset);
BUG_ON_OPT_ARG(arg);
+ if (opts->type != REBASE_UNSPECIFIED && opts->type != REBASE_APPLY)
+ die(_("apply options and merge options cannot be used together"));
+
opts->type = REBASE_APPLY;
return 0;
@@ -920,8 +931,10 @@ static int parse_opt_merge(const struct option *opt, const char *arg, int unset)
BUG_ON_OPT_NEG(unset);
BUG_ON_OPT_ARG(arg);
- if (!is_merge(opts))
- opts->type = REBASE_MERGE;
+ if (opts->type != REBASE_UNSPECIFIED && opts->type != REBASE_MERGE)
+ die(_("apply options and merge options cannot be used together"));
+
+ opts->type = REBASE_MERGE;
return 0;
}
@@ -935,6 +948,9 @@ static int parse_opt_interactive(const struct option *opt, const char *arg,
BUG_ON_OPT_NEG(unset);
BUG_ON_OPT_ARG(arg);
+ if (opts->type != REBASE_UNSPECIFIED && opts->type != REBASE_MERGE)
+ die(_("apply options and merge options cannot be used together"));
+
opts->type = REBASE_MERGE;
opts->flags |= REBASE_INTERACTIVE_EXPLICIT;
@@ -1150,8 +1166,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
prepare_repo_settings(the_repository);
the_repository->settings.command_requires_full_index = 0;
- options.reapply_cherry_picks = -1;
- options.allow_empty_message = 1;
git_config(rebase_config, &options);
/* options.gpg_sign_opt will be either "-S" or NULL */
gpg_sign = options.gpg_sign_opt ? "" : NULL;
@@ -1216,13 +1230,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
if (options.fork_point < 0)
options.fork_point = 0;
}
- /*
- * --keep-base defaults to --reapply-cherry-picks to avoid losing
- * commits when using this option.
- */
- if (options.reapply_cherry_picks < 0)
- options.reapply_cherry_picks = keep_base;
-
if (options.root && options.fork_point > 0)
die(_("options '%s' and '%s' cannot be used together"), "--root", "--fork-point");
@@ -1365,7 +1372,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
if ((options.flags & REBASE_INTERACTIVE_EXPLICIT) ||
(options.action != ACTION_NONE) ||
(options.exec.nr > 0) ||
- options.autosquash) {
+ (options.autosquash == -1 && options.config_autosquash == 1) ||
+ options.autosquash == 1) {
allow_preemptive_ff = 0;
}
if (options.committer_date_is_author_date || options.ignore_date)
@@ -1398,12 +1406,27 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
if (options.empty != EMPTY_UNSPECIFIED)
imply_merge(&options, "--empty");
- /*
- * --keep-base implements --reapply-cherry-picks by altering upstream so
- * it works with both backends.
- */
- if (options.reapply_cherry_picks && !keep_base)
- imply_merge(&options, "--reapply-cherry-picks");
+ if (options.reapply_cherry_picks < 0)
+ /*
+ * We default to --no-reapply-cherry-picks unless
+ * --keep-base is given; when --keep-base is given, we want
+ * to default to --reapply-cherry-picks.
+ */
+ options.reapply_cherry_picks = keep_base;
+ else if (!keep_base)
+ /*
+ * The apply backend always searches for and drops cherry
+ * picks. This is often not wanted with --keep-base, so
+ * --keep-base allows --reapply-cherry-picks to be
+ * simulated by altering the upstream such that
+ * cherry-picks cannot be detected and thus all commits are
+ * reapplied. Thus, --[no-]reapply-cherry-picks is
+ * supported when --keep-base is specified, but not when
+ * --keep-base is left out.
+ */
+ imply_merge(&options, options.reapply_cherry_picks ?
+ "--reapply-cherry-picks" :
+ "--no-reapply-cherry-picks");
if (gpg_sign)
options.gpg_sign_opt = xstrfmt("-S%s", gpg_sign);
@@ -1483,15 +1506,29 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
if (strcmp(options.git_am_opts.v[i], "-q"))
break;
- if (i >= 0) {
+ if (i >= 0 || options.type == REBASE_APPLY) {
if (is_merge(&options))
die(_("apply options and merge options "
"cannot be used together"));
+ else if (options.autosquash == -1 && options.config_autosquash == 1)
+ die(_("apply options are incompatible with rebase.autosquash. Consider adding --no-autosquash"));
+ else if (options.update_refs == -1 && options.config_update_refs == 1)
+ die(_("apply options are incompatible with rebase.updateRefs. Consider adding --no-update-refs"));
else
options.type = REBASE_APPLY;
}
}
+ if (options.update_refs == 1)
+ imply_merge(&options, "--update-refs");
+ options.update_refs = (options.update_refs >= 0) ? options.update_refs :
+ ((options.config_update_refs >= 0) ? options.config_update_refs : 0);
+
+ if (options.autosquash == 1)
+ imply_merge(&options, "--autosquash");
+ options.autosquash = (options.autosquash >= 0) ? options.autosquash :
+ ((options.config_autosquash >= 0) ? options.config_autosquash : 0);
+
if (options.type == REBASE_UNSPECIFIED) {
if (!strcmp(options.default_backend, "merge"))
imply_merge(&options, "--merge");
diff --git a/fsck.c b/fsck.c
index 47eaeedd70..2b18717ee8 100644
--- a/fsck.c
+++ b/fsck.c
@@ -748,6 +748,23 @@ static int fsck_tree(const struct object_id *tree_oid,
return retval;
}
+/*
+ * Confirm that the headers of a commit or tag object end in a reasonable way,
+ * either with the usual "\n\n" separator, or at least with a trailing newline
+ * on the final header line.
+ *
+ * This property is important for the memory safety of our callers. It allows
+ * them to scan the buffer linewise without constantly checking the remaining
+ * size as long as:
+ *
+ * - they check that there are bytes left in the buffer at the start of any
+ * line (i.e., that the last newline they saw was not the final one we
+ * found here)
+ *
+ * - any intra-line scanning they do will stop at a newline, which will worst
+ * case hit the newline we found here as the end-of-header. This makes it
+ * OK for them to use helpers like parse_oid_hex(), or even skip_prefix().
+ */
static int verify_headers(const void *data, unsigned long size,
const struct object_id *oid, enum object_type type,
struct fsck_options *options)
@@ -808,6 +825,20 @@ static int fsck_ident(const char **ident,
if (*p != ' ')
return report(options, oid, type, FSCK_MSG_MISSING_SPACE_BEFORE_DATE, "invalid author/committer line - missing space before date");
p++;
+ /*
+ * Our timestamp parser is based on the C strto*() functions, which
+ * will happily eat whitespace, including the newline that is supposed
+ * to prevent us walking past the end of the buffer. So do our own
+ * scan, skipping linear whitespace but not newlines, and then
+ * confirming we found a digit. We _could_ be even more strict here,
+ * as we really expect only a single space, but since we have
+ * traditionally allowed extra whitespace, we'll continue to do so.
+ */
+ while (*p == ' ' || *p == '\t')
+ p++;
+ if (!isdigit(*p))
+ return report(options, oid, type, FSCK_MSG_BAD_DATE,
+ "invalid author/committer line - bad date");
if (*p == '0' && p[1] != ' ')
return report(options, oid, type, FSCK_MSG_ZERO_PADDED_DATE, "invalid author/committer line - zero-padded date");
if (date_overflows(parse_timestamp(p, &end, 10)))
@@ -834,12 +865,18 @@ static int fsck_commit(const struct object_id *oid,
unsigned author_count;
int err;
const char *buffer_begin = buffer;
+ const char *buffer_end = buffer + size;
const char *p;
+ /*
+ * We _must_ stop parsing immediately if this reports failure, as the
+ * memory safety of the rest of the function depends on it. See the
+ * comment above the definition of verify_headers() for more details.
+ */
if (verify_headers(buffer, size, oid, OBJ_COMMIT, options))
return -1;
- if (!skip_prefix(buffer, "tree ", &buffer))
+ if (buffer >= buffer_end || !skip_prefix(buffer, "tree ", &buffer))
return report(options, oid, OBJ_COMMIT, FSCK_MSG_MISSING_TREE, "invalid format - expected 'tree' line");
if (parse_oid_hex(buffer, &tree_oid, &p) || *p != '\n') {
err = report(options, oid, OBJ_COMMIT, FSCK_MSG_BAD_TREE_SHA1, "invalid 'tree' line format - bad sha1");
@@ -847,7 +884,7 @@ static int fsck_commit(const struct object_id *oid,
return err;
}
buffer = p + 1;
- while (skip_prefix(buffer, "parent ", &buffer)) {
+ while (buffer < buffer_end && skip_prefix(buffer, "parent ", &buffer)) {
if (parse_oid_hex(buffer, &parent_oid, &p) || *p != '\n') {
err = report(options, oid, OBJ_COMMIT, FSCK_MSG_BAD_PARENT_SHA1, "invalid 'parent' line format - bad sha1");
if (err)
@@ -856,7 +893,7 @@ static int fsck_commit(const struct object_id *oid,
buffer = p + 1;
}
author_count = 0;
- while (skip_prefix(buffer, "author ", &buffer)) {
+ while (buffer < buffer_end && skip_prefix(buffer, "author ", &buffer)) {
author_count++;
err = fsck_ident(&buffer, oid, OBJ_COMMIT, options);
if (err)
@@ -868,7 +905,7 @@ static int fsck_commit(const struct object_id *oid,
err = report(options, oid, OBJ_COMMIT, FSCK_MSG_MULTIPLE_AUTHORS, "invalid format - multiple 'author' lines");
if (err)
return err;
- if (!skip_prefix(buffer, "committer ", &buffer))
+ if (buffer >= buffer_end || !skip_prefix(buffer, "committer ", &buffer))
return report(options, oid, OBJ_COMMIT, FSCK_MSG_MISSING_COMMITTER, "invalid format - expected 'committer' line");
err = fsck_ident(&buffer, oid, OBJ_COMMIT, options);
if (err)
@@ -899,13 +936,19 @@ int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
int ret = 0;
char *eol;
struct strbuf sb = STRBUF_INIT;
+ const char *buffer_end = buffer + size;
const char *p;
+ /*
+ * We _must_ stop parsing immediately if this reports failure, as the
+ * memory safety of the rest of the function depends on it. See the
+ * comment above the definition of verify_headers() for more details.
+ */
ret = verify_headers(buffer, size, oid, OBJ_TAG, options);
if (ret)
goto done;
- if (!skip_prefix(buffer, "object ", &buffer)) {
+ if (buffer >= buffer_end || !skip_prefix(buffer, "object ", &buffer)) {
ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_OBJECT, "invalid format - expected 'object' line");
goto done;
}
@@ -916,11 +959,11 @@ int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
}
buffer = p + 1;
- if (!skip_prefix(buffer, "type ", &buffer)) {
+ if (buffer >= buffer_end || !skip_prefix(buffer, "type ", &buffer)) {
ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_TYPE_ENTRY, "invalid format - expected 'type' line");
goto done;
}
- eol = strchr(buffer, '\n');
+ eol = memchr(buffer, '\n', buffer_end - buffer);
if (!eol) {
ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_TYPE, "invalid format - unexpected end after 'type' line");
goto done;
@@ -932,11 +975,11 @@ int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
goto done;
buffer = eol + 1;
- if (!skip_prefix(buffer, "tag ", &buffer)) {
+ if (buffer >= buffer_end || !skip_prefix(buffer, "tag ", &buffer)) {
ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_TAG_ENTRY, "invalid format - expected 'tag' line");
goto done;
}
- eol = strchr(buffer, '\n');
+ eol = memchr(buffer, '\n', buffer_end - buffer);
if (!eol) {
ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_TAG, "invalid format - unexpected end after 'type' line");
goto done;
@@ -952,7 +995,7 @@ int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
}
buffer = eol + 1;
- if (!skip_prefix(buffer, "tagger ", &buffer)) {
+ if (buffer >= buffer_end || !skip_prefix(buffer, "tagger ", &buffer)) {
/* early tags do not contain 'tagger' lines; warn only */
ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_TAGGER_ENTRY, "invalid format - expected 'tagger' line");
if (ret)
@@ -960,10 +1003,8 @@ int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
}
else
ret = fsck_ident(&buffer, oid, OBJ_TAG, options);
- if (!*buffer)
- goto done;
- if (!starts_with(buffer, "\n")) {
+ if (buffer < buffer_end && !starts_with(buffer, "\n")) {
/*
* The verify_headers() check will allow
* e.g. "[...]tagger <tagger>\nsome
@@ -1237,19 +1278,26 @@ int fsck_object(struct object *obj, void *data, unsigned long size,
if (!obj)
return report(options, NULL, OBJ_NONE, FSCK_MSG_BAD_OBJECT_SHA1, "no valid object to fsck");
- if (obj->type == OBJ_BLOB)
- return fsck_blob(&obj->oid, data, size, options);
- if (obj->type == OBJ_TREE)
- return fsck_tree(&obj->oid, data, size, options);
- if (obj->type == OBJ_COMMIT)
- return fsck_commit(&obj->oid, data, size, options);
- if (obj->type == OBJ_TAG)
- return fsck_tag(&obj->oid, data, size, options);
+ return fsck_buffer(&obj->oid, obj->type, data, size, options);
+}
+
+int fsck_buffer(const struct object_id *oid, enum object_type type,
+ void *data, unsigned long size,
+ struct fsck_options *options)
+{
+ if (type == OBJ_BLOB)
+ return fsck_blob(oid, data, size, options);
+ if (type == OBJ_TREE)
+ return fsck_tree(oid, data, size, options);
+ if (type == OBJ_COMMIT)
+ return fsck_commit(oid, data, size, options);
+ if (type == OBJ_TAG)
+ return fsck_tag(oid, data, size, options);
- return report(options, &obj->oid, obj->type,
+ return report(options, oid, type,
FSCK_MSG_UNKNOWN_TYPE,
"unknown type '%d' (internal fsck error)",
- obj->type);
+ type);
}
int fsck_error_function(struct fsck_options *o,
diff --git a/fsck.h b/fsck.h
index fcecf4101c..668330880e 100644
--- a/fsck.h
+++ b/fsck.h
@@ -184,6 +184,14 @@ int fsck_object(struct object *obj, void *data, unsigned long size,
struct fsck_options *options);
/*
+ * Same as fsck_object(), but for when the caller doesn't have an object
+ * struct.
+ */
+int fsck_buffer(const struct object_id *oid, enum object_type,
+ void *data, unsigned long size,
+ struct fsck_options *options);
+
+/*
* fsck a tag, and pass info about it back to the caller. This is
* exposed fsck_object() internals for git-mktag(1).
*/
diff --git a/git-request-pull.sh b/git-request-pull.sh
index 2d0e44656c..01640a044b 100755
--- a/git-request-pull.sh
+++ b/git-request-pull.sh
@@ -153,7 +153,7 @@ for you to fetch changes up to %H:
if test $(git cat-file -t "$head") = tag
then
git cat-file tag "$head" |
- sed -n -e '1,/^$/d' -e '/^-----BEGIN PGP /q' -e p
+ sed -n -e '1,/^$/d' -e '/^-----BEGIN \(PGP\|SSH\|SIGNED\) /q' -e p
echo
echo "----------------------------------------------------------------"
fi &&
diff --git a/gpg-interface.c b/gpg-interface.c
index f877a1ea56..687236430b 100644
--- a/gpg-interface.c
+++ b/gpg-interface.c
@@ -998,6 +998,7 @@ static int sign_buffer_ssh(struct strbuf *buffer, struct strbuf *signature,
char *ssh_signing_key_file = NULL;
struct strbuf ssh_signature_filename = STRBUF_INIT;
const char *literal_key = NULL;
+ int literal_ssh_key = 0;
if (!signing_key || signing_key[0] == '\0')
return error(
@@ -1005,6 +1006,7 @@ static int sign_buffer_ssh(struct strbuf *buffer, struct strbuf *signature,
if (is_literal_ssh_key(signing_key, &literal_key)) {
/* A literal ssh key */
+ literal_ssh_key = 1;
key_file = mks_tempfile_t(".git_signing_key_tmpXXXXXX");
if (!key_file)
return error_errno(
@@ -1039,8 +1041,10 @@ static int sign_buffer_ssh(struct strbuf *buffer, struct strbuf *signature,
"-Y", "sign",
"-n", "git",
"-f", ssh_signing_key_file,
- buffer_file->filename.buf,
NULL);
+ if (literal_ssh_key)
+ strvec_push(&signer.args, "-U");
+ strvec_push(&signer.args, buffer_file->filename.buf);
sigchain_push(SIGPIPE, SIG_IGN);
ret = pipe_command(&signer, NULL, 0, NULL, 0, &signer_stderr, 0);
diff --git a/object-file.c b/object-file.c
index ce9efae994..939865c1ae 100644
--- a/object-file.c
+++ b/object-file.c
@@ -33,6 +33,7 @@
#include "object-store.h"
#include "promisor-remote.h"
#include "submodule.h"
+#include "fsck.h"
/* The maximum size for an object header. */
#define MAX_HEADER_LEN 32
@@ -2284,32 +2285,21 @@ int repo_has_object_file(struct repository *r,
return repo_has_object_file_with_flags(r, oid, 0);
}
-static void check_tree(const void *buf, size_t size)
-{
- struct tree_desc desc;
- struct name_entry entry;
-
- init_tree_desc(&desc, buf, size);
- while (tree_entry(&desc, &entry))
- /* do nothing
- * tree_entry() will die() on malformed entries */
- ;
-}
-
-static void check_commit(const void *buf, size_t size)
-{
- struct commit c;
- memset(&c, 0, sizeof(c));
- if (parse_commit_buffer(the_repository, &c, buf, size, 0))
- die(_("corrupt commit"));
-}
-
-static void check_tag(const void *buf, size_t size)
-{
- struct tag t;
- memset(&t, 0, sizeof(t));
- if (parse_tag_buffer(the_repository, &t, buf, size))
- die(_("corrupt tag"));
+/*
+ * We can't use the normal fsck_error_function() for index_mem(),
+ * because we don't yet have a valid oid for it to report. Instead,
+ * report the minimal fsck error here, and rely on the caller to
+ * give more context.
+ */
+static int hash_format_check_report(struct fsck_options *opts,
+ const struct object_id *oid,
+ enum object_type object_type,
+ enum fsck_msg_type msg_type,
+ enum fsck_msg_id msg_id,
+ const char *message)
+{
+ error(_("object fails fsck: %s"), message);
+ return 1;
}
static int index_mem(struct index_state *istate,
@@ -2336,12 +2326,13 @@ static int index_mem(struct index_state *istate,
}
}
if (flags & HASH_FORMAT_CHECK) {
- if (type == OBJ_TREE)
- check_tree(buf, size);
- if (type == OBJ_COMMIT)
- check_commit(buf, size);
- if (type == OBJ_TAG)
- check_tag(buf, size);
+ struct fsck_options opts = FSCK_OPTIONS_DEFAULT;
+
+ opts.strict = 1;
+ opts.error_func = hash_format_check_report;
+ if (fsck_buffer(null_oid(), type, buf, size, &opts))
+ die(_("refusing to create malformed object"));
+ fsck_finish(&opts);
}
if (write_object)
diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh
index a8af15b91c..89b306cb11 100755
--- a/t/t0003-attributes.sh
+++ b/t/t0003-attributes.sh
@@ -442,7 +442,7 @@ test_expect_success 'large attributes line ignores trailing content in tree' '
test_expect_success EXPENSIVE 'large attributes file ignored in tree' '
test_when_finished "rm .gitattributes" &&
- dd if=/dev/zero of=.gitattributes bs=101M count=1 2>/dev/null &&
+ dd if=/dev/zero of=.gitattributes bs=1048576 count=101 2>/dev/null &&
git check-attr --all path >/dev/null 2>err &&
echo "warning: ignoring overly large gitattributes file ${SQ}.gitattributes${SQ}" >expect &&
test_cmp expect err
@@ -470,7 +470,7 @@ test_expect_success 'large attributes line ignores trailing content in index' '
test_expect_success EXPENSIVE 'large attributes file ignored in index' '
test_when_finished "git update-index --remove .gitattributes" &&
- blob=$(dd if=/dev/zero bs=101M count=1 2>/dev/null | git hash-object -w --stdin) &&
+ blob=$(dd if=/dev/zero bs=1048576 count=101 2>/dev/null | git hash-object -w --stdin) &&
git update-index --add --cacheinfo 100644,$blob,.gitattributes &&
git check-attr --cached --all path >/dev/null 2>err &&
echo "warning: ignoring overly large gitattributes blob ${SQ}.gitattributes${SQ}" >expect &&
diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh
index 23b8942edb..2d875b17d8 100755
--- a/t/t1006-cat-file.sh
+++ b/t/t1006-cat-file.sh
@@ -292,8 +292,8 @@ commit_message="Initial commit"
commit_sha1=$(echo_without_newline "$commit_message" | git commit-tree $tree_sha1)
commit_size=$(($(test_oid hexsz) + 137))
commit_content="tree $tree_sha1
-author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> 0000000000 +0000
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 0000000000 +0000
+author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> 0 +0000
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 0 +0000
$commit_message"
@@ -304,7 +304,7 @@ type blob
tag hellotag
tagger $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
tag_description="This is a tag"
-tag_content="$tag_header_without_timestamp 0000000000 +0000
+tag_content="$tag_header_without_timestamp 0 +0000
$tag_description"
diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh
index ac5ad8c740..ac3d173767 100755
--- a/t/t1007-hash-object.sh
+++ b/t/t1007-hash-object.sh
@@ -203,23 +203,34 @@ done
test_expect_success 'too-short tree' '
echo abc >malformed-tree &&
test_must_fail git hash-object -t tree malformed-tree 2>err &&
- test_i18ngrep "too-short tree object" err
+ grep "too-short tree object" err
'
test_expect_success 'malformed mode in tree' '
- hex_sha1=$(echo foo | git hash-object --stdin -w) &&
- bin_sha1=$(echo $hex_sha1 | hex2oct) &&
- printf "9100644 \0$bin_sha1" >tree-with-malformed-mode &&
+ hex_oid=$(echo foo | git hash-object --stdin -w) &&
+ bin_oid=$(echo $hex_oid | hex2oct) &&
+ printf "9100644 \0$bin_oid" >tree-with-malformed-mode &&
test_must_fail git hash-object -t tree tree-with-malformed-mode 2>err &&
- test_i18ngrep "malformed mode in tree entry" err
+ grep "malformed mode in tree entry" err
'
test_expect_success 'empty filename in tree' '
- hex_sha1=$(echo foo | git hash-object --stdin -w) &&
- bin_sha1=$(echo $hex_sha1 | hex2oct) &&
- printf "100644 \0$bin_sha1" >tree-with-empty-filename &&
+ hex_oid=$(echo foo | git hash-object --stdin -w) &&
+ bin_oid=$(echo $hex_oid | hex2oct) &&
+ printf "100644 \0$bin_oid" >tree-with-empty-filename &&
test_must_fail git hash-object -t tree tree-with-empty-filename 2>err &&
- test_i18ngrep "empty filename in tree entry" err
+ grep "empty filename in tree entry" err
+'
+
+test_expect_success 'duplicate filename in tree' '
+ hex_oid=$(echo foo | git hash-object --stdin -w) &&
+ bin_oid=$(echo $hex_oid | hex2oct) &&
+ {
+ printf "100644 file\0$bin_oid" &&
+ printf "100644 file\0$bin_oid"
+ } >tree-with-duplicate-filename &&
+ test_must_fail git hash-object -t tree tree-with-duplicate-filename 2>err &&
+ grep "duplicateEntries" err
'
test_expect_success 'corrupt commit' '
diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
index de0f6d5e7f..fdb886dfe4 100755
--- a/t/t1450-fsck.sh
+++ b/t/t1450-fsck.sh
@@ -212,7 +212,7 @@ test_expect_success 'email without @ is okay' '
test_expect_success 'email with embedded > is not okay' '
git cat-file commit HEAD >basis &&
sed "s/@[a-z]/&>/" basis >bad-email &&
- new=$(git hash-object -t commit -w --stdin <bad-email) &&
+ new=$(git hash-object --literally -t commit -w --stdin <bad-email) &&
test_when_finished "remove_object $new" &&
git update-ref refs/heads/bogus "$new" &&
test_when_finished "git update-ref -d refs/heads/bogus" &&
@@ -223,7 +223,7 @@ test_expect_success 'email with embedded > is not okay' '
test_expect_success 'missing < email delimiter is reported nicely' '
git cat-file commit HEAD >basis &&
sed "s/<//" basis >bad-email-2 &&
- new=$(git hash-object -t commit -w --stdin <bad-email-2) &&
+ new=$(git hash-object --literally -t commit -w --stdin <bad-email-2) &&
test_when_finished "remove_object $new" &&
git update-ref refs/heads/bogus "$new" &&
test_when_finished "git update-ref -d refs/heads/bogus" &&
@@ -234,7 +234,7 @@ test_expect_success 'missing < email delimiter is reported nicely' '
test_expect_success 'missing email is reported nicely' '
git cat-file commit HEAD >basis &&
sed "s/[a-z]* <[^>]*>//" basis >bad-email-3 &&
- new=$(git hash-object -t commit -w --stdin <bad-email-3) &&
+ new=$(git hash-object --literally -t commit -w --stdin <bad-email-3) &&
test_when_finished "remove_object $new" &&
git update-ref refs/heads/bogus "$new" &&
test_when_finished "git update-ref -d refs/heads/bogus" &&
@@ -245,7 +245,7 @@ test_expect_success 'missing email is reported nicely' '
test_expect_success '> in name is reported' '
git cat-file commit HEAD >basis &&
sed "s/ </> </" basis >bad-email-4 &&
- new=$(git hash-object -t commit -w --stdin <bad-email-4) &&
+ new=$(git hash-object --literally -t commit -w --stdin <bad-email-4) &&
test_when_finished "remove_object $new" &&
git update-ref refs/heads/bogus "$new" &&
test_when_finished "git update-ref -d refs/heads/bogus" &&
@@ -258,7 +258,7 @@ test_expect_success 'integer overflow in timestamps is reported' '
git cat-file commit HEAD >basis &&
sed "s/^\\(author .*>\\) [0-9]*/\\1 18446744073709551617/" \
<basis >bad-timestamp &&
- new=$(git hash-object -t commit -w --stdin <bad-timestamp) &&
+ new=$(git hash-object --literally -t commit -w --stdin <bad-timestamp) &&
test_when_finished "remove_object $new" &&
git update-ref refs/heads/bogus "$new" &&
test_when_finished "git update-ref -d refs/heads/bogus" &&
@@ -269,7 +269,7 @@ test_expect_success 'integer overflow in timestamps is reported' '
test_expect_success 'commit with NUL in header' '
git cat-file commit HEAD >basis &&
sed "s/author ./author Q/" <basis | q_to_nul >commit-NUL-header &&
- new=$(git hash-object -t commit -w --stdin <commit-NUL-header) &&
+ new=$(git hash-object --literally -t commit -w --stdin <commit-NUL-header) &&
test_when_finished "remove_object $new" &&
git update-ref refs/heads/bogus "$new" &&
test_when_finished "git update-ref -d refs/heads/bogus" &&
@@ -292,7 +292,7 @@ test_expect_success 'tree object with duplicate entries' '
git cat-file tree $T &&
git cat-file tree $T
) |
- git hash-object -w -t tree --stdin
+ git hash-object --literally -w -t tree --stdin
) &&
test_must_fail git fsck 2>out &&
test_i18ngrep "error in tree .*contains duplicate file entries" out
@@ -426,7 +426,7 @@ test_expect_success 'tag with incorrect tag name & missing tagger' '
This is an invalid tag.
EOF
- tag=$(git hash-object -t tag -w --stdin <wrong-tag) &&
+ tag=$(git hash-object --literally -t tag -w --stdin <wrong-tag) &&
test_when_finished "remove_object $tag" &&
echo $tag >.git/refs/tags/wrong &&
test_when_finished "git update-ref -d refs/tags/wrong" &&
@@ -558,7 +558,7 @@ test_expect_success 'rev-list --verify-objects with commit graph (parent)' '
test_expect_success 'force fsck to ignore double author' '
git cat-file commit HEAD >basis &&
sed "s/^author .*/&,&/" <basis | tr , \\n >multiple-authors &&
- new=$(git hash-object -t commit -w --stdin <multiple-authors) &&
+ new=$(git hash-object --literally -t commit -w --stdin <multiple-authors) &&
test_when_finished "remove_object $new" &&
git update-ref refs/heads/bogus "$new" &&
test_when_finished "git update-ref -d refs/heads/bogus" &&
@@ -573,7 +573,7 @@ test_expect_success 'fsck notices blob entry pointing to null sha1' '
(git init null-blob &&
cd null-blob &&
sha=$(printf "100644 file$_bz$_bzoid" |
- git hash-object -w --stdin -t tree) &&
+ git hash-object --literally -w --stdin -t tree) &&
git fsck 2>out &&
test_i18ngrep "warning.*null sha1" out
)
@@ -583,7 +583,7 @@ test_expect_success 'fsck notices submodule entry pointing to null sha1' '
(git init null-commit &&
cd null-commit &&
sha=$(printf "160000 submodule$_bz$_bzoid" |
- git hash-object -w --stdin -t tree) &&
+ git hash-object --literally -w --stdin -t tree) &&
git fsck 2>out &&
test_i18ngrep "warning.*null sha1" out
)
@@ -648,7 +648,7 @@ test_expect_success 'NUL in commit' '
git commit --allow-empty -m "initial commitQNUL after message" &&
git cat-file commit HEAD >original &&
q_to_nul <original >munged &&
- git hash-object -w -t commit --stdin <munged >name &&
+ git hash-object --literally -w -t commit --stdin <munged >name &&
git branch bad $(cat name) &&
test_must_fail git -c fsck.nulInCommit=error fsck 2>warn.1 &&
@@ -794,8 +794,8 @@ test_expect_success 'fsck errors in packed objects' '
git cat-file commit HEAD >basis &&
sed "s/</one/" basis >one &&
sed "s/</foo/" basis >two &&
- one=$(git hash-object -t commit -w one) &&
- two=$(git hash-object -t commit -w two) &&
+ one=$(git hash-object --literally -t commit -w one) &&
+ two=$(git hash-object --literally -t commit -w two) &&
pack=$(
{
echo $one &&
diff --git a/t/t1451-fsck-buffer.sh b/t/t1451-fsck-buffer.sh
new file mode 100755
index 0000000000..9ac270abab
--- /dev/null
+++ b/t/t1451-fsck-buffer.sh
@@ -0,0 +1,140 @@
+#!/bin/sh
+
+test_description='fsck on buffers without NUL termination
+
+The goal here is to make sure that the various fsck parsers never look
+past the end of the buffer they are given, even when encountering broken
+or truncated objects.
+
+We have to use "hash-object" for this because most code paths that read objects
+append an extra NUL for safety after the buffer. But hash-object, since it is
+reading straight from a file (and possibly even mmap-ing it) cannot always do
+so.
+
+These tests _might_ catch such overruns in normal use, but should be run with
+ASan or valgrind for more confidence.
+'
+. ./test-lib.sh
+
+# the general idea for tags and commits is to build up the "base" file
+# progressively, and then test new truncations on top of it.
+reset () {
+ test_expect_success 'reset input to empty' '
+ >base
+ '
+}
+
+add () {
+ content="$1"
+ type=${content%% *}
+ test_expect_success "add $type line" '
+ echo "$content" >>base
+ '
+}
+
+check () {
+ type=$1
+ fsck=$2
+ content=$3
+ test_expect_success "truncated $type ($fsck, \"$content\")" '
+ # do not pipe into hash-object here; we want to increase
+ # the chance that it uses a fixed-size buffer or mmap,
+ # and a pipe would be read into a strbuf.
+ {
+ cat base &&
+ echo "$content"
+ } >input &&
+ test_must_fail git hash-object -t "$type" input 2>err &&
+ grep "$fsck" err
+ '
+}
+
+test_expect_success 'create valid objects' '
+ git commit --allow-empty -m foo &&
+ commit=$(git rev-parse --verify HEAD) &&
+ tree=$(git rev-parse --verify HEAD^{tree})
+'
+
+reset
+check commit missingTree ""
+check commit missingTree "tr"
+check commit missingTree "tree"
+check commit badTreeSha1 "tree "
+check commit badTreeSha1 "tree 1234"
+add "tree $tree"
+
+# these expect missingAuthor because "parent" is optional
+check commit missingAuthor ""
+check commit missingAuthor "par"
+check commit missingAuthor "parent"
+check commit badParentSha1 "parent "
+check commit badParentSha1 "parent 1234"
+add "parent $commit"
+
+check commit missingAuthor ""
+check commit missingAuthor "au"
+check commit missingAuthor "author"
+ident_checks () {
+ check $1 missingEmail "$2 "
+ check $1 missingEmail "$2 name"
+ check $1 badEmail "$2 name <"
+ check $1 badEmail "$2 name <email"
+ check $1 missingSpaceBeforeDate "$2 name <email>"
+ check $1 badDate "$2 name <email> "
+ check $1 badDate "$2 name <email> 1234"
+ check $1 badTimezone "$2 name <email> 1234 "
+ check $1 badTimezone "$2 name <email> 1234 +"
+}
+ident_checks commit author
+add "author name <email> 1234 +0000"
+
+check commit missingCommitter ""
+check commit missingCommitter "co"
+check commit missingCommitter "committer"
+ident_checks commit committer
+add "committer name <email> 1234 +0000"
+
+reset
+check tag missingObject ""
+check tag missingObject "obj"
+check tag missingObject "object"
+check tag badObjectSha1 "object "
+check tag badObjectSha1 "object 1234"
+add "object $commit"
+
+check tag missingType ""
+check tag missingType "ty"
+check tag missingType "type"
+check tag badType "type "
+check tag badType "type com"
+add "type commit"
+
+check tag missingTagEntry ""
+check tag missingTagEntry "ta"
+check tag missingTagEntry "tag"
+check tag badTagName "tag "
+add "tag foo"
+
+check tag missingTagger ""
+check tag missingTagger "ta"
+check tag missingTagger "tagger"
+ident_checks tag tagger
+
+# trees are a binary format and can't use our earlier helpers
+test_expect_success 'truncated tree (short hash)' '
+ printf "100644 foo\0\1\1\1\1" >input &&
+ test_must_fail git hash-object -t tree input 2>err &&
+ grep badTree err
+'
+
+test_expect_success 'truncated tree (missing nul)' '
+ # these two things are indistinguishable to the parser. The important
+ # thing about this is example is that there are enough bytes to
+ # make up a hash, and that there is no NUL (and we confirm that the
+ # parser does not walk past the end of the buffer).
+ printf "100644 a long filename, or a hash with missing nul?" >input &&
+ test_must_fail git hash-object -t tree input 2>err &&
+ grep badTree err
+'
+
+test_done
diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
index 6dabb05a2a..4711b37a28 100755
--- a/t/t3422-rebase-incompatible-options.sh
+++ b/t/t3422-rebase-incompatible-options.sh
@@ -25,11 +25,11 @@ test_expect_success 'setup' '
'
#
-# Rebase has lots of useful options like --whitepsace=fix, which are
-# actually all built in terms of flags to git-am. Since neither
-# --merge nor --interactive (nor any options that imply those two) use
-# git-am, using them together will result in flags like --whitespace=fix
-# being ignored. Make sure rebase warns the user and aborts instead.
+# Rebase has a couple options which are specific to the apply backend,
+# and several options which are specific to the merge backend. Flags
+# from the different sets cannot work together, and we do not want to
+# just ignore one of the sets of flags. Make sure rebase warns the
+# user and aborts instead.
#
test_rebase_am_only () {
@@ -50,6 +50,11 @@ test_rebase_am_only () {
test_must_fail git rebase $opt --strategy-option=ours A
"
+ test_expect_success "$opt incompatible with --autosquash" "
+ git checkout B^0 &&
+ test_must_fail git rebase $opt --autosquash A
+ "
+
test_expect_success "$opt incompatible with --interactive" "
git checkout B^0 &&
test_must_fail git rebase $opt --interactive A
@@ -60,9 +65,65 @@ test_rebase_am_only () {
test_must_fail git rebase $opt --exec 'true' A
"
+ test_expect_success "$opt incompatible with --keep-empty" "
+ git checkout B^0 &&
+ test_must_fail git rebase $opt --keep-empty A
+ "
+
+ test_expect_success "$opt incompatible with --empty=..." "
+ git checkout B^0 &&
+ test_must_fail git rebase $opt --empty=ask A
+ "
+
+ test_expect_success "$opt incompatible with --no-reapply-cherry-picks" "
+ git checkout B^0 &&
+ test_must_fail git rebase $opt --no-reapply-cherry-picks A
+ "
+
+ test_expect_success "$opt incompatible with --reapply-cherry-picks" "
+ git checkout B^0 &&
+ test_must_fail git rebase $opt --reapply-cherry-picks A
+ "
+
+ test_expect_success "$opt incompatible with --update-refs" "
+ git checkout B^0 &&
+ test_must_fail git rebase $opt --update-refs A
+ "
+
+ test_expect_success "$opt incompatible with --root without --onto" "
+ git checkout B^0 &&
+ test_must_fail git rebase $opt --root A
+ "
+
+ test_expect_success "$opt incompatible with rebase.autosquash" "
+ git checkout B^0 &&
+ test_must_fail git -c rebase.autosquash=true rebase $opt A 2>err &&
+ grep -e --no-autosquash err
+ "
+
+ test_expect_success "$opt incompatible with rebase.updateRefs" "
+ git checkout B^0 &&
+ test_must_fail git -c rebase.updateRefs=true rebase $opt A 2>err &&
+ grep -e --no-update-refs err
+ "
+
+ test_expect_success "$opt okay with overridden rebase.autosquash" "
+ test_when_finished \"git reset --hard B^0\" &&
+ git checkout B^0 &&
+ git -c rebase.autosquash=true rebase --no-autosquash $opt A
+ "
+
+ test_expect_success "$opt okay with overridden rebase.updateRefs" "
+ test_when_finished \"git reset --hard B^0\" &&
+ git checkout B^0 &&
+ git -c rebase.updateRefs=true rebase --no-update-refs $opt A
+ "
}
+# Check options which imply --apply
test_rebase_am_only --whitespace=fix
test_rebase_am_only -C4
+# Also check an explicit --apply
+test_rebase_am_only --apply
test_done
diff --git a/t/t4054-diff-bogus-tree.sh b/t/t4054-diff-bogus-tree.sh
index 294fb55313..05c88f8cdf 100755
--- a/t/t4054-diff-bogus-tree.sh
+++ b/t/t4054-diff-bogus-tree.sh
@@ -10,7 +10,7 @@ test_expect_success 'create bogus tree' '
bogus_tree=$(
printf "100644 fooQ$name" |
q_to_nul |
- git hash-object -w --stdin -t tree
+ git hash-object --literally -w --stdin -t tree
)
'
diff --git a/t/t4058-diff-duplicates.sh b/t/t4058-diff-duplicates.sh
index 54614b814d..2501c89c1c 100755
--- a/t/t4058-diff-duplicates.sh
+++ b/t/t4058-diff-duplicates.sh
@@ -29,7 +29,7 @@ make_tree () {
make_tree_entry "$1" "$2" "$3"
shift; shift; shift
done |
- git hash-object -w -t tree --stdin
+ git hash-object --literally -w -t tree --stdin
}
# this is kind of a convoluted setup, but matches
diff --git a/t/t4205-log-pretty-formats.sh b/t/t4205-log-pretty-formats.sh
index 3e7ad9d5de..4cf8a77667 100755
--- a/t/t4205-log-pretty-formats.sh
+++ b/t/t4205-log-pretty-formats.sh
@@ -1094,4 +1094,31 @@ test_expect_success EXPENSIVE,SIZE_T_IS_64BIT 'log --pretty with huge commit mes
test_cmp expect error
'
+# pretty-formats note wide char limitations, and add tests
+test_expect_failure 'wide and decomposed characters column counting' '
+
+# from t/lib-unicode-nfc-nfd.sh hex values converted to octal
+ utf8_nfc=$(printf "\303\251") && # e acute combined.
+ utf8_nfd=$(printf "\145\314\201") && # e with a combining acute (i.e. decomposed)
+ utf8_emoji=$(printf "\360\237\221\250") &&
+
+# replacement character when requesting a wide char fits in a single display colum.
+# "half wide" alternative could be a plain ASCII dot `.`
+ utf8_vert_ell=$(printf "\342\213\256") &&
+
+# use ${xxx} here!
+ nfc10="${utf8_nfc}${utf8_nfc}${utf8_nfc}${utf8_nfc}${utf8_nfc}${utf8_nfc}${utf8_nfc}${utf8_nfc}${utf8_nfc}${utf8_nfc}" &&
+ nfd10="${utf8_nfd}${utf8_nfd}${utf8_nfd}${utf8_nfd}${utf8_nfd}${utf8_nfd}${utf8_nfd}${utf8_nfd}${utf8_nfd}${utf8_nfd}" &&
+ emoji5="${utf8_emoji}${utf8_emoji}${utf8_emoji}${utf8_emoji}${utf8_emoji}" &&
+# emoji5 uses 10 display columns
+
+ test_commit "abcdefghij" &&
+ test_commit --no-tag "${nfc10}" &&
+ test_commit --no-tag "${nfd10}" &&
+ test_commit --no-tag "${emoji5}" &&
+ printf "${utf8_emoji}..${utf8_emoji}${utf8_vert_ell}\n${utf8_nfd}..${utf8_nfd}${utf8_nfd}\n${utf8_nfc}..${utf8_nfc}${utf8_nfc}\na..ij\n" >expected &&
+ git log --format="%<(5,mtrunc)%s" -4 >actual &&
+ test_cmp expected actual
+'
+
test_done
diff --git a/t/t4212-log-corrupt.sh b/t/t4212-log-corrupt.sh
index 30a219894b..e89e1f54b6 100755
--- a/t/t4212-log-corrupt.sh
+++ b/t/t4212-log-corrupt.sh
@@ -10,7 +10,7 @@ test_expect_success 'setup' '
git cat-file commit HEAD |
sed "/^author /s/>/>-<>/" >broken_email.commit &&
- git hash-object -w -t commit broken_email.commit >broken_email.hash &&
+ git hash-object --literally -w -t commit broken_email.commit >broken_email.hash &&
git update-ref refs/heads/broken_email $(cat broken_email.hash)
'
@@ -46,7 +46,7 @@ test_expect_success 'git log --format with broken author email' '
munge_author_date () {
git cat-file commit "$1" >commit.orig &&
sed "s/^\(author .*>\) [0-9]*/\1 $2/" <commit.orig >commit.munge &&
- git hash-object -w -t commit commit.munge
+ git hash-object --literally -w -t commit commit.munge
}
test_expect_success 'unparsable dates produce sentinel value' '
diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh
index b0095ab41d..59e9e77223 100755
--- a/t/t5302-pack-index.sh
+++ b/t/t5302-pack-index.sh
@@ -263,7 +263,7 @@ tag guten tag
This is an invalid tag.
EOF
- tag=$(git hash-object -t tag -w --stdin <wrong-tag) &&
+ tag=$(git hash-object -t tag -w --stdin --literally <wrong-tag) &&
pack1=$(echo $tag $sha | git pack-objects tag-test) &&
echo remove tag object &&
thirtyeight=${tag#??} &&
diff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh
index ac4099ca89..88d3c56750 100755
--- a/t/t5504-fetch-receive-strict.sh
+++ b/t/t5504-fetch-receive-strict.sh
@@ -138,7 +138,7 @@ This commit object intentionally broken
EOF
test_expect_success 'setup bogus commit' '
- commit="$(git hash-object -t commit -w --stdin <bogus-commit)"
+ commit="$(git hash-object --literally -t commit -w --stdin <bogus-commit)"
'
test_expect_success 'fsck with no skipList input' '
diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh
index b33cd4afca..e4db7513f4 100755
--- a/t/t5702-protocol-v2.sh
+++ b/t/t5702-protocol-v2.sh
@@ -1114,7 +1114,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects fails on bad object'
This commit object intentionally broken
EOF
- BOGUS=$(git -C "$P" hash-object -t commit -w --stdin <bogus-commit) &&
+ BOGUS=$(git -C "$P" hash-object -t commit -w --stdin --literally <bogus-commit) &&
git -C "$P" branch bogus-branch "$BOGUS" &&
echo my-blob >"$P/my-blob" &&
diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh
index 2ae1fc721b..c466fd989f 100755
--- a/t/t6300-for-each-ref.sh
+++ b/t/t6300-for-each-ref.sh
@@ -606,7 +606,7 @@ test_expect_success 'create tag without tagger' '
git tag -a -m "Broken tag" taggerless &&
git tag -f taggerless $(git cat-file tag taggerless |
sed -e "/^tagger /d" |
- git hash-object --stdin -w -t tag)
+ git hash-object --literally --stdin -w -t tag)
'
test_atom refs/tags/taggerless type 'commit'
diff --git a/t/t7030-verify-tag.sh b/t/t7030-verify-tag.sh
index 10faa64515..6f526c37c2 100755
--- a/t/t7030-verify-tag.sh
+++ b/t/t7030-verify-tag.sh
@@ -115,7 +115,7 @@ test_expect_success GPGSM 'verify and show signatures x509 with high minTrustLev
test_expect_success GPG 'detect fudged signature' '
git cat-file tag seventh-signed >raw &&
- sed -e "/^tag / s/seventh/7th forged/" raw >forged1 &&
+ sed -e "/^tag / s/seventh/7th-forged/" raw >forged1 &&
git hash-object -w -t tag forged1 >forged1.tag &&
test_must_fail git verify-tag $(cat forged1.tag) 2>actual1 &&
grep "BAD signature from" actual1 &&
diff --git a/t/t7031-verify-tag-signed-ssh.sh b/t/t7031-verify-tag-signed-ssh.sh
index 1cb36b9ab8..36eb86a4b1 100755
--- a/t/t7031-verify-tag-signed-ssh.sh
+++ b/t/t7031-verify-tag-signed-ssh.sh
@@ -125,7 +125,7 @@ test_expect_success GPGSSH,GPGSSH_VERIFYTIME 'verify-tag failes with tag date ou
test_expect_success GPGSSH 'detect fudged ssh signature' '
test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
git cat-file tag seventh-signed >raw &&
- sed -e "/^tag / s/seventh/7th forged/" raw >forged1 &&
+ sed -e "/^tag / s/seventh/7th-forged/" raw >forged1 &&
git hash-object -w -t tag forged1 >forged1.tag &&
test_must_fail git verify-tag $(cat forged1.tag) 2>actual1 &&
grep "${GPGSSH_BAD_SIGNATURE}" actual1 &&
diff --git a/t/t7509-commit-authorship.sh b/t/t7509-commit-authorship.sh
index 21c668f75e..5d890949f7 100755
--- a/t/t7509-commit-authorship.sh
+++ b/t/t7509-commit-authorship.sh
@@ -105,7 +105,7 @@ test_expect_success '--amend option with empty author' '
test_expect_success '--amend option with missing author' '
git cat-file commit Initial >tmp &&
sed "s/author [^<]* </author </" tmp >malformed &&
- sha=$(git hash-object -t commit -w malformed) &&
+ sha=$(git hash-object --literally -t commit -w malformed) &&
test_when_finished "remove_object $sha" &&
git checkout $sha &&
test_when_finished "git checkout Initial" &&
diff --git a/t/t7510-signed-commit.sh b/t/t7510-signed-commit.sh
index 8593b7e3cb..bc7a31ba3e 100755
--- a/t/t7510-signed-commit.sh
+++ b/t/t7510-signed-commit.sh
@@ -202,7 +202,7 @@ test_expect_success GPG 'detect fudged signature with NUL' '
git cat-file commit seventh-signed >raw &&
cat raw >forged2 &&
echo Qwik | tr "Q" "\000" >>forged2 &&
- git hash-object -w -t commit forged2 >forged2.commit &&
+ git hash-object --literally -w -t commit forged2 >forged2.commit &&
test_must_fail git verify-commit $(cat forged2.commit) &&
git show --pretty=short --show-signature $(cat forged2.commit) >actual2 &&
grep "BAD signature from" actual2 &&
diff --git a/t/t7528-signed-commit-ssh.sh b/t/t7528-signed-commit-ssh.sh
index f47e995179..065f780636 100755
--- a/t/t7528-signed-commit-ssh.sh
+++ b/t/t7528-signed-commit-ssh.sh
@@ -270,7 +270,7 @@ test_expect_success GPGSSH 'detect fudged signature with NUL' '
git cat-file commit seventh-signed >raw &&
cat raw >forged2 &&
echo Qwik | tr "Q" "\000" >>forged2 &&
- git hash-object -w -t commit forged2 >forged2.commit &&
+ git hash-object --literally -w -t commit forged2 >forged2.commit &&
test_must_fail git verify-commit $(cat forged2.commit) &&
git show --pretty=short --show-signature $(cat forged2.commit) >actual2 &&
grep "${GPGSSH_BAD_SIGNATURE}" actual2 &&
diff --git a/t/t8003-blame-corner-cases.sh b/t/t8003-blame-corner-cases.sh
index d751d48b7d..8bcd39e81b 100755
--- a/t/t8003-blame-corner-cases.sh
+++ b/t/t8003-blame-corner-cases.sh
@@ -201,7 +201,7 @@ committer David Reiss <dreiss@facebook.com> 1234567890 +0000
some message
EOF
- COMMIT=$(git hash-object -t commit -w badcommit) &&
+ COMMIT=$(git hash-object --literally -t commit -w badcommit) &&
git --no-pager blame $COMMIT -- uno >/dev/null
'
diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh
index ff21a12ee6..26c25c0eb2 100755
--- a/t/t9350-fast-export.sh
+++ b/t/t9350-fast-export.sh
@@ -373,7 +373,7 @@ EOF
test_expect_success 'cope with tagger-less tags' '
- TAG=$(git hash-object -t tag -w tag-content) &&
+ TAG=$(git hash-object --literally -t tag -w tag-content) &&
git update-ref refs/tags/sonnenschein $TAG &&
git fast-export -C -C --signed-tags=strip --all > output &&
test $(grep -c "^tag " output) = 4 &&