Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
388517c
fast-import: refactor finalize_commit_buffer()
chriscool Nov 17, 2025
cb034c0
commit: refactor verify_commit_buffer()
chriscool Nov 17, 2025
c64eb84
make strip: include `scalar`
dscho Nov 17, 2025
6971934
doc: define unambiguous type mappings across C and Rust
ezekielnewren Nov 18, 2025
f007f4f
xdiff: use ptrdiff_t for dstart/dend
ezekielnewren Nov 18, 2025
10f97d6
xdiff: make xrecord_t.ptr a uint8_t instead of char
ezekielnewren Nov 18, 2025
9bd1932
xdiff: use size_t for xrecord_t.size
ezekielnewren Nov 18, 2025
b0d4ae3
xdiff: use unambiguous types in xdl_hash_record()
ezekielnewren Nov 18, 2025
6a26019
xdiff: split xrecord_t.ha into line_hash and minimal_perfect_hash
ezekielnewren Nov 18, 2025
0165387
xdiff: make xdfile_t.nrec a size_t instead of long
ezekielnewren Nov 18, 2025
e35877e
xdiff: make xdfile_t.nreff a size_t instead of long
ezekielnewren Nov 18, 2025
5004a8d
xdiff: change rindex from long to size_t in xdfile_t
ezekielnewren Nov 18, 2025
22ce0cb
xdiff: rename rindex -> reference_index
ezekielnewren Nov 18, 2025
c6def6a
Merge branch 'ps/object-source-loose' into ps/object-source-management
gitster Nov 19, 2025
831e023
path: move `enter_repo()` into "setup.c"
pks-t Nov 19, 2025
7c188a9
setup: convert `set_git_dir()` to have file scope
pks-t Nov 19, 2025
9aaba57
odb: adopt logic to close object databases
pks-t Nov 19, 2025
f8bdf31
odb: refactor `odb_clear()` to `odb_free()`
pks-t Nov 19, 2025
fbf3d06
doc: warn against --committer-date-is-author-date
LemmingAvalanche Nov 20, 2025
770afe4
config: mark otherwise unused function as file-scope static
gitster Nov 20, 2025
df963f0
config: fix suggestion for failed set of multi-valued option
rscharfe Nov 24, 2025
18bf67b
config: fix short help of unset flags
rscharfe Nov 24, 2025
ce1a5a2
config: really pretend missing :(optional) value is not there
gitster Nov 20, 2025
0bd1685
config: really treat missing optional path as not configured
gitster Nov 20, 2025
b67b2d9
odb: move logic to disable ref updates into repo
pks-t Nov 19, 2025
5d795b3
oidset: introduce `oidset_equal()`
pks-t Nov 19, 2025
8dc22e8
builtin/index-pack: fix deferred fsck outside repos
pks-t Nov 19, 2025
eea83c0
t/helper: stop setting up `the_repository` repeatedly
pks-t Nov 19, 2025
c257bd5
http-push: stop setting up `the_repository` for each reference
pks-t Nov 19, 2025
35d9fc6
odb: handle initialization of sources in `odb_new()`
pks-t Nov 19, 2025
2574c61
chdir-notify: add function to unregister listeners
pks-t Nov 19, 2025
2816b74
odb: handle changing a repository's commondir
pks-t Nov 19, 2025
ac65c70
odb: handle recreation of quarantine directories
pks-t Nov 19, 2025
c20f112
fast-import: add 'strip-if-invalid' mode to --signed-commits=<mode>
chriscool Nov 17, 2025
0458e8b
ci(dockerized): do show the result of failing tests again
dscho Nov 17, 2025
0c67076
Merge branch 'en/xdiff-cleanup-2'
gitster Dec 5, 2025
5eadcbf
Merge branch 'js/strip-scalar-too'
gitster Dec 5, 2025
0534b78
Merge branch 'jc/optional-path'
gitster Dec 5, 2025
77f8d99
Merge branch 'kh/doc-committer-date-is-author-date'
gitster Dec 5, 2025
85f9933
Merge branch 'js/ci-show-breakage-in-dockerized-jobs'
gitster Dec 5, 2025
1b40ddc
Merge branch 'cc/fast-import-strip-if-invalid'
gitster Dec 5, 2025
9d442ce
Merge branch 'ps/object-source-management'
gitster Dec 5, 2025
e74a6e0
Merge branch 'rs/config-unset-opthelp-fix'
gitster Dec 5, 2025
644aed8
Merge branch 'rs/config-set-multi-error-message-fix'
gitster Dec 5, 2025
bdc5341
The sixth batch
gitster Dec 5, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ jobs:
- run: ci/install-dependencies.sh
- run: useradd builder --create-home
- run: chown -R builder .
- run: sudo --preserve-env --set-home --user=builder ci/run-build-and-tests.sh
- run: chmod a+w $GITHUB_ENV && sudo --preserve-env --set-home --user=builder ci/run-build-and-tests.sh
- name: print test failures
if: failure() && env.FAILED_TEST_ARTIFACTS != ''
run: sudo --preserve-env --set-home --user=builder ci/print-test-failures.sh
Expand Down
1 change: 1 addition & 0 deletions Documentation/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ TECH_DOCS += technical/shallow
TECH_DOCS += technical/sparse-checkout
TECH_DOCS += technical/sparse-index
TECH_DOCS += technical/trivial-merge
TECH_DOCS += technical/unambiguous-types
TECH_DOCS += technical/unit-tests
SP_ARTICLES += $(TECH_DOCS)
SP_ARTICLES += technical/api-index
Expand Down
31 changes: 31 additions & 0 deletions Documentation/RelNotes/2.53.0.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ UI, Workflows & Features

* Add a new manual that describes the data model.

* "git fast-import" learns "--strip-if-invalid" option to drop
invalid cryptographic signature from objects.


Performance, Internal Implementation, Development Support etc.
--------------------------------------------------------------
Expand All @@ -38,6 +41,13 @@ Performance, Internal Implementation, Development Support etc.
* A part of code paths that deals with loose objects has been cleaned
up.

* "make strip" has been taught to strip "scalar" as well as "git".

* Dockerised jobs at the GitHub Actions CI have been taught to show
more details of failed tests.

* Code refactoring around object database sources.


Fixes since v2.52
-----------------
Expand Down Expand Up @@ -105,8 +115,29 @@ Fixes since v2.52
* Various issues detected by Asan have been corrected.
(merge a031b6181a jk/asan-bonanza later to maint).

* "git config get --path" segfaulted on an ":(optional)path" that
does not exist, which has been corrected.
(merge 0bd16856ff jc/optional-path later to maint).

* The "--committer-date-is-author-date" option of "git am/rebase" is
a misguided one. The documentation is updated to discourage its
use.
(merge fbf3d0669f kh/doc-committer-date-is-author-date later to maint).

* The option help text given by "git config unset -h" described
the "--all" option to "replace", not "unset", multiple variables,
which has been corrected.
(merge 18bf67b753 rs/config-unset-opthelp-fix later to maint).

* The error message given by "git config set", when the variable
being updated has more than one values defined, used old style "git
config" syntax with an incorrect option in its hint, both of which
have been corrected.
(merge df963f0df4 rs/config-set-multi-error-message-fix later to maint).

* Other code cleanup, docfix, build fix, etc.
(merge 46207a54cc qj/doc-http-bad-want-response later to maint).
(merge df90eccd93 kh/doc-commit-extra-references later to maint).
(merge f18aa68861 rs/xmkstemp-simplify later to maint).
(merge fddba8f737 ja/doc-synopsis-style later to maint).
(merge 22ce0cb639 en/xdiff-cleanup-2 later to maint).
7 changes: 7 additions & 0 deletions Documentation/git-am.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,13 @@ Valid <action> for the `--whitespace` option are:
commit creation as the committer date. This allows the
user to lie about the committer date by using the same
value as the author date.
+
WARNING: The history walking machinery assumes that commits have
non-decreasing commit timestamps. You should consider if you really need
to use this option. Then you should only use this option to override the
committer date when applying commits on top of a base which commit is
older (in terms of the commit date) than the oldest patch you are
applying.

--ignore-date::
By default the command records the date from the e-mail
Expand Down
29 changes: 20 additions & 9 deletions Documentation/git-fast-import.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,26 @@ fast-import stream! This option is enabled automatically for
remote-helpers that use the `import` capability, as they are
already trusted to run their own code.

--signed-tags=(verbatim|warn-verbatim|warn-strip|strip|abort)::
Specify how to handle signed tags. Behaves in the same way
as the same option in linkgit:git-fast-export[1], except that
default is 'verbatim' (instead of 'abort').

--signed-commits=(verbatim|warn-verbatim|warn-strip|strip|abort)::
Specify how to handle signed commits. Behaves in the same way
as the same option in linkgit:git-fast-export[1], except that
default is 'verbatim' (instead of 'abort').
`--signed-tags=(verbatim|warn-verbatim|warn-strip|strip|abort)`::
Specify how to handle signed tags. Behaves in the same way as
the `--signed-commits=<mode>` below, except that the
`strip-if-invalid` mode is not yet supported. Like for signed
commits, the default mode is `verbatim`.

`--signed-commits=<mode>`::
Specify how to handle signed commits. The following <mode>s
are supported:
+
* `verbatim`, which is the default, will silently import commit
signatures.
* `warn-verbatim` will import them, but will display a warning.
* `abort` will make this program die when encountering a signed
commit.
* `strip` will silently make the commits unsigned.
* `warn-strip` will make them unsigned, but will display a warning.
* `strip-if-invalid` will check signatures and, if they are invalid,
will strip them and display a warning. The validation is performed
in the same way as linkgit:git-verify-commit[1] does it.

Options for Frontends
~~~~~~~~~~~~~~~~~~~~~
Expand Down
7 changes: 7 additions & 0 deletions Documentation/git-rebase.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,13 @@ See also INCOMPATIBLE OPTIONS below.
Instead of using the current time as the committer date, use
the author date of the commit being rebased as the committer
date. This option implies `--force-rebase`.
+
WARNING: The history walking machinery assumes that commits have
non-decreasing commit timestamps. You should consider if you really need
to use this option. Then you should only use this option to override the
committer date when rebasing commits on top of a base which commit is
older (in terms of the commit date) than the oldest commit you are
applying (in terms of the author date).

--ignore-date::
--reset-author-date::
Expand Down
1 change: 1 addition & 0 deletions Documentation/technical/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ articles = [
'sparse-checkout.adoc',
'sparse-index.adoc',
'trivial-merge.adoc',
'unambiguous-types.adoc',
'unit-tests.adoc',
]

Expand Down
224 changes: 224 additions & 0 deletions Documentation/technical/unambiguous-types.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
= Unambiguous types

Most of these mappings are obvious, but there are some nuances and gotchas with
Rust FFI (Foreign Function Interface).

This document defines clear, one-to-one mappings between primitive types in C,
Rust (and possible other languages in the future). Its purpose is to eliminate
ambiguity in type widths, signedness, and binary representation across
platforms and languages.

For Git, the only header required to use these unambiguous types in C is
`git-compat-util.h`.

== Boolean types
[cols="1,1", options="header"]
|===
| C Type | Rust Type
| bool^1^ | bool
|===

== Integer types

In C, `<stdint.h>` (or an equivalent) must be included.

[cols="1,1", options="header"]
|===
| C Type | Rust Type
| uint8_t | u8
| uint16_t | u16
| uint32_t | u32
| uint64_t | u64

| int8_t | i8
| int16_t | i16
| int32_t | i32
| int64_t | i64
|===

== Floating-point types

Rust requires IEEE-754 semantics.
In C, that is typically true, but not guaranteed by the standard.

[cols="1,1", options="header"]
|===
| C Type | Rust Type
| float^2^ | f32
| double^2^ | f64
|===

== Size types

These types represent pointer-sized integers and are typically defined in
`<stddef.h>` or an equivalent header.

Size types should be used any time pointer arithmetic is performed e.g.
indexing an array, describing the number of elements in memory, etc...

[cols="1,1", options="header"]
|===
| C Type | Rust Type
| size_t^3^ | usize
| ptrdiff_t^3^ | isize
|===

== Character types

This is where C and Rust don't have a clean one-to-one mapping.

A C `char` and a Rust `u8` share the same bit width, so any C struct containing
a `char` will have the same size as the corresponding Rust struct using `u8`.
In that sense, such structs are safe to pass over the FFI boundary, because
their fields will be laid out identically. However, beyond bit width, C `char`
has additional semantics and platform-dependent behavior that can cause
problems, as discussed below.

The C language leaves the signedness of `char` implementation defined. Because
our developer build enables -Wsign-compare, comparison of a value of `char`
type with either signed or unsigned integers may trigger warnings from the
compiler.

Note: Rust's `char` type is an unsigned 32-bit integer that is used to describe
Unicode code points.

=== Notes
^1^ This is only true if stdbool.h (or equivalent) is used. +
^2^ C does not enforce IEEE-754 compatibility, but Rust expects it. If the
platform/arch for C does not follow IEEE-754 then this equivalence does not
hold. Also, it's assumed that `float` is 32 bits and `double` is 64, but
there may be a strange platform/arch where even this isn't true. +
^3^ C also defines uintptr_t, ssize_t and intptr_t, but these types are
discouraged for FFI purposes. For functions like `read()` and `write()` ssize_t
should be cast to a different, and unambiguous, type before being passed over
the FFI boundary. +

== Problems with std::ffi::c_* types in Rust
TL;DR: In practice, Rust's `c_*` types aren't guaranteed to match C types for
all possible C compilers, platforms, or architectures, because Rust only
ensures correctness of C types on officially supported targets. These
definitions have changed over time to match more targets which means that the
c_* definitions will differ based on which Rust version Git chooses to use.

Current list of safe, Rust side, FFI types in Git: +

* `c_void`
* `CStr`
* `CString`

Even then, they should be used sparingly, and only where the semantics match
exactly.

The std::os::raw::c_* directly inherits the problems of core::ffi, which
changes over time and seems to make a best guess at the correct definition for
a given platform/target. This probably isn't a problem for all other platforms
that Rust supports currently, but can anyone say that Rust got it right for all
C compilers of all platforms/targets?

To give an example: c_long is defined in
footnote:[https://doc.rust-lang.org/1.63.0/src/core/ffi/mod.rs.html#175-189[c_long in 1.63.0]]
footnote:[https://doc.rust-lang.org/1.89.0/src/core/ffi/primitives.rs.html#135-151[c_long in 1.89.0]]

=== Rust version 1.63.0

```
mod c_long_definition {
cfg_if! {
if #[cfg(all(target_pointer_width = "64", not(windows)))] {
pub type c_long = i64;
pub type NonZero_c_long = crate::num::NonZeroI64;
pub type c_ulong = u64;
pub type NonZero_c_ulong = crate::num::NonZeroU64;
} else {
// The minimal size of `long` in the C standard is 32 bits
pub type c_long = i32;
pub type NonZero_c_long = crate::num::NonZeroI32;
pub type c_ulong = u32;
pub type NonZero_c_ulong = crate::num::NonZeroU32;
}
}
}
```

=== Rust version 1.89.0

```
mod c_long_definition {
crate::cfg_select! {
any(
all(target_pointer_width = "64", not(windows)),
// wasm32 Linux ABI uses 64-bit long
all(target_arch = "wasm32", target_os = "linux")
) => {
pub(super) type c_long = i64;
pub(super) type c_ulong = u64;
}
_ => {
// The minimal size of `long` in the C standard is 32 bits
pub(super) type c_long = i32;
pub(super) type c_ulong = u32;
}
}
}
```

Even for the cases where C types are correctly mapped to Rust types via
std::ffi::c_* there are still problems. Let's take c_char for example. On some
platforms it's u8 on others it's i8.

=== Subtraction underflow in debug mode

The following code will panic in debug on platforms that define c_char as u8,
but won't if it's an i8.

```
let mut x: std::ffi::c_char = 0;
x -= 1;
```

=== Inconsistent shift behavior

`x` will be 0xC0 for platforms that use i8, but will be 0x40 where it's u8.

```
let mut x: std::ffi::c_char = 0x80;
x >>= 1;
```

=== Equality fails to compile on some platforms

The following will not compile on platforms that define c_char as i8, but will
if it's u8. You can cast x e.g. `assert_eq!(x as u8, b'a');`, but then you get
a warning on platforms that use u8 and a clean compilation where i8 is used.

```
let mut x: std::ffi::c_char = 0x61;
assert_eq!(x, b'a');
```

== Enum types
Rust enum types should not be used as FFI types. Rust enum types are more like
C union types than C enum's. For something like:

```
#[repr(C, u8)]
enum Fruit {
Apple,
Banana,
Cherry,
}
```

It's easy enough to make sure the Rust enum matches what C would expect, but a
more complex type like.

```
enum HashResult {
SHA1([u8; 20]),
SHA256([u8; 32]),
}
```

The Rust compiler has to add a discriminant to the enum to distinguish between
the variants. The width, location, and values for that discriminant is up to
the Rust compiler and is not ABI stable.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2567,7 +2567,7 @@ please_set_SHELL_PATH_to_a_more_modern_shell:

shell_compatibility_test: please_set_SHELL_PATH_to_a_more_modern_shell

strip: $(PROGRAMS) git$X
strip: $(PROGRAMS) git$X scalar$X
$(STRIP) $(STRIP_OPTS) $^

### Target-specific flags and dependencies
Expand Down
3 changes: 2 additions & 1 deletion builtin/blame.c
Original file line number Diff line number Diff line change
Expand Up @@ -739,7 +739,8 @@ static int git_blame_config(const char *var, const char *value,
ret = git_config_pathname(&str, var, value);
if (ret)
return ret;
string_list_insert(&ignore_revs_file_list, str);
if (str)
string_list_insert(&ignore_revs_file_list, str);
free(str);
return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion builtin/clone.c
Original file line number Diff line number Diff line change
Expand Up @@ -1617,7 +1617,7 @@ int cmd_clone(int argc,
transport_disconnect(transport);

if (option_dissociate) {
close_object_store(the_repository->objects);
odb_close(the_repository->objects);
dissociate_from_references();
}

Expand Down
Loading