Compare commits

..

60 Commits

Author SHA1 Message Date
7fe9bf55b8 Git 2.33.6
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-13 21:13:48 +09:00
5f22dcc02d Sync with Git 2.32.5 2022-12-13 21:13:11 +09:00
d96ea538e8 Git 2.32.5
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-13 21:10:27 +09:00
32e357b6df Merge branch 'ps/attr-limits-with-fsck' into maint-2.32 2022-12-13 21:09:56 +09:00
8a755eddf5 Sync with Git 2.31.6 2022-12-13 21:09:40 +09:00
82689d5e5d Git 2.31.6
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-13 21:04:03 +09:00
16128765d7 Sync with Git 2.30.7 2022-12-13 21:02:20 +09:00
b7b37a3371 Git 2.30.7
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-13 20:56:43 +09:00
27ab4784d5 fsck: implement checks for gitattributes
Recently, a vulnerability was reported that can lead to an out-of-bounds
write when reading an unreasonably large gitattributes file. The root
cause of this error are multiple integer overflows in different parts of
the code when there are either too many lines, when paths are too long,
when attribute names are too long, or when there are too many attributes
declared for a pattern.

As all of these are related to size, it seems reasonable to restrict the
size of the gitattributes file via git-fsck(1). This allows us to both
stop distributing known-vulnerable objects via common hosting platforms
that have fsck enabled, and users to protect themselves by enabling the
`fetch.fsckObjects` config.

There are basically two checks:

    1. We verify that size of the gitattributes file is smaller than
       100MB.

    2. We verify that the maximum line length does not exceed 2048
       bytes.

With the preceding commits, both of these conditions would cause us to
either ignore the complete gitattributes file or blob in the first case,
or the specific line in the second case. Now with these consistency
checks added, we also grow the ability to stop distributing such files
in the first place when `receive.fsckObjects` is enabled.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-09 17:07:04 +09:00
f8587c31c9 fsck: move checks for gitattributes
Move the checks for gitattributes so that they can be extended more
readily.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-09 17:05:00 +09:00
a59a8c687f fsck: pull out function to check a set of blobs
In `fsck_finish()` we check all blobs for consistency that we have found
during the tree walk, but that haven't yet been checked. This is only
required for gitmodules right now, but will also be required for a new
check for gitattributes.

Pull out a function `fsck_blobs()` that allows the caller to check a set
of blobs for consistency.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-09 17:05:00 +09:00
bb3a9265e5 fsck: refactor fsck_blob() to allow for more checks
In general, we don't need to validate blob contents as they are opaque
blobs about whose content Git doesn't need to care about. There are some
exceptions though when blobs are linked into trees so that they would be
interpreted by Git. We only have a single such check right now though,
which is the one for gitmodules that has been added in the context of
CVE-2018-11235.

Now we have found another vulnerability with gitattributes that can lead
to out-of-bounds writes and reads. So let's refactor `fsck_blob()` so
that it is more extensible and can check different types of blobs.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-09 17:05:00 +09:00
e0bfc0b3b9 Merge branch 'ps/attr-limits' into maint-2.32 2022-12-09 17:03:49 +09:00
6662a836eb Merge branch 'ps/attr-limits' into maint-2.30 2022-12-09 16:05:52 +09:00
3305300f4c Merge branch 'ps/format-padding-fix' into maint-2.30 2022-12-09 16:02:39 +09:00
304a50adff pretty: restrict input lengths for padding and wrapping formats
Both the padding and wrapping formatting directives allow the caller to
specify an integer that ultimately leads to us adding this many chars to
the result buffer. As a consequence, it is trivial to e.g. allocate 2GB
of RAM via a single formatting directive and cause resource exhaustion
on the machine executing this logic. Furthermore, it is debatable
whether there are any sane usecases that require the user to pad data to
2GB boundaries or to indent wrapped data by 2GB.

Restrict the input sizes to 16 kilobytes at a maximum to limit the
amount of bytes that can be requested by the user. This is not meant
as a fix because there are ways to trivially amplify the amount of
data we generate via formatting directives; the real protection is
achieved by the changes in previous steps to catch and avoid integer
wraparound that causes us to under-allocate and access beyond the
end of allocated memory reagions. But having such a limit
significantly helps fuzzing the pretty format, because the fuzzer is
otherwise quite fast to run out-of-memory as it discovers these
formatters.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-09 14:26:21 +09:00
f930a23943 utf8: refactor strbuf_utf8_replace to not rely on preallocated buffer
In `strbuf_utf8_replace`, we preallocate the destination buffer and then
use `memcpy` to copy bytes into it at computed offsets. This feels
rather fragile and is hard to understand at times. Refactor the code to
instead use `strbuf_add` and `strbuf_addstr` so that we can be sure that
there is no possibility to perform an out-of-bounds write.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-09 14:26:21 +09:00
81c2d4c3a5 utf8: fix checking for glyph width in strbuf_utf8_replace()
In `strbuf_utf8_replace()`, we call `utf8_width()` to compute the width
of the current glyph. If the glyph is a control character though it can
be that `utf8_width()` returns `-1`, but because we assign this value to
a `size_t` the conversion will cause us to underflow. This bug can
easily be triggered with the following command:

    $ git log --pretty='format:xxx%<|(1,trunc)%x10'

>From all I can see though this seems to be a benign underflow that has
no security-related consequences.

Fix the bug by using an `int` instead. When we see a control character,
we now copy it into the target buffer but don't advance the current
width of the string.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-09 14:26:21 +09:00
937b71cc8b utf8: fix overflow when returning string width
The return type of both `utf8_strwidth()` and `utf8_strnwidth()` is
`int`, but we operate on string lengths which are typically of type
`size_t`. This means that when the string is longer than `INT_MAX`, we
will overflow and thus return a negative result.

This can lead to an out-of-bounds write with `--pretty=format:%<1)%B`
and a commit message that is 2^31+1 bytes long:

    =================================================================
    ==26009==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x603000001168 at pc 0x7f95c4e5f427 bp 0x7ffd8541c900 sp 0x7ffd8541c0a8
    WRITE of size 2147483649 at 0x603000001168 thread T0
        #0 0x7f95c4e5f426 in __interceptor_memcpy /usr/src/debug/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:827
        #1 0x5612bbb1068c in format_and_pad_commit pretty.c:1763
        #2 0x5612bbb1087a in format_commit_item pretty.c:1801
        #3 0x5612bbc33bab in strbuf_expand strbuf.c:429
        #4 0x5612bbb110e7 in repo_format_commit_message pretty.c:1869
        #5 0x5612bbb12d96 in pretty_print_commit pretty.c:2161
        #6 0x5612bba0a4d5 in show_log log-tree.c:781
        #7 0x5612bba0d6c7 in log_tree_commit log-tree.c:1117
        #8 0x5612bb691ed5 in cmd_log_walk_no_free builtin/log.c:508
        #9 0x5612bb69235b in cmd_log_walk builtin/log.c:549
        #10 0x5612bb6951a2 in cmd_log builtin/log.c:883
        #11 0x5612bb56c993 in run_builtin git.c:466
        #12 0x5612bb56d397 in handle_builtin git.c:721
        #13 0x5612bb56db07 in run_argv git.c:788
        #14 0x5612bb56e8a7 in cmd_main git.c:923
        #15 0x5612bb803682 in main common-main.c:57
        #16 0x7f95c4c3c28f  (/usr/lib/libc.so.6+0x2328f)
        #17 0x7f95c4c3c349 in __libc_start_main (/usr/lib/libc.so.6+0x23349)
        #18 0x5612bb5680e4 in _start ../sysdeps/x86_64/start.S:115

    0x603000001168 is located 0 bytes to the right of 24-byte region [0x603000001150,0x603000001168)
    allocated by thread T0 here:
        #0 0x7f95c4ebe7ea in __interceptor_realloc /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:85
        #1 0x5612bbcdd556 in xrealloc wrapper.c:136
        #2 0x5612bbc310a3 in strbuf_grow strbuf.c:99
        #3 0x5612bbc32acd in strbuf_add strbuf.c:298
        #4 0x5612bbc33aec in strbuf_expand strbuf.c:418
        #5 0x5612bbb110e7 in repo_format_commit_message pretty.c:1869
        #6 0x5612bbb12d96 in pretty_print_commit pretty.c:2161
        #7 0x5612bba0a4d5 in show_log log-tree.c:781
        #8 0x5612bba0d6c7 in log_tree_commit log-tree.c:1117
        #9 0x5612bb691ed5 in cmd_log_walk_no_free builtin/log.c:508
        #10 0x5612bb69235b in cmd_log_walk builtin/log.c:549
        #11 0x5612bb6951a2 in cmd_log builtin/log.c:883
        #12 0x5612bb56c993 in run_builtin git.c:466
        #13 0x5612bb56d397 in handle_builtin git.c:721
        #14 0x5612bb56db07 in run_argv git.c:788
        #15 0x5612bb56e8a7 in cmd_main git.c:923
        #16 0x5612bb803682 in main common-main.c:57
        #17 0x7f95c4c3c28f  (/usr/lib/libc.so.6+0x2328f)

    SUMMARY: AddressSanitizer: heap-buffer-overflow /usr/src/debug/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:827 in __interceptor_memcpy
    Shadow bytes around the buggy address:
      0x0c067fff81d0: fd fd fd fa fa fa fd fd fd fa fa fa fd fd fd fa
      0x0c067fff81e0: fa fa fd fd fd fd fa fa fd fd fd fd fa fa fd fd
      0x0c067fff81f0: fd fa fa fa fd fd fd fa fa fa fd fd fd fa fa fa
      0x0c067fff8200: fd fd fd fa fa fa fd fd fd fd fa fa 00 00 00 fa
      0x0c067fff8210: fa fa fd fd fd fa fa fa fd fd fd fa fa fa fd fd
    =>0x0c067fff8220: fd fa fa fa fd fd fd fa fa fa 00 00 00[fa]fa fa
      0x0c067fff8230: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c067fff8240: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c067fff8250: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c067fff8260: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c067fff8270: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
    Shadow byte legend (one shadow byte represents 8 application bytes):
      Addressable:           00
      Partially addressable: 01 02 03 04 05 06 07
      Heap left redzone:       fa
      Freed heap region:       fd
      Stack left redzone:      f1
      Stack mid redzone:       f2
      Stack right redzone:     f3
      Stack after return:      f5
      Stack use after scope:   f8
      Global redzone:          f9
      Global init order:       f6
      Poisoned by user:        f7
      Container overflow:      fc
      Array cookie:            ac
      Intra object redzone:    bb
      ASan internal:           fe
      Left alloca redzone:     ca
      Right alloca redzone:    cb
    ==26009==ABORTING

Now the proper fix for this would be to convert both functions to return
an `size_t` instead of an `int`. But given that this commit may be part
of a security release, let's instead do the minimal viable fix and die
in case we see an overflow.

Add a test that would have previously caused us to crash.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-09 14:26:21 +09:00
17d23e8a38 utf8: fix returning negative string width
The `utf8_strnwidth()` function calls `utf8_width()` in a loop and adds
its returned width to the end result. `utf8_width()` can return `-1`
though in case it reads a control character, which means that the
computed string width is going to be wrong. In the worst case where
there are more control characters than non-control characters, we may
even return a negative string width.

Fix this bug by treating control characters as having zero width.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-09 14:26:21 +09:00
522cc87fdc utf8: fix truncated string lengths in utf8_strnwidth()
The `utf8_strnwidth()` function accepts an optional string length as
input parameter. This parameter can either be set to `-1`, in which case
we call `strlen()` on the input. Or it can be set to a positive integer
that indicates a precomputed length, which callers typically compute by
calling `strlen()` at some point themselves.

The input parameter is an `int` though, whereas `strlen()` returns a
`size_t`. This can lead to implementation-defined behaviour though when
the `size_t` cannot be represented by the `int`. In the general case
though this leads to wrap-around and thus to negative string sizes,
which is sure enough to not lead to well-defined behaviour.

Fix this by accepting a `size_t` instead of an `int` as string length.
While this takes away the ability of callers to simply pass in `-1` as
string length, it really is trivial enough to convert them to instead
pass in `strlen()` instead.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-09 14:26:21 +09:00
48050c42c7 pretty: fix integer overflow in wrapping format
The `%w(width,indent1,indent2)` formatting directive can be used to
rewrap text to a specific width and is designed after git-shortlog(1)'s
`-w` parameter. While the three parameters are all stored as `size_t`
internally, `strbuf_add_wrapped_text()` accepts integers as input. As a
result, the casted integers may overflow. As these now-negative integers
are later on passed to `strbuf_addchars()`, we will ultimately run into
implementation-defined behaviour due to casting a negative number back
to `size_t` again. On my platform, this results in trying to allocate
9000 petabyte of memory.

Fix this overflow by using `cast_size_t_to_int()` so that we reject
inputs that cannot be represented as an integer.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-09 14:26:21 +09:00
1de69c0cdd pretty: fix adding linefeed when placeholder is not expanded
When a formatting directive has a `+` or ` ` after the `%`, then we add
either a line feed or space if the placeholder expands to a non-empty
string. In specific cases though this logic doesn't work as expected,
and we try to add the character even in the case where the formatting
directive is empty.

One such pattern is `%w(1)%+d%+w(2)`. `%+d` expands to reference names
pointing to a certain commit, like in `git log --decorate`. For a tagged
commit this would for example expand to `\n (tag: v1.0.0)`, which has a
leading newline due to the `+` modifier and a space added by `%d`. Now
the second wrapping directive will cause us to rewrap the text to
`\n(tag:\nv1.0.0)`, which is one byte shorter due to the missing leading
space. The code that handles the `+` magic now notices that the length
has changed and will thus try to insert a leading line feed at the
original posititon. But as the string was shortened, the original
position is past the buffer's boundary and thus we die with an error.

Now there are two issues here:

    1. We check whether the buffer length has changed, not whether it
       has been extended. This causes us to try and add the character
       past the string boundary.

    2. The current logic does not make any sense whatsoever. When the
       string got expanded due to the rewrap, putting the separator into
       the original position is likely to put it somewhere into the
       middle of the rewrapped contents.

It is debatable whether `%+w()` makes any sense in the first place.
Strictly speaking, the placeholder never expands to a non-empty string,
and consequentially we shouldn't ever accept this combination. We thus
fix the bug by simply refusing `%+w()`.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-09 14:26:21 +09:00
f6e0b9f389 pretty: fix out-of-bounds read when parsing invalid padding format
An out-of-bounds read can be triggered when parsing an incomplete
padding format string passed via `--pretty=format` or in Git archives
when files are marked with the `export-subst` gitattribute.

This bug exists since we have introduced support for truncating output
via the `trunc` keyword a7f01c6b4d (pretty: support truncating in %>, %<
and %><, 2013-04-19). Before this commit, we used to find the end of the
formatting string by using strchr(3P). This function returns a `NULL`
pointer in case the character in question wasn't found. The subsequent
check whether any character was found thus simply checked the returned
pointer. After the commit we switched to strcspn(3P) though, which only
returns the offset to the first found character or to the trailing NUL
byte. As the end pointer is now computed by adding the offset to the
start pointer it won't be `NULL` anymore, and as a consequence the check
doesn't do anything anymore.

The out-of-bounds data that is being read can in fact end up in the
formatted string. As a consequence, it is possible to leak memory
contents either by calling git-log(1) or via git-archive(1) when any of
the archived files is marked with the `export-subst` gitattribute.

    ==10888==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000398 at pc 0x7f0356047cb2 bp 0x7fff3ffb95d0 sp 0x7fff3ffb8d78
    READ of size 1 at 0x602000000398 thread T0
        #0 0x7f0356047cb1 in __interceptor_strchrnul /usr/src/debug/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:725
        #1 0x563b7cec9a43 in strbuf_expand strbuf.c:417
        #2 0x563b7cda7060 in repo_format_commit_message pretty.c:1869
        #3 0x563b7cda8d0f in pretty_print_commit pretty.c:2161
        #4 0x563b7cca04c8 in show_log log-tree.c:781
        #5 0x563b7cca36ba in log_tree_commit log-tree.c:1117
        #6 0x563b7c927ed5 in cmd_log_walk_no_free builtin/log.c:508
        #7 0x563b7c92835b in cmd_log_walk builtin/log.c:549
        #8 0x563b7c92b1a2 in cmd_log builtin/log.c:883
        #9 0x563b7c802993 in run_builtin git.c:466
        #10 0x563b7c803397 in handle_builtin git.c:721
        #11 0x563b7c803b07 in run_argv git.c:788
        #12 0x563b7c8048a7 in cmd_main git.c:923
        #13 0x563b7ca99682 in main common-main.c:57
        #14 0x7f0355e3c28f  (/usr/lib/libc.so.6+0x2328f)
        #15 0x7f0355e3c349 in __libc_start_main (/usr/lib/libc.so.6+0x23349)
        #16 0x563b7c7fe0e4 in _start ../sysdeps/x86_64/start.S:115

    0x602000000398 is located 0 bytes to the right of 8-byte region [0x602000000390,0x602000000398)
    allocated by thread T0 here:
        #0 0x7f0356072faa in __interceptor_strdup /usr/src/debug/gcc/libsanitizer/asan/asan_interceptors.cpp:439
        #1 0x563b7cf7317c in xstrdup wrapper.c:39
        #2 0x563b7cd9a06a in save_user_format pretty.c:40
        #3 0x563b7cd9b3e5 in get_commit_format pretty.c:173
        #4 0x563b7ce54ea0 in handle_revision_opt revision.c:2456
        #5 0x563b7ce597c9 in setup_revisions revision.c:2850
        #6 0x563b7c9269e0 in cmd_log_init_finish builtin/log.c:269
        #7 0x563b7c927362 in cmd_log_init builtin/log.c:348
        #8 0x563b7c92b193 in cmd_log builtin/log.c:882
        #9 0x563b7c802993 in run_builtin git.c:466
        #10 0x563b7c803397 in handle_builtin git.c:721
        #11 0x563b7c803b07 in run_argv git.c:788
        #12 0x563b7c8048a7 in cmd_main git.c:923
        #13 0x563b7ca99682 in main common-main.c:57
        #14 0x7f0355e3c28f  (/usr/lib/libc.so.6+0x2328f)
        #15 0x7f0355e3c349 in __libc_start_main (/usr/lib/libc.so.6+0x23349)
        #16 0x563b7c7fe0e4 in _start ../sysdeps/x86_64/start.S:115

    SUMMARY: AddressSanitizer: heap-buffer-overflow /usr/src/debug/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:725 in __interceptor_strchrnul
    Shadow bytes around the buggy address:
      0x0c047fff8020: fa fa fd fd fa fa 00 06 fa fa 05 fa fa fa fd fd
      0x0c047fff8030: fa fa 00 02 fa fa 06 fa fa fa 05 fa fa fa fd fd
      0x0c047fff8040: fa fa 00 07 fa fa 03 fa fa fa fd fd fa fa 00 00
      0x0c047fff8050: fa fa 00 01 fa fa fd fd fa fa 00 00 fa fa 00 01
      0x0c047fff8060: fa fa 00 06 fa fa 00 06 fa fa 05 fa fa fa 05 fa
    =>0x0c047fff8070: fa fa 00[fa]fa fa fd fa fa fa fd fd fa fa fd fd
      0x0c047fff8080: fa fa fd fd fa fa 00 00 fa fa 00 fa fa fa fd fa
      0x0c047fff8090: fa fa fd fd fa fa 00 00 fa fa fa fa fa fa fa fa
      0x0c047fff80a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c047fff80b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c047fff80c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
    Shadow byte legend (one shadow byte represents 8 application bytes):
      Addressable:           00
      Partially addressable: 01 02 03 04 05 06 07
      Heap left redzone:       fa
      Freed heap region:       fd
      Stack left redzone:      f1
      Stack mid redzone:       f2
      Stack right redzone:     f3
      Stack after return:      f5
      Stack use after scope:   f8
      Global redzone:          f9
      Global init order:       f6
      Poisoned by user:        f7
      Container overflow:      fc
      Array cookie:            ac
      Intra object redzone:    bb
      ASan internal:           fe
      Left alloca redzone:     ca
      Right alloca redzone:    cb
    ==10888==ABORTING

Fix this bug by checking whether `end` points at the trailing NUL byte.
Add a test which catches this out-of-bounds read and which demonstrates
that we used to write out-of-bounds data into the formatted message.

Reported-by: Markus Vervier <markus.vervier@x41-dsec.de>
Original-patch-by: Markus Vervier <markus.vervier@x41-dsec.de>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-09 14:26:21 +09:00
b49f309aa1 pretty: fix out-of-bounds read when left-flushing with stealing
With the `%>>(<N>)` pretty formatter, you can ask git-log(1) et al to
steal spaces. To do so we need to look ahead of the next token to see
whether there are spaces there. This loop takes into account ANSI
sequences that end with an `m`, and if it finds any it will skip them
until it finds the first space. While doing so it does not take into
account the buffer's limits though and easily does an out-of-bounds
read.

Add a test that hits this behaviour. While we don't have an easy way to
verify this, the test causes the following failure when run with
`SANITIZE=address`:

    ==37941==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x603000000baf at pc 0x55ba6f88e0d0 bp 0x7ffc84c50d20 sp 0x7ffc84c50d10
    READ of size 1 at 0x603000000baf thread T0
        #0 0x55ba6f88e0cf in format_and_pad_commit pretty.c:1712
        #1 0x55ba6f88e7b4 in format_commit_item pretty.c:1801
        #2 0x55ba6f9b1ae4 in strbuf_expand strbuf.c:429
        #3 0x55ba6f88f020 in repo_format_commit_message pretty.c:1869
        #4 0x55ba6f890ccf in pretty_print_commit pretty.c:2161
        #5 0x55ba6f7884c8 in show_log log-tree.c:781
        #6 0x55ba6f78b6ba in log_tree_commit log-tree.c:1117
        #7 0x55ba6f40fed5 in cmd_log_walk_no_free builtin/log.c:508
        #8 0x55ba6f41035b in cmd_log_walk builtin/log.c:549
        #9 0x55ba6f4131a2 in cmd_log builtin/log.c:883
        #10 0x55ba6f2ea993 in run_builtin git.c:466
        #11 0x55ba6f2eb397 in handle_builtin git.c:721
        #12 0x55ba6f2ebb07 in run_argv git.c:788
        #13 0x55ba6f2ec8a7 in cmd_main git.c:923
        #14 0x55ba6f581682 in main common-main.c:57
        #15 0x7f2d08c3c28f  (/usr/lib/libc.so.6+0x2328f)
        #16 0x7f2d08c3c349 in __libc_start_main (/usr/lib/libc.so.6+0x23349)
        #17 0x55ba6f2e60e4 in _start ../sysdeps/x86_64/start.S:115

    0x603000000baf is located 1 bytes to the left of 24-byte region [0x603000000bb0,0x603000000bc8)
    allocated by thread T0 here:
        #0 0x7f2d08ebe7ea in __interceptor_realloc /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:85
        #1 0x55ba6fa5b494 in xrealloc wrapper.c:136
        #2 0x55ba6f9aefdc in strbuf_grow strbuf.c:99
        #3 0x55ba6f9b0a06 in strbuf_add strbuf.c:298
        #4 0x55ba6f9b1a25 in strbuf_expand strbuf.c:418
        #5 0x55ba6f88f020 in repo_format_commit_message pretty.c:1869
        #6 0x55ba6f890ccf in pretty_print_commit pretty.c:2161
        #7 0x55ba6f7884c8 in show_log log-tree.c:781
        #8 0x55ba6f78b6ba in log_tree_commit log-tree.c:1117
        #9 0x55ba6f40fed5 in cmd_log_walk_no_free builtin/log.c:508
        #10 0x55ba6f41035b in cmd_log_walk builtin/log.c:549
        #11 0x55ba6f4131a2 in cmd_log builtin/log.c:883
        #12 0x55ba6f2ea993 in run_builtin git.c:466
        #13 0x55ba6f2eb397 in handle_builtin git.c:721
        #14 0x55ba6f2ebb07 in run_argv git.c:788
        #15 0x55ba6f2ec8a7 in cmd_main git.c:923
        #16 0x55ba6f581682 in main common-main.c:57
        #17 0x7f2d08c3c28f  (/usr/lib/libc.so.6+0x2328f)
        #18 0x7f2d08c3c349 in __libc_start_main (/usr/lib/libc.so.6+0x23349)
        #19 0x55ba6f2e60e4 in _start ../sysdeps/x86_64/start.S:115

    SUMMARY: AddressSanitizer: heap-buffer-overflow pretty.c:1712 in format_and_pad_commit
    Shadow bytes around the buggy address:
      0x0c067fff8120: fa fa fd fd fd fa fa fa fd fd fd fa fa fa fd fd
      0x0c067fff8130: fd fd fa fa fd fd fd fd fa fa fd fd fd fa fa fa
      0x0c067fff8140: fd fd fd fa fa fa fd fd fd fa fa fa fd fd fd fa
      0x0c067fff8150: fa fa fd fd fd fd fa fa 00 00 00 fa fa fa fd fd
      0x0c067fff8160: fd fa fa fa fd fd fd fa fa fa fd fd fd fa fa fa
    =>0x0c067fff8170: fd fd fd fa fa[fa]00 00 00 fa fa fa 00 00 00 fa
      0x0c067fff8180: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c067fff8190: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c067fff81a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c067fff81b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c067fff81c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
    Shadow byte legend (one shadow byte represents 8 application bytes):
      Addressable:           00
      Partially addressable: 01 02 03 04 05 06 07
      Heap left redzone:       fa
      Freed heap region:       fd
      Stack left redzone:      f1
      Stack mid redzone:       f2
      Stack right redzone:     f3
      Stack after return:      f5
      Stack use after scope:   f8
      Global redzone:          f9
      Global init order:       f6
      Poisoned by user:        f7
      Container overflow:      fc
      Array cookie:            ac
      Intra object redzone:    bb
      ASan internal:           fe
      Left alloca redzone:     ca
      Right alloca redzone:    cb

Luckily enough, this would only cause us to copy the out-of-bounds data
into the formatted commit in case we really had an ANSI sequence
preceding our buffer. So this bug likely has no security consequences.

Fix it regardless by not traversing past the buffer's start.

Reported-by: Patrick Steinhardt <ps@pks.im>
Reported-by: Eric Sesterhenn <eric.sesterhenn@x41-dsec.de>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-09 14:26:21 +09:00
81dc898df9 pretty: fix out-of-bounds write caused by integer overflow
When using a padding specifier in the pretty format passed to git-log(1)
we need to calculate the string length in several places. These string
lengths are stored in `int`s though, which means that these can easily
overflow when the input lengths exceeds 2GB. This can ultimately lead to
an out-of-bounds write when these are used in a call to memcpy(3P):

        ==8340==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7f1ec62f97fe at pc 0x7f2127e5f427 bp 0x7ffd3bd63de0 sp 0x7ffd3bd63588
    WRITE of size 1 at 0x7f1ec62f97fe thread T0
        #0 0x7f2127e5f426 in __interceptor_memcpy /usr/src/debug/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:827
        #1 0x5628e96aa605 in format_and_pad_commit pretty.c:1762
        #2 0x5628e96aa7f4 in format_commit_item pretty.c:1801
        #3 0x5628e97cdb24 in strbuf_expand strbuf.c:429
        #4 0x5628e96ab060 in repo_format_commit_message pretty.c:1869
        #5 0x5628e96acd0f in pretty_print_commit pretty.c:2161
        #6 0x5628e95a44c8 in show_log log-tree.c:781
        #7 0x5628e95a76ba in log_tree_commit log-tree.c:1117
        #8 0x5628e922bed5 in cmd_log_walk_no_free builtin/log.c:508
        #9 0x5628e922c35b in cmd_log_walk builtin/log.c:549
        #10 0x5628e922f1a2 in cmd_log builtin/log.c:883
        #11 0x5628e9106993 in run_builtin git.c:466
        #12 0x5628e9107397 in handle_builtin git.c:721
        #13 0x5628e9107b07 in run_argv git.c:788
        #14 0x5628e91088a7 in cmd_main git.c:923
        #15 0x5628e939d682 in main common-main.c:57
        #16 0x7f2127c3c28f  (/usr/lib/libc.so.6+0x2328f)
        #17 0x7f2127c3c349 in __libc_start_main (/usr/lib/libc.so.6+0x23349)
        #18 0x5628e91020e4 in _start ../sysdeps/x86_64/start.S:115

    0x7f1ec62f97fe is located 2 bytes to the left of 4831838265-byte region [0x7f1ec62f9800,0x7f1fe62f9839)
    allocated by thread T0 here:
        #0 0x7f2127ebe7ea in __interceptor_realloc /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:85
        #1 0x5628e98774d4 in xrealloc wrapper.c:136
        #2 0x5628e97cb01c in strbuf_grow strbuf.c:99
        #3 0x5628e97ccd42 in strbuf_addchars strbuf.c:327
        #4 0x5628e96aa55c in format_and_pad_commit pretty.c:1761
        #5 0x5628e96aa7f4 in format_commit_item pretty.c:1801
        #6 0x5628e97cdb24 in strbuf_expand strbuf.c:429
        #7 0x5628e96ab060 in repo_format_commit_message pretty.c:1869
        #8 0x5628e96acd0f in pretty_print_commit pretty.c:2161
        #9 0x5628e95a44c8 in show_log log-tree.c:781
        #10 0x5628e95a76ba in log_tree_commit log-tree.c:1117
        #11 0x5628e922bed5 in cmd_log_walk_no_free builtin/log.c:508
        #12 0x5628e922c35b in cmd_log_walk builtin/log.c:549
        #13 0x5628e922f1a2 in cmd_log builtin/log.c:883
        #14 0x5628e9106993 in run_builtin git.c:466
        #15 0x5628e9107397 in handle_builtin git.c:721
        #16 0x5628e9107b07 in run_argv git.c:788
        #17 0x5628e91088a7 in cmd_main git.c:923
        #18 0x5628e939d682 in main common-main.c:57
        #19 0x7f2127c3c28f  (/usr/lib/libc.so.6+0x2328f)
        #20 0x7f2127c3c349 in __libc_start_main (/usr/lib/libc.so.6+0x23349)
        #21 0x5628e91020e4 in _start ../sysdeps/x86_64/start.S:115

    SUMMARY: AddressSanitizer: heap-buffer-overflow /usr/src/debug/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:827 in __interceptor_memcpy
    Shadow bytes around the buggy address:
      0x0fe458c572a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0fe458c572b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0fe458c572c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0fe458c572d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0fe458c572e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
    =>0x0fe458c572f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa[fa]
      0x0fe458c57300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0fe458c57310: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0fe458c57320: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0fe458c57330: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0fe458c57340: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    Shadow byte legend (one shadow byte represents 8 application bytes):
      Addressable:           00
      Partially addressable: 01 02 03 04 05 06 07
      Heap left redzone:       fa
      Freed heap region:       fd
      Stack left redzone:      f1
      Stack mid redzone:       f2
      Stack right redzone:     f3
      Stack after return:      f5
      Stack use after scope:   f8
      Global redzone:          f9
      Global init order:       f6
      Poisoned by user:        f7
      Container overflow:      fc
      Array cookie:            ac
      Intra object redzone:    bb
      ASan internal:           fe
      Left alloca redzone:     ca
      Right alloca redzone:    cb
    ==8340==ABORTING

The pretty format can also be used in `git archive` operations via the
`export-subst` attribute. So this is what in our opinion makes this a
critical issue in the context of Git forges which allow to download an
archive of user supplied Git repositories.

Fix this vulnerability by using `size_t` instead of `int` to track the
string lengths. Add tests which detect this vulnerability when Git is
compiled with the address sanitizer.

Reported-by: Joern Schneeweisz <jschneeweisz@gitlab.com>
Original-patch-by: Joern Schneeweisz <jschneeweisz@gitlab.com>
Modified-by: Taylor  Blau <me@ttalorr.com>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-09 14:26:21 +09:00
a244dc5b0a test-lib: add prerequisite for 64-bit platforms
Allow tests that assume a 64-bit `size_t` to be skipped in 32-bit
platforms and regardless of the size of `long`.

This imitates the `LONG_IS_64BIT` prerequisite.

Signed-off-by: Carlo Marcelo Arenas Belón <carenas@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-09 14:26:04 +09:00
3c50032ff5 attr: ignore overly large gitattributes files
Similar as with the preceding commit, start ignoring gitattributes files
that are overly large to protect us against out-of-bounds reads and
writes caused by integer overflows. Unfortunately, we cannot just define
"overly large" in terms of any preexisting limits in the codebase.

Instead, we choose a very conservative limit of 100MB. This is plenty of
room for specifying gitattributes, and incidentally it is also the limit
for blob sizes for GitHub. While we don't want GitHub to dictate limits
here, it is still sensible to use this fact for an informed decision
given that it is hosting a huge set of repositories. Furthermore, over
at GitLab we scanned a subset of repositories for their root-level
attribute files. We found that 80% of them have a gitattributes file
smaller than 100kB, 99.99% have one smaller than 1MB, and only a single
repository had one that was almost 3MB in size. So enforcing a limit of
100MB seems to give us ample of headroom.

With this limit in place we can be reasonably sure that there is no easy
way to exploit the gitattributes file via integer overflows anymore.
Furthermore, it protects us against resource exhaustion caused by
allocating the in-memory data structures required to represent the
parsed attributes.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-05 15:50:03 +09:00
dfa6b32b5e attr: ignore attribute lines exceeding 2048 bytes
There are two different code paths to read gitattributes: once via a
file, and once via the index. These two paths used to behave differently
because when reading attributes from a file, we used fgets(3P) with a
buffer size of 2kB. Consequentially, we silently truncate line lengths
when lines are longer than that and will then parse the remainder of the
line as a new pattern. It goes without saying that this is entirely
unexpected, but it's even worse that the behaviour depends on how the
gitattributes are parsed.

While this is simply wrong, the silent truncation saves us with the
recently discovered vulnerabilities that can cause out-of-bound writes
or reads with unreasonably long lines due to integer overflows. As the
common path is to read gitattributes via the worktree file instead of
via the index, we can assume that any gitattributes file that had lines
longer than that is already broken anyway. So instead of lifting the
limit here, we can double down on it to fix the vulnerabilities.

Introduce an explicit line length limit of 2kB that is shared across all
paths that read attributes and ignore any line that hits this limit
while printing a warning.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-05 15:33:07 +09:00
d74b1fd54f attr: fix silently splitting up lines longer than 2048 bytes
When reading attributes from a file we use fgets(3P) with a buffer size
of 2048 bytes. This means that as soon as a line exceeds the buffer size
we split it up into multiple parts and parse each of them as a separate
pattern line. This is of course not what the user intended, and even
worse the behaviour is inconsistent with how we read attributes from the
index.

Fix this bug by converting the code to use `strbuf_getline()` instead.
This will indeed read in the whole line, which may theoretically lead to
an out-of-memory situation when the gitattributes file is huge. We're
about to reject any gitattributes files larger than 100MB in the next
commit though, which makes this less of a concern.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-05 15:29:30 +09:00
a60a66e409 attr: harden allocation against integer overflows
When parsing an attributes line, we need to allocate an array that holds
all attributes specified for the given file pattern. The calculation to
determine the number of bytes that need to be allocated was prone to an
overflow though when there was an unreasonable amount of attributes.

Harden the allocation by instead using the `st_` helper functions that
cause us to die when we hit an integer overflow.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-05 15:14:16 +09:00
e1e12e97ac attr: fix integer overflow with more than INT_MAX macros
Attributes have a field that tracks the position in the `all_attrs`
array they're stored inside. This field gets set via `hashmap_get_size`
when adding the attribute to the global map of attributes. But while the
field is of type `int`, the value returned by `hashmap_get_size` is an
`unsigned int`. It can thus happen that the value overflows, where we
would now dereference teh `all_attrs` array at an out-of-bounds value.

We do have a sanity check for this overflow via an assert that verifies
the index matches the new hashmap's size. But asserts are not a proper
mechanism to detect against any such overflows as they may not in fact
be compiled into production code.

Fix this by using an `unsigned int` to track the index and convert the
assert to a call `die()`.

Reported-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-05 15:14:16 +09:00
447ac906e1 attr: fix out-of-bounds read with unreasonable amount of patterns
The `struct attr_stack` tracks the stack of all patterns together with
their attributes. When parsing a gitattributes file that has more than
2^31 such patterns though we may trigger multiple out-of-bounds reads on
64 bit platforms. This is because while the `num_matches` variable is an
unsigned integer, we always use a signed integer to iterate over them.

I have not been able to reproduce this issue due to memory constraints
on my systems. But despite the out-of-bounds reads, the worst thing that
can seemingly happen is to call free(3P) with a garbage pointer when
calling `attr_stack_free()`.

Fix this bug by using unsigned integers to iterate over the array. While
this makes the iteration somewhat awkward when iterating in reverse, it
is at least better than knowingly running into an out-of-bounds read.
While at it, convert the call to `ALLOC_GROW` to use `ALLOC_GROW_BY`
instead.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-05 15:14:16 +09:00
34ace8bad0 attr: fix out-of-bounds write when parsing huge number of attributes
It is possible to trigger an integer overflow when parsing attribute
names when there are more than 2^31 of them for a single pattern. This
can either lead to us dying due to trying to request too many bytes:

     blob=$(perl -e 'print "f" . " a=" x 2147483649' | git hash-object -w --stdin)
     git update-index --add --cacheinfo 100644,$blob,.gitattributes
     git attr-check --all file

    =================================================================
    ==1022==ERROR: AddressSanitizer: requested allocation size 0xfffffff800000032 (0xfffffff800001038 after adjustments for alignment, red zones etc.) exceeds maximum supported size of 0x10000000000 (thread T0)
        #0 0x7fd3efabf411 in __interceptor_calloc /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:77
        #1 0x5563a0a1e3d3 in xcalloc wrapper.c:150
        #2 0x5563a058d005 in parse_attr_line attr.c:384
        #3 0x5563a058e661 in handle_attr_line attr.c:660
        #4 0x5563a058eddb in read_attr_from_index attr.c:769
        #5 0x5563a058ef12 in read_attr attr.c:797
        #6 0x5563a058f24c in bootstrap_attr_stack attr.c:867
        #7 0x5563a058f4a3 in prepare_attr_stack attr.c:902
        #8 0x5563a05905da in collect_some_attrs attr.c:1097
        #9 0x5563a059093d in git_all_attrs attr.c:1128
        #10 0x5563a02f636e in check_attr builtin/check-attr.c:67
        #11 0x5563a02f6c12 in cmd_check_attr builtin/check-attr.c:183
        #12 0x5563a02aa993 in run_builtin git.c:466
        #13 0x5563a02ab397 in handle_builtin git.c:721
        #14 0x5563a02abb2b in run_argv git.c:788
        #15 0x5563a02ac991 in cmd_main git.c:926
        #16 0x5563a05432bd in main common-main.c:57
        #17 0x7fd3ef82228f  (/usr/lib/libc.so.6+0x2328f)

    ==1022==HINT: if you don't care about these errors you may set allocator_may_return_null=1
    SUMMARY: AddressSanitizer: allocation-size-too-big /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:77 in __interceptor_calloc
    ==1022==ABORTING

Or, much worse, it can lead to an out-of-bounds write because we
underallocate and then memcpy(3P) into an array:

    perl -e '
        print "A " . "\rh="x2000000000;
        print "\rh="x2000000000;
        print "\rh="x294967294 . "\n"
    ' >.gitattributes
    git add .gitattributes
    git commit -am "evil attributes"

    $ git clone --quiet /path/to/repo
    =================================================================
    ==15062==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000002550 at pc 0x5555559884d5 bp 0x7fffffffbc60 sp 0x7fffffffbc58
    WRITE of size 8 at 0x602000002550 thread T0
        #0 0x5555559884d4 in parse_attr_line attr.c:393
        #1 0x5555559884d4 in handle_attr_line attr.c:660
        #2 0x555555988902 in read_attr_from_index attr.c:784
        #3 0x555555988902 in read_attr_from_index attr.c:747
        #4 0x555555988a1d in read_attr attr.c:800
        #5 0x555555989b0c in bootstrap_attr_stack attr.c:882
        #6 0x555555989b0c in prepare_attr_stack attr.c:917
        #7 0x555555989b0c in collect_some_attrs attr.c:1112
        #8 0x55555598b141 in git_check_attr attr.c:1126
        #9 0x555555a13004 in convert_attrs convert.c:1311
        #10 0x555555a95e04 in checkout_entry_ca entry.c:553
        #11 0x555555d58bf6 in checkout_entry entry.h:42
        #12 0x555555d58bf6 in check_updates unpack-trees.c:480
        #13 0x555555d5eb55 in unpack_trees unpack-trees.c:2040
        #14 0x555555785ab7 in checkout builtin/clone.c:724
        #15 0x555555785ab7 in cmd_clone builtin/clone.c:1384
        #16 0x55555572443c in run_builtin git.c:466
        #17 0x55555572443c in handle_builtin git.c:721
        #18 0x555555727872 in run_argv git.c:788
        #19 0x555555727872 in cmd_main git.c:926
        #20 0x555555721fa0 in main common-main.c:57
        #21 0x7ffff73f1d09 in __libc_start_main ../csu/libc-start.c:308
        #22 0x555555723f39 in _start (git+0x1cff39)

    0x602000002552 is located 0 bytes to the right of 2-byte region [0x602000002550,0x602000002552) allocated by thread T0 here:
        #0 0x7ffff768c037 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:154
        #1 0x555555d7fff7 in xcalloc wrapper.c:150
        #2 0x55555598815f in parse_attr_line attr.c:384
        #3 0x55555598815f in handle_attr_line attr.c:660
        #4 0x555555988902 in read_attr_from_index attr.c:784
        #5 0x555555988902 in read_attr_from_index attr.c:747
        #6 0x555555988a1d in read_attr attr.c:800
        #7 0x555555989b0c in bootstrap_attr_stack attr.c:882
        #8 0x555555989b0c in prepare_attr_stack attr.c:917
        #9 0x555555989b0c in collect_some_attrs attr.c:1112
        #10 0x55555598b141 in git_check_attr attr.c:1126
        #11 0x555555a13004 in convert_attrs convert.c:1311
        #12 0x555555a95e04 in checkout_entry_ca entry.c:553
        #13 0x555555d58bf6 in checkout_entry entry.h:42
        #14 0x555555d58bf6 in check_updates unpack-trees.c:480
        #15 0x555555d5eb55 in unpack_trees unpack-trees.c:2040
        #16 0x555555785ab7 in checkout builtin/clone.c:724
        #17 0x555555785ab7 in cmd_clone builtin/clone.c:1384
        #18 0x55555572443c in run_builtin git.c:466
        #19 0x55555572443c in handle_builtin git.c:721
        #20 0x555555727872 in run_argv git.c:788
        #21 0x555555727872 in cmd_main git.c:926
        #22 0x555555721fa0 in main common-main.c:57
        #23 0x7ffff73f1d09 in __libc_start_main ../csu/libc-start.c:308

    SUMMARY: AddressSanitizer: heap-buffer-overflow attr.c:393 in parse_attr_line
    Shadow bytes around the buggy address:
      0x0c047fff8450: fa fa 00 02 fa fa 00 07 fa fa fd fd fa fa 00 00
      0x0c047fff8460: fa fa 02 fa fa fa fd fd fa fa 00 06 fa fa 05 fa
      0x0c047fff8470: fa fa fd fd fa fa 00 02 fa fa 06 fa fa fa 05 fa
      0x0c047fff8480: fa fa 07 fa fa fa fd fd fa fa 00 01 fa fa 00 02
      0x0c047fff8490: fa fa 00 03 fa fa 00 fa fa fa 00 01 fa fa 00 03
    =>0x0c047fff84a0: fa fa 00 01 fa fa 00 02 fa fa[02]fa fa fa fa fa
      0x0c047fff84b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c047fff84c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c047fff84d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c047fff84e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c047fff84f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
    Shadow byte legend (one shadow byte represents 8 application bytes):
      Addressable:           00
      Partially addressable: 01 02 03 04 05 06 07
      Heap left redzone:       fa
      Freed heap region:       fd
      Stack left redzone:      f1
      Stack mid redzone:       f2
      Stack right redzone:     f3
      Stack after return:      f5
      Stack use after scope:   f8
      Global redzone:          f9
      Global init order:       f6
      Poisoned by user:        f7
      Container overflow:      fc
      Array cookie:            ac
      Intra object redzone:    bb
      ASan internal:           fe
      Left alloca redzone:     ca
      Right alloca redzone:    cb
      Shadow gap:              cc
    ==15062==ABORTING

Fix this bug by using `size_t` instead to count the number of attributes
so that this value cannot reasonably overflow without running out of
memory before already.

Reported-by: Markus Vervier <markus.vervier@x41-dsec.de>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-05 15:14:16 +09:00
2455720950 attr: fix integer overflow when parsing huge attribute names
It is possible to trigger an integer overflow when parsing attribute
names that are longer than 2^31 bytes because we assign the result of
strlen(3P) to an `int` instead of to a `size_t`. This can lead to an
abort in vsnprintf(3P) with the following reproducer:

    blob=$(perl -e 'print "A " . "B"x2147483648 . "\n"' | git hash-object -w --stdin)
    git update-index --add --cacheinfo 100644,$blob,.gitattributes
    git check-attr --all path

    BUG: strbuf.c:400: your vsnprintf is broken (returned -1)

But furthermore, assuming that the attribute name is even longer than
that, it can cause us to silently truncate the attribute and thus lead
to wrong results.

Fix this integer overflow by using a `size_t` instead. This fixes the
silent truncation of attribute names, but it only partially fixes the
BUG we hit: even though the initial BUG is fixed, we can still hit a BUG
when parsing invalid attribute lines via `report_invalid_attr()`.

This is due to an underlying design issue in vsnprintf(3P) which only
knows to return an `int`, and thus it may always overflow with large
inputs. This issue is benign though: the worst that can happen is that
the error message is misreported to be either truncated or too long, but
due to the buffer being NUL terminated we wouldn't ever do an
out-of-bounds read here.

Reported-by: Markus Vervier <markus.vervier@x41-dsec.de>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-05 15:14:16 +09:00
8d0d48cf21 attr: fix out-of-bounds read with huge attribute names
There is an out-of-bounds read possible when parsing gitattributes that
have an attribute that is 2^31+1 bytes long. This is caused due to an
integer overflow when we assign the result of strlen(3P) to an `int`,
where we use the wrapped-around value in a subsequent call to
memcpy(3P). The following code reproduces the issue:

    blob=$(perl -e 'print "a" x 2147483649 . " attr"' | git hash-object -w --stdin)
    git update-index --add --cacheinfo 100644,$blob,.gitattributes
    git check-attr --all file

    AddressSanitizer:DEADLYSIGNAL
    =================================================================
    ==8451==ERROR: AddressSanitizer: SEGV on unknown address 0x7f93efa00800 (pc 0x7f94f1f8f082 bp 0x7ffddb59b3a0 sp 0x7ffddb59ab28 T0)
    ==8451==The signal is caused by a READ memory access.
        #0 0x7f94f1f8f082  (/usr/lib/libc.so.6+0x176082)
        #1 0x7f94f2047d9c in __interceptor_strspn /usr/src/debug/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:752
        #2 0x560e190f7f26 in parse_attr_line attr.c:375
        #3 0x560e190f9663 in handle_attr_line attr.c:660
        #4 0x560e190f9ddd in read_attr_from_index attr.c:769
        #5 0x560e190f9f14 in read_attr attr.c:797
        #6 0x560e190fa24e in bootstrap_attr_stack attr.c:867
        #7 0x560e190fa4a5 in prepare_attr_stack attr.c:902
        #8 0x560e190fb5dc in collect_some_attrs attr.c:1097
        #9 0x560e190fb93f in git_all_attrs attr.c:1128
        #10 0x560e18e6136e in check_attr builtin/check-attr.c:67
        #11 0x560e18e61c12 in cmd_check_attr builtin/check-attr.c:183
        #12 0x560e18e15993 in run_builtin git.c:466
        #13 0x560e18e16397 in handle_builtin git.c:721
        #14 0x560e18e16b2b in run_argv git.c:788
        #15 0x560e18e17991 in cmd_main git.c:926
        #16 0x560e190ae2bd in main common-main.c:57
        #17 0x7f94f1e3c28f  (/usr/lib/libc.so.6+0x2328f)
        #18 0x7f94f1e3c349 in __libc_start_main (/usr/lib/libc.so.6+0x23349)
        #19 0x560e18e110e4 in _start ../sysdeps/x86_64/start.S:115

    AddressSanitizer can not provide additional info.
    SUMMARY: AddressSanitizer: SEGV (/usr/lib/libc.so.6+0x176082)
    ==8451==ABORTING

Fix this bug by converting the variable to a `size_t` instead.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-05 15:14:16 +09:00
eb22e7dfa2 attr: fix overflow when upserting attribute with overly long name
The function `git_attr_internal()` is called to upsert attributes into
the global map. And while all callers pass a `size_t`, the function
itself accepts an `int` as the attribute name's length. This can lead to
an integer overflow in case the attribute name is longer than `INT_MAX`.

Now this overflow seems harmless as the first thing we do is to call
`attr_name_valid()`, and that function only succeeds in case all chars
in the range of `namelen` match a certain small set of chars. We thus
can't do an out-of-bounds read as NUL is not part of that set and all
strings passed to this function are NUL-terminated. And furthermore, we
wouldn't ever read past the current attribute name anyway due to the
same reason. And if validation fails we will return early.

On the other hand it feels fragile to rely on this behaviour, even more
so given that we pass `namelen` to `FLEX_ALLOC_MEM()`. So let's instead
just do the correct thing here and accept a `size_t` as line length.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-05 15:14:16 +09:00
7800e1dccf Git 2.33.5
Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-10-06 17:42:27 -04:00
3957f3c84e Sync with 2.32.4
Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-10-06 17:42:02 -04:00
af778cd9be Git 2.32.4
Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-10-06 17:41:15 -04:00
9cbd2827c5 Sync with 2.31.5
Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-10-06 17:40:44 -04:00
ecf9b4a443 Git 2.31.5
Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-10-06 17:39:26 -04:00
122512967e Sync with 2.30.6
Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-10-06 17:39:15 -04:00
abd4d67ab0 Git 2.30.6
Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-10-06 17:38:16 -04:00
067aa8fb41 t2080: prepare for changing protocol.file.allow
Explicitly cloning over the "file://" protocol in t1092 in preparation
for merging a security release which will change the default value of
this configuration to be "user".

Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-10-01 00:27:18 -04:00
4a7dab5ce4 t1092: prepare for changing protocol.file.allow
Explicitly cloning over the "file://" protocol in t1092 in preparation
for merging a security release which will change the default value of
this configuration to be "user".

Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-10-01 00:27:14 -04:00
0ca6ead81e alias.c: reject too-long cmdline strings in split_cmdline()
This function improperly uses an int to represent the number of entries
in the resulting argument array. This allows a malicious actor to
intentionally overflow the return value, leading to arbitrary heap
writes.

Because the resulting argv array is typically passed to execv(), it may
be possible to leverage this attack to gain remote code execution on a
victim machine. This was almost certainly the case for certain
configurations of git-shell until the previous commit limited the size
of input it would accept. Other calls to split_cmdline() are typically
limited by the size of argv the OS is willing to hand us, so are
similarly protected.

So this is not strictly fixing a known vulnerability, but is a hardening
of the function that is worth doing to protect against possible unknown
vulnerabilities.

One approach to fixing this would be modifying the signature of
`split_cmdline()` to look something like:

    int split_cmdline(char *cmdline, const char ***argv, size_t *argc);

Where the return value of `split_cmdline()` is negative for errors, and
zero otherwise. If non-NULL, the `*argc` pointer is modified to contain
the size of the `**argv` array.

But this implies an absurdly large `argv` array, which more than likely
larger than the system's argument limit. So even if split_cmdline()
allowed this, it would fail immediately afterwards when we called
execv(). So instead of converting all of `split_cmdline()`'s callers to
work with `size_t` types in this patch, instead pursue the minimal fix
here to prevent ever returning an array with more than INT_MAX entries
in it.

Signed-off-by: Kevin Backhouse <kevinbackhouse@github.com>
Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-10-01 00:23:38 -04:00
71ad7fe1bc shell: limit size of interactive commands
When git-shell is run in interactive mode (which must be enabled by
creating $HOME/git-shell-commands), it reads commands from stdin, one
per line, and executes them.

We read the commands with git_read_line_interactively(), which uses a
strbuf under the hood. That means we'll accept an input of arbitrary
size (limited only by how much heap we can allocate). That creates two
problems:

  - the rest of the code is not prepared to handle large inputs. The
    most serious issue here is that split_cmdline() uses "int" for most
    of its types, which can lead to integer overflow and out-of-bounds
    array reads and writes. But even with that fixed, we assume that we
    can feed the command name to snprintf() (via xstrfmt()), which is
    stuck for historical reasons using "int", and causes it to fail (and
    even trigger a BUG() call).

  - since the point of git-shell is to take input from untrusted or
    semi-trusted clients, it's a mild denial-of-service. We'll allocate
    as many bytes as the client sends us (actually twice as many, since
    we immediately duplicate the buffer).

We can fix both by just limiting the amount of per-command input we're
willing to receive.

We should also fix split_cmdline(), of course, which is an accident
waiting to happen, but that can come on top. Most calls to
split_cmdline(), including the other one in git-shell, are OK because
they are reading from an OS-provided argv, which is limited in practice.
This patch should eliminate the immediate vulnerabilities.

I picked 4MB as an arbitrary limit. It's big enough that nobody should
ever run into it in practice (since the point is to run the commands via
exec, we're subject to OS limits which are typically much lower). But
it's small enough that allocating it isn't that big a deal.

The code is mostly just swapping out fgets() for the strbuf call, but we
have to add a few niceties like flushing and trimming line endings. We
could simplify things further by putting the buffer on the stack, but
4MB is probably a bit much there. Note that we'll _always_ allocate 4MB,
which for normal, non-malicious requests is more than we would before
this patch. But on the other hand, other git programs are happy to use
96MB for a delta cache. And since we'd never touch most of those pages,
on a lazy-allocating OS like Linux they won't even get allocated to
actual RAM.

The ideal would be a version of strbuf_getline() that accepted a maximum
value. But for a minimal vulnerability fix, let's keep things localized
and simple. We can always refactor further on top.

The included test fails in an obvious way with ASan or UBSan (which
notice the integer overflow and out-of-bounds reads). Without them, it
fails in a less obvious way: we may segfault, or we may try to xstrfmt()
a long string, leading to a BUG(). Either way, it fails reliably before
this patch, and passes with it. Note that we don't need an EXPENSIVE
prereq on it. It does take 10-15s to fail before this patch, but with
the new limit, we fail almost immediately (and the perl process
generating 2GB of data exits via SIGPIPE).

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-10-01 00:23:38 -04:00
32696a4cbe shell: add basic tests
We have no tests of even basic functionality of git-shell. Let's add a
couple of obvious ones. This will serve as a framework for adding tests
for new things we fix, as well as making sure we don't screw anything up
too badly while doing so.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-10-01 00:23:38 -04:00
a1d4f67c12 transport: make protocol.file.allow be "user" by default
An earlier patch discussed and fixed a scenario where Git could be used
as a vector to exfiltrate sensitive data through a Docker container when
a potential victim clones a suspicious repository with local submodules
that contain symlinks.

That security hole has since been plugged, but a similar one still
exists.  Instead of convincing a would-be victim to clone an embedded
submodule via the "file" protocol, an attacker could convince an
individual to clone a repository that has a submodule pointing to a
valid path on the victim's filesystem.

For example, if an individual (with username "foo") has their home
directory ("/home/foo") stored as a Git repository, then an attacker
could exfiltrate data by convincing a victim to clone a malicious
repository containing a submodule pointing at "/home/foo/.git" with
`--recurse-submodules`. Doing so would expose any sensitive contents in
stored in "/home/foo" tracked in Git.

For systems (such as Docker) that consider everything outside of the
immediate top-level working directory containing a Dockerfile as
inaccessible to the container (with the exception of volume mounts, and
so on), this is a violation of trust by exposing unexpected contents in
the working copy.

To mitigate the likelihood of this kind of attack, adjust the "file://"
protocol's default policy to be "user" to prevent commands that execute
without user input (including recursive submodule initialization) from
taking place by default.

Suggested-by: Jeff King <peff@peff.net>
Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-10-01 00:23:38 -04:00
f4a32a550f t/t9NNN: allow local submodules
To prepare for the default value of `protocol.file.allow` to change to
"user", ensure tests that rely on local submodules can initialize them
over the file protocol.

Tests that interact with submodules a handful of times use
`test_config_global`.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-10-01 00:23:38 -04:00
0d3beb71da t/t7NNN: allow local submodules
To prepare for the default value of `protocol.file.allow` to change to
"user", ensure tests that rely on local submodules can initialize them
over the file protocol.

Tests that only need to interact with submodules in a limited capacity
have individual Git commands annotated with the appropriate
configuration via `-c`. Tests that interact with submodules a handful of
times use `test_config_global` instead. Test scripts that rely on
submodules throughout use a `git config --global` during a setup test
towards the beginning of the script.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-10-01 00:23:38 -04:00
0f21b8f468 t/t6NNN: allow local submodules
To prepare for the default value of `protocol.file.allow` to change to
"user", ensure tests that rely on local submodules can initialize them
over the file protocol.

Tests that only need to interact with submodules in a limited capacity
have individual Git commands annotated with the appropriate
configuration via `-c`.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-10-01 00:23:38 -04:00
225d2d50cc t/t5NNN: allow local submodules
To prepare for the default value of `protocol.file.allow` to change to
"user", ensure tests that rely on local submodules can initialize them
over the file protocol.

Tests that only need to interact with submodules in a limited capacity
have individual Git commands annotated with the appropriate
configuration via `-c`. Tests that interact with submodules a handful of
times use `test_config_global` instead. Test scripts that rely on
submodules throughout use a `git config --global` during a setup test
towards the beginning of the script.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-10-01 00:23:38 -04:00
ac7e57fa28 t/t4NNN: allow local submodules
To prepare for the default value of `protocol.file.allow` to change to
"user", ensure tests that rely on local submodules can initialize them
over the file protocol.

Tests that only need to interact with submodules in a limited capacity
have individual Git commands annotated with the appropriate
configuration via `-c`. Tests that interact with submodules a handful of
times use `test_config_global` instead. Test scripts that rely on
submodules throughout use a `git config --global` during a setup test
towards the beginning of the script.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-10-01 00:23:38 -04:00
f8d510ed0b t/t3NNN: allow local submodules
To prepare for the default value of `protocol.file.allow` to change to
"user", ensure tests that rely on local submodules can initialize them
over the file protocol.

Tests that only need to interact with submodules in a limited capacity
have individual Git commands annotated with the appropriate
configuration via `-c`. Tests that interact with submodules a handful of
times use `test_config_global` instead. Test scripts that rely on
submodules throughout use a `git config --global` during a setup test
towards the beginning of the script.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-10-01 00:23:38 -04:00
99f4abb8da t/2NNNN: allow local submodules
To prepare for the default value of `protocol.file.allow` to change to
"user", ensure tests that rely on local submodules can initialize them
over the file protocol.

Tests that only need to interact with submodules in a limited capacity
have individual Git commands annotated with the appropriate
configuration via `-c`. Tests that interact with submodules a handful of
times use `test_config_global` instead. Test scripts that rely on
submodules throughout use a `git config --global` during a setup test
towards the beginning of the script.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-10-01 00:23:38 -04:00
8a96dbcb33 t/t1NNN: allow local submodules
To prepare for the default value of `protocol.file.allow` to change to
"user", ensure tests that rely on local submodules can initialize them
over the file protocol.

Tests that only need to interact with submodules in a limited capacity
have individual Git commands annotated with the appropriate
configuration via `-c`. Tests that interact with submodules a handful of
times use `test_config_global` instead.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-10-01 00:23:38 -04:00
7de0c306f7 t/lib-submodule-update.sh: allow local submodules
To prepare for changing the default value of `protocol.file.allow` to
"user", update the `prolog()` function in lib-submodule-update to allow
submodules to be cloned over the file protocol.

This is used by a handful of submodule-related test scripts, which
themselves will have to tweak the value of `protocol.file.allow` in
certain locations. Those will be done in subsequent commits.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-10-01 00:23:38 -04:00
6f054f9fb3 builtin/clone.c: disallow --local clones with symlinks
When cloning a repository with `--local`, Git relies on either making a
hardlink or copy to every file in the "objects" directory of the source
repository. This is done through the callpath `cmd_clone()` ->
`clone_local()` -> `copy_or_link_directory()`.

The way this optimization works is by enumerating every file and
directory recursively in the source repository's `$GIT_DIR/objects`
directory, and then either making a copy or hardlink of each file. The
only exception to this rule is when copying the "alternates" file, in
which case paths are rewritten to be absolute before writing a new
"alternates" file in the destination repo.

One quirk of this implementation is that it dereferences symlinks when
cloning. This behavior was most recently modified in 36596fd2df (clone:
better handle symlinked files at .git/objects/, 2019-07-10), which
attempted to support `--local` clones of repositories with symlinks in
their objects directory in a platform-independent way.

Unfortunately, this behavior of dereferencing symlinks (that is,
creating a hardlink or copy of the source's link target in the
destination repository) can be used as a component in attacking a
victim by inadvertently exposing the contents of file stored outside of
the repository.

Take, for example, a repository that stores a Dockerfile and is used to
build Docker images. When building an image, Docker copies the directory
contents into the VM, and then instructs the VM to execute the
Dockerfile at the root of the copied directory. This protects against
directory traversal attacks by copying symbolic links as-is without
dereferencing them.

That is, if a user has a symlink pointing at their private key material
(where the symlink is present in the same directory as the Dockerfile,
but the key itself is present outside of that directory), the key is
unreadable to a Docker image, since the link will appear broken from the
container's point of view.

This behavior enables an attack whereby a victim is convinced to clone a
repository containing an embedded submodule (with a URL like
"file:///proc/self/cwd/path/to/submodule") which has a symlink pointing
at a path containing sensitive information on the victim's machine. If a
user is tricked into doing this, the contents at the destination of
those symbolic links are exposed to the Docker image at runtime.

One approach to preventing this behavior is to recreate symlinks in the
destination repository. But this is problematic, since symlinking the
objects directory are not well-supported. (One potential problem is that
when sharing, e.g. a "pack" directory via symlinks, different writers
performing garbage collection may consider different sets of objects to
be reachable, enabling a situation whereby garbage collecting one
repository may remove reachable objects in another repository).

Instead, prohibit the local clone optimization when any symlinks are
present in the `$GIT_DIR/objects` directory of the source repository.
Users may clone the repository again by prepending the "file://" scheme
to their clone URL, or by adding the `--no-local` option to their `git
clone` invocation.

The directory iterator used by `copy_or_link_directory()` must no longer
dereference symlinks (i.e., it *must* call `lstat()` instead of `stat()`
in order to discover whether or not there are symlinks present). This has
no bearing on the overall behavior, since we will immediately `die()` on
encounter a symlink.

Note that t5604.33 suggests that we do support local clones with
symbolic links in the source repository's objects directory, but this
was likely unintentional, or at least did not take into consideration
the problem with sharing parts of the objects directory with symbolic
links at the time. Update this test to reflect which options are and
aren't supported.

Helped-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-10-01 00:23:38 -04:00
644 changed files with 70823 additions and 80163 deletions

View File

@ -1,105 +0,0 @@
name: git-l10n
on: [push, pull_request_target]
jobs:
git-po-helper:
if: >-
endsWith(github.repository, '/git-po') ||
contains(github.head_ref, 'l10n') ||
contains(github.ref, 'l10n')
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- name: Setup base and head objects
id: setup-tips
run: |
if test "${{ github.event_name }}" = "pull_request_target"
then
base=${{ github.event.pull_request.base.sha }}
head=${{ github.event.pull_request.head.sha }}
else
base=${{ github.event.before }}
head=${{ github.event.after }}
fi
echo "::set-output name=base::$base"
echo "::set-output name=head::$head"
- name: Run partial clone
run: |
git -c init.defaultBranch=master init --bare .
git remote add \
--mirror=fetch \
origin \
https://github.com/${{ github.repository }}
# Fetch tips that may be unreachable from github.ref:
# - For a forced push, "$base" may be unreachable.
# - For a "pull_request_target" event, "$head" may be unreachable.
args=
for commit in \
${{ steps.setup-tips.outputs.base }} \
${{ steps.setup-tips.outputs.head }}
do
case $commit in
*[^0]*)
args="$args $commit"
;;
*)
# Should not fetch ZERO-OID.
;;
esac
done
git -c protocol.version=2 fetch \
--progress \
--no-tags \
--no-write-fetch-head \
--filter=blob:none \
origin \
${{ github.ref }} \
$args
- uses: actions/setup-go@v2
with:
go-version: '>=1.16'
- name: Install git-po-helper
run: go install github.com/git-l10n/git-po-helper@main
- name: Install other dependencies
run: |
sudo apt-get update -q &&
sudo apt-get install -q -y gettext
- name: Run git-po-helper
id: check-commits
run: |
exit_code=0
git-po-helper check-commits \
--github-action-event="${{ github.event_name }}" -- \
${{ steps.setup-tips.outputs.base }}..${{ steps.setup-tips.outputs.head }} \
>git-po-helper.out 2>&1 || exit_code=$?
if test $exit_code -ne 0 || grep -q WARNING git-po-helper.out
then
# Remove ANSI colors which are proper for console logs but not
# proper for PR comment.
echo "COMMENT_BODY<<EOF" >>$GITHUB_ENV
perl -pe 's/\e\[[0-9;]*m//g; s/\bEOF$//g' git-po-helper.out >>$GITHUB_ENV
echo "EOF" >>$GITHUB_ENV
fi
cat git-po-helper.out
exit $exit_code
- name: Create comment in pull request for report
uses: mshick/add-pr-comment@v1
if: >-
always() &&
github.event_name == 'pull_request_target' &&
env.COMMENT_BODY != ''
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
repo-token-user-login: 'github-actions[bot]'
message: >
${{ steps.check-commits.outcome == 'failure' && 'Errors and warnings' || 'Warnings' }}
found by [git-po-helper](https://github.com/git-l10n/git-po-helper#readme) in workflow
[#${{ github.run_number }}](${{ env.GITHUB_SERVER_URL }}/${{ github.repository }}/actions/runs/${{ github.run_id }}):
```
${{ env.COMMENT_BODY }}
```

View File

@ -88,7 +88,7 @@ jobs:
env:
HOME: ${{runner.workspace}}
NO_PERL: 1
run: . /etc/profile && ci/make-test-artifacts.sh artifacts
run: ci/make-test-artifacts.sh artifacts
- name: zip up tracked files
run: git archive -o artifacts/tracked.tar.gz HEAD
- name: upload tracked files and build artifacts
@ -115,7 +115,7 @@ jobs:
- uses: git-for-windows/setup-git-for-windows-sdk@v1
- name: test
shell: bash
run: . /etc/profile && ci/run-test-slice.sh ${{matrix.nr}} 10
run: ci/run-test-slice.sh ${{matrix.nr}} 10
- name: ci/print-test-failures.sh
if: failure()
shell: bash
@ -198,7 +198,8 @@ jobs:
shell: bash
env:
NO_SVN_TESTS: 1
run: . /etc/profile && ci/run-test-slice.sh ${{matrix.nr}} 10
GIT_TEST_SKIP_REBASE_P: 1
run: ci/run-test-slice.sh ${{matrix.nr}} 10
- name: ci/print-test-failures.sh
if: failure()
shell: bash
@ -231,9 +232,6 @@ jobs:
- jobname: linux-gcc-default
cc: gcc
pool: ubuntu-latest
- jobname: linux-leaks
cc: gcc
pool: ubuntu-latest
env:
CC: ${{matrix.vector.cc}}
jobname: ${{matrix.vector.jobname}}

3
.gitignore vendored
View File

@ -125,6 +125,7 @@
/git-range-diff
/git-read-tree
/git-rebase
/git-rebase--preserve-merges
/git-receive-pack
/git-reflog
/git-remote
@ -189,7 +190,6 @@
/gitweb/static/gitweb.min.*
/config-list.h
/command-list.h
/hook-list.h
*.tar.gz
*.dsc
*.deb
@ -224,7 +224,6 @@
*.lib
*.res
*.sln
*.sp
*.suo
*.ncb
*.vcproj

View File

@ -14,5 +14,4 @@ manpage-base-url.xsl
SubmittingPatches.txt
tmp-doc-diff/
GIT-ASCIIDOCFLAGS
/.build/
/GIT-EXCLUDED-PROGRAMS

View File

@ -90,7 +90,6 @@ SP_ARTICLES += $(API_DOCS)
TECH_DOCS += MyFirstContribution
TECH_DOCS += MyFirstObjectWalk
TECH_DOCS += SubmittingPatches
TECH_DOCS += technical/bundle-format
TECH_DOCS += technical/hash-function-transition
TECH_DOCS += technical/http-protocol
TECH_DOCS += technical/index-format
@ -226,7 +225,6 @@ endif
ifneq ($(findstring $(MAKEFLAGS),s),s)
ifndef V
QUIET = @
QUIET_ASCIIDOC = @echo ' ' ASCIIDOC $@;
QUIET_XMLTO = @echo ' ' XMLTO $@;
QUIET_DB2TEXI = @echo ' ' DB2TEXI $@;
@ -234,15 +232,11 @@ ifndef V
QUIET_DBLATEX = @echo ' ' DBLATEX $@;
QUIET_XSLTPROC = @echo ' ' XSLTPROC $@;
QUIET_GEN = @echo ' ' GEN $@;
QUIET_LINT = @echo ' ' LINT $@;
QUIET_STDERR = 2> /dev/null
QUIET_SUBDIR0 = +@subdir=
QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \
$(MAKE) $(PRINT_DIR) -C $$subdir
QUIET_LINT_GITLINK = @echo ' ' LINT GITLINK $<;
QUIET_LINT_MANSEC = @echo ' ' LINT MAN SEC $<;
QUIET_LINT_MANEND = @echo ' ' LINT MAN END $<;
export V
endif
endif
@ -290,7 +284,7 @@ install-html: html
../GIT-VERSION-FILE: FORCE
$(QUIET_SUBDIR0)../ $(QUIET_SUBDIR1) GIT-VERSION-FILE
ifneq ($(filter-out lint-docs clean,$(MAKECMDGOALS)),)
ifneq ($(MAKECMDGOALS),clean)
-include ../GIT-VERSION-FILE
endif
@ -349,7 +343,6 @@ GIT-ASCIIDOCFLAGS: FORCE
fi
clean:
$(RM) -rf .build/
$(RM) *.xml *.xml+ *.html *.html+ *.1 *.5 *.7
$(RM) *.texi *.texi+ *.texi++ git.info gitman.info
$(RM) *.pdf
@ -463,61 +456,14 @@ quick-install-html: require-htmlrepo
print-man1:
@for i in $(MAN1_TXT); do echo $$i; done
## Lint: Common
.build:
$(QUIET)mkdir $@
.build/lint-docs: | .build
$(QUIET)mkdir $@
## Lint: gitlink
.build/lint-docs/gitlink: | .build/lint-docs
$(QUIET)mkdir $@
.build/lint-docs/gitlink/howto: | .build/lint-docs/gitlink
$(QUIET)mkdir $@
.build/lint-docs/gitlink/config: | .build/lint-docs/gitlink
$(QUIET)mkdir $@
LINT_DOCS_GITLINK = $(patsubst %.txt,.build/lint-docs/gitlink/%.ok,$(HOWTO_TXT) $(DOC_DEP_TXT))
$(LINT_DOCS_GITLINK): | .build/lint-docs/gitlink
$(LINT_DOCS_GITLINK): | .build/lint-docs/gitlink/howto
$(LINT_DOCS_GITLINK): | .build/lint-docs/gitlink/config
$(LINT_DOCS_GITLINK): lint-gitlink.perl
$(LINT_DOCS_GITLINK): .build/lint-docs/gitlink/%.ok: %.txt
$(QUIET_LINT_GITLINK)$(PERL_PATH) lint-gitlink.perl \
$< \
lint-docs::
$(QUIET_LINT)$(PERL_PATH) lint-gitlink.perl \
$(HOWTO_TXT) $(DOC_DEP_TXT) \
--section=1 $(MAN1_TXT) \
--section=5 $(MAN5_TXT) \
--section=7 $(MAN7_TXT) >$@
.PHONY: lint-docs-gitlink
lint-docs-gitlink: $(LINT_DOCS_GITLINK)
## Lint: man-end-blurb
.build/lint-docs/man-end-blurb: | .build/lint-docs
$(QUIET)mkdir $@
LINT_DOCS_MAN_END_BLURB = $(patsubst %.txt,.build/lint-docs/man-end-blurb/%.ok,$(MAN_TXT))
$(LINT_DOCS_MAN_END_BLURB): | .build/lint-docs/man-end-blurb
$(LINT_DOCS_MAN_END_BLURB): lint-man-end-blurb.perl
$(LINT_DOCS_MAN_END_BLURB): .build/lint-docs/man-end-blurb/%.ok: %.txt
$(QUIET_LINT_MANEND)$(PERL_PATH) lint-man-end-blurb.perl $< >$@
.PHONY: lint-docs-man-end-blurb
lint-docs-man-end-blurb: $(LINT_DOCS_MAN_END_BLURB)
## Lint: man-section-order
.build/lint-docs/man-section-order: | .build/lint-docs
$(QUIET)mkdir $@
LINT_DOCS_MAN_SECTION_ORDER = $(patsubst %.txt,.build/lint-docs/man-section-order/%.ok,$(MAN_TXT))
$(LINT_DOCS_MAN_SECTION_ORDER): | .build/lint-docs/man-section-order
$(LINT_DOCS_MAN_SECTION_ORDER): lint-man-section-order.perl
$(LINT_DOCS_MAN_SECTION_ORDER): .build/lint-docs/man-section-order/%.ok: %.txt
$(QUIET_LINT_MANSEC)$(PERL_PATH) lint-man-section-order.perl $< >$@
.PHONY: lint-docs-man-section-order
lint-docs-man-section-order: $(LINT_DOCS_MAN_SECTION_ORDER)
## Lint: list of targets above
.PHONY: lint-docs
lint-docs: lint-docs-gitlink
lint-docs: lint-docs-man-end-blurb
lint-docs: lint-docs-man-section-order
--section=7 $(MAN7_TXT); \
$(PERL_PATH) lint-man-end-blurb.perl $(MAN_TXT); \
$(PERL_PATH) lint-man-section-order.perl $(MAN_TXT);
ifeq ($(wildcard po/Makefile),po/Makefile)
doc-l10n install-l10n::

View File

@ -1029,42 +1029,22 @@ kidding - be patient!)
[[v2-git-send-email]]
=== Sending v2
This section will focus on how to send a v2 of your patchset. To learn what
should go into v2, skip ahead to <<reviewing,Responding to Reviews>> for
information on how to handle comments from reviewers.
Skip ahead to <<reviewing,Responding to Reviews>> for information on how to
handle comments from reviewers. Continue this section when your topic branch is
shaped the way you want it to look for your patchset v2.
We'll reuse our `psuh` topic branch for v2. Before we make any changes, we'll
mark the tip of our v1 branch for easy reference:
When you're ready with the next iteration of your patch, the process is fairly
similar.
First, generate your v2 patches again:
----
$ git checkout psuh
$ git branch psuh-v1
$ git format-patch -v2 --cover-letter -o psuh/ master..psuh
----
Refine your patch series by using `git rebase -i` to adjust commits based upon
reviewer comments. Once the patch series is ready for submission, generate your
patches again, but with some new flags:
----
$ git format-patch -v2 --cover-letter -o psuh/ --range-diff master..psuh-v1 master..
----
The `--range-diff master..psuh-v1` parameter tells `format-patch` to include a
range-diff between `psuh-v1` and `psuh` in the cover letter (see
linkgit:git-range-diff[1]). This helps tell reviewers about the differences
between your v1 and v2 patches.
The `-v2` parameter tells `format-patch` to output your patches
as version "2". For instance, you may notice that your v2 patches are
all named like `v2-000n-my-commit-subject.patch`. `-v2` will also format
your patches by prefixing them with "[PATCH v2]" instead of "[PATCH]",
and your range-diff will be prefaced with "Range-diff against v1".
Afer you run this command, `format-patch` will output the patches to the `psuh/`
directory, alongside the v1 patches. Using a single directory makes it easy to
refer to the old v1 patches while proofreading the v2 patches, but you will need
to be careful to send out only the v2 patches. We will use a pattern like
"psuh/v2-*.patch" (not "psuh/*.patch", which would match v1 and v2 patches).
This will add your v2 patches, all named like `v2-000n-my-commit-subject.patch`,
to the `psuh/` directory. You may notice that they are sitting alongside the v1
patches; that's fine, but be careful when you are ready to send them.
Edit your cover letter again. Now is a good time to mention what's different
between your last version and now, if it's something significant. You do not
@ -1102,7 +1082,7 @@ to the command:
----
$ git send-email --to=target@example.com
--in-reply-to="<foo.12345.author@example.com>"
psuh/v2-*.patch
psuh/v2*
----
[[single-patch]]

View File

@ -0,0 +1,60 @@
Git v2.30.6 Release Notes
=========================
This release addresses the security issues CVE-2022-39253 and
CVE-2022-39260.
Fixes since v2.30.5
-------------------
* CVE-2022-39253:
When relying on the `--local` clone optimization, Git dereferences
symbolic links in the source repository before creating hardlinks
(or copies) of the dereferenced link in the destination repository.
This can lead to surprising behavior where arbitrary files are
present in a repository's `$GIT_DIR` when cloning from a malicious
repository.
Git will no longer dereference symbolic links via the `--local`
clone mechanism, and will instead refuse to clone repositories that
have symbolic links present in the `$GIT_DIR/objects` directory.
Additionally, the value of `protocol.file.allow` is changed to be
"user" by default.
* CVE-2022-39260:
An overly-long command string given to `git shell` can result in
overflow in `split_cmdline()`, leading to arbitrary heap writes and
remote code execution when `git shell` is exposed and the directory
`$HOME/git-shell-commands` exists.
`git shell` is taught to refuse interactive commands that are
longer than 4MiB in size. `split_cmdline()` is hardened to reject
inputs larger than 2GiB.
Credit for finding CVE-2022-39253 goes to Cory Snider of Mirantis. The
fix was authored by Taylor Blau, with help from Johannes Schindelin.
Credit for finding CVE-2022-39260 goes to Kevin Backhouse of GitHub.
The fix was authored by Kevin Backhouse, Jeff King, and Taylor Blau.
Jeff King (2):
shell: add basic tests
shell: limit size of interactive commands
Kevin Backhouse (1):
alias.c: reject too-long cmdline strings in split_cmdline()
Taylor Blau (11):
builtin/clone.c: disallow `--local` clones with symlinks
t/lib-submodule-update.sh: allow local submodules
t/t1NNN: allow local submodules
t/2NNNN: allow local submodules
t/t3NNN: allow local submodules
t/t4NNN: allow local submodules
t/t5NNN: allow local submodules
t/t6NNN: allow local submodules
t/t7NNN: allow local submodules
t/t9NNN: allow local submodules
transport: make `protocol.file.allow` be "user" by default

View File

@ -0,0 +1,86 @@
Git v2.30.7 Release Notes
=========================
This release addresses the security issues CVE-2022-41903 and
CVE-2022-23521.
Fixes since v2.30.6
-------------------
* CVE-2022-41903:
git log has the ability to display commits using an arbitrary
format with its --format specifiers. This functionality is also
exposed to git archive via the export-subst gitattribute.
When processing the padding operators (e.g., %<(, %<|(, %>(,
%>>(, or %><( ), an integer overflow can occur in
pretty.c::format_and_pad_commit() where a size_t is improperly
stored as an int, and then added as an offset to a subsequent
memcpy() call.
This overflow can be triggered directly by a user running a
command which invokes the commit formatting machinery (e.g., git
log --format=...). It may also be triggered indirectly through
git archive via the export-subst mechanism, which expands format
specifiers inside of files within the repository during a git
archive.
This integer overflow can result in arbitrary heap writes, which
may result in remote code execution.
* CVE-2022-23521:
gitattributes are a mechanism to allow defining attributes for
paths. These attributes can be defined by adding a `.gitattributes`
file to the repository, which contains a set of file patterns and
the attributes that should be set for paths matching this pattern.
When parsing gitattributes, multiple integer overflows can occur
when there is a huge number of path patterns, a huge number of
attributes for a single pattern, or when the declared attribute
names are huge.
These overflows can be triggered via a crafted `.gitattributes` file
that may be part of the commit history. Git silently splits lines
longer than 2KB when parsing gitattributes from a file, but not when
parsing them from the index. Consequentially, the failure mode
depends on whether the file exists in the working tree, the index or
both.
This integer overflow can result in arbitrary heap reads and writes,
which may result in remote code execution.
Credit for finding CVE-2022-41903 goes to Joern Schneeweisz of GitLab.
An initial fix was authored by Markus Vervier of X41 D-Sec. Credit for
finding CVE-2022-23521 goes to Markus Vervier and Eric Sesterhenn of X41
D-Sec. This work was sponsored by OSTIF.
The proposed fixes have been polished and extended to cover additional
findings by Patrick Steinhardt of GitLab, with help from others on the
Git security mailing list.
Patrick Steinhardt (21):
attr: fix overflow when upserting attribute with overly long name
attr: fix out-of-bounds read with huge attribute names
attr: fix integer overflow when parsing huge attribute names
attr: fix out-of-bounds write when parsing huge number of attributes
attr: fix out-of-bounds read with unreasonable amount of patterns
attr: fix integer overflow with more than INT_MAX macros
attr: harden allocation against integer overflows
attr: fix silently splitting up lines longer than 2048 bytes
attr: ignore attribute lines exceeding 2048 bytes
attr: ignore overly large gitattributes files
pretty: fix out-of-bounds write caused by integer overflow
pretty: fix out-of-bounds read when left-flushing with stealing
pretty: fix out-of-bounds read when parsing invalid padding format
pretty: fix adding linefeed when placeholder is not expanded
pretty: fix integer overflow in wrapping format
utf8: fix truncated string lengths in `utf8_strnwidth()`
utf8: fix returning negative string width
utf8: fix overflow when returning string width
utf8: fix checking for glyph width in `strbuf_utf8_replace()`
utf8: refactor `strbuf_utf8_replace` to not rely on preallocated buffer
pretty: restrict input lengths for padding and wrapping formats

View File

@ -0,0 +1,5 @@
Git v2.31.5 Release Notes
=========================
This release merges the security fix that appears in v2.30.6; see
the release notes for that version for details.

View File

@ -0,0 +1,5 @@
Git v2.31.6 Release Notes
=========================
This release merges the security fix that appears in v2.30.7; see
the release notes for that version for details.

View File

@ -0,0 +1,5 @@
Git v2.32.4 Release Notes
=========================
This release merges the security fix that appears in v2.30.6; see
the release notes for that version for details.

View File

@ -0,0 +1,8 @@
Git v2.32.5 Release Notes
=========================
This release merges the security fix that appears in v2.30.7; see
the release notes for that version for details.
In addition, included are additional code for "git fsck" to check
for questionable .gitattributes files.

View File

@ -0,0 +1,5 @@
Git v2.33.5 Release Notes
=========================
This release merges the security fix that appears in v2.30.6; see
the release notes for that version for details.

View File

@ -0,0 +1,5 @@
Git v2.33.6 Release Notes
=========================
This release merges the security fix that appears in v2.30.7; see
the release notes for that version for details.

View File

@ -1,438 +0,0 @@
Git 2.34 Release Notes
======================
Updates since Git 2.33
----------------------
Backward compatibility notes
* The "--preserve-merges" option of "git rebase" has been removed.
UI, Workflows & Features
* Pathname expansion (like "~username/") learned a way to specify a
location relative to Git installation (e.g. its $sharedir which is
$(prefix)/share), with "%(prefix)".
* The `ort` strategy is used instead of `recursive` as the default
merge strategy.
* The userdiff pattern for "java" language has been updated.
* "git rebase" by default skips changes that are equivalent to
commits that are already in the history the branch is rebased onto;
give messages when this happens to let the users be aware of
skipped commits, and also teach them how to tell "rebase" to keep
duplicated changes.
* The advice message that "git cherry-pick" gives when it asks
conflicted replay of a commit to be resolved by the end user has
been updated.
* After "git clone --recurse-submodules", all submodules are cloned
but they are not by default recursed into by other commands. With
submodule.stickyRecursiveClone configuration set, submodule.recurse
configuration is set to true in a repository created by "clone"
with "--recurse-submodules" option.
* The logic for auto-correction of misspelt subcommands learned to go
interactive when the help.autocorrect configuration variable is set
to 'prompt'.
* "git maintenance" scheduler learned to use systemd timers as a
possible backend.
* "git diff --submodule=diff" showed failure from run_command() when
trying to run diff inside a submodule, when the user manually
removes the submodule directory.
* "git bundle unbundle" learned to show progress display.
* In cone mode, the sparse-index code path learned to remove ignored
files (like build artifacts) outside the sparse cone, allowing the
entire directory outside the sparse cone to be removed, which is
especially useful when the sparse patterns change.
* Taking advantage of the CGI interface, http-backend has been
updated to enable protocol v2 automatically when the other side
asks for it.
* The credential-cache helper has been adjusted to Windows.
* The error in "git help no-such-git-command" is handled better.
* The unicode character width table (used for output alignment) has
been updated.
* The ref iteration code used to optionally allow dangling refs to be
shown, which has been tightened up.
* "git add", "git mv", and "git rm" have been adjusted to avoid
updating paths outside of the sparse-checkout definition unless
the user specifies a "--sparse" option.
* "git repack" has been taught to generate multi-pack reachability
bitmaps.
* "git fsck" has been taught to report mismatch between expected and
actual types of an object better.
* In addition to GnuPG, ssh public crypto can be used for object and
push-cert signing. Note that this feature cannot be used with
ssh-keygen from OpenSSH 8.7, whose support for it is broken. Avoid
using it unless you update to OpenSSH 8.8.
* "git log --grep=string --author=name" learns to highlight hits just
like "git grep string" does.
Performance, Internal Implementation, Development Support etc.
* "git bisect" spawned "git show-branch" only to pretty-print the
title of the commit after checking out the next version to be
tested; this has been rewritten in C.
* "git add" can work better with the sparse index.
* Support for ancient versions of cURL library (pre 7.19.4) has been
dropped.
* A handful of tests that assumed implementation details of files
backend for refs have been cleaned up.
* trace2 logs learned to show parent process name to see in what
context Git was invoked.
* Loading of ref tips to prepare for common ancestry negotiation in
"git fetch-pack" has been optimized by taking advantage of the
commit graph when available.
* Remind developers that the userdiff patterns should be kept simple
and permissive, assuming that the contents they apply are always
syntactically correct.
* The current implementation of GIT_TEST_FAIL_PREREQS is broken in
that checking for the lack of a prerequisite would not work. Avoid
the use of "if ! test_have_prereq X" in a test script.
* The revision traversal API has been optimized by taking advantage
of the commit-graph, when available, to determine if a commit is
reachable from any of the existing refs.
* "git fetch --quiet" optimization to avoid useless computation of
info that will never be displayed.
* Callers from older advice_config[] based API has been updated to
use the newer advice_if_enabled() and advice_enabled() API.
* Teach "test_pause" and "debug" helpers to allow using the HOME and
TERM environment variables the user usually uses.
* "make INSTALL_STRIP=-s install" allows the installation step to use
"install -s" to strip the binaries as they get installed.
* Code that handles large number of refs in the "git fetch" code
path has been optimized.
* The reachability bitmap file used to be generated only for a single
pack, but now we've learned to generate bitmaps for history that
span across multiple packfiles.
* The code to make "git grep" recurse into submodules has been
updated to migrate away from the "add submodule's object store as
an alternate object store" mechanism (which is suboptimal).
* The tracing of process ancestry information has been enhanced.
* Reduce number of write(2) system calls while sending the
ref advertisement.
* Update the build procedure to use the "-pedantic" build when
DEVELOPER makefile macro is in effect.
* Large part of "git submodule add" gets rewritten in C.
* The run-command API has been updated so that the callers can easily
ask the file descriptors open for packfiles to be closed immediately
before spawning commands that may trigger auto-gc.
* An oddball OPTION_ARGUMENT feature has been removed from the
parse-options API.
* The mergesort implementation used to sort linked list has been
optimized.
* Remove external declaration of functions that no longer exist.
* "git multi-pack-index write --bitmap" learns to propagate the
hashcache from original bitmap to resulting bitmap.
* CI learns to run the leak sanitizer builds.
* "git grep --recurse-submodules" takes trees and blobs from the
submodule repository, but the textconv settings when processing a
blob from the submodule is not taken from the submodule repository.
A test is added to demonstrate the issue, without fixing it.
* Teach "git help -c" into helping the command line completion of
configuration variables.
* When "git cmd -h" shows more than one line of usage text (e.g.
the cmd subcommand may take sub-sub-command), parse-options API
learned to align these lines, even across i18n/l10n.
* Prevent "make sparse" from running for the source files that
haven't been modified.
* The code path to write a new version of .midx multi-pack index files
has learned to release the mmaped memory holding the current
version of .midx before removing them from the disk, as some
platforms do not allow removal of a file that still has mapping.
* A new feature has been added to abort early in the test framework.
Fixes since v2.33
-----------------
* Input validation of "git pack-objects --stdin-packs" has been
corrected.
* Bugfix for common ancestor negotiation recently introduced in "git
push" code path.
* "git pull" had various corner cases that were not well thought out
around its --rebase backend, e.g. "git pull --ff-only" did not stop
but went ahead and rebased when the history on other side is not a
descendant of our history. The series tries to fix them up.
* "git apply" miscounted the bytes and failed to read to the end of
binary hunks.
* "git range-diff" code clean-up.
* "git commit --fixup" now works with "--edit" again, after it was
broken in v2.32.
* Use upload-artifacts v1 (instead of v2) for 32-bit linux, as the
new version has a blocker bug for that architecture.
* Checking out all the paths from HEAD during the last conflicted
step in "git rebase" and continuing would cause the step to be
skipped (which is expected), but leaves MERGE_MSG file behind in
$GIT_DIR and confuses the next "git commit", which has been
corrected.
* Various bugs in "git rebase -r" have been fixed.
* mmap() imitation used to call xmalloc() that dies upon malloc()
failure, which has been corrected to just return an error to the
caller to be handled.
* "git diff --relative" segfaulted and/or produced incorrect result
when there are unmerged paths.
* The delayed checkout code path in "git checkout" etc. were chatty
even when --quiet and/or --no-progress options were given.
* "git branch -D <branch>" used to refuse to remove a broken branch
ref that points at a missing commit, which has been corrected.
* Build update for Apple clang.
* The parser for the "--nl" option of "git column" has been
corrected.
* "git upload-pack" which runs on the other side of "git fetch"
forgot to take the ref namespaces into account when handling
want-ref requests.
* The sparse-index support can corrupt the index structure by storing
a stale and/or uninitialized data, which has been corrected.
* Buggy tests could damage repositories outside the throw-away test
area we created. We now by default export GIT_CEILING_DIRECTORIES
to limit the damage from such a stray test.
* Even when running "git send-email" without its own threaded
discussion support, a threading related header in one message is
carried over to the subsequent message to result in an unwanted
threading, which has been corrected.
* The output from "git fast-export", when its anonymization feature
is in use, showed an annotated tag incorrectly.
* Recent "diff -m" changes broke "gitk", which has been corrected.
* The "git apply -3" code path learned not to bother the lower level
merge machinery when the three-way merge can be trivially resolved
without the content level merge. This fixes a regression caused by
recent "-3way first and fall back to direct application" change.
* The code that optionally creates the *.rev reverse index file has
been optimized to avoid needless computation when it is not writing
the file out.
* "git range-diff -I... <range> <range>" segfaulted, which has been
corrected.
* The order in which various files that make up a single (conceptual)
packfile has been reevaluated and straightened up. This matters in
correctness, as an incomplete set of files must not be shown to a
running Git.
* The "mode" word is useless in a call to open(2) that does not
create a new file. Such a call in the files backend of the ref
subsystem has been cleaned up.
* "git update-ref --stdin" failed to flush its output as needed,
which potentially led the conversation to a deadlock.
* When "git am --abort" fails to abort correctly, it still exited
with exit status of 0, which has been corrected.
* Correct nr and alloc members of strvec struct to be of type size_t.
* "git stash", where the tentative change involves changing a
directory to a file (or vice versa), was confused, which has been
corrected.
* "git clone" from a repository whose HEAD is unborn into a bare
repository didn't follow the branch name the other side used, which
is corrected.
* "git cvsserver" had a long-standing bug in its authentication code,
which has finally been corrected (it is unclear and is a separate
question if anybody is seriously using it, though).
* "git difftool --dir-diff" mishandled symbolic links.
* Sensitive data in the HTTP trace were supposed to be redacted, but
we failed to do so in HTTP/2 requests.
* "make clean" has been updated to remove leftover .depend/
directories, even when it is not told to use them to compute header
dependencies.
* Protocol v0 clients can get stuck parsing a malformed feature line.
* A few kinds of changes "git status" can show were not documented.
(merge d2a534c515 ja/doc-status-types-and-copies later to maint).
* The mergesort implementation used to sort linked list has been
optimized.
(merge c90cfc225b rs/mergesort later to maint).
* An editor session launched during a Git operation (e.g. during 'git
commit') can leave the terminal in a funny state. The code path
has updated to save the terminal state before, and restore it
after, it spawns an editor.
(merge 3d411afabc cm/save-restore-terminal later to maint).
* "git cat-file --batch" with the "--batch-all-objects" option is
supposed to iterate over all the objects found in a repository, but
it used to translate these object names using the replace mechanism,
which defeats the point of enumerating all objects in the repository.
This has been corrected.
(merge bf972896d7 jk/cat-file-batch-all-wo-replace later to maint).
* Recent sparse-index work broke safety against attempts to add paths
with trailing slashes to the index, which has been corrected.
(merge c8ad9d04c6 rs/make-verify-path-really-verify-again later to maint).
* The "--color-lines" and "--color-by-age" options of "git blame"
have been missing, which are now documented.
(merge 8c32856133 bs/doc-blame-color-lines later to maint).
* The PATH used in CI job may be too wide and let incompatible dlls
to be grabbed, which can cause the build&test to fail. Tighten it.
(merge 7491ef6198 js/windows-ci-path-fix later to maint).
* Avoid performance measurements from getting ruined by gc and other
housekeeping pauses interfering in the middle.
(merge be79131a53 rs/disable-gc-during-perf-tests later to maint).
* Stop "git add --dry-run" from creating new blob and tree objects.
(merge e578d0311d rs/add-dry-run-without-objects later to maint).
* "git commit" gave duplicated error message when the object store
was unwritable, which has been corrected.
(merge 4ef91a2d79 ab/fix-commit-error-message-upon-unwritable-object-store later to maint).
* Recent sparse-index addition, namely any use of index_name_pos(),
can expand sparse index entries and breaks any code that walks
cache-tree or existing index entries. One such instance of such a
breakage has been corrected.
* The xxdiff difftool backend can exit with status 128, which the
difftool-helper that launches the backend takes as a significant
failure, when it is not significant at all. Work it around.
(merge 571f4348dd da/mergetools-special-case-xxdiff-exit-128 later to maint).
* Improve test framework around unwritable directories.
(merge 5d22e18965 ab/test-cleanly-recreate-trash-directory later to maint).
* "git push" client talking to an HTTP server did not diagnose the
lack of the final status report from the other side correctly,
which has been corrected.
(merge c5c3486f38 jk/http-push-status-fix later to maint).
* Update "git archive" documentation and give explicit mention on the
compression level for both zip and tar.gz format.
(merge c4b208c309 bs/archive-doc-compression-level later to maint).
* Drop "git sparse-checkout" from the list of common commands.
(merge 6a9a50a8af sg/sparse-index-not-that-common-a-command later to maint).
* "git branch -c/-m new old" was not described to copy config, which
has been corrected.
(merge 8252ec300e jc/branch-copy-doc later to maint).
* Squelch over-eager warning message added during this cycle.
* Fix long-standing shell syntax error in the completion script.
(merge 46b0585286 re/completion-fix-test-equality later to maint).
* Teach "git commit-graph" command not to allow using replace objects
at all, as we do not use the commit-graph at runtime when we see
object replacement.
(merge 095d112f8c ab/ignore-replace-while-working-on-commit-graph later to maint).
* "git pull --no-verify" did not affect the underlying "git merge".
(merge 47bfdfb3fd ar/fix-git-pull-no-verify later to maint).
* One CI task based on Fedora image noticed a not-quite-kosher
construct recently, which has been corrected.
* "git pull --ff-only" and "git pull --rebase --ff-only" should make
it a no-op to attempt pulling from a remote that is behind us, but
instead the command errored out by saying it was impossible to
fast-forward, which may technically be true, but not a useful thing
to diagnose as an error. This has been corrected.
(merge 361cb52383 jc/fix-pull-ff-only-when-already-up-to-date later to maint).
* The way Cygwin emulates a unix-domain socket, on top of which the
simple-ipc mechanism is implemented, can race with the program on
the other side that wants to use the socket, and briefly make it
appear as a regular file before lstat(2) starts reporting it as a
socket. We now have a workaround on the side that connects to a
unix domain socket.
* Other code cleanup, docfix, build fix, etc.
(merge f188160be9 ab/bundle-remove-verbose-option later to maint).
(merge 8c6b4332b4 rs/close-pack-leakfix later to maint).
(merge 51b04c05b7 bs/difftool-msg-tweak later to maint).
(merge dd20e4a6db ab/make-compdb-fix later to maint).
(merge 6ffb990dc4 os/status-docfix later to maint).
(merge 100c2da2d3 rs/p3400-lose-tac later to maint).
(merge 76f3b69896 tb/aggregate-ignore-leading-whitespaces later to maint).
(merge 6e4fd8bfcd tz/doc-link-to-bundle-format-fix later to maint).
(merge f6c013dfa1 jc/doc-commit-header-continuation-line later to maint).
(merge ec9a37d69b ab/pkt-line-cleanup later to maint).
(merge 8650c6298c ab/fix-make-lint-docs later to maint).
(merge 1c720357ce ab/test-lib-diff-cleanup later to maint).
(merge 6b615dbece ks/submodule-add-message-fix later to maint).
(merge 203eb8381a jc/doc-format-patch-clarify-auto-base later to maint).
(merge 559664c792 ab/test-lib later to maint).

View File

@ -1,23 +0,0 @@
Git v2.34.1 Release Notes
=========================
This release is primarily to fix a handful of regressions in Git 2.34.
Fixes since v2.34
-----------------
* "git grep" looking in a blob that has non-UTF8 payload was
completely broken when linked with certain versions of PCREv2
library in the latest release.
* "git pull" with any strategy when the other side is behind us
should succeed as it is a no-op, but doesn't.
* An earlier change in 2.34.0 caused JGit application (that abused
GIT_EDITOR mechanism when invoking "git config") to get stuck with
a SIGTTOU signal; it has been reverted.
* An earlier change that broke .gitignore matching has been reverted.
* SubmittingPatches document gained a syntactically incorrect mark-up,
which has been corrected.

View File

@ -1,6 +0,0 @@
Git v2.34.2 Release Notes
=========================
This release merges up the fixes that appear in v2.30.3, v2.31.2,
v2.32.1 and v2.33.2 to address the security issue CVE-2022-24765;
see the release notes for these versions for details.

View File

@ -1,4 +0,0 @@
Git Documentation/RelNotes/2.34.3.txt Release Notes
=========================
This release merges up the fixes that appear in v2.34.3.

View File

@ -1,6 +0,0 @@
Git v2.34.4 Release Notes
=========================
This release merges up the fixes that appear in v2.30.5, v2.31.4,
v2.32.3 and v2.33.4 to address the security issue CVE-2022-29187;
see the release notes for these versions for details.

View File

@ -448,7 +448,7 @@ their trees themselves.
entitled "What's cooking in git.git" and "What's in git.git" giving
the status of various proposed changes.
== GitHub CI[[GHCI]]
== GitHub CI[[GHCI]]]
With an account at GitHub, you can use GitHub CI to test your changes
on Linux, Mac and Windows. See
@ -463,7 +463,7 @@ Follow these steps for the initial setup:
After the initial setup, CI will run whenever you push new changes
to your fork of Git on GitHub. You can monitor the test state of all your
branches here: `https://github.com/<Your GitHub handle>/git/actions/workflows/main.yml`
branches here: https://github.com/<Your GitHub handle>/git/actions/workflows/main.yml
If a branch did not pass all test cases then it is marked with a red
cross. In that case you can click on the failing job and navigate to

View File

@ -136,16 +136,5 @@ take effect.
option. An empty file name, `""`, will clear the list of revs from
previously processed files.
--color-lines::
Color line annotations in the default format differently if they come from
the same commit as the preceding line. This makes it easier to distinguish
code blocks introduced by different commits. The color defaults to cyan and
can be adjusted using the `color.blame.repeatedLines` config option.
--color-by-age::
Color line annotations depending on the age of the line in the default format.
The `color.blame.highlightRecent` config option controls what color is used for
each range of age.
-h::
Show help message.

View File

@ -298,15 +298,6 @@ pathname::
tilde expansion happens to such a string: `~/`
is expanded to the value of `$HOME`, and `~user/` to the
specified user's home directory.
+
If a path starts with `%(prefix)/`, the remainder is interpreted as a
path relative to Git's "runtime prefix", i.e. relative to the location
where Git itself was installed. For example, `%(prefix)/bin/` refers to
the directory in which the Git executable itself lives. If Git was
compiled without runtime prefix support, the compiled-in prefix will be
substituted instead. In the unlikely event that a literal path needs to
be specified that should _not_ be expanded, it needs to be prefixed by
`./`, like so: `./%(prefix)/bin`.
Variables

View File

@ -44,9 +44,6 @@ advice.*::
Shown when linkgit:git-push[1] rejects a forced update of
a branch when its remote-tracking ref has updates that we
do not have locally.
skippedCherryPicks::
Shown when linkgit:git-rebase[1] skips a commit that has already
been cherry-picked onto the upstream branch.
statusAheadBehind::
Shown when linkgit:git-status[1] computes the ahead/behind
counts for a local ref compared to its remote tracking ref,

View File

@ -85,6 +85,10 @@ When `merges` (or just 'm'), pass the `--rebase-merges` option to 'git rebase'
so that the local merge commits are included in the rebase (see
linkgit:git-rebase[1] for details).
+
When `preserve` (or just 'p', deprecated in favor of `merges`), also pass
`--preserve-merges` along to 'git rebase' so that locally committed merge
commits will not be flattened by running 'git pull'.
+
When the value is `interactive` (or just 'i'), the rebase is run in interactive
mode.
+

View File

@ -9,27 +9,26 @@ color.advice.hint::
Use customized color for hints.
color.blame.highlightRecent::
Specify the line annotation color for `git blame --color-by-age`
depending upon the age of the line.
This can be used to color the metadata of a blame line depending
on age of the line.
+
This setting should be set to a comma-separated list of color and
date settings, starting and ending with a color, the dates should be
set from oldest to newest. The metadata will be colored with the
specified colors if the line was introduced before the given
timestamp, overwriting older timestamped colors.
This setting should be set to a comma-separated list of color and date settings,
starting and ending with a color, the dates should be set from oldest to newest.
The metadata will be colored given the colors if the line was introduced
before the given timestamp, overwriting older timestamped colors.
+
Instead of an absolute timestamp relative timestamps work as well,
e.g. `2.weeks.ago` is valid to address anything older than 2 weeks.
Instead of an absolute timestamp relative timestamps work as well, e.g.
2.weeks.ago is valid to address anything older than 2 weeks.
+
It defaults to `blue,12 month ago,white,1 month ago,red`, which
colors everything older than one year blue, recent changes between
one month and one year old are kept white, and lines introduced
within the last month are colored red.
It defaults to 'blue,12 month ago,white,1 month ago,red', which colors
everything older than one year blue, recent changes between one month and
one year old are kept white, and lines introduced within the last month are
colored red.
color.blame.repeatedLines::
Use the specified color to colorize line annotations for
`git blame --color-lines`, if they come from the same commit as the
preceding line. Defaults to cyan.
Use the customized color for the part of git-blame output that
is repeated meta information per line (such as commit id,
author name, date and timezone). Defaults to cyan.
color.branch::
A boolean to enable/disable color in the output of
@ -105,12 +104,9 @@ color.grep.<slot>::
`matchContext`;;
matching text in context lines
`matchSelected`;;
matching text in selected lines. Also, used to customize the following
linkgit:git-log[1] subcommands: `--grep`, `--author` and `--committer`.
matching text in selected lines
`selected`;;
non-matching text in selected lines. Also, used to customize the
following linkgit:git-log[1] subcommands: `--grep`, `--author` and
`--committer`.
non-matching text in selected lines
`separator`;;
separators between fields on a line (`:`, `-`, and `=`)
and between hunks (`--`)

View File

@ -11,13 +11,13 @@ gpg.program::
gpg.format::
Specifies which key format to use when signing with `--gpg-sign`.
Default is "openpgp". Other possible values are "x509", "ssh".
Default is "openpgp" and another possible value is "x509".
gpg.<format>.program::
Use this to customize the program used for the signing format you
chose. (see `gpg.program` and `gpg.format`) `gpg.program` can still
be used as a legacy synonym for `gpg.openpgp.program`. The default
value for `gpg.x509.program` is "gpgsm" and `gpg.ssh.program` is "ssh-keygen".
value for `gpg.x509.program` is "gpgsm".
gpg.minTrustLevel::
Specifies a minimum trust level for signature verification. If
@ -33,42 +33,3 @@ gpg.minTrustLevel::
* `marginal`
* `fully`
* `ultimate`
gpg.ssh.defaultKeyCommand:
This command that will be run when user.signingkey is not set and a ssh
signature is requested. On successful exit a valid ssh public key is
expected in the first line of its output. To automatically use the first
available key from your ssh-agent set this to "ssh-add -L".
gpg.ssh.allowedSignersFile::
A file containing ssh public keys which you are willing to trust.
The file consists of one or more lines of principals followed by an ssh
public key.
e.g.: user1@example.com,user2@example.com ssh-rsa AAAAX1...
See ssh-keygen(1) "ALLOWED SIGNERS" for details.
The principal is only used to identify the key and is available when
verifying a signature.
+
SSH has no concept of trust levels like gpg does. To be able to differentiate
between valid signatures and trusted signatures the trust level of a signature
verification is set to `fully` when the public key is present in the allowedSignersFile.
Otherwise the trust level is `undefined` and git verify-commit/tag will fail.
+
This file can be set to a location outside of the repository and every developer
maintains their own trust store. A central repository server could generate this
file automatically from ssh keys with push access to verify the code against.
In a corporate setting this file is probably generated at a global location
from automation that already handles developer ssh keys.
+
A repository that only allows signed commits can store the file
in the repository itself using a path relative to the top-level of the working tree.
This way only committers with an already valid key can add or change keys in the keyring.
+
Using a SSH CA key with the cert-authority option
(see ssh-keygen(1) "CERTIFICATES") is also valid.
gpg.ssh.revocationFile::
Either a SSH KRL or a list of revoked public keys (without the principal prefix).
See ssh-keygen(1) for details.
If a public key is found in this file then it will always be treated
as having trust level "never" and signatures will show as invalid.

View File

@ -9,15 +9,13 @@ help.format::
help.autoCorrect::
If git detects typos and can identify exactly one valid command similar
to the error, git will try to suggest the correct command or even
run the suggestion automatically. Possible config values are:
- 0 (default): show the suggested command.
- positive number: run the suggested command after specified
deciseconds (0.1 sec).
- "immediate": run the suggested command immediately.
- "prompt": show the suggestion and prompt for confirmation to run
the command.
- "never": don't run or show any suggested command.
to the error, git will automatically run the intended command after
waiting a duration of time defined by this configuration value in
deciseconds (0.1 sec). If this value is 0, the suggested corrections
will be shown, but not executed. If it is a negative integer, or
"immediate", the suggested command
is run immediately. If "never", suggestions are not shown at all. The
default value is zero.
help.htmlPath::
Specify the path where the HTML documentation resides. File system paths

View File

@ -159,10 +159,6 @@ pack.writeBitmapHashCache::
between an older, bitmapped pack and objects that have been
pushed since the last gc). The downside is that it consumes 4
bytes per object of disk space. Defaults to true.
+
When writing a multi-pack reachability bitmap, no new namehashes are
computed; instead, any namehashes stored in an existing bitmap are
permuted into their appropriate location when writing a new bitmap.
pack.writeReverseIndex::
When true, git will write a corresponding .rev file (see:

View File

@ -1,10 +1,10 @@
protocol.allow::
If set, provide a user defined default policy for all protocols which
don't explicitly have a policy (`protocol.<name>.allow`). By default,
if unset, known-safe protocols (http, https, git, ssh, file) have a
if unset, known-safe protocols (http, https, git, ssh) have a
default policy of `always`, known-dangerous protocols (ext) have a
default policy of `never`, and all other protocols have a default
policy of `user`. Supported policies:
default policy of `never`, and all other protocols (including file)
have a default policy of `user`. Supported policies:
+
--

View File

@ -18,6 +18,10 @@ When `merges` (or just 'm'), pass the `--rebase-merges` option to 'git rebase'
so that the local merge commits are included in the rebase (see
linkgit:git-rebase[1] for details).
+
When `preserve` (or just 'p', deprecated in favor of `merges`), also pass
`--preserve-merges` along to 'git rebase' so that locally committed merge
commits will not be flattened by running 'git pull'.
+
When the value is `interactive` (or just 'i'), the rebase is run in interactive
mode.
+

View File

@ -36,10 +36,3 @@ user.signingKey::
commit, you can override the default selection with this variable.
This option is passed unchanged to gpg's --local-user parameter,
so you may specify a key using any method that gpg supports.
If gpg.format is set to "ssh" this can contain the literal ssh public
key (e.g.: "ssh-rsa XXXXXX identifier") or a file which contains it and
corresponds to the private key used for signing. The private key
needs to be available via ssh-agent. Alternatively it can be set to
a file containing a private key directly. If not set git will call
gpg.ssh.defaultKeyCommand (e.g.: "ssh-add -L") and try to use the first
key available.

View File

@ -59,7 +59,7 @@ Possible status letters are:
- D: deletion of a file
- M: modification of the contents or mode of a file
- R: renaming of a file
- T: change in the type of the file (regular file, symbolic link or submodule)
- T: change in the type of the file
- U: file is unmerged (you must complete the merge before it can
be committed)
- X: "unknown" change type (most probably a bug, please report it)

View File

@ -9,7 +9,7 @@ SYNOPSIS
--------
[verse]
'git add' [--verbose | -v] [--dry-run | -n] [--force | -f] [--interactive | -i] [--patch | -p]
[--edit | -e] [--[no-]all | --[no-]ignore-removal | [--update | -u]] [--sparse]
[--edit | -e] [--[no-]all | --[no-]ignore-removal | [--update | -u]]
[--intent-to-add | -N] [--refresh] [--ignore-errors] [--ignore-missing] [--renormalize]
[--chmod=(+|-)x] [--pathspec-from-file=<file> [--pathspec-file-nul]]
[--] [<pathspec>...]
@ -79,13 +79,6 @@ in linkgit:gitglossary[7].
--force::
Allow adding otherwise ignored files.
--sparse::
Allow updating index entries outside of the sparse-checkout cone.
Normally, `git add` refuses to update index entries whose paths do
not fit within the sparse-checkout cone, since those files might
be removed from the working tree without warning. See
linkgit:git-sparse-checkout[1] for more details.
-i::
--interactive::
Add modified contents in the working tree interactively to

View File

@ -93,19 +93,12 @@ BACKEND EXTRA OPTIONS
zip
~~~
-<digit>::
Specify compression level. Larger values allow the command
to spend more time to compress to smaller size. Supported
values are from `-0` (store-only) to `-9` (best ratio).
Default is `-6` if not given.
-0::
Store the files instead of deflating them.
-9::
Highest and slowest compression level. You can specify any
number from 1 to 9 to adjust compression speed and ratio.
tar
~~~
-<number>::
Specify compression level. The value will be passed to the
compression command configured in `tar.<format>.command`. See
manual page of the configured command for the list of supported
levels and the default level if this option isn't specified.
CONFIGURATION
-------------

View File

@ -11,8 +11,8 @@ SYNOPSIS
'git blame' [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-e] [-p] [-w] [--incremental]
[-L <range>] [-S <revs-file>] [-M] [-C] [-C] [-C] [--since=<date>]
[--ignore-rev <rev>] [--ignore-revs-file <file>]
[--color-lines] [--color-by-age] [--progress] [--abbrev=<n>]
[<rev> | --contents <file> | --reverse <rev>..<rev>] [--] <file>
[--progress] [--abbrev=<n>] [<rev> | --contents <file> | --reverse <rev>..<rev>]
[--] <file>
DESCRIPTION
-----------
@ -93,19 +93,6 @@ include::blame-options.txt[]
is used for a caret to mark the boundary commit.
THE DEFAULT FORMAT
------------------
When neither `--porcelain` nor `--incremental` option is specified,
`git blame` will output annotation for each line with:
- abbreviated object name for the commit the line came from;
- author ident (by default author name and date, unless `-s` or `-e`
is specified); and
- line number
before the line contents.
THE PORCELAIN FORMAT
--------------------

View File

@ -125,14 +125,14 @@ OPTIONS
-m::
--move::
Move/rename a branch, together with its config and reflog.
Move/rename a branch and the corresponding reflog.
-M::
Shortcut for `--move --force`.
-c::
--copy::
Copy a branch, together with its config and reflog.
Copy a branch and the corresponding reflog.
-C::
Shortcut for `--copy --force`.

View File

@ -13,7 +13,7 @@ SYNOPSIS
[--version=<version>] <file> <git-rev-list-args>
'git bundle' verify [-q | --quiet] <file>
'git bundle' list-heads <file> [<refname>...]
'git bundle' unbundle [--progress] <file> [<refname>...]
'git bundle' unbundle <file> [<refname>...]
DESCRIPTION
-----------
@ -51,10 +51,10 @@ using the `--thin` option to linkgit:git-pack-objects[1], and
unbundled using the `--fix-thin` option to linkgit:git-index-pack[1].
There is no option to create a "thick pack" when using revision
exclusions, and users should not be concerned about the difference. By
using "thin packs", bundles created using exclusions are smaller in
exclusions, users should not be concerned about the difference. By
using "thin packs" bundles created using exclusions are smaller in
size. That they're "thin" under the hood is merely noted here as a
curiosity, and as a reference to other documentation.
curiosity, and as a reference to other documentation
See link:technical/bundle-format.html[the `bundle-format`
documentation] for more details and the discussion of "thin pack" in
@ -144,7 +144,7 @@ unbundle <file>::
SPECIFYING REFERENCES
---------------------
Revisions must be accompanied by reference names to be packaged in a
Revisions must accompanied by reference names to be packaged in a
bundle.
More than one reference may be packaged, and more than one set of prerequisite objects can

View File

@ -94,10 +94,8 @@ OPTIONS
Instead of reading a list of objects on stdin, perform the
requested batch operation on all objects in the repository and
any alternate object stores (not just reachable objects).
Requires `--batch` or `--batch-check` be specified. By default,
the objects are visited in order sorted by their hashes; see
also `--unordered` below. Objects are presented as-is, without
respecting the "replace" mechanism of linkgit:git-replace[1].
Requires `--batch` or `--batch-check` be specified. Note that
the objects are visited in order sorted by their hashes.
--buffer::
Normally batch output is flushed after each object is output, so

View File

@ -118,9 +118,8 @@ OPTIONS
-f::
--force::
When switching branches, proceed even if the index or the
working tree differs from `HEAD`, and even if there are untracked
files in the way. This is used to throw away local changes and
any untracked files or directories that are in the way.
working tree differs from `HEAD`. This is used to throw away
local changes.
+
When checking out paths from the index, do not fail upon unmerged
entries; instead, unmerged entries are ignored.

View File

@ -212,9 +212,8 @@ include::signoff-option.txt[]
each trailer would appear, and other details.
-n::
--[no-]verify::
By default, the pre-commit and commit-msg hooks are run.
When any of `--no-verify` or `-n` is given, these are bypassed.
--no-verify::
This option bypasses the pre-commit and commit-msg hooks.
See also linkgit:githooks[5].
--allow-empty::

View File

@ -235,15 +235,6 @@ and `date` to extract the named component. For email fields (`authoremail`,
without angle brackets, and `:localpart` to get the part before the `@` symbol
out of the trimmed email.
The raw data in an object is `raw`.
raw:size::
The raw data size of the object.
Note that `--format=%(raw)` can not be used with `--python`, `--shell`, `--tcl`,
because such language may not support arbitrary binary data in their string
variable type.
The message in a commit or a tag object is `contents`, from which
`contents:<part>` can be used to extract various parts out of:

View File

@ -689,10 +689,10 @@ You can also use `git format-patch --base=P -3 C` to generate patches
for A, B and C, and the identifiers for P, X, Y, Z are appended at the
end of the first message.
If set `--base=auto` in cmdline, it will automatically compute
the base commit as the merge base of tip commit of the remote-tracking
If set `--base=auto` in cmdline, it will track base commit automatically,
the base commit will be the merge base of tip commit of the remote-tracking
branch and revision-range specified in cmdline.
For a local branch, you need to make it to track a remote branch by `git branch
For a local branch, you need to track a remote branch by `git branch
--set-upstream-to` before using this option.
EXAMPLES

View File

@ -8,10 +8,8 @@ git-help - Display help information about Git
SYNOPSIS
--------
[verse]
'git help' [-a|--all [--[no-]verbose]]
[[-i|--info] [-m|--man] [-w|--web]] [COMMAND|GUIDE]
'git help' [-g|--guides]
'git help' [-c|--config]
'git help' [-a|--all [--[no-]verbose]] [-g|--guides]
[-i|--info|-m|--man|-w|--web] [COMMAND|GUIDE]
DESCRIPTION
-----------
@ -60,7 +58,8 @@ OPTIONS
-g::
--guides::
Prints a list of the Git concept guides on the standard output.
Prints a list of the Git concept guides on the standard output. This
option overrides any given command or guide name.
-i::
--info::

View File

@ -16,9 +16,7 @@ A simple CGI program to serve the contents of a Git repository to Git
clients accessing the repository over http:// and https:// protocols.
The program supports clients fetching using both the smart HTTP protocol
and the backwards-compatible dumb HTTP protocol, as well as clients
pushing using the smart HTTP protocol. It also supports Git's
more-efficient "v2" protocol if properly configured; see the
discussion of `GIT_PROTOCOL` in the ENVIRONMENT section below.
pushing using the smart HTTP protocol.
It verifies that the directory has the magic file
"git-daemon-export-ok", and it will refuse to export any Git directory
@ -79,18 +77,6 @@ Apache 2.x::
SetEnv GIT_PROJECT_ROOT /var/www/git
SetEnv GIT_HTTP_EXPORT_ALL
ScriptAlias /git/ /usr/libexec/git-core/git-http-backend/
# This is not strictly necessary using Apache and a modern version of
# git-http-backend, as the webserver will pass along the header in the
# environment as HTTP_GIT_PROTOCOL, and http-backend will copy that into
# GIT_PROTOCOL. But you may need this line (or something similar if you
# are using a different webserver), or if you want to support older Git
# versions that did not do that copying.
#
# Having the webserver set up GIT_PROTOCOL is perfectly fine even with
# modern versions (and will take precedence over HTTP_GIT_PROTOCOL,
# which means it can be used to override the client's request).
SetEnvIf Git-Protocol ".*" GIT_PROTOCOL=$0
----------------------------------------------------------------
+
To enable anonymous read access but authenticated write access,
@ -278,16 +264,6 @@ a repository with an extremely large number of refs. The value can be
specified with a unit (e.g., `100M` for 100 megabytes). The default is
10 megabytes.
Clients may probe for optional protocol capabilities (like the v2
protocol) using the `Git-Protocol` HTTP header. In order to support
these, the contents of that header must appear in the `GIT_PROTOCOL`
environment variable. Most webservers will pass this header to the CGI
via the `HTTP_GIT_PROTOCOL` variable, and `git-http-backend` will
automatically copy that to `GIT_PROTOCOL`. However, some webservers may
be more selective about which headers they'll pass, in which case they
need to be configured explicitly (see the mention of `Git-Protocol` in
the Apache config from the earlier EXAMPLES section).
The backend process sets GIT_COMMITTER_NAME to '$REMOTE_USER' and
GIT_COMMITTER_EMAIL to '$\{REMOTE_USER}@http.$\{REMOTE_ADDR\}',
ensuring that any reflogs created by 'git-receive-pack' contain some

View File

@ -82,12 +82,6 @@ OPTIONS
--strict::
Die, if the pack contains broken objects or links.
--progress-title::
For internal use only.
+
Set the title of the progress bar. The title is "Receiving objects" by
default and "Indexing objects" when `--stdin` is specified.
--check-self-contained-and-connected::
Die if the pack contains broken links. For internal use only.

View File

@ -179,17 +179,6 @@ OPTIONS
`maintenance.<task>.enabled` configured as `true` are considered.
See the 'TASKS' section for the list of accepted `<task>` values.
--scheduler=auto|crontab|systemd-timer|launchctl|schtasks::
When combined with the `start` subcommand, specify the scheduler
for running the hourly, daily and weekly executions of
`git maintenance run`.
Possible values for `<scheduler>` are `auto`, `crontab`
(POSIX), `systemd-timer` (Linux), `launchctl` (macOS), and
`schtasks` (Windows). When `auto` is specified, the
appropriate platform-specific scheduler is used; on Linux,
`systemd-timer` is used if available, otherwise
`crontab`. Default is `auto`.
TROUBLESHOOTING
---------------
@ -288,52 +277,6 @@ schedule to ensure you are executing the correct binaries in your
schedule.
BACKGROUND MAINTENANCE ON LINUX SYSTEMD SYSTEMS
-----------------------------------------------
While Linux supports `cron`, depending on the distribution, `cron` may
be an optional package not necessarily installed. On modern Linux
distributions, systemd timers are superseding it.
If user systemd timers are available, they will be used as a replacement
of `cron`.
In this case, `git maintenance start` will create user systemd timer units
and start the timers. The current list of user-scheduled tasks can be found
by running `systemctl --user list-timers`. The timers written by `git
maintenance start` are similar to this:
-----------------------------------------------------------------------
$ systemctl --user list-timers
NEXT LEFT LAST PASSED UNIT ACTIVATES
Thu 2021-04-29 19:00:00 CEST 42min left Thu 2021-04-29 18:00:11 CEST 17min ago git-maintenance@hourly.timer git-maintenance@hourly.service
Fri 2021-04-30 00:00:00 CEST 5h 42min left Thu 2021-04-29 00:00:11 CEST 18h ago git-maintenance@daily.timer git-maintenance@daily.service
Mon 2021-05-03 00:00:00 CEST 3 days left Mon 2021-04-26 00:00:11 CEST 3 days ago git-maintenance@weekly.timer git-maintenance@weekly.service
-----------------------------------------------------------------------
One timer is registered for each `--schedule=<frequency>` option.
The definition of the systemd units can be inspected in the following files:
-----------------------------------------------------------------------
~/.config/systemd/user/git-maintenance@.timer
~/.config/systemd/user/git-maintenance@.service
~/.config/systemd/user/timers.target.wants/git-maintenance@hourly.timer
~/.config/systemd/user/timers.target.wants/git-maintenance@daily.timer
~/.config/systemd/user/timers.target.wants/git-maintenance@weekly.timer
-----------------------------------------------------------------------
`git maintenance start` will overwrite these files and start the timer
again with `systemctl --user`, so any customization should be done by
creating a drop-in file, i.e. a `.conf` suffixed file in the
`~/.config/systemd/user/git-maintenance@.service.d` directory.
`git maintenance stop` will stop the user systemd timers and delete
the above mentioned files.
For more details, see `systemd.timer(5)`.
BACKGROUND MAINTENANCE ON MACOS SYSTEMS
---------------------------------------

View File

@ -9,7 +9,8 @@ git-multi-pack-index - Write and verify multi-pack-indexes
SYNOPSIS
--------
[verse]
'git multi-pack-index' [--object-dir=<dir>] [--[no-]bitmap] <sub-command>
'git multi-pack-index' [--object-dir=<dir>] [--[no-]progress]
[--preferred-pack=<pack>] <subcommand>
DESCRIPTION
-----------
@ -22,13 +23,10 @@ OPTIONS
Use given directory for the location of Git objects. We check
`<dir>/packs/multi-pack-index` for the current MIDX file, and
`<dir>/packs` for the pack-files to index.
+
`<dir>` must be an alternate of the current repository.
--[no-]progress::
Turn progress on/off explicitly. If neither is specified, progress is
shown if standard error is connected to a terminal. Supported by
sub-commands `write`, `verify`, `expire`, and `repack.
shown if standard error is connected to a terminal.
The following subcommands are available:
@ -39,31 +37,9 @@ write::
--
--preferred-pack=<pack>::
Optionally specify the tie-breaking pack used when
multiple packs contain the same object. `<pack>` must
contain at least one object. If not given, ties are
broken in favor of the pack with the lowest mtime.
--[no-]bitmap::
Control whether or not a multi-pack bitmap is written.
--stdin-packs::
Write a multi-pack index containing only the set of
line-delimited pack index basenames provided over stdin.
--refs-snapshot=<path>::
With `--bitmap`, optionally specify a file which
contains a "refs snapshot" taken prior to repacking.
+
A reference snapshot is composed of line-delimited OIDs corresponding to
the reference tips, usually taken by `git repack` prior to generating a
new pack. A line may optionally start with a `+` character to indicate
that the reference which corresponds to that OID is "preferred" (see
linkgit:git-config[1]'s `pack.preferBitmapTips`.)
+
The file given at `<path>` is expected to be readable, and can contain
duplicates. (If a given OID is given more than once, it is marked as
preferred if at least one instance of it begins with the special `+`
marker).
multiple packs contain the same object. If not given,
ties are broken in favor of the pack with the lowest
mtime.
--
verify::
@ -99,26 +75,19 @@ associated `.keep` file will not be selected for the batch to repack.
EXAMPLES
--------
* Write a MIDX file for the packfiles in the current `.git` directory.
* Write a MIDX file for the packfiles in the current .git folder.
+
-----------------------------------------------
$ git multi-pack-index write
-----------------------------------------------
* Write a MIDX file for the packfiles in the current `.git` directory with a
corresponding bitmap.
+
-------------------------------------------------------------
$ git multi-pack-index write --preferred-pack=<pack> --bitmap
-------------------------------------------------------------
* Write a MIDX file for the packfiles in an alternate object store.
+
-----------------------------------------------
$ git multi-pack-index --object-dir <alt> write
-----------------------------------------------
* Verify the MIDX file for the packfiles in the current `.git` directory.
* Verify the MIDX file for the packfiles in the current .git folder.
+
-----------------------------------------------
$ git multi-pack-index verify

View File

@ -105,7 +105,7 @@ Options related to merging
include::merge-options.txt[]
-r::
--rebase[=false|true|merges|interactive]::
--rebase[=false|true|merges|preserve|interactive]::
When true, rebase the current branch on top of the upstream
branch after fetching. If there is a remote-tracking branch
corresponding to the upstream branch and the upstream branch
@ -116,6 +116,10 @@ When set to `merges`, rebase using `git rebase --rebase-merges` so that
the local merge commits are included in the rebase (see
linkgit:git-rebase[1] for details).
+
When set to `preserve` (deprecated in favor of `merges`), rebase with the
`--preserve-merges` option passed to `git rebase` so that locally created
merge commits will not be flattened.
+
When false, merge the upstream branch into the current branch.
+
When `interactive`, enable the interactive mode of rebase.

View File

@ -10,7 +10,8 @@ SYNOPSIS
--------
[verse]
'git read-tree' [[-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>]
[-u | -i]] [--index-output=<file>] [--no-sparse-checkout]
[-u [--exclude-per-directory=<gitignore>] | -i]]
[--index-output=<file>] [--no-sparse-checkout]
(--empty | <tree-ish1> [<tree-ish2> [<tree-ish3>]])
@ -38,9 +39,8 @@ OPTIONS
--reset::
Same as -m, except that unmerged entries are discarded instead
of failing. When used with `-u`, updates leading to loss of
working tree changes or untracked files or directories will not
abort the operation.
of failing. When used with `-u`, updates leading to loss of
working tree changes will not abort the operation.
-u::
After a successful merge, update the files in the work
@ -88,6 +88,21 @@ OPTIONS
The command will refuse to overwrite entries that already
existed in the original index file.
--exclude-per-directory=<gitignore>::
When running the command with `-u` and `-m` options, the
merge result may need to overwrite paths that are not
tracked in the current branch. The command usually
refuses to proceed with the merge to avoid losing such a
path. However this safety valve sometimes gets in the
way. For example, it often happens that the other
branch added a file that used to be a generated file in
your branch, and the safety valve triggers when you try
to switch to that branch after you ran `make` but before
running `make clean` to remove the generated file. This
option tells the command to read per-directory exclude
file (usually '.gitignore') and allows such an untracked
but explicitly ignored file to be overwritten.
--index-output=<file>::
Instead of writing the results out to `$GIT_INDEX_FILE`,
write the resulting index in the named file. While the

View File

@ -79,10 +79,9 @@ remain the checked-out branch.
If the upstream branch already contains a change you have made (e.g.,
because you mailed a patch which was applied upstream), then that commit
will be skipped and warnings will be issued (if the `merge` backend is
used). For example, running `git rebase master` on the following
history (in which `A'` and `A` introduce the same set of changes, but
have different committer information):
will be skipped. For example, running `git rebase master` on the
following history (in which `A'` and `A` introduce the same set of changes,
but have different committer information):
------------
A---B---C topic
@ -313,10 +312,7 @@ See also INCOMPATIBLE OPTIONS below.
By default (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 repos with a large number
of upstream commits that need to be 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]).
of upstream commits that need to be read.
+
`--reapply-cherry-picks` allows rebase to forgo reading all upstream
commits, potentially improving performance.
@ -356,8 +352,8 @@ See also INCOMPATIBLE OPTIONS below.
-s <strategy>::
--strategy=<strategy>::
Use the given merge strategy, instead of the default `ort`.
This implies `--merge`.
Use the given merge strategy, instead of the default
`recursive`. This implies `--merge`.
+
Because 'git rebase' replays each commit from the working branch
on top of the <upstream> branch using the given strategy, using
@ -370,7 +366,7 @@ See also INCOMPATIBLE OPTIONS below.
--strategy-option=<strategy-option>::
Pass the <strategy-option> through to the merge strategy.
This implies `--merge` and, if no strategy has been
specified, `-s ort`. Note the reversal of 'ours' and
specified, `-s recursive`. Note the reversal of 'ours' and
'theirs' as noted above for the `-m` option.
+
See also INCOMPATIBLE OPTIONS below.
@ -446,8 +442,7 @@ When --fork-point is active, 'fork_point' will be used instead of
ends up being empty, the <upstream> will be used as a fallback.
+
If <upstream> is given on the command line, then the default is
`--no-fork-point`, otherwise the default is `--fork-point`. See also
`rebase.forkpoint` in linkgit:git-config[1].
`--no-fork-point`, otherwise the default is `--fork-point`.
+
If your branch was based on <upstream> but <upstream> was rewound and
your branch contains commits which were dropped, this option can be used
@ -527,12 +522,29 @@ i.e. commits that would be excluded by linkgit:git-log[1]'s
the `rebase-cousins` mode is turned on, such commits are instead rebased
onto `<upstream>` (or `<onto>`, if specified).
+
The `--rebase-merges` mode is similar in spirit to the deprecated
`--preserve-merges` but works with interactive rebases,
where commits can be reordered, inserted and dropped at will.
+
It is currently only possible to recreate the merge commits using the
`ort` merge strategy; different merge strategies can be used only via
`recursive` merge strategy; different merge strategies can be used only via
explicit `exec git merge -s <strategy> [...]` commands.
+
See also REBASING MERGES and INCOMPATIBLE OPTIONS below.
-p::
--preserve-merges::
[DEPRECATED: use `--rebase-merges` instead] Recreate merge commits
instead of flattening the history by replaying commits a merge commit
introduces. Merge conflict resolutions or manual amendments to merge
commits are not preserved.
+
This uses the `--interactive` machinery internally, but combining it
with the `--interactive` option explicitly is generally not a good
idea unless you know what you are doing (see BUGS below).
+
See also INCOMPATIBLE OPTIONS below.
-x <cmd>::
--exec <cmd>::
Append "exec <cmd>" after each line creating a commit in the
@ -564,6 +576,9 @@ See also INCOMPATIBLE OPTIONS below.
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.
When used together with both --onto and --preserve-merges,
'all' root commits will be rewritten to have <newbase> as parent
instead.
+
See also INCOMPATIBLE OPTIONS below.
@ -625,6 +640,7 @@ are incompatible with the following options:
* --allow-empty-message
* --[no-]autosquash
* --rebase-merges
* --preserve-merges
* --interactive
* --exec
* --no-keep-empty
@ -635,6 +651,13 @@ are incompatible with the following options:
In addition, the following pairs of options are incompatible:
* --preserve-merges and --interactive
* --preserve-merges and --signoff
* --preserve-merges and --rebase-merges
* --preserve-merges and --empty=
* --preserve-merges and --ignore-whitespace
* --preserve-merges and --committer-date-is-author-date
* --preserve-merges and --ignore-date
* --keep-base and --onto
* --keep-base and --root
* --fork-point and --root
@ -1193,16 +1216,16 @@ successful merge so that the user can edit the message.
If a `merge` command fails for any reason other than merge conflicts (i.e.
when the merge operation did not even start), it is rescheduled immediately.
By default, the `merge` command will use the `ort` merge strategy for
regular merges, and `octopus` for octopus merges. One can specify a
default strategy for all merges using the `--strategy` argument when
invoking rebase, or can override specific merges in the interactive
list of commands by using an `exec` command to call `git merge`
explicitly with a `--strategy` argument. Note that when calling `git
merge` explicitly like this, you can make use of the fact that the
labels are worktree-local refs (the ref `refs/rewritten/onto` would
correspond to the label `onto`, for example) in order to refer to the
branches you want to merge.
By default, the `merge` command will use the `recursive` merge
strategy for regular merges, and `octopus` for octopus merges. One
can specify a default strategy for all merges using the `--strategy`
argument when invoking rebase, or can override specific merges in the
interactive list of commands by using an `exec` command to call `git
merge` explicitly with a `--strategy` argument. Note that when
calling `git merge` explicitly like this, you can make use of the fact
that the labels are worktree-local refs (the ref `refs/rewritten/onto`
would correspond to the label `onto`, for example) in order to refer
to the branches you want to merge.
Note: the first command (`label onto`) labels the revision onto which
the commits are rebased; The name `onto` is just a convention, as a nod
@ -1252,6 +1275,29 @@ CONFIGURATION
include::config/rebase.txt[]
include::config/sequencer.txt[]
BUGS
----
The todo list presented by the deprecated `--preserve-merges --interactive`
does not represent the topology of the revision graph (use `--rebase-merges`
instead). Editing commits and rewording their commit messages should work
fine, but attempts to reorder commits tend to produce counterintuitive results.
Use `--rebase-merges` in such scenarios instead.
For example, an attempt to rearrange
------------
1 --- 2 --- 3 --- 4 --- 5
------------
to
------------
1 --- 2 --- 4 --- 3 --- 5
------------
by moving the "pick 4" line will result in the following history:
------------
3
/
1 --- 2 --- 4 --- 5
------------
GIT
---
Part of the linkgit:git[1] suite

View File

@ -41,11 +41,6 @@ OPTIONS
<directory>::
The repository to sync into.
--http-backend-info-refs::
Used by linkgit:git-http-backend[1] to serve up
`$GIT_URL/info/refs?service=git-receive-pack` requests. See
`--http-backend-info-refs` in linkgit:git-upload-pack[1].
PRE-RECEIVE HOOK
----------------
Before any ref is updated, if $GIT_DIR/hooks/pre-receive file exists

View File

@ -9,7 +9,7 @@ git-repack - Pack unpacked objects in a repository
SYNOPSIS
--------
[verse]
'git repack' [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m] [--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>] [--write-midx]
'git repack' [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]
DESCRIPTION
-----------
@ -128,11 +128,10 @@ depth is 4095.
-b::
--write-bitmap-index::
Write a reachability bitmap index as part of the repack. This
only makes sense when used with `-a`, `-A` or `-m`, as the bitmaps
only makes sense when used with `-a` or `-A`, as the bitmaps
must be able to refer to all reachable objects. This option
overrides the setting of `repack.writeBitmaps`. This option
has no effect if multiple packfiles are created, unless writing a
MIDX (in which case a multi-pack bitmap is created).
overrides the setting of `repack.writeBitmaps`. This option
has no effect if multiple packfiles are created.
--pack-kept-objects::
Include objects in `.keep` files when repacking. Note that we
@ -190,15 +189,6 @@ this "roll-up", without respect to their reachability. This is subject
to change in the future. This option (implying a drastically different
repack mode) is not guaranteed to work with all other combinations of
option to `git repack`.
+
When writing a multi-pack bitmap, `git repack` selects the largest resulting
pack as the preferred pack for object selection by the MIDX (see
linkgit:git-multi-pack-index[1]).
-m::
--write-midx::
Write a multi-pack index (see linkgit:git-multi-pack-index[1])
containing the non-redundant packs.
CONFIGURATION
-------------

View File

@ -69,8 +69,7 @@ linkgit:git-add[1]).
--hard::
Resets the index and working tree. Any changes to tracked files in the
working tree since `<commit>` are discarded. Any untracked files or
directories in the way of writing any tracked files are simply deleted.
working tree since `<commit>` are discarded.
--merge::
Resets the index and updates the files in the working tree that are

View File

@ -72,12 +72,6 @@ For more details, see the 'pathspec' entry in linkgit:gitglossary[7].
--ignore-unmatch::
Exit with a zero status even if no files matched.
--sparse::
Allow updating index entries outside of the sparse-checkout cone.
Normally, `git rm` refuses to update index entries whose paths do
not fit within the sparse-checkout cone. See
linkgit:git-sparse-checkout[1] for more.
-q::
--quiet::
`git rm` normally outputs one line (in the form of an `rm` command)

View File

@ -9,10 +9,10 @@ git-send-pack - Push objects over Git protocol to another repository
SYNOPSIS
--------
[verse]
'git send-pack' [--dry-run] [--force] [--receive-pack=<git-receive-pack>]
'git send-pack' [--all] [--dry-run] [--force] [--receive-pack=<git-receive-pack>]
[--verbose] [--thin] [--atomic]
[--[no-]signed|--signed=(true|false|if-asked)]
[<host>:]<directory> (--all | <ref>...)
[<host>:]<directory> [<ref>...]
DESCRIPTION
-----------

View File

@ -210,16 +210,6 @@ case-insensitive check. This corrects for case mismatched filenames in the
'git sparse-checkout set' command to reflect the expected cone in the working
directory.
When changing the sparse-checkout patterns in cone mode, Git will inspect each
tracked directory that is not within the sparse-checkout cone to see if it
contains any untracked files. If all of those files are ignored due to the
`.gitignore` patterns, then the directory will be deleted. If any of the
untracked files within that directory is not ignored, then no deletions will
occur within that directory and a warning message will appear. If these files
are important, then reset your sparse-checkout definition so they are included,
use `git add` and `git commit` to store them, then remove any remaining files
manually to ensure Git can behave optimally.
SUBMODULES
----------

View File

@ -207,29 +207,26 @@ show tracked paths:
* ' ' = unmodified
* 'M' = modified
* 'T' = file type changed (regular file, symbolic link or submodule)
* 'A' = added
* 'D' = deleted
* 'R' = renamed
* 'C' = copied (if config option status.renames is set to "copies")
* 'C' = copied
* 'U' = updated but unmerged
....
X Y Meaning
-------------------------------------------------
[AMD] not updated
M [ MTD] updated in index
T [ MTD] type changed in index
A [ MTD] added to index
M [ MD] updated in index
A [ MD] added to index
D deleted from index
R [ MTD] renamed in index
C [ MTD] copied in index
[MTARC] index and work tree matches
[ MTARC] M work tree changed since index
[ MTARC] T type changed in work tree since index
[ MTARC] D deleted in work tree
R renamed in work tree
C copied in work tree
R [ MD] renamed in index
C [ MD] copied in index
[MARC] index and work tree matches
[ MARC] M work tree changed since index
[ MARC] D deleted in work tree
[ D] R renamed in work tree
[ D] C copied in work tree
-------------------------------------------------
D D unmerged, both deleted
A U unmerged, added by us
@ -366,7 +363,7 @@ Field Meaning
Unmerged entries have the following format; the first character is
a "u" to distinguish from ordinary changed entries.
u <XY> <sub> <m1> <m2> <m3> <mW> <h1> <h2> <h3> <path>
u <xy> <sub> <m1> <m2> <m3> <mW> <h1> <h2> <h3> <path>
....
Field Meaning

View File

@ -678,6 +678,7 @@ config key: svn.authorsProg
--strategy=<strategy>::
-p::
--rebase-merges::
--preserve-merges (DEPRECATED)::
These are only used with the 'dcommit' and 'rebase' commands.
+
Passed directly to 'git rebase' when using 'dcommit' if a

View File

@ -36,26 +36,14 @@ OPTIONS
This fits with the HTTP POST request processing model where
a program may read the request, write a response, and must exit.
--http-backend-info-refs::
Used by linkgit:git-http-backend[1] to serve up
`$GIT_URL/info/refs?service=git-upload-pack` requests. See
"Smart Clients" in link:technical/http-protocol.html[the HTTP
transfer protocols] documentation and "HTTP Transport" in
link:technical/protocol-v2.html[the Git Wire Protocol, Version
2] documentation. Also understood by
linkgit:git-receive-pack[1].
--advertise-refs::
Only the initial ref advertisement is output, and the program exits
immediately. This fits with the HTTP GET request model, where
no request content is received but a response must be produced.
<directory>::
The repository to sync from.
ENVIRONMENT
-----------
`GIT_PROTOCOL`::
Internal variable used for handshaking the wire protocol. Server
admins may need to configure some transports to allow this
variable to be passed. See the discussion in linkgit:git[1].
SEE ALSO
--------
linkgit:gitnamespaces[7]

View File

@ -867,16 +867,15 @@ for full details.
end user, to be recorded in the body of the reflog.
`GIT_REF_PARANOIA`::
If set to `0`, ignore broken or badly named refs when iterating
over lists of refs. Normally Git will try to include any such
refs, which may cause some operations to fail. This is usually
preferable, as potentially destructive operations (e.g.,
linkgit:git-prune[1]) are better off aborting rather than
ignoring broken refs (and thus considering the history they
point to as not worth saving). The default value is `1` (i.e.,
be paranoid about detecting and aborting all operations). You
should not normally need to set this to `0`, but it may be
useful when trying to salvage data from a corrupted repository.
If set to `1`, include broken or badly named refs when iterating
over lists of refs. In a normal, non-corrupted repository, this
does nothing. However, enabling it may help git to detect and
abort some operations in the presence of broken refs. Git sets
this variable automatically when performing destructive
operations like linkgit:git-prune[1]. You should not need to set
it yourself unless you want to be paranoid about making sure
an operation has touched every ref (e.g., because you are
cloning a repository to make a backup).
`GIT_ALLOW_PROTOCOL`::
If set to a colon-separated list of protocols, behave as if
@ -899,21 +898,6 @@ for full details.
Contains a colon ':' separated list of keys with optional values
'key[=value]'. Presence of unknown keys and values must be
ignored.
+
Note that servers may need to be configured to allow this variable to
pass over some transports. It will be propagated automatically when
accessing local repositories (i.e., `file://` or a filesystem path), as
well as over the `git://` protocol. For git-over-http, it should work
automatically in most configurations, but see the discussion in
linkgit:git-http-backend[1]. For git-over-ssh, the ssh server may need
to be configured to allow clients to pass this variable (e.g., by using
`AcceptEnv GIT_PROTOCOL` with OpenSSH).
+
This configuration is optional. If the variable is not propagated, then
clients will fall back to the original "v0" protocol (but may miss out
on some performance improvements or features). This variable currently
only affects clones and fetches; it is not yet used for pushes (but may
be in the future).
`GIT_OPTIONAL_LOCKS`::
If set to `0`, Git will complete any requested operation without

View File

@ -275,7 +275,7 @@ best to always use a regular merge commit.
[[merge-two-revert-one]]
If I make a change on two branches but revert it on one, why does the merge of those branches include the change?::
By default, when Git does a merge, it uses a strategy called the `ort`
By default, when Git does a merge, it uses a strategy called the recursive
strategy, which does a fancy three-way merge. In such a case, when Git
performs the merge, it considers exactly three points: the two heads and a
third point, called the _merge base_, which is usually the common ancestor of

View File

@ -155,7 +155,7 @@ accessed from the index or a tree versus from the filesystem.
EXAMPLES
--------
- The pattern `hello.*` matches any file or directory
- The pattern `hello.*` matches any file or folder
whose name begins with `hello.`. If one wants to restrict
this only to the directory and not in its subdirectories,
one can prepend the pattern with a slash, i.e. `/hello.*`;

View File

@ -547,7 +547,7 @@ like this:
# make the front page an internal rewrite to the gitweb script
RewriteRule ^/$ /cgi-bin/gitweb.cgi [QSA,L,PT]
# look for a public_git directory in unix users' home
# look for a public_git folder in unix users' home
# http://git.example.org/~<user>/
RewriteRule ^/\~([^\/]+)(/|/gitweb.cgi)?$ /cgi-bin/gitweb.cgi \
[QSA,E=GITWEB_PROJECTROOT:/home/$1/public_git/,L,PT]

View File

@ -5,12 +5,11 @@ use warnings;
# Parse arguments, a simple state machine for input like:
#
# <file-to-check.txt> <valid-files-to-link-to> --section=1 git.txt git-add.txt [...] --to-lint git-add.txt a-file.txt [...]
# howto/*.txt config/*.txt --section=1 git.txt git-add.txt [...] --to-lint git-add.txt a-file.txt [...]
my %TXT;
my %SECTION;
my $section;
my $lint_these = 0;
my $to_check = shift @ARGV;
for my $arg (@ARGV) {
if (my ($sec) = $arg =~ /^--section=(\d+)$/s) {
$section = $sec;
@ -31,14 +30,13 @@ sub report {
my ($pos, $line, $target, $msg) = @_;
substr($line, $pos) = "' <-- HERE";
$line =~ s/^\s+//;
print STDERR "$ARGV:$.: error: $target: $msg, shown with 'HERE' below:\n";
print STDERR "$ARGV:$.:\t'$line\n";
print "$ARGV:$.: error: $target: $msg, shown with 'HERE' below:\n";
print "$ARGV:$.:\t'$line\n";
$exit_code = 1;
}
@ARGV = sort values %TXT;
die "BUG: No list of valid linkgit:* files given" unless @ARGV;
@ARGV = $to_check;
die "BUG: Nothing to process!" unless @ARGV;
while (<>) {
my $line = $_;
while ($line =~ m/linkgit:((.*?)\[(\d)\])/g) {

View File

@ -6,7 +6,7 @@ use warnings;
my $exit_code = 0;
sub report {
my ($target, $msg) = @_;
print STDERR "error: $target: $msg\n";
print "error: $target: $msg\n";
$exit_code = 1;
}

View File

@ -46,7 +46,7 @@ my $SECTION_RX = do {
my $exit_code = 0;
sub report {
my ($msg) = @_;
print STDERR "$ARGV:$.: $msg\n";
print "$ARGV:$.: $msg\n";
$exit_code = 1;
}

View File

@ -132,9 +132,8 @@ ifdef::git-pull[]
Only useful when merging.
endif::git-pull[]
--[no-]verify::
By default, the pre-merge and commit-msg hooks are run.
When `--no-verify` is given, these are bypassed.
--no-verify::
This option bypasses the pre-merge and commit-msg hooks.
See also linkgit:githooks[5].
ifdef::git-pull[]
Only useful when merging.
@ -145,7 +144,7 @@ endif::git-pull[]
Use the given merge strategy; can be supplied more than
once to specify them in the order they should be tried.
If there is no `-s` option, a built-in list of strategies
is used instead (`ort` when merging a single head,
is used instead (`recursive` when merging a single head,
`octopus` otherwise).
-X <option>::

View File

@ -6,23 +6,21 @@ backend 'merge strategies' to be chosen with `-s` option. Some strategies
can also take their own options, which can be passed by giving `-X<option>`
arguments to `git merge` and/or `git pull`.
ort::
This is the default merge strategy when pulling or merging one
branch. This strategy can only resolve two heads using a
3-way merge algorithm. When there is more than one common
ancestor that can be used for 3-way merge, it creates a merged
tree of the common ancestors and uses that as the reference
tree for the 3-way merge. This has been reported to result in
fewer merge conflicts without causing mismerges by tests done
on actual merge commits taken from Linux 2.6 kernel
development history. Additionally this strategy can detect
and handle merges involving renames. It does not make use of
detected copies. The name for this algorithm is an acronym
("Ostensibly Recursive's Twin") and came from the fact that it
was written as a replacement for the previous default
algorithm, `recursive`.
recursive::
This can only resolve two heads using a 3-way merge
algorithm. When there is more than one common
ancestor that can be used for 3-way merge, it creates a
merged tree of the common ancestors and uses that as
the reference tree for the 3-way merge. This has been
reported to result in fewer merge conflicts without
causing mismerges by tests done on actual merge commits
taken from Linux 2.6 kernel development history.
Additionally this can detect and handle merges involving
renames. It does not make use of detected copies. This
is the default merge strategy when pulling or merging one
branch.
+
The 'ort' strategy can take the following options:
The 'recursive' strategy can take the following options:
ours;;
This option forces conflicting hunks to be auto-resolved cleanly by
@ -38,6 +36,16 @@ theirs;;
This is the opposite of 'ours'; note that, unlike 'ours', there is
no 'theirs' merge strategy to confuse this merge option with.
patience;;
Deprecated synonym for `diff-algorithm=patience`.
diff-algorithm=[patience|minimal|histogram|myers];;
Use a different diff algorithm while merging, which can help
avoid mismerges that occur due to unimportant matching lines
(such as braces from distinct functions). See also
linkgit:git-diff[1] `--diff-algorithm`. Defaults to the
`diff.algorithm` config setting.
ignore-space-change;;
ignore-all-space;;
ignore-space-at-eol;;
@ -66,6 +74,11 @@ no-renormalize;;
Disables the `renormalize` option. This overrides the
`merge.renormalize` configuration variable.
no-renames;;
Turn off rename detection. This overrides the `merge.renames`
configuration variable.
See also linkgit:git-diff[1] `--no-renames`.
find-renames[=<n>];;
Turn on rename detection, optionally setting the similarity
threshold. This is the default. This overrides the
@ -82,39 +95,19 @@ subtree[=<path>];;
is prefixed (or stripped from the beginning) to make the shape of
two trees to match.
recursive::
This can only resolve two heads using a 3-way merge
algorithm. When there is more than one common
ancestor that can be used for 3-way merge, it creates a
merged tree of the common ancestors and uses that as
the reference tree for the 3-way merge. This has been
reported to result in fewer merge conflicts without
causing mismerges by tests done on actual merge commits
taken from Linux 2.6 kernel development history.
Additionally this can detect and handle merges involving
renames. It does not make use of detected copies. This was
the default strategy for resolving two heads from Git v0.99.9k
until v2.33.0.
ort::
This is meant as a drop-in replacement for the `recursive`
algorithm (as reflected in its acronym -- "Ostensibly
Recursive's Twin"), and will likely replace it in the future.
It fixes corner cases that the `recursive` strategy handles
suboptimally, and is significantly faster in large
repositories -- especially when many renames are involved.
+
The 'recursive' strategy takes the same options as 'ort'. However,
there are three additional options that 'ort' ignores (not documented
above) that are potentially useful with the 'recursive' strategy:
patience;;
Deprecated synonym for `diff-algorithm=patience`.
diff-algorithm=[patience|minimal|histogram|myers];;
Use a different diff algorithm while merging, which can help
avoid mismerges that occur due to unimportant matching lines
(such as braces from distinct functions). See also
linkgit:git-diff[1] `--diff-algorithm`. Note that `ort`
specifically uses `diff-algorithm=histogram`, while `recursive`
defaults to the `diff.algorithm` config setting.
no-renames;;
Turn off rename detection. This overrides the `merge.renames`
configuration variable.
See also linkgit:git-diff[1] `--no-renames`.
The `ort` strategy takes all the same options as `recursive`.
However, it ignores three of those options: `no-renames`,
`patience` and `diff-algorithm`. It always runs with rename
detection (it handles it much faster than `recursive` does), and
it specifically uses `diff-algorithm=histogram`.
resolve::
This can only resolve two heads (i.e. the current branch
@ -138,13 +131,13 @@ ours::
the 'recursive' merge strategy.
subtree::
This is a modified `ort` strategy. When merging trees A and
This is a modified recursive strategy. When merging trees A and
B, if B corresponds to a subtree of A, B is first adjusted to
match the tree structure of A, instead of reading the trees at
the same level. This adjustment is also done to the common
ancestor tree.
With the strategies that use 3-way merge (including the default, 'ort'),
With the strategies that use 3-way merge (including the default, 'recursive'),
if a change is made on both branches, but later reverted on one of the
branches, that change will be present in the merged result; some people find
this behavior confusing. It occurs because only the heads and the merge base

View File

@ -198,6 +198,11 @@ There are some macros to easily define options:
The filename will be prefixed by passing the filename along with
the prefix argument of `parse_options()` to `prefix_filename()`.
`OPT_ARGUMENT(long, &int_var, description)`::
Introduce a long-option argument that will be kept in `argv[]`.
If this option was seen, `int_var` will be set to one (except
if a `NULL` pointer was passed).
`OPT_NUMBER_CALLBACK(&var, description, func_ptr)`::
Recognize numerical options like -123 and feed the integer as
if it was an argument to the function given by `func_ptr`.

View File

@ -128,7 +128,7 @@ yields
------------
$ cat ~/log.event
{"event":"version","sid":"sid":"20190408T191610.507018Z-H9b68c35f-P000059a8","thread":"main","time":"2019-01-16T17:28:42.620713Z","file":"common-main.c","line":38,"evt":"3","exe":"2.20.1.155.g426c96fcdb"}
{"event":"version","sid":"sid":"20190408T191610.507018Z-H9b68c35f-P000059a8","thread":"main","time":"2019-01-16T17:28:42.620713Z","file":"common-main.c","line":38,"evt":"2","exe":"2.20.1.155.g426c96fcdb"}
{"event":"start","sid":"20190408T191610.507018Z-H9b68c35f-P000059a8","thread":"main","time":"2019-01-16T17:28:42.621027Z","file":"common-main.c","line":39,"t_abs":0.001173,"argv":["git","version"]}
{"event":"cmd_name","sid":"20190408T191610.507018Z-H9b68c35f-P000059a8","thread":"main","time":"2019-01-16T17:28:42.621122Z","file":"git.c","line":432,"name":"version","hierarchy":"version"}
{"event":"exit","sid":"20190408T191610.507018Z-H9b68c35f-P000059a8","thread":"main","time":"2019-01-16T17:28:42.621236Z","file":"git.c","line":662,"t_abs":0.001227,"code":0}
@ -391,7 +391,7 @@ only present on the "start" and "atexit" events.
{
"event":"version",
...
"evt":"3", # EVENT format version
"evt":"2", # EVENT format version
"exe":"2.20.1.155.g426c96fcdb" # git version
}
------------
@ -493,20 +493,6 @@ about specific error arguments.
}
------------
`"cmd_ancestry"`::
This event contains the text command name for the parent (and earlier
generations of parents) of the current process, in an array ordered from
nearest parent to furthest great-grandparent. It may not be implemented
on all platforms.
+
------------
{
"event":"cmd_ancestry",
...
"ancestry":["bash","tmux: server","systemd"]
}
------------
`"cmd_name"`::
This event contains the command name for this git process
and the hierarchy of commands from parent git processes.
@ -613,46 +599,6 @@ stopping after the waitpid() and includes OS process creation overhead).
So this time will be slightly larger than the atexit time reported by
the child process itself.
`"child_ready"`::
This event is generated after the current process has started
a background process and released all handles to it.
+
------------
{
"event":"child_ready",
...
"child_id":2,
"pid":14708, # child PID
"ready":"ready", # child ready state
"t_rel":0.110605 # observed run-time of child process
}
------------
+
Note that the session-id of the child process is not available to
the current/spawning process, so the child's PID is reported here as
a hint for post-processing. (But it is only a hint because the child
process may be a shell script which doesn't have a session-id.)
+
This event is generated after the child is started in the background
and given a little time to boot up and start working. If the child
startups normally and while the parent is still waiting, the "ready"
field will have the value "ready".
If the child is too slow to start and the parent times out, the field
will have the value "timeout".
If the child starts but the parent is unable to probe it, the field
will have the value "error".
+
After the parent process emits this event, it will release all of its
handles to the child process and treat the child as a background
daemon. So even if the child does eventually finish booting up,
the parent will not emit an updated event.
+
Note that the `t_rel` field contains the observed run time in seconds
when the parent released the child process into the background.
The child is assumed to be a long-running daemon process and may
outlive the parent process. So the parent's child event times should
not be compared to the child's atexit times.
`"exec"`::
This event is generated before git attempts to `exec()`
another command rather than starting a child process.

View File

@ -1,44 +1,6 @@
GIT bitmap v1 format
====================
== Pack and multi-pack bitmaps
Bitmaps store reachability information about the set of objects in a packfile,
or a multi-pack index (MIDX). The former is defined obviously, and the latter is
defined as the union of objects in packs contained in the MIDX.
A bitmap may belong to either one pack, or the repository's multi-pack index (if
it exists). A repository may have at most one bitmap.
An object is uniquely described by its bit position within a bitmap:
- If the bitmap belongs to a packfile, the __n__th bit corresponds to
the __n__th object in pack order. For a function `offset` which maps
objects to their byte offset within a pack, pack order is defined as
follows:
o1 <= o2 <==> offset(o1) <= offset(o2)
- If the bitmap belongs to a MIDX, the __n__th bit corresponds to the
__n__th object in MIDX order. With an additional function `pack` which
maps objects to the pack they were selected from by the MIDX, MIDX order
is defined as follows:
o1 <= o2 <==> pack(o1) <= pack(o2) /\ offset(o1) <= offset(o2)
The ordering between packs is done according to the MIDX's .rev file.
Notably, the preferred pack sorts ahead of all other packs.
The on-disk representation (described below) of a bitmap is the same regardless
of whether or not that bitmap belongs to a packfile or a MIDX. The only
difference is the interpretation of the bits, which is described above.
Certain bitmap extensions are supported (see: Appendix B). No extensions are
required for bitmaps corresponding to packfiles. For bitmaps that correspond to
MIDXs, both the bit-cache and rev-cache extensions are required.
== On-disk format
- A header appears at the beginning:
4-byte signature: {'B', 'I', 'T', 'M'}
@ -52,19 +14,17 @@ MIDXs, both the bit-cache and rev-cache extensions are required.
The following flags are supported:
- BITMAP_OPT_FULL_DAG (0x1) REQUIRED
This flag must always be present. It implies that the
bitmap index has been generated for a packfile or
multi-pack index (MIDX) with full closure (i.e. where
every single object in the packfile/MIDX can find its
parent links inside the same packfile/MIDX). This is a
requirement for the bitmap index format, also present in
JGit, that greatly reduces the complexity of the
implementation.
This flag must always be present. It implies that the bitmap
index has been generated for a packfile with full closure
(i.e. where every single object in the packfile can find
its parent links inside the same packfile). This is a
requirement for the bitmap index format, also present in JGit,
that greatly reduces the complexity of the implementation.
- BITMAP_OPT_HASH_CACHE (0x4)
If present, the end of the bitmap file contains
`N` 32-bit name-hash values, one per object in the
pack/MIDX. The format and meaning of the name-hash is
pack. The format and meaning of the name-hash is
described below.
4-byte entry count (network byte order)
@ -73,8 +33,7 @@ MIDXs, both the bit-cache and rev-cache extensions are required.
20-byte checksum
The SHA1 checksum of the pack/MIDX this bitmap index
belongs to.
The SHA1 checksum of the pack this bitmap index belongs to.
- 4 EWAH bitmaps that act as type indexes
@ -91,7 +50,7 @@ MIDXs, both the bit-cache and rev-cache extensions are required.
- Tags
In each bitmap, the `n`th bit is set to true if the `n`th object
in the packfile or multi-pack index is of that type.
in the packfile is of that type.
The obvious consequence is that the OR of all 4 bitmaps will result
in a full set (all bits set), and the AND of all 4 bitmaps will
@ -103,9 +62,8 @@ MIDXs, both the bit-cache and rev-cache extensions are required.
Each entry contains the following:
- 4-byte object position (network byte order)
The position **in the index for the packfile or
multi-pack index** where the bitmap for this commit is
found.
The position **in the index for the packfile** where the
bitmap for this commit is found.
- 1-byte XOR-offset
The xor offset used to compress this bitmap. For an entry
@ -188,11 +146,10 @@ Name-hash cache
---------------
If the BITMAP_OPT_HASH_CACHE flag is set, the end of the bitmap contains
a cache of 32-bit values, one per object in the pack/MIDX. The value at
a cache of 32-bit values, one per object in the pack. The value at
position `i` is the hash of the pathname at which the `i`th object
(counting in index or multi-pack index order) in the pack/MIDX can be found.
This can be fed into the delta heuristics to compare objects with similar
pathnames.
(counting in index order) in the pack can be found. This can be fed
into the delta heuristics to compare objects with similar pathnames.
The hash algorithm used is:

View File

@ -225,9 +225,6 @@ The client may send Extra Parameters (see
Documentation/technical/pack-protocol.txt) as a colon-separated string
in the Git-Protocol HTTP header.
Uses the `--http-backend-info-refs` option to
linkgit:git-upload-pack[1].
Dumb Server Response
^^^^^^^^^^^^^^^^^^^^
Dumb servers MUST respond with the dumb server reply format.

View File

@ -36,9 +36,7 @@ Design Details
directory of an alternate. It refers only to packfiles in that
same directory.
- The core.multiPackIndex config setting must be on (which is the
default) to consume MIDX files. Setting it to `false` prevents
Git from reading a MIDX file, even if one exists.
- The core.multiPackIndex config setting must be on to consume MIDX files.
- The file format includes parameters for the object ID hash
function, so a future change of hash algorithm does not require
@ -73,10 +71,14 @@ Future Work
still reducing the number of binary searches required for object
lookups.
- If the multi-pack-index is extended to store a "stable object order"
- The reachability bitmap is currently paired directly with a single
packfile, using the pack-order as the object order to hopefully
compress the bitmaps well using run-length encoding. This could be
extended to pair a reachability bitmap with a multi-pack-index. If
the multi-pack-index is extended to store a "stable object order"
(a function Order(hash) = integer that is constant for a given hash,
even as the multi-pack-index is updated) then MIDX bitmaps could be
updated independently of the MIDX.
even as the multi-pack-index is updated) then a reachability bitmap
could point to a multi-pack-index and be updated independently.
- Packfiles can be marked as "special" using empty files that share
the initial name but replace ".pack" with ".keep" or ".promisor".

View File

@ -42,8 +42,7 @@ Initial Client Request
In general a client can request to speak protocol v2 by sending
`version=2` through the respective side-channel for the transport being
used which inevitably sets `GIT_PROTOCOL`. More information can be
found in `pack-protocol.txt` and `http-protocol.txt`, as well as the
`GIT_PROTOCOL` definition in `git.txt`. In all cases the
found in `pack-protocol.txt` and `http-protocol.txt`. In all cases the
response from the server is the capability advertisement.
Git Transport
@ -59,8 +58,6 @@ SSH and File Transport
When using either the ssh:// or file:// transport, the GIT_PROTOCOL
environment variable must be set explicitly to include "version=2".
The server may need to be configured to allow this environment variable
to pass.
HTTP Transport
~~~~~~~~~~~~~~
@ -84,12 +81,6 @@ A v2 server would reply:
Subsequent requests are then made directly to the service
`$GIT_URL/git-upload-pack`. (This works the same for git-receive-pack).
Uses the `--http-backend-info-refs` option to
linkgit:git-upload-pack[1].
The server may need to be configured to pass this header's contents via
the `GIT_PROTOCOL` variable. See the discussion in `git-http-backend.txt`.
Capability Advertisement
------------------------
@ -199,11 +190,7 @@ ls-refs takes in the following arguments:
Show peeled tags.
ref-prefix <prefix>
When specified, only references having a prefix matching one of
the provided prefixes are displayed. Multiple instances may be
given, in which case references matching any prefix will be
shown. Note that this is purely for optimization; a server MAY
show refs not matching the prefix if it chooses, and clients
should filter the result themselves.
the provided prefixes are displayed.
If the 'unborn' feature is advertised the following argument can be
included in the client's request.

View File

@ -13,22 +13,6 @@ Signatures always begin with `-----BEGIN PGP SIGNATURE-----`
and end with `-----END PGP SIGNATURE-----`, unless gpg is told to
produce RFC1991 signatures which use `MESSAGE` instead of `SIGNATURE`.
Signatures sometimes appear as a part of the normal payload
(e.g. a signed tag has the signature block appended after the payload
that the signature applies to), and sometimes appear in the value of
an object header (e.g. a merge commit that merged a signed tag would
have the entire tag contents on its "mergetag" header). In the case
of the latter, the usual multi-line formatting rule for object
headers applies. I.e. the second and subsequent lines are prefixed
with a SP to signal that the line is continued from the previous
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
primarily to highlight extra whitespace at the end of some lines.
The signed payload and the way the signature is embedded depends
on the type of the object resp. transaction.
@ -94,7 +78,7 @@ author A U Thor <author@example.com> 1465981137 +0000
committer C O Mitter <committer@example.com> 1465981137 +0000
gpgsig -----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
$
iQEcBAABAgAGBQJXYRjRAAoJEGEJLoW3InGJ3IwIAIY4SA6GxY3BjL60YyvsJPh/
HRCJwH+w7wt3Yc/9/bW2F+gF72kdHOOs2jfv+OZhq0q4OAN6fvVSczISY/82LpS7
DVdMQj2/YcHDT4xrDNBnXnviDO9G7am/9OE77kEbXrp7QPxvhjkicHNwy2rEflAA
@ -144,13 +128,13 @@ mergetag object 04b871796dc0420f8e7561a895b52484b701d51a
type commit
tag signedtag
tagger C O Mitter <committer@example.com> 1465981006 +0000
$
signed tag
$
signed tag message body
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
$
iQEcBAABAgAGBQJXYRhOAAoJEGEJLoW3InGJklkIAIcnhL7RwEb/+QeX9enkXhxn
rxfdqrvWd1K80sl2TOt8Bg/NYwrUBw/RWJ+sg/hhHp4WtvE1HDGHlkEz3y11Lkuh
8tSxS3qKTxXUGozyPGuE90sJfExhZlW4knIQ1wt/yWqM+33E9pN4hzPqLwyrdods

View File

@ -3190,7 +3190,7 @@ that *updated* thing--the old state that you added originally ends up
not being pointed to by any commit or tree, so it's now a dangling blob
object.
Similarly, when the "ort" merge strategy runs, and finds that
Similarly, when the "recursive" merge strategy runs, and finds that
there are criss-cross merges and thus more than one merge base (which is
fairly unusual, but it does happen), it will generate one temporary
midway tree (or possibly even more, if you had lots of criss-crossing

View File

@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
DEF_VER=v2.34.4
DEF_VER=v2.33.6
LF='
'

15
INSTALL
View File

@ -138,15 +138,12 @@ Issues of note:
BLK_SHA1. Also included is a version optimized for PowerPC
(PPC_SHA1).
- "libcurl" library is used for fetching and pushing
repositories over http:// or https://, as well as by
git-imap-send if the curl version is >= 7.34.0. If you do
not need that functionality, use NO_CURL to build without
it.
Git requires version "7.19.4" or later of "libcurl" to build
without NO_CURL. This version requirement may be bumped in
the future.
- "libcurl" library is used by git-http-fetch, git-fetch, and, if
the curl version >= 7.34.0, for git-imap-send. You might also
want the "curl" executable for debugging purposes. If you do not
use http:// or https:// repositories, and do not want to put
patches into an IMAP mailbox, you do not have to have them
(use NO_CURL).
- "expat" library; git-http-push uses it for remote lock
management over DAV. Similar to "curl" above, this is optional

135
Makefile
View File

@ -409,6 +409,15 @@ all::
# Define NEEDS_LIBRT if your platform requires linking with librt (glibc version
# before 2.17) for clock_gettime and CLOCK_MONOTONIC.
#
# Define USE_PARENS_AROUND_GETTEXT_N to "yes" if your compiler happily
# compiles the following initialization:
#
# static const char s[] = ("FOO");
#
# and define it to "no" if you need to remove the parentheses () around the
# constant. The default is "auto", which means to use parentheses if your
# compiler is detected to support it.
#
# Define HAVE_BSD_SYSCTL if your platform has a BSD-compatible sysctl function.
#
# Define HAVE_GETDELIM if your system has the getdelim() function.
@ -456,9 +465,6 @@ all::
# the global variable _wpgmptr containing the absolute path of the current
# executable (this is the case on Windows).
#
# INSTALL_STRIP can be set to "-s" to strip binaries during installation,
# if your $(INSTALL) command supports the option.
#
# Define GENERATE_COMPILATION_DATABASE to "yes" to generate JSON compilation
# database entries during compilation if your compiler supports it, using the
# `-MJ` flag. The JSON entries will be placed in the `compile_commands/`
@ -489,9 +495,10 @@ all::
# setting this flag the exceptions are removed, and all of
# -Wextra is used.
#
# no-pedantic:
# pedantic:
#
# Disable -pedantic compilation.
# Enable -pedantic compilation. This also disables
# USE_PARENS_AROUND_GETTEXT_N to produce only relevant warnings.
GIT-VERSION-FILE: FORCE
@$(SHELL_PATH) ./GIT-VERSION-GEN
@ -609,6 +616,7 @@ SCRIPT_SH += git-submodule.sh
SCRIPT_SH += git-web--browse.sh
SCRIPT_LIB += git-mergetool--lib
SCRIPT_LIB += git-rebase--preserve-merges
SCRIPT_LIB += git-sh-i18n
SCRIPT_LIB += git-sh-setup
@ -816,10 +824,6 @@ XDIFF_LIB = xdiff/lib.a
GENERATED_H += command-list.h
GENERATED_H += config-list.h
GENERATED_H += hook-list.h
.PHONY: generated-hdrs
generated-hdrs: $(GENERATED_H)
LIB_H := $(sort $(patsubst ./%,%,$(shell git ls-files '*.h' ':!t/' ':!Documentation/' 2>/dev/null || \
$(FIND) . \
@ -905,7 +909,6 @@ LIB_OBJS += hash-lookup.o
LIB_OBJS += hashmap.o
LIB_OBJS += help.o
LIB_OBJS += hex.o
LIB_OBJS += hook.o
LIB_OBJS += ident.o
LIB_OBJS += json-writer.o
LIB_OBJS += kwset.o
@ -1218,9 +1221,6 @@ PTHREAD_CFLAGS =
SPARSE_FLAGS ?=
SP_EXTRA_FLAGS = -Wno-universal-initializer
# For informing GIT-BUILD-OPTIONS of the SANITIZE=leak target
SANITIZE_LEAK =
# For the 'coccicheck' target; setting SPATCH_BATCH_SIZE higher will
# usually result in less CPU usage at the cost of higher peak memory.
# Setting it to 0 will feed all files in a single spatch invocation.
@ -1265,7 +1265,6 @@ BASIC_CFLAGS += -DSHA1DC_FORCE_ALIGNED_ACCESS
endif
ifneq ($(filter leak,$(SANITIZERS)),)
BASIC_CFLAGS += -DSUPPRESS_ANNOTATED_LEAKS
SANITIZE_LEAK = YesCompiledWithIt
endif
ifneq ($(filter address,$(SANITIZERS)),)
NO_REGEX = NeededForASAN
@ -1286,7 +1285,6 @@ endif
ifeq ($(COMPUTE_HEADER_DEPENDENCIES),auto)
dep_check = $(shell $(CC) $(ALL_CFLAGS) \
-Wno-pedantic \
-c -MF /dev/null -MQ /dev/null -MMD -MP \
-x c /dev/null -o /dev/null 2>&1; \
echo $$?)
@ -1312,7 +1310,6 @@ endif
ifeq ($(GENERATE_COMPILATION_DATABASE),yes)
compdb_check = $(shell $(CC) $(ALL_CFLAGS) \
-Wno-pedantic \
-c -MJ /dev/null \
-x c /dev/null -o /dev/null 2>&1; \
echo $$?)
@ -1350,6 +1347,14 @@ ifneq (,$(SOCKLEN_T))
BASIC_CFLAGS += -Dsocklen_t=$(SOCKLEN_T)
endif
ifeq (yes,$(USE_PARENS_AROUND_GETTEXT_N))
BASIC_CFLAGS += -DUSE_PARENS_AROUND_GETTEXT_N=1
else
ifeq (no,$(USE_PARENS_AROUND_GETTEXT_N))
BASIC_CFLAGS += -DUSE_PARENS_AROUND_GETTEXT_N=0
endif
endif
ifeq ($(uname_S),Darwin)
ifndef NO_FINK
ifeq ($(shell test -d /sw/lib && echo y),y)
@ -1431,8 +1436,15 @@ else
REMOTE_CURL_NAMES = $(REMOTE_CURL_PRIMARY) $(REMOTE_CURL_ALIASES)
PROGRAM_OBJS += http-fetch.o
PROGRAMS += $(REMOTE_CURL_NAMES)
ifndef NO_EXPAT
PROGRAM_OBJS += http-push.o
curl_check := $(shell (echo 070908; $(CURL_CONFIG) --vernum | sed -e '/^70[BC]/s/^/0/') 2>/dev/null | sort -r | sed -ne 2p)
ifeq "$(curl_check)" "070908"
ifndef NO_EXPAT
PROGRAM_OBJS += http-push.o
else
EXCLUDED_PROGRAMS += git-http-push
endif
else
EXCLUDED_PROGRAMS += git-http-push
endif
curl_check := $(shell (echo 072200; $(CURL_CONFIG) --vernum | sed -e '/^70[BC]/s/^/0/') 2>/dev/null | sort -r | sed -ne 2p)
ifeq "$(curl_check)" "072200"
@ -1905,10 +1917,6 @@ ifneq ($(PROCFS_EXECUTABLE_PATH),)
BASIC_CFLAGS += '-DPROCFS_EXECUTABLE_PATH="$(procfs_executable_path_SQ)"'
endif
ifndef HAVE_PLATFORM_PROCINFO
COMPAT_OBJS += compat/stub/procinfo.o
endif
ifdef HAVE_NS_GET_EXECUTABLE_PATH
BASIC_CFLAGS += -DHAVE_NS_GET_EXECUTABLE_PATH
endif
@ -2215,9 +2223,8 @@ git$X: git.o GIT-LDFLAGS $(BUILTIN_OBJS) $(GITLIBS)
$(filter %.o,$^) $(LIBS)
help.sp help.s help.o: command-list.h
hook.sp hook.s hook.o: hook-list.h
builtin/help.sp builtin/help.s builtin/help.o: config-list.h hook-list.h GIT-PREFIX
builtin/help.sp builtin/help.s builtin/help.o: config-list.h GIT-PREFIX
builtin/help.sp builtin/help.s builtin/help.o: EXTRA_CPPFLAGS = \
'-DGIT_HTML_PATH="$(htmldir_relative_SQ)"' \
'-DGIT_MAN_PATH="$(mandir_relative_SQ)"' \
@ -2240,17 +2247,15 @@ $(BUILT_INS): git$X
config-list.h: generate-configlist.sh
config-list.h: Documentation/*config.txt Documentation/config/*.txt
$(QUIET_GEN)$(SHELL_PATH) ./generate-configlist.sh >$@
$(QUIET_GEN)$(SHELL_PATH) ./generate-configlist.sh \
>$@+ && mv $@+ $@
command-list.h: generate-cmdlist.sh command-list.txt
command-list.h: $(wildcard Documentation/git*.txt)
$(QUIET_GEN)$(SHELL_PATH) ./generate-cmdlist.sh \
$(patsubst %,--exclude-program %,$(EXCLUDED_PROGRAMS)) \
command-list.txt >$@
hook-list.h: generate-hooklist.sh Documentation/githooks.txt
$(QUIET_GEN)$(SHELL_PATH) ./generate-hooklist.sh >$@
command-list.txt >$@+ && mv $@+ $@
SCRIPT_DEFINES = $(SHELL_PATH_SQ):$(DIFF_SQ):$(GIT_VERSION):\
$(localedir_SQ):$(NO_CURL):$(USE_GETTEXT_SCHEME):$(SANE_TOOL_PATH_SQ):\
@ -2512,6 +2517,13 @@ ifneq ($(dep_files_present),)
include $(dep_files_present)
endif
else
# Dependencies on header files, for platforms that do not support
# the gcc -MMD option.
#
# Dependencies on automatically generated headers such as command-list.h
# should _not_ be included here, since they are necessary even when
# building an object for the first time.
$(OBJECTS): $(LIB_H) $(GENERATED_H)
endif
@ -2636,6 +2648,7 @@ XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --language=Perl \
--keyword=__ --keyword=N__ --keyword="__n:1,2"
LOCALIZED_C = $(C_OBJ:o=c) $(LIB_H) $(GENERATED_H)
LOCALIZED_SH = $(SCRIPT_SH)
LOCALIZED_SH += git-rebase--preserve-merges.sh
LOCALIZED_SH += git-sh-setup.sh
LOCALIZED_PERL = $(SCRIPT_PERL)
@ -2732,25 +2745,19 @@ FIND_SOURCE_FILES = ( \
| sed -e 's|^\./||' \
)
FOUND_SOURCE_FILES = $(shell $(FIND_SOURCE_FILES))
$(ETAGS_TARGET): FORCE
$(QUIET_GEN)$(RM) "$(ETAGS_TARGET)+" && \
$(FIND_SOURCE_FILES) | xargs etags -a -o "$(ETAGS_TARGET)+" && \
mv "$(ETAGS_TARGET)+" "$(ETAGS_TARGET)"
$(ETAGS_TARGET): $(FOUND_SOURCE_FILES)
$(QUIET_GEN)$(RM) $@+ && \
echo $(FOUND_SOURCE_FILES) | xargs etags -a -o $@+ && \
mv $@+ $@
tags: FORCE
$(QUIET_GEN)$(RM) tags+ && \
$(FIND_SOURCE_FILES) | xargs ctags -a -o tags+ && \
mv tags+ tags
tags: $(FOUND_SOURCE_FILES)
$(QUIET_GEN)$(RM) $@+ && \
echo $(FOUND_SOURCE_FILES) | xargs ctags -a -o $@+ && \
mv $@+ $@
cscope.out: $(FOUND_SOURCE_FILES)
$(QUIET_GEN)$(RM) $@+ && \
echo $(FOUND_SOURCE_FILES) | xargs cscope -f$@+ -b && \
mv $@+ $@
.PHONY: cscope
cscope: cscope.out
cscope:
$(RM) cscope*
$(FIND_SOURCE_FILES) | xargs cscope -b
### Detect prefix changes
TRACK_PREFIX = $(bindir_SQ):$(gitexecdir_SQ):$(template_dir_SQ):$(prefix_SQ):\
@ -2800,7 +2807,6 @@ GIT-BUILD-OPTIONS: FORCE
@echo NO_UNIX_SOCKETS=\''$(subst ','\'',$(subst ','\'',$(NO_UNIX_SOCKETS)))'\' >>$@+
@echo PAGER_ENV=\''$(subst ','\'',$(subst ','\'',$(PAGER_ENV)))'\' >>$@+
@echo DC_SHA1=\''$(subst ','\'',$(subst ','\'',$(DC_SHA1)))'\' >>$@+
@echo SANITIZE_LEAK=\''$(subst ','\'',$(subst ','\'',$(SANITIZE_LEAK)))'\' >>$@+
@echo X=\'$(X)\' >>$@+
ifdef TEST_OUTPUT_DIRECTORY
@echo TEST_OUTPUT_DIRECTORY=\''$(subst ','\'',$(subst ','\'',$(TEST_OUTPUT_DIRECTORY)))'\' >>$@+
@ -2841,11 +2847,6 @@ ifdef GIT_TEST_INDEX_VERSION
endif
ifdef GIT_TEST_PERL_FATAL_WARNINGS
@echo GIT_TEST_PERL_FATAL_WARNINGS=\''$(subst ','\'',$(subst ','\'',$(GIT_TEST_PERL_FATAL_WARNINGS)))'\' >>$@+
endif
ifdef RUNTIME_PREFIX
@echo RUNTIME_PREFIX=\'true\' >>$@+
else
@echo RUNTIME_PREFIX=\'false\' >>$@+
endif
@if cmp $@+ $@ >/dev/null 2>&1; then $(RM) $@+; else mv $@+ $@; fi
@ -2901,16 +2902,14 @@ check-sha1:: t/helper/test-tool$X
SP_OBJ = $(patsubst %.o,%.sp,$(C_OBJ))
$(SP_OBJ): %.sp: %.c %.o
$(SP_OBJ): %.sp: %.c GIT-CFLAGS FORCE
$(QUIET_SP)cgcc -no-compile $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) \
-Wsparse-error \
$(SPARSE_FLAGS) $(SP_EXTRA_FLAGS) $< && \
>$@
$(SPARSE_FLAGS) $(SP_EXTRA_FLAGS) $<
.PHONY: sparse
.PHONY: sparse $(SP_OBJ)
sparse: $(SP_OBJ)
EXCEPT_HDRS := $(GENERATED_H) unicode-width.h compat/% xdiff/%
EXCEPT_HDRS := command-list.h config-list.h unicode-width.h compat/% xdiff/%
ifndef GCRYPT_SHA256
EXCEPT_HDRS += sha256/gcrypt.h
endif
@ -2932,8 +2931,7 @@ hdr-check: $(HCO)
style:
git clang-format --style file --diff --extensions c,h
.PHONY: check
check: $(GENERATED_H)
check: config-list.h command-list.h
@if sparse; \
then \
echo >&2 "Use 'make sparse' instead"; \
@ -2943,7 +2941,7 @@ check: $(GENERATED_H)
exit 1; \
fi
FOUND_C_SOURCES = $(filter %.c,$(FOUND_SOURCE_FILES))
FOUND_C_SOURCES = $(filter %.c,$(shell $(FIND_SOURCE_FILES)))
COCCI_SOURCES = $(filter-out $(THIRD_PARTY_SOURCES),$(FOUND_C_SOURCES))
%.cocci.patch: %.cocci $(COCCI_SOURCES)
@ -2996,8 +2994,7 @@ mergetools_instdir = $(prefix)/$(mergetoolsdir)
endif
mergetools_instdir_SQ = $(subst ','\'',$(mergetools_instdir))
install_bindir_xprograms := $(patsubst %,%$X,$(BINDIR_PROGRAMS_NEED_X))
install_bindir_programs := $(install_bindir_xprograms) $(BINDIR_PROGRAMS_NO_X)
install_bindir_programs := $(patsubst %,%$X,$(BINDIR_PROGRAMS_NEED_X)) $(BINDIR_PROGRAMS_NO_X)
.PHONY: profile-install profile-fast-install
profile-install: profile
@ -3006,17 +3003,12 @@ profile-install: profile
profile-fast-install: profile-fast
$(MAKE) install
INSTALL_STRIP =
install: all
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
$(INSTALL) $(INSTALL_STRIP) $(PROGRAMS) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
$(INSTALL) $(SCRIPTS) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
$(INSTALL) $(ALL_PROGRAMS) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
$(INSTALL) -m 644 $(SCRIPT_LIB) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
$(INSTALL) $(INSTALL_STRIP) $(install_bindir_xprograms) '$(DESTDIR_SQ)$(bindir_SQ)'
$(INSTALL) $(BINDIR_PROGRAMS_NO_X) '$(DESTDIR_SQ)$(bindir_SQ)'
$(INSTALL) $(install_bindir_programs) '$(DESTDIR_SQ)$(bindir_SQ)'
ifdef MSVC
# We DO NOT install the individual foo.o.pdb files because they
# have already been rolled up into the exe's pdb file.
@ -3235,7 +3227,6 @@ clean: profile-clean coverage-clean cocciclean
$(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git$X
$(RM) $(TEST_PROGRAMS)
$(RM) $(FUZZ_PROGRAMS)
$(RM) $(SP_OBJ)
$(RM) $(HCC)
$(RM) -r bin-wrappers $(dep_dirs) $(compdb_dir) compile_commands.json
$(RM) -r po/build/
@ -3274,7 +3265,7 @@ endif
.PHONY: all install profile-clean cocciclean clean strip
.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
.PHONY: FORCE
.PHONY: FORCE cscope
### Check documentation
#

View File

@ -1 +1 @@
Documentation/RelNotes/2.34.4.txt
Documentation/RelNotes/2.33.6.txt

View File

@ -102,12 +102,8 @@ struct prefix_item_list {
int *selected; /* for multi-selections */
size_t min_length, max_length;
};
#define PREFIX_ITEM_LIST_INIT { \
.items = STRING_LIST_INIT_DUP, \
.sorted = STRING_LIST_INIT_NODUP, \
.min_length = 1, \
.max_length = 4, \
}
#define PREFIX_ITEM_LIST_INIT \
{ STRING_LIST_INIT_DUP, STRING_LIST_INIT_NODUP, NULL, 1, 4 }
static void prefix_item_list_clear(struct prefix_item_list *list)
{

View File

@ -4,6 +4,37 @@
#include "help.h"
#include "string-list.h"
int advice_fetch_show_forced_updates = 1;
int advice_push_update_rejected = 1;
int advice_push_non_ff_current = 1;
int advice_push_non_ff_matching = 1;
int advice_push_already_exists = 1;
int advice_push_fetch_first = 1;
int advice_push_needs_force = 1;
int advice_push_unqualified_ref_name = 1;
int advice_push_ref_needs_update = 1;
int advice_status_hints = 1;
int advice_status_u_option = 1;
int advice_status_ahead_behind_warning = 1;
int advice_commit_before_merge = 1;
int advice_reset_quiet_warning = 1;
int advice_resolve_conflict = 1;
int advice_sequencer_in_use = 1;
int advice_implicit_identity = 1;
int advice_detached_head = 1;
int advice_set_upstream_failure = 1;
int advice_object_name_warning = 1;
int advice_amworkdir = 1;
int advice_rm_hints = 1;
int advice_add_embedded_repo = 1;
int advice_ignored_hook = 1;
int advice_waiting_for_editor = 1;
int advice_graft_file_deprecated = 1;
int advice_checkout_ambiguous_remote_branch_name = 1;
int advice_submodule_alternate_error_strategy_die = 1;
int advice_add_ignored_file = 1;
int advice_add_empty_pathspec = 1;
static int advice_use_color = -1;
static char advice_colors[][COLOR_MAXLEN] = {
GIT_COLOR_RESET,
@ -31,13 +62,50 @@ static const char *advise_get_color(enum color_advice ix)
return "";
}
static struct {
const char *name;
int *preference;
} advice_config[] = {
{ "fetchShowForcedUpdates", &advice_fetch_show_forced_updates },
{ "pushUpdateRejected", &advice_push_update_rejected },
{ "pushNonFFCurrent", &advice_push_non_ff_current },
{ "pushNonFFMatching", &advice_push_non_ff_matching },
{ "pushAlreadyExists", &advice_push_already_exists },
{ "pushFetchFirst", &advice_push_fetch_first },
{ "pushNeedsForce", &advice_push_needs_force },
{ "pushUnqualifiedRefName", &advice_push_unqualified_ref_name },
{ "pushRefNeedsUpdate", &advice_push_ref_needs_update },
{ "statusHints", &advice_status_hints },
{ "statusUoption", &advice_status_u_option },
{ "statusAheadBehindWarning", &advice_status_ahead_behind_warning },
{ "commitBeforeMerge", &advice_commit_before_merge },
{ "resetQuiet", &advice_reset_quiet_warning },
{ "resolveConflict", &advice_resolve_conflict },
{ "sequencerInUse", &advice_sequencer_in_use },
{ "implicitIdentity", &advice_implicit_identity },
{ "detachedHead", &advice_detached_head },
{ "setUpstreamFailure", &advice_set_upstream_failure },
{ "objectNameWarning", &advice_object_name_warning },
{ "amWorkDir", &advice_amworkdir },
{ "rmHints", &advice_rm_hints },
{ "addEmbeddedRepo", &advice_add_embedded_repo },
{ "ignoredHook", &advice_ignored_hook },
{ "waitingForEditor", &advice_waiting_for_editor },
{ "graftFileDeprecated", &advice_graft_file_deprecated },
{ "checkoutAmbiguousRemoteBranchName", &advice_checkout_ambiguous_remote_branch_name },
{ "submoduleAlternateErrorStrategyDie", &advice_submodule_alternate_error_strategy_die },
{ "addIgnoredFile", &advice_add_ignored_file },
{ "addEmptyPathspec", &advice_add_empty_pathspec },
/* make this an alias for backward compatibility */
{ "pushNonFastForward", &advice_push_update_rejected }
};
static struct {
const char *key;
int enabled;
} advice_setting[] = {
[ADVICE_ADD_EMBEDDED_REPO] = { "addEmbeddedRepo", 1 },
[ADVICE_ADD_EMPTY_PATHSPEC] = { "addEmptyPathspec", 1 },
[ADVICE_ADD_IGNORED_FILE] = { "addIgnoredFile", 1 },
[ADVICE_AM_WORK_DIR] = { "amWorkDir", 1 },
[ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME] = { "checkoutAmbiguousRemoteBranchName", 1 },
[ADVICE_COMMIT_BEFORE_MERGE] = { "commitBeforeMerge", 1 },
@ -65,7 +133,6 @@ static struct {
[ADVICE_RM_HINTS] = { "rmHints", 1 },
[ADVICE_SEQUENCER_IN_USE] = { "sequencerInUse", 1 },
[ADVICE_SET_UPSTREAM_FAILURE] = { "setUpstreamFailure", 1 },
[ADVICE_SKIPPED_CHERRY_PICKS] = { "skippedCherryPicks", 1 },
[ADVICE_STATUS_AHEAD_BEHIND_WARNING] = { "statusAheadBehindWarning", 1 },
[ADVICE_STATUS_HINTS] = { "statusHints", 1 },
[ADVICE_STATUS_U_OPTION] = { "statusUoption", 1 },
@ -154,6 +221,13 @@ int git_default_advice_config(const char *var, const char *value)
if (!skip_prefix(var, "advice.", &k))
return 0;
for (i = 0; i < ARRAY_SIZE(advice_config); i++) {
if (strcasecmp(k, advice_config[i].name))
continue;
*advice_config[i].preference = git_config_bool(var, value);
break;
}
for (i = 0; i < ARRAY_SIZE(advice_setting); i++) {
if (strcasecmp(k, advice_setting[i].key))
continue;
@ -188,7 +262,7 @@ int error_resolve_conflict(const char *me)
error(_("It is not possible to %s because you have unmerged files."),
me);
if (advice_enabled(ADVICE_RESOLVE_CONFLICT))
if (advice_resolve_conflict)
/*
* Message used both when 'git commit' fails and when
* other commands doing a merge do.
@ -207,7 +281,7 @@ void NORETURN die_resolve_conflict(const char *me)
void NORETURN die_conclude_merge(void)
{
error(_("You have not concluded your merge (MERGE_HEAD exists)."));
if (advice_enabled(ADVICE_RESOLVE_CONFLICT))
if (advice_resolve_conflict)
advise(_("Please, commit your changes before merging."));
die(_("Exiting because of unfinished merge."));
}
@ -224,16 +298,15 @@ void advise_on_updating_sparse_paths(struct string_list *pathspec_list)
if (!pathspec_list->nr)
return;
fprintf(stderr, _("The following paths and/or pathspecs matched paths that exist\n"
"outside of your sparse-checkout definition, so will not be\n"
"updated in the index:\n"));
fprintf(stderr, _("The following pathspecs didn't match any"
" eligible path, but they do match index\n"
"entries outside the current sparse checkout:\n"));
for_each_string_list_item(item, pathspec_list)
fprintf(stderr, "%s\n", item->string);
advise_if_enabled(ADVICE_UPDATE_SPARSE_PATH,
_("If you intend to update such entries, try one of the following:\n"
"* Use the --sparse option.\n"
"* Disable or modify the sparsity rules."));
_("Disable or modify the sparsity rules if you intend"
" to update such entries."));
}
void detach_advice(const char *new_name)

View File

@ -5,6 +5,37 @@
struct string_list;
extern int advice_fetch_show_forced_updates;
extern int advice_push_update_rejected;
extern int advice_push_non_ff_current;
extern int advice_push_non_ff_matching;
extern int advice_push_already_exists;
extern int advice_push_fetch_first;
extern int advice_push_needs_force;
extern int advice_push_unqualified_ref_name;
extern int advice_push_ref_needs_update;
extern int advice_status_hints;
extern int advice_status_u_option;
extern int advice_status_ahead_behind_warning;
extern int advice_commit_before_merge;
extern int advice_reset_quiet_warning;
extern int advice_resolve_conflict;
extern int advice_sequencer_in_use;
extern int advice_implicit_identity;
extern int advice_detached_head;
extern int advice_set_upstream_failure;
extern int advice_object_name_warning;
extern int advice_amworkdir;
extern int advice_rm_hints;
extern int advice_add_embedded_repo;
extern int advice_ignored_hook;
extern int advice_waiting_for_editor;
extern int advice_graft_file_deprecated;
extern int advice_checkout_ambiguous_remote_branch_name;
extern int advice_submodule_alternate_error_strategy_die;
extern int advice_add_ignored_file;
extern int advice_add_empty_pathspec;
/*
* To add a new advice, you need to:
* Define a new advice_type.
@ -14,8 +45,6 @@ struct string_list;
*/
enum advice_type {
ADVICE_ADD_EMBEDDED_REPO,
ADVICE_ADD_EMPTY_PATHSPEC,
ADVICE_ADD_IGNORED_FILE,
ADVICE_AM_WORK_DIR,
ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME,
ADVICE_COMMIT_BEFORE_MERGE,
@ -46,7 +75,6 @@ struct string_list;
ADVICE_SUBMODULE_ALTERNATE_ERROR_STRATEGY_DIE,
ADVICE_UPDATE_SPARSE_PATH,
ADVICE_WAITING_FOR_EDITOR,
ADVICE_SKIPPED_CHERRY_PICKS,
};
int git_default_advice_config(const char *var, const char *value);

11
alias.c
View File

@ -46,14 +46,16 @@ void list_aliases(struct string_list *list)
#define SPLIT_CMDLINE_BAD_ENDING 1
#define SPLIT_CMDLINE_UNCLOSED_QUOTE 2
#define SPLIT_CMDLINE_ARGC_OVERFLOW 3
static const char *split_cmdline_errors[] = {
N_("cmdline ends with \\"),
N_("unclosed quote")
N_("unclosed quote"),
N_("too many arguments"),
};
int split_cmdline(char *cmdline, const char ***argv)
{
int src, dst, count = 0, size = 16;
size_t src, dst, count = 0, size = 16;
char quoted = 0;
ALLOC_ARRAY(*argv, size);
@ -96,6 +98,11 @@ int split_cmdline(char *cmdline, const char ***argv)
return -SPLIT_CMDLINE_UNCLOSED_QUOTE;
}
if (count >= INT_MAX) {
FREE_AND_NULL(*argv);
return -SPLIT_CMDLINE_ARGC_OVERFLOW;
}
ALLOC_GROW(*argv, count + 1, size);
(*argv)[count] = NULL;

106
attr.c
View File

@ -14,7 +14,6 @@
#include "utf8.h"
#include "quote.h"
#include "thread-utils.h"
#include "dir.h"
const char git_attr__true[] = "(builtin)true";
const char git_attr__false[] = "\0(builtin)false";
@ -29,7 +28,7 @@ static const char git_attr__unknown[] = "(builtin)unknown";
#endif
struct git_attr {
int attr_nr; /* unique attribute number */
unsigned int attr_nr; /* unique attribute number */
char name[FLEX_ARRAY]; /* attribute name */
};
@ -211,7 +210,7 @@ static void report_invalid_attr(const char *name, size_t len,
* dictionary. If no entry is found, create a new attribute and store it in
* the dictionary.
*/
static const struct git_attr *git_attr_internal(const char *name, int namelen)
static const struct git_attr *git_attr_internal(const char *name, size_t namelen)
{
struct git_attr *a;
@ -227,8 +226,8 @@ static const struct git_attr *git_attr_internal(const char *name, int namelen)
a->attr_nr = hashmap_get_size(&g_attr_hashmap.map);
attr_hashmap_add(&g_attr_hashmap, a->name, namelen, a);
assert(a->attr_nr ==
(hashmap_get_size(&g_attr_hashmap.map) - 1));
if (a->attr_nr != hashmap_get_size(&g_attr_hashmap.map) - 1)
die(_("unable to add additional attribute"));
}
hashmap_unlock(&g_attr_hashmap);
@ -273,7 +272,7 @@ struct match_attr {
const struct git_attr *attr;
} u;
char is_macro;
unsigned num_attr;
size_t num_attr;
struct attr_state state[FLEX_ARRAY];
};
@ -294,7 +293,7 @@ static const char *parse_attr(const char *src, int lineno, const char *cp,
struct attr_state *e)
{
const char *ep, *equals;
int len;
size_t len;
ep = cp + strcspn(cp, blank);
equals = strchr(cp, '=');
@ -338,8 +337,7 @@ static const char *parse_attr(const char *src, int lineno, const char *cp,
static struct match_attr *parse_attr_line(const char *line, const char *src,
int lineno, unsigned flags)
{
int namelen;
int num_attr, i;
size_t namelen, num_attr, i;
const char *cp, *name, *states;
struct match_attr *res = NULL;
int is_macro;
@ -350,6 +348,11 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
return NULL;
name = cp;
if (strlen(line) >= ATTR_MAX_LINE_LENGTH) {
warning(_("ignoring overly long attributes line %d"), lineno);
return NULL;
}
if (*cp == '"' && !unquote_c_style(&pattern, name, &states)) {
name = pattern.buf;
namelen = pattern.len;
@ -386,10 +389,9 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
goto fail_return;
}
res = xcalloc(1,
sizeof(*res) +
sizeof(struct attr_state) * num_attr +
(is_macro ? 0 : namelen + 1));
res = xcalloc(1, st_add3(sizeof(*res),
st_mult(sizeof(struct attr_state), num_attr),
is_macro ? 0 : namelen + 1));
if (is_macro) {
res->u.attr = git_attr_internal(name, namelen);
} else {
@ -452,11 +454,12 @@ struct attr_stack {
static void attr_stack_free(struct attr_stack *e)
{
int i;
unsigned i;
free(e->origin);
for (i = 0; i < e->num_matches; i++) {
struct match_attr *a = e->attrs[i];
int j;
size_t j;
for (j = 0; j < a->num_attr; j++) {
const char *setto = a->state[j].setto;
if (setto == ATTR__TRUE ||
@ -665,8 +668,8 @@ static void handle_attr_line(struct attr_stack *res,
a = parse_attr_line(line, src, lineno, flags);
if (!a)
return;
ALLOC_GROW(res->attrs, res->num_matches + 1, res->alloc);
res->attrs[res->num_matches++] = a;
ALLOC_GROW_BY(res->attrs, res->num_matches, 1, res->alloc);
res->attrs[res->num_matches - 1] = a;
}
static struct attr_stack *read_attr_from_array(const char **list)
@ -706,11 +709,12 @@ void git_attr_set_direction(enum git_attr_direction new_direction)
static struct attr_stack *read_attr_from_file(const char *path, unsigned flags)
{
struct strbuf buf = STRBUF_INIT;
int fd;
FILE *fp;
struct attr_stack *res;
char buf[2048];
int lineno = 0;
struct stat st;
if (flags & READ_ATTR_NOFOLLOW)
fd = open_nofollow(path, O_RDONLY);
@ -722,15 +726,26 @@ static struct attr_stack *read_attr_from_file(const char *path, unsigned flags)
return NULL;
}
fp = xfdopen(fd, "r");
if (fstat(fd, &st)) {
warning_errno(_("cannot fstat gitattributes file '%s'"), path);
fclose(fp);
return NULL;
}
if (st.st_size >= ATTR_MAX_FILE_SIZE) {
warning(_("ignoring overly large gitattributes file '%s'"), path);
fclose(fp);
return NULL;
}
CALLOC_ARRAY(res, 1);
while (fgets(buf, sizeof(buf), fp)) {
char *bufp = buf;
if (!lineno)
skip_utf8_bom(&bufp, strlen(bufp));
handle_attr_line(res, bufp, path, ++lineno, flags);
while (strbuf_getline(&buf, fp) != EOF) {
if (!lineno && starts_with(buf.buf, utf8_bom))
strbuf_remove(&buf, 0, strlen(utf8_bom));
handle_attr_line(res, buf.buf, path, ++lineno, flags);
}
fclose(fp);
strbuf_release(&buf);
return res;
}
@ -741,27 +756,18 @@ static struct attr_stack *read_attr_from_index(struct index_state *istate,
struct attr_stack *res;
char *buf, *sp;
int lineno = 0;
size_t size;
if (!istate)
return NULL;
/*
* The .gitattributes file only applies to files within its
* parent directory. In the case of cone-mode sparse-checkout,
* the .gitattributes file is sparse if and only if all paths
* within that directory are also sparse. Thus, don't load the
* .gitattributes file since it will not matter.
*
* In the case of a sparse index, it is critical that we don't go
* looking for a .gitattributes file, as doing so would cause the
* index to expand.
*/
if (!path_in_cone_mode_sparse_checkout(path, istate))
return NULL;
buf = read_blob_data_from_index(istate, path, NULL);
buf = read_blob_data_from_index(istate, path, &size);
if (!buf)
return NULL;
if (size >= ATTR_MAX_FILE_SIZE) {
warning(_("ignoring overly large gitattributes blob '%s'"), path);
return NULL;
}
CALLOC_ARRAY(res, 1);
for (sp = buf; *sp; ) {
@ -1032,12 +1038,12 @@ static int macroexpand_one(struct all_attrs_item *all_attrs, int nr, int rem);
static int fill_one(const char *what, struct all_attrs_item *all_attrs,
const struct match_attr *a, int rem)
{
int i;
size_t i;
for (i = a->num_attr - 1; rem > 0 && i >= 0; i--) {
const struct git_attr *attr = a->state[i].attr;
for (i = a->num_attr; rem > 0 && i > 0; i--) {
const struct git_attr *attr = a->state[i - 1].attr;
const char **n = &(all_attrs[attr->attr_nr].value);
const char *v = a->state[i].setto;
const char *v = a->state[i - 1].setto;
if (*n == ATTR__UNKNOWN) {
debug_set(what,
@ -1056,11 +1062,11 @@ static int fill(const char *path, int pathlen, int basename_offset,
struct all_attrs_item *all_attrs, int rem)
{
for (; rem > 0 && stack; stack = stack->prev) {
int i;
unsigned i;
const char *base = stack->origin ? stack->origin : "";
for (i = stack->num_matches - 1; 0 < rem && 0 <= i; i--) {
const struct match_attr *a = stack->attrs[i];
for (i = stack->num_matches; 0 < rem && 0 < i; i--) {
const struct match_attr *a = stack->attrs[i - 1];
if (a->is_macro)
continue;
if (path_matches(path, pathlen, basename_offset,
@ -1091,11 +1097,11 @@ static void determine_macros(struct all_attrs_item *all_attrs,
const struct attr_stack *stack)
{
for (; stack; stack = stack->prev) {
int i;
for (i = stack->num_matches - 1; i >= 0; i--) {
const struct match_attr *ma = stack->attrs[i];
unsigned i;
for (i = stack->num_matches; i > 0; i--) {
const struct match_attr *ma = stack->attrs[i - 1];
if (ma->is_macro) {
int n = ma->u.attr->attr_nr;
unsigned int n = ma->u.attr->attr_nr;
if (!all_attrs[n].macro) {
all_attrs[n].macro = ma;
}
@ -1147,7 +1153,7 @@ void git_check_attr(struct index_state *istate,
collect_some_attrs(istate, path, check);
for (i = 0; i < check->nr; i++) {
size_t n = check->items[i].attr->attr_nr;
unsigned int n = check->items[i].attr->attr_nr;
const char *value = check->all_attrs[n].value;
if (value == ATTR__UNKNOWN)
value = ATTR__UNSET;

12
attr.h
View File

@ -107,6 +107,18 @@
* - Free the `attr_check` struct by calling `attr_check_free()`.
*/
/**
* The maximum line length for a gitattributes file. If the line exceeds this
* length we will ignore it.
*/
#define ATTR_MAX_LINE_LENGTH 2048
/**
* The maximum size of the giattributes file. If the file exceeds this size we
* will ignore it.
*/
#define ATTR_MAX_FILE_SIZE (100 * 1024 * 1024)
struct index_state;
/**

View File

@ -23,6 +23,7 @@ static struct oid_array skipped_revs;
static struct object_id *current_bad_oid;
static const char *argv_checkout[] = {"checkout", "-q", NULL, "--", NULL};
static const char *argv_show_branch[] = {"show-branch", NULL, NULL};
static const char *term_bad;
static const char *term_good;
@ -727,9 +728,7 @@ static int is_expected_rev(const struct object_id *oid)
static enum bisect_error bisect_checkout(const struct object_id *bisect_rev, int no_checkout)
{
char bisect_rev_hex[GIT_MAX_HEXSZ + 1];
struct commit *commit;
struct pretty_print_context pp = {0};
struct strbuf commit_msg = STRBUF_INIT;
enum bisect_error res = BISECT_OK;
oid_to_hex_r(bisect_rev_hex, bisect_rev);
update_ref(NULL, "BISECT_EXPECTED_REV", bisect_rev, NULL, 0, UPDATE_REFS_DIE_ON_ERR);
@ -739,21 +738,24 @@ static enum bisect_error bisect_checkout(const struct object_id *bisect_rev, int
update_ref(NULL, "BISECT_HEAD", bisect_rev, NULL, 0,
UPDATE_REFS_DIE_ON_ERR);
} else {
if (run_command_v_opt(argv_checkout, RUN_GIT_CMD))
res = run_command_v_opt(argv_checkout, RUN_GIT_CMD);
if (res)
/*
* Errors in `run_command()` itself, signaled by res < 0,
* and errors in the child process, signaled by res > 0
* can both be treated as regular BISECT_FAILED (-1).
* can both be treated as regular BISECT_FAILURE (-1).
*/
return BISECT_FAILED;
return -abs(res);
}
commit = lookup_commit_reference(the_repository, bisect_rev);
format_commit_message(commit, "[%H] %s%n", &commit_msg, &pp);
fputs(commit_msg.buf, stdout);
strbuf_release(&commit_msg);
return BISECT_OK;
argv_show_branch[1] = bisect_rev_hex;
res = run_command_v_opt(argv_show_branch, RUN_GIT_CMD);
/*
* Errors in `run_command()` itself, signaled by res < 0,
* and errors in the child process, signaled by res > 0
* can both be treated as regular BISECT_FAILURE (-1).
*/
return -abs(res);
}
static struct commit *get_commit_reference(struct repository *r,

View File

@ -271,7 +271,7 @@ void create_branch(struct repository *r,
real_ref = NULL;
if (get_oid_mb(start_name, &oid)) {
if (explicit_tracking) {
if (advice_enabled(ADVICE_SET_UPSTREAM_FAILURE)) {
if (advice_set_upstream_failure) {
error(_(upstream_missing), start_name);
advise(_(upstream_advice));
exit(1);

View File

@ -225,6 +225,7 @@ int cmd_submodule__helper(int argc, const char **argv, const char *prefix);
int cmd_switch(int argc, const char **argv, const char *prefix);
int cmd_symbolic_ref(int argc, const char **argv, const char *prefix);
int cmd_tag(int argc, const char **argv, const char *prefix);
int cmd_tar_tree(int argc, const char **argv, const char *prefix);
int cmd_unpack_file(int argc, const char **argv, const char *prefix);
int cmd_unpack_objects(int argc, const char **argv, const char *prefix);
int cmd_update_index(int argc, const char **argv, const char *prefix);

View File

@ -30,7 +30,6 @@ static int patch_interactive, add_interactive, edit_interactive;
static int take_worktree_changes;
static int add_renormalize;
static int pathspec_file_nul;
static int include_sparse;
static const char *pathspec_from_file;
static int legacy_stash_p; /* support for the scripted `git stash` */
@ -47,9 +46,7 @@ static int chmod_pathspec(struct pathspec *pathspec, char flip, int show_only)
struct cache_entry *ce = active_cache[i];
int err;
if (!include_sparse &&
(ce_skip_worktree(ce) ||
!path_in_sparse_checkout(ce->name, &the_index)))
if (ce_skip_worktree(ce))
continue;
if (pathspec && !ce_path_match(&the_index, ce, pathspec, NULL))
@ -97,10 +94,6 @@ static void update_callback(struct diff_queue_struct *q,
for (i = 0; i < q->nr; i++) {
struct diff_filepair *p = q->queue[i];
const char *path = p->one->path;
if (!include_sparse && !path_in_sparse_checkout(path, &the_index))
continue;
switch (fix_unmerged_status(p, data)) {
default:
die(_("unexpected diff status %c"), p->status);
@ -151,12 +144,12 @@ static int renormalize_tracked_files(const struct pathspec *pathspec, int flags)
{
int i, retval = 0;
/* TODO: audit for interaction with sparse-index. */
ensure_full_index(&the_index);
for (i = 0; i < active_nr; i++) {
struct cache_entry *ce = active_cache[i];
if (!include_sparse &&
(ce_skip_worktree(ce) ||
!path_in_sparse_checkout(ce->name, &the_index)))
if (ce_skip_worktree(ce))
continue;
if (ce_stage(ce))
continue; /* do not touch unmerged paths */
@ -205,10 +198,7 @@ static int refresh(int verbose, const struct pathspec *pathspec)
_("Unstaged changes after refreshing the index:"));
for (i = 0; i < pathspec->nr; i++) {
if (!seen[i]) {
const char *path = pathspec->items[i].original;
if (matches_skip_worktree(pathspec, i, &skip_worktree_seen) ||
!path_in_sparse_checkout(path, &the_index)) {
if (matches_skip_worktree(pathspec, i, &skip_worktree_seen)) {
string_list_append(&only_match_skip_worktree,
pathspec->items[i].original);
} else {
@ -386,7 +376,6 @@ static struct option builtin_add_options[] = {
OPT_BOOL( 0 , "refresh", &refresh_only, N_("don't add, only refresh the index")),
OPT_BOOL( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")),
OPT_BOOL( 0 , "ignore-missing", &ignore_missing, N_("check if - even missing - files are ignored in dry run")),
OPT_BOOL(0, "sparse", &include_sparse, N_("allow updating entries outside of the sparse-checkout cone")),
OPT_STRING(0, "chmod", &chmod_arg, "(+|-)x",
N_("override the executable bit of the listed files")),
OPT_HIDDEN_BOOL(0, "warn-embedded-repo", &warn_on_embedded_repo,
@ -428,7 +417,6 @@ static const char embedded_advice[] = N_(
static void check_embedded_repo(const char *path)
{
struct strbuf name = STRBUF_INIT;
static int adviced_on_embedded_repo = 0;
if (!warn_on_embedded_repo)
return;
@ -440,10 +428,10 @@ static void check_embedded_repo(const char *path)
strbuf_strip_suffix(&name, "/");
warning(_("adding embedded git repository: %s"), name.buf);
if (!adviced_on_embedded_repo &&
advice_enabled(ADVICE_ADD_EMBEDDED_REPO)) {
if (advice_add_embedded_repo) {
advise(embedded_advice, name.buf, name.buf);
adviced_on_embedded_repo = 1;
/* there may be multiple entries; advise only once */
advice_add_embedded_repo = 0;
}
strbuf_release(&name);
@ -452,13 +440,12 @@ static void check_embedded_repo(const char *path)
static int add_files(struct dir_struct *dir, int flags)
{
int i, exit_status = 0;
struct string_list matched_sparse_paths = STRING_LIST_INIT_NODUP;
if (dir->ignored_nr) {
fprintf(stderr, _(ignore_error));
for (i = 0; i < dir->ignored_nr; i++)
fprintf(stderr, "%s\n", dir->ignored[i]->name);
if (advice_enabled(ADVICE_ADD_IGNORED_FILE))
if (advice_add_ignored_file)
advise(_("Use -f if you really want to add them.\n"
"Turn this message off by running\n"
"\"git config advice.addIgnoredFile false\""));
@ -466,12 +453,6 @@ static int add_files(struct dir_struct *dir, int flags)
}
for (i = 0; i < dir->nr; i++) {
if (!include_sparse &&
!path_in_sparse_checkout(dir->entries[i]->name, &the_index)) {
string_list_append(&matched_sparse_paths,
dir->entries[i]->name);
continue;
}
if (add_file_to_index(&the_index, dir->entries[i]->name, flags)) {
if (!ignore_add_errors)
die(_("adding files failed"));
@ -480,14 +461,6 @@ static int add_files(struct dir_struct *dir, int flags)
check_embedded_repo(dir->entries[i]->name);
}
}
if (matched_sparse_paths.nr) {
advise_on_updating_sparse_paths(&matched_sparse_paths);
exit_status = 1;
}
string_list_clear(&matched_sparse_paths, 0);
return exit_status;
}
@ -553,9 +526,6 @@ int cmd_add(int argc, const char **argv, const char *prefix)
add_new_files = !take_worktree_changes && !refresh_only && !add_renormalize;
require_pathspec = !(take_worktree_changes || (0 < addremove_explicit));
prepare_repo_settings(the_repository);
the_repository->settings.command_requires_full_index = 0;
hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
/*
@ -581,7 +551,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
if (require_pathspec && pathspec.nr == 0) {
fprintf(stderr, _("Nothing specified, nothing added.\n"));
if (advice_enabled(ADVICE_ADD_EMPTY_PATHSPEC))
if (advice_add_empty_pathspec)
advise( _("Maybe you wanted to say 'git add .'?\n"
"Turn this message off by running\n"
"\"git config advice.addEmptyPathspec false\""));
@ -652,8 +622,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
if (seen[i])
continue;
if (!include_sparse &&
matches_skip_worktree(&pathspec, i, &skip_worktree_seen)) {
if (matches_skip_worktree(&pathspec, i, &skip_worktree_seen)) {
string_list_append(&only_match_skip_worktree,
pathspec.items[i].original);
continue;

View File

@ -11,7 +11,6 @@
#include "parse-options.h"
#include "dir.h"
#include "run-command.h"
#include "hook.h"
#include "quote.h"
#include "tempfile.h"
#include "lockfile.h"
@ -1821,7 +1820,7 @@ static void am_run(struct am_state *state, int resume)
printf_ln(_("Patch failed at %s %.*s"), msgnum(state),
linelen(state->msg), state->msg);
if (advice_enabled(ADVICE_AM_WORK_DIR))
if (advice_amworkdir)
advise(_("Use 'git am --show-current-patch=diff' to see the failed patch"));
die_user_resolve(state);
@ -1849,6 +1848,7 @@ next:
*/
if (!state->rebasing) {
am_destroy(state);
close_object_store(the_repository->objects);
run_auto_maintenance(state->quiet);
}
}
@ -1918,8 +1918,7 @@ static int fast_forward_to(struct tree *head, struct tree *remote, int reset)
opts.dst_index = &the_index;
opts.update = 1;
opts.merge = 1;
opts.reset = reset ? UNPACK_RESET_PROTECT_UNTRACKED : 0;
opts.preserve_ignored = 0; /* FIXME: !overwrite_ignore */
opts.reset = reset;
opts.fn = twoway_merge;
init_tree_desc(&t[0], head->buffer, head->size);
init_tree_desc(&t[1], remote->buffer, remote->size);

View File

@ -18,10 +18,10 @@ static GIT_PATH_FUNC(git_path_bisect_log, "BISECT_LOG")
static GIT_PATH_FUNC(git_path_head_name, "head-name")
static GIT_PATH_FUNC(git_path_bisect_names, "BISECT_NAMES")
static GIT_PATH_FUNC(git_path_bisect_first_parent, "BISECT_FIRST_PARENT")
static GIT_PATH_FUNC(git_path_bisect_run, "BISECT_RUN")
static const char * const git_bisect_helper_usage[] = {
N_("git bisect--helper --bisect-reset [<commit>]"),
N_("git bisect--helper --bisect-next-check <good_term> <bad_term> [<term>]"),
N_("git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]"),
N_("git bisect--helper --bisect-start [--term-{new,bad}=<term> --term-{old,good}=<term>]"
" [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<paths>...]"),
@ -30,8 +30,6 @@ static const char * const git_bisect_helper_usage[] = {
N_("git bisect--helper --bisect-state (good|old) [<rev>...]"),
N_("git bisect--helper --bisect-replay <filename>"),
N_("git bisect--helper --bisect-skip [(<rev>|<range>)...]"),
N_("git bisect--helper --bisect-visualize"),
N_("git bisect--helper --bisect-run <cmd>..."),
NULL
};
@ -145,19 +143,6 @@ static int append_to_file(const char *path, const char *format, ...)
return res;
}
static int print_file_to_stdout(const char *path)
{
int fd = open(path, O_RDONLY);
int ret = 0;
if (fd < 0)
return error_errno(_("cannot open file '%s' for reading"), path);
if (copy_fd(fd, 1) < 0)
ret = error_errno(_("failed to read '%s'"), path);
close(fd);
return ret;
}
static int check_term_format(const char *term, const char *orig_term)
{
int res;
@ -1051,125 +1036,6 @@ static enum bisect_error bisect_skip(struct bisect_terms *terms, const char **ar
return res;
}
static int bisect_visualize(struct bisect_terms *terms, const char **argv, int argc)
{
struct strvec args = STRVEC_INIT;
int flags = RUN_COMMAND_NO_STDIN, res = 0;
struct strbuf sb = STRBUF_INIT;
if (bisect_next_check(terms, NULL) != 0)
return BISECT_FAILED;
if (!argc) {
if ((getenv("DISPLAY") || getenv("SESSIONNAME") || getenv("MSYSTEM") ||
getenv("SECURITYSESSIONID")) && exists_in_PATH("gitk")) {
strvec_push(&args, "gitk");
} else {
strvec_push(&args, "log");
flags |= RUN_GIT_CMD;
}
} else {
if (argv[0][0] == '-') {
strvec_push(&args, "log");
flags |= RUN_GIT_CMD;
} else if (strcmp(argv[0], "tig") && !starts_with(argv[0], "git"))
flags |= RUN_GIT_CMD;
strvec_pushv(&args, argv);
}
strvec_pushl(&args, "--bisect", "--", NULL);
strbuf_read_file(&sb, git_path_bisect_names(), 0);
sq_dequote_to_strvec(sb.buf, &args);
strbuf_release(&sb);
res = run_command_v_opt(args.v, flags);
strvec_clear(&args);
return res;
}
static int bisect_run(struct bisect_terms *terms, const char **argv, int argc)
{
int res = BISECT_OK;
struct strbuf command = STRBUF_INIT;
struct strvec args = STRVEC_INIT;
struct strvec run_args = STRVEC_INIT;
const char *new_state;
int temporary_stdout_fd, saved_stdout;
if (bisect_next_check(terms, NULL))
return BISECT_FAILED;
if (argc)
sq_quote_argv(&command, argv);
else {
error(_("bisect run failed: no command provided."));
return BISECT_FAILED;
}
strvec_push(&run_args, command.buf);
while (1) {
strvec_clear(&args);
printf(_("running %s\n"), command.buf);
res = run_command_v_opt(run_args.v, RUN_USING_SHELL);
if (res < 0 || 128 <= res) {
error(_("bisect run failed: exit code %d from"
" '%s' is < 0 or >= 128"), res, command.buf);
strbuf_release(&command);
return res;
}
if (res == 125)
new_state = "skip";
else if (!res)
new_state = terms->term_good;
else
new_state = terms->term_bad;
temporary_stdout_fd = open(git_path_bisect_run(), O_CREAT | O_WRONLY | O_TRUNC, 0666);
if (temporary_stdout_fd < 0)
return error_errno(_("cannot open file '%s' for writing"), git_path_bisect_run());
fflush(stdout);
saved_stdout = dup(1);
dup2(temporary_stdout_fd, 1);
res = bisect_state(terms, &new_state, 1);
fflush(stdout);
dup2(saved_stdout, 1);
close(saved_stdout);
close(temporary_stdout_fd);
print_file_to_stdout(git_path_bisect_run());
if (res == BISECT_ONLY_SKIPPED_LEFT)
error(_("bisect run cannot continue any more"));
else if (res == BISECT_INTERNAL_SUCCESS_MERGE_BASE) {
printf(_("bisect run success"));
res = BISECT_OK;
} else if (res == BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND) {
printf(_("bisect found first bad commit"));
res = BISECT_OK;
} else if (res) {
error(_("bisect run failed: 'git bisect--helper --bisect-state"
" %s' exited with error code %d"), args.v[0], res);
} else {
continue;
}
strbuf_release(&command);
strvec_clear(&args);
strvec_clear(&run_args);
return res;
}
}
int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
{
enum {
@ -1182,9 +1048,7 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
BISECT_STATE,
BISECT_LOG,
BISECT_REPLAY,
BISECT_SKIP,
BISECT_VISUALIZE,
BISECT_RUN,
BISECT_SKIP
} cmdmode = 0;
int res = 0, nolog = 0;
struct option options[] = {
@ -1206,10 +1070,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
N_("replay the bisection process from the given file"), BISECT_REPLAY),
OPT_CMDMODE(0, "bisect-skip", &cmdmode,
N_("skip some commits for checkout"), BISECT_SKIP),
OPT_CMDMODE(0, "bisect-visualize", &cmdmode,
N_("visualize the bisection"), BISECT_VISUALIZE),
OPT_CMDMODE(0, "bisect-run", &cmdmode,
N_("use <cmd>... to automatically bisect."), BISECT_RUN),
OPT_BOOL(0, "no-log", &nolog,
N_("no log for BISECT_WRITE")),
OPT_END()
@ -1229,6 +1089,12 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
return error(_("--bisect-reset requires either no argument or a commit"));
res = bisect_reset(argc ? argv[0] : NULL);
break;
case BISECT_NEXT_CHECK:
if (argc != 2 && argc != 3)
return error(_("--bisect-next-check requires 2 or 3 arguments"));
set_terms(&terms, argv[1], argv[0]);
res = bisect_next_check(&terms, argc == 3 ? argv[2] : NULL);
break;
case BISECT_TERMS:
if (argc > 1)
return error(_("--bisect-terms requires 0 or 1 argument"));
@ -1265,16 +1131,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
get_terms(&terms);
res = bisect_skip(&terms, argv, argc);
break;
case BISECT_VISUALIZE:
get_terms(&terms);
res = bisect_visualize(&terms, argv, argc);
break;
case BISECT_RUN:
if (!argc)
return error(_("bisect run failed: no command provided."));
get_terms(&terms);
res = bisect_run(&terms, argv, argc);
break;
default:
BUG("unknown subcommand %d", cmdmode);
}

View File

@ -101,16 +101,6 @@ struct commit_info {
struct strbuf summary;
};
#define COMMIT_INFO_INIT { \
.author = STRBUF_INIT, \
.author_mail = STRBUF_INIT, \
.author_tz = STRBUF_INIT, \
.committer = STRBUF_INIT, \
.committer_mail = STRBUF_INIT, \
.committer_tz = STRBUF_INIT, \
.summary = STRBUF_INIT, \
}
/*
* Parse author/committer line in the commit object buffer
*/
@ -170,6 +160,18 @@ static void get_ac_line(const char *inbuf, const char *what,
strbuf_add(name, namebuf, namelen);
}
static void commit_info_init(struct commit_info *ci)
{
strbuf_init(&ci->author, 0);
strbuf_init(&ci->author_mail, 0);
strbuf_init(&ci->author_tz, 0);
strbuf_init(&ci->committer, 0);
strbuf_init(&ci->committer_mail, 0);
strbuf_init(&ci->committer_tz, 0);
strbuf_init(&ci->summary, 0);
}
static void commit_info_destroy(struct commit_info *ci)
{
@ -190,6 +192,8 @@ static void get_commit_info(struct commit *commit,
const char *subject, *encoding;
const char *message;
commit_info_init(ret);
encoding = get_log_output_encoding();
message = logmsg_reencode(commit, NULL, encoding);
get_ac_line(message, "\nauthor ",
@ -242,7 +246,7 @@ static void write_filename_info(struct blame_origin *suspect)
*/
static int emit_one_suspect_detail(struct blame_origin *suspect, int repeat)
{
struct commit_info ci = COMMIT_INFO_INIT;
struct commit_info ci;
if (!repeat && (suspect->commit->object.flags & METAINFO_SHOWN))
return 0;
@ -436,7 +440,7 @@ static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent, int
int cnt;
const char *cp;
struct blame_origin *suspect = ent->suspect;
struct commit_info ci = COMMIT_INFO_INIT;
struct commit_info ci;
char hex[GIT_MAX_HEXSZ + 1];
int show_raw_time = !!(opt & OUTPUT_RAW_TIMESTAMP);
const char *default_color = NULL, *color = NULL, *reset = NULL;
@ -626,7 +630,7 @@ static void find_alignment(struct blame_scoreboard *sb, int *option)
if (longest_file < num)
longest_file = num;
if (!(suspect->commit->object.flags & METAINFO_SHOWN)) {
struct commit_info ci = COMMIT_INFO_INIT;
struct commit_info ci;
suspect->commit->object.flags |= METAINFO_SHOWN;
get_commit_info(suspect->commit, &ci, 1);
if (*option & OUTPUT_SHOW_EMAIL)
@ -913,9 +917,6 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_ARGV0);
for (;;) {
switch (parse_options_step(&ctx, options, blame_opt_usage)) {
case PARSE_OPT_NON_OPTION:
case PARSE_OPT_UNKNOWN:
break;
case PARSE_OPT_HELP:
case PARSE_OPT_ERROR:
exit(129);

View File

@ -407,8 +407,7 @@ static char *build_format(struct ref_filter *filter, int maxwidth, const char *r
return strbuf_detach(&fmt, NULL);
}
static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sorting,
struct ref_format *format, struct string_list *output)
static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sorting, struct ref_format *format)
{
int i;
struct ref_array array;
@ -428,7 +427,7 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin
memset(&array, 0, sizeof(array));
filter_refs(&array, filter, filter->kind);
filter_refs(&array, filter, filter->kind | FILTER_REFS_INCLUDE_BROKEN);
if (filter->verbose)
maxwidth = calc_maxwidth(&array, strlen(remote_prefix));
@ -450,7 +449,7 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin
if (column_active(colopts)) {
assert(!filter->verbose && "--column and --verbose are incompatible");
/* format to a string_list to let print_columns() do its job */
string_list_append(output, out.buf);
string_list_append(&output, out.buf);
} else {
fwrite(out.buf, 1, out.len, stdout);
putchar('\n');
@ -754,10 +753,9 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
ref_sorting_set_sort_flags_all(sorting, REF_SORTING_ICASE, icase);
ref_sorting_set_sort_flags_all(
sorting, REF_SORTING_DETACHED_HEAD_FIRST, 1);
print_ref_list(&filter, sorting, &format, &output);
print_ref_list(&filter, sorting, &format);
print_columns(&output, colopts, NULL);
string_list_clear(&output, 0);
ref_sorting_release(sorting);
return 0;
} else if (edit_description) {
const char *branch_name;

View File

@ -3,8 +3,7 @@
#include "strbuf.h"
#include "help.h"
#include "compat/compiler.h"
#include "hook.h"
#include "hook-list.h"
#include "run-command.h"
static void get_system_info(struct strbuf *sys_info)
@ -42,7 +41,39 @@ static void get_system_info(struct strbuf *sys_info)
static void get_populated_hooks(struct strbuf *hook_info, int nongit)
{
const char **p;
/*
* NEEDSWORK: Doesn't look like there is a list of all possible hooks;
* so below is a transcription of `git help hooks`. Later, this should
* be replaced with some programmatically generated list (generated from
* doc or else taken from some library which tells us about all the
* hooks)
*/
static const char *hook[] = {
"applypatch-msg",
"pre-applypatch",
"post-applypatch",
"pre-commit",
"pre-merge-commit",
"prepare-commit-msg",
"commit-msg",
"post-commit",
"pre-rebase",
"post-checkout",
"post-merge",
"pre-push",
"pre-receive",
"update",
"post-receive",
"post-update",
"push-to-checkout",
"pre-auto-gc",
"post-rewrite",
"sendemail-validate",
"fsmonitor-watchman",
"p4-pre-submit",
"post-index-change",
};
int i;
if (nongit) {
strbuf_addstr(hook_info,
@ -50,12 +81,9 @@ static void get_populated_hooks(struct strbuf *hook_info, int nongit)
return;
}
for (p = hook_name_list; *p; p++) {
const char *hook = *p;
if (hook_exists(hook))
strbuf_addf(hook_info, "%s\n", hook);
}
for (i = 0; i < ARRAY_SIZE(hook); i++)
if (find_hook(hook[i]))
strbuf_addf(hook_info, "%s\n", hook[i]);
}
static const char * const bugreport_usage[] = {

View File

@ -39,6 +39,8 @@ static const char * const builtin_bundle_unbundle_usage[] = {
NULL
};
static int verbose;
static int parse_options_cmd_bundle(int argc,
const char **argv,
const char* prefix,
@ -160,15 +162,10 @@ static int cmd_bundle_unbundle(int argc, const char **argv, const char *prefix)
struct bundle_header header = BUNDLE_HEADER_INIT;
int bundle_fd = -1;
int ret;
int progress = isatty(2);
struct option options[] = {
OPT_BOOL(0, "progress", &progress,
N_("show progress meter")),
OPT_END()
};
char *bundle_file;
struct strvec extra_index_pack_args = STRVEC_INIT;
argc = parse_options_cmd_bundle(argc, argv, prefix,
builtin_bundle_unbundle_usage, options, &bundle_file);
@ -180,11 +177,7 @@ static int cmd_bundle_unbundle(int argc, const char **argv, const char *prefix)
}
if (!startup_info->have_repository)
die(_("Need a repository to unbundle."));
if (progress)
strvec_pushl(&extra_index_pack_args, "-v", "--progress-title",
_("Unbundling objects"), NULL);
ret = !!unbundle(the_repository, &header, bundle_fd,
&extra_index_pack_args) ||
ret = !!unbundle(the_repository, &header, bundle_fd, 0) ||
list_bundle_refs(&header, argc, argv);
bundle_header_release(&header);
cleanup:
@ -195,6 +188,7 @@ cleanup:
int cmd_bundle(int argc, const char **argv, const char *prefix)
{
struct option options[] = {
OPT__VERBOSE(&verbose, N_("be verbose; must be placed before a subcommand")),
OPT_END()
};
int result;

View File

@ -355,34 +355,18 @@ static void print_object_or_die(struct batch_options *opt, struct expand_data *d
}
}
/*
* If "pack" is non-NULL, then "offset" is the byte offset within the pack from
* which the object may be accessed (though note that we may also rely on
* data->oid, too). If "pack" is NULL, then offset is ignored.
*/
static void batch_object_write(const char *obj_name,
struct strbuf *scratch,
struct batch_options *opt,
struct expand_data *data,
struct packed_git *pack,
off_t offset)
struct expand_data *data)
{
if (!data->skip_object_info) {
int ret;
if (pack)
ret = packed_object_info(the_repository, pack, offset,
&data->info);
else
ret = oid_object_info_extended(the_repository,
&data->oid, &data->info,
OBJECT_INFO_LOOKUP_REPLACE);
if (ret < 0) {
printf("%s missing\n",
obj_name ? obj_name : oid_to_hex(&data->oid));
fflush(stdout);
return;
}
if (!data->skip_object_info &&
oid_object_info_extended(the_repository, &data->oid, &data->info,
OBJECT_INFO_LOOKUP_REPLACE) < 0) {
printf("%s missing\n",
obj_name ? obj_name : oid_to_hex(&data->oid));
fflush(stdout);
return;
}
strbuf_reset(scratch);
@ -444,7 +428,7 @@ static void batch_one_object(const char *obj_name,
return;
}
batch_object_write(obj_name, scratch, opt, data, NULL, 0);
batch_object_write(obj_name, scratch, opt, data);
}
struct object_cb_data {
@ -458,8 +442,7 @@ static int batch_object_cb(const struct object_id *oid, void *vdata)
{
struct object_cb_data *data = vdata;
oidcpy(&data->expand->oid, oid);
batch_object_write(NULL, data->scratch, data->opt, data->expand,
NULL, 0);
batch_object_write(NULL, data->scratch, data->opt, data->expand);
return 0;
}
@ -480,26 +463,21 @@ static int collect_packed_object(const struct object_id *oid,
return 0;
}
static int batch_unordered_object(const struct object_id *oid,
struct packed_git *pack, off_t offset,
void *vdata)
static int batch_unordered_object(const struct object_id *oid, void *vdata)
{
struct object_cb_data *data = vdata;
if (oidset_insert(data->seen, oid))
return 0;
oidcpy(&data->expand->oid, oid);
batch_object_write(NULL, data->scratch, data->opt, data->expand,
pack, offset);
return 0;
return batch_object_cb(oid, data);
}
static int batch_unordered_loose(const struct object_id *oid,
const char *path,
void *data)
{
return batch_unordered_object(oid, NULL, 0, data);
return batch_unordered_object(oid, data);
}
static int batch_unordered_packed(const struct object_id *oid,
@ -507,9 +485,7 @@ static int batch_unordered_packed(const struct object_id *oid,
uint32_t pos,
void *data)
{
return batch_unordered_object(oid, pack,
nth_packed_object_offset(pack, pos),
data);
return batch_unordered_object(oid, data);
}
static int batch_objects(struct batch_options *opt)
@ -553,8 +529,6 @@ static int batch_objects(struct batch_options *opt)
if (has_promisor_remote())
warning("This repository uses promisor remotes. Some objects may not be loaded.");
read_replace_refs = 0;
cb.opt = opt;
cb.expand = &data;
cb.scratch = &output;

View File

@ -82,8 +82,8 @@ static void worker_loop(struct checkout *state)
size_t i, nr = 0, alloc = 0;
while (1) {
int len = packet_read(0, packet_buffer, sizeof(packet_buffer),
0);
int len = packet_read(0, NULL, NULL, packet_buffer,
sizeof(packet_buffer), 0);
if (len < 0)
BUG("packet_read() returned negative value");

View File

@ -646,9 +646,7 @@ static int reset_tree(struct tree *tree, const struct checkout_opts *o,
opts.head_idx = -1;
opts.update = worktree;
opts.skip_unmerged = !worktree;
opts.reset = o->force ? UNPACK_RESET_OVERWRITE_UNTRACKED :
UNPACK_RESET_PROTECT_UNTRACKED;
opts.preserve_ignored = (!o->force && !o->overwrite_ignore);
opts.reset = 1;
opts.merge = 1;
opts.fn = oneway_merge;
opts.verbose_update = o->show_progress;
@ -748,7 +746,11 @@ static int merge_working_tree(const struct checkout_opts *opts,
new_branch_info->commit ?
&new_branch_info->commit->object.oid :
&new_branch_info->oid, NULL);
topts.preserve_ignored = !opts->overwrite_ignore;
if (opts->overwrite_ignore) {
topts.dir = xcalloc(1, sizeof(*topts.dir));
topts.dir->flags |= DIR_SHOW_IGNORED;
setup_standard_excludes(topts.dir);
}
tree = parse_tree_indirect(old_branch_info->commit ?
&old_branch_info->commit->object.oid :
the_hash_algo->empty_tree);
@ -916,7 +918,7 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
REF_NO_DEREF, UPDATE_REFS_DIE_ON_ERR);
if (!opts->quiet) {
if (old_branch_info->path &&
advice_enabled(ADVICE_DETACHED_HEAD) && !opts->force_detach)
advice_detached_head && !opts->force_detach)
detach_advice(new_branch_info->name);
describe_detached_head(_("HEAD is now at"), new_branch_info->commit);
}
@ -1009,7 +1011,7 @@ static void suggest_reattach(struct commit *commit, struct rev_info *revs)
sb.buf);
strbuf_release(&sb);
if (advice_enabled(ADVICE_DETACHED_HEAD))
if (advice_detached_head)
fprintf(stderr,
Q_(
/* The singular version */
@ -1180,7 +1182,7 @@ static const char *parse_remote_branch(const char *arg,
}
if (!remote && num_matches > 1) {
if (advice_enabled(ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME)) {
if (advice_checkout_ambiguous_remote_branch_name) {
advise(_("If you meant to check out a remote tracking branch on, e.g. 'origin',\n"
"you can do so by fully qualifying the name with the --track option:\n"
"\n"

View File

@ -217,6 +217,120 @@ static char *get_repo_path(const char *repo, int *is_bundle)
return canon;
}
static char *guess_dir_name(const char *repo, int is_bundle, int is_bare)
{
const char *end = repo + strlen(repo), *start, *ptr;
size_t len;
char *dir;
/*
* Skip scheme.
*/
start = strstr(repo, "://");
if (start == NULL)
start = repo;
else
start += 3;
/*
* Skip authentication data. The stripping does happen
* greedily, such that we strip up to the last '@' inside
* the host part.
*/
for (ptr = start; ptr < end && !is_dir_sep(*ptr); ptr++) {
if (*ptr == '@')
start = ptr + 1;
}
/*
* Strip trailing spaces, slashes and /.git
*/
while (start < end && (is_dir_sep(end[-1]) || isspace(end[-1])))
end--;
if (end - start > 5 && is_dir_sep(end[-5]) &&
!strncmp(end - 4, ".git", 4)) {
end -= 5;
while (start < end && is_dir_sep(end[-1]))
end--;
}
/*
* Strip trailing port number if we've got only a
* hostname (that is, there is no dir separator but a
* colon). This check is required such that we do not
* strip URI's like '/foo/bar:2222.git', which should
* result in a dir '2222' being guessed due to backwards
* compatibility.
*/
if (memchr(start, '/', end - start) == NULL
&& memchr(start, ':', end - start) != NULL) {
ptr = end;
while (start < ptr && isdigit(ptr[-1]) && ptr[-1] != ':')
ptr--;
if (start < ptr && ptr[-1] == ':')
end = ptr - 1;
}
/*
* Find last component. To remain backwards compatible we
* also regard colons as path separators, such that
* cloning a repository 'foo:bar.git' would result in a
* directory 'bar' being guessed.
*/
ptr = end;
while (start < ptr && !is_dir_sep(ptr[-1]) && ptr[-1] != ':')
ptr--;
start = ptr;
/*
* Strip .{bundle,git}.
*/
len = end - start;
strip_suffix_mem(start, &len, is_bundle ? ".bundle" : ".git");
if (!len || (len == 1 && *start == '/'))
die(_("No directory name could be guessed.\n"
"Please specify a directory on the command line"));
if (is_bare)
dir = xstrfmt("%.*s.git", (int)len, start);
else
dir = xstrndup(start, len);
/*
* Replace sequences of 'control' characters and whitespace
* with one ascii space, remove leading and trailing spaces.
*/
if (*dir) {
char *out = dir;
int prev_space = 1 /* strip leading whitespace */;
for (end = dir; *end; ++end) {
char ch = *end;
if ((unsigned char)ch < '\x20')
ch = '\x20';
if (isspace(ch)) {
if (prev_space)
continue;
prev_space = 1;
} else
prev_space = 0;
*out++ = ch;
}
*out = '\0';
if (out > dir && prev_space)
out[-1] = '\0';
}
return dir;
}
static void strip_trailing_slashes(char *dir)
{
char *end = dir + strlen(dir);
while (dir < end - 1 && is_dir_sep(end[-1]))
end--;
*end = '\0';
}
static int add_one_reference(struct string_list_item *item, void *cb_data)
{
struct strbuf err = STRBUF_INIT;
@ -310,13 +424,11 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,
int src_len, dest_len;
struct dir_iterator *iter;
int iter_status;
unsigned int flags;
struct strbuf realpath = STRBUF_INIT;
mkdir_if_missing(dest->buf, 0777);
flags = DIR_ITERATOR_PEDANTIC | DIR_ITERATOR_FOLLOW_SYMLINKS;
iter = dir_iterator_begin(src->buf, flags);
iter = dir_iterator_begin(src->buf, DIR_ITERATOR_PEDANTIC);
if (!iter)
die_errno(_("failed to start iterator over '%s'"), src->buf);
@ -332,6 +444,10 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,
strbuf_setlen(dest, dest_len);
strbuf_addstr(dest, iter->relative_path);
if (S_ISLNK(iter->st.st_mode))
die(_("symlink '%s' exists, refusing to clone with --local"),
iter->relative_path);
if (S_ISDIR(iter->st.st_mode)) {
mkdir_if_missing(dest->buf, 0777);
continue;
@ -543,7 +659,7 @@ static void write_followtags(const struct ref *refs, const char *msg)
}
}
static const struct object_id *iterate_ref_map(void *cb_data)
static int iterate_ref_map(void *cb_data, struct object_id *oid)
{
struct ref **rm = cb_data;
struct ref *ref = *rm;
@ -554,11 +670,13 @@ static const struct object_id *iterate_ref_map(void *cb_data)
*/
while (ref && !ref->peer_ref)
ref = ref->next;
/* Returning -1 notes "end of list" to the caller. */
if (!ref)
return NULL;
return -1;
oidcpy(oid, &ref->old_oid);
*rm = ref->next;
return &ref->old_oid;
return 0;
}
static void update_remote_refs(const struct ref *refs,
@ -670,7 +788,7 @@ static int checkout(int submodule_progress)
return 0;
}
if (!strcmp(head, "HEAD")) {
if (advice_enabled(ADVICE_DETACHED_HEAD))
if (advice_detached_head)
detach_advice(oid_to_hex(&oid));
FREE_AND_NULL(head);
} else {
@ -687,7 +805,6 @@ static int checkout(int submodule_progress)
opts.update = 1;
opts.merge = 1;
opts.clone = 1;
opts.preserve_ignored = 0;
opts.fn = oneway_merge;
opts.verbose_update = (option_verbosity >= 0);
opts.src_index = &the_index;
@ -926,8 +1043,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
if (argc == 2)
dir = xstrdup(argv[1]);
else
dir = git_url_basename(repo_name, is_bundle, option_bare);
strip_dir_trailing_slashes(dir);
dir = guess_dir_name(repo_name, is_bundle, option_bare);
strip_trailing_slashes(dir);
dest_exists = path_exists(dir);
if (dest_exists && !is_empty_dir(dir))
@ -999,7 +1116,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
if (option_recurse_submodules.nr > 0) {
struct string_list_item *item;
struct strbuf sb = STRBUF_INIT;
int val;
/* remove duplicates */
string_list_sort(&option_recurse_submodules);
@ -1016,10 +1132,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
strbuf_detach(&sb, NULL));
}
if (!git_config_get_bool("submodule.stickyRecursiveClone", &val) &&
val)
string_list_append(&option_config, "submodule.recurse=true");
if (option_required_reference.nr &&
option_optional_reference.nr)
die(_("clone --recursive is not compatible with "
@ -1040,10 +1152,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, NULL,
INIT_DB_QUIET);
if (real_git_dir) {
free((char *)git_dir);
if (real_git_dir)
git_dir = real_git_dir;
}
/*
* additional config can be injected with -c, make sure it's included

Some files were not shown because too many files have changed in this diff Show More