Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
8b5636a
Revert "gitk: Only restore window size from ~/.gitk, not position"
j6t Oct 17, 2025
bf5a55a
gitk: persist position and size of the Tags and Heads window
j6t Oct 17, 2025
77e7aab
gitk: fix a 'continue' statement outside a loop to 'return'
j6t Nov 6, 2025
d445a78
gitk: show unescaped file names on 'rename' and 'copy' lines
j6t Nov 6, 2025
bdb1cf8
gitk: add external diff file rename detection
ToBoMi Nov 6, 2025
881793c
xdiff: add 'minimal' to XDF_DIFF_ALGORITHM_MASK
wetneb Nov 17, 2025
ffffb98
blame: make diff algorithm configurable
wetneb Nov 17, 2025
f18aa68
wrapper: simplify xmkstemp()
rscharfe Nov 17, 2025
ffe702b
t6429: update comment to mention correct tool
newren Nov 3, 2025
d5663a4
merge-ort: remove debugging crud
newren Nov 3, 2025
a562d90
merge-ort: fix failing merges in special corner case
newren Nov 3, 2025
d22a488
wincred: avoid memory corruption
elieux Nov 17, 2025
b0d5c88
cmake: stop trying to build the reftable and xdiff libraries
dscho Nov 17, 2025
af39198
mingw: avoid the comma operator
dscho Nov 17, 2025
cd99203
ci: bump actions/setup-go from 5 to 6
dscho Nov 18, 2025
e96105a
unit-test: ignore --no-chain-lint
peff Nov 18, 2025
17bd110
ci(windows-meson-test): handle options and output like other test jobs
peff Nov 18, 2025
14b561e
test-mktemp: plug memory and descriptor leaks
peff Nov 18, 2025
a6238ee
worktree list: fix column spacing
phillipwood Nov 18, 2025
08dfa59
worktree list: quote paths
phillipwood Nov 18, 2025
2367c6b
win32: return error if SleepConditionVariableCS fails
AZero13 Nov 18, 2025
bd3fd7e
Merge branch 'js/persist-ref-window-geometry'
j6t Nov 26, 2025
776223c
Merge branch 'tb/external-diff-renamed'
j6t Nov 26, 2025
42bf8a5
Merge branch 'master' of https://github.com/j6t/gitk
gitster Nov 26, 2025
716e871
Merge branch 'en/ort-rename-another-fix'
gitster Nov 26, 2025
1b93acd
Merge branch 'ad/blame-diff-algorithm'
gitster Nov 26, 2025
370470e
Merge branch 'rs/xmkstemp-simplify'
gitster Nov 26, 2025
24ddb3f
Merge branch 'jk/test-mktemp-leakfix'
gitster Nov 26, 2025
fa40522
Merge branch 'js/ci-github-setup-go-update'
gitster Nov 26, 2025
eb474aa
Merge branch 'js/mingw-assign-comma-fix'
gitster Nov 26, 2025
35eaf96
Merge branch 'js/cmake-libgit-fix'
gitster Nov 26, 2025
e539545
Merge branch 'js/wincred-get-credential-alloc-fix'
gitster Nov 26, 2025
d65eab5
Merge branch 'pw/worktree-list-display-width-fix'
gitster Nov 26, 2025
536d284
Merge branch 'jk/ci-windows-meson-test-fix'
gitster Nov 26, 2025
54af646
Merge branch 'gf/win32-pthread-cond-wait-err'
gitster Nov 26, 2025
b31ab93
The fourth batch
gitster Nov 26, 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/l10n.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ jobs:
origin \
${{ github.ref }} \
$args
- uses: actions/setup-go@v5
- uses: actions/setup-go@v6
with:
go-version: '>=1.16'
cache: false
Expand Down
12 changes: 11 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,17 @@ jobs:
path: build
- name: Test
shell: pwsh
run: meson test -C build --no-rebuild --print-errorlogs --slice "$(1+${{ matrix.nr }})/10"
run: ci/run-test-slice-meson.sh build ${{matrix.nr}} 10
- name: print test failures
if: failure() && env.FAILED_TEST_ARTIFACTS != ''
shell: bash
run: ci/print-test-failures.sh
- name: Upload failed tests' directories
if: failure() && env.FAILED_TEST_ARTIFACTS != ''
uses: actions/upload-artifact@v4
with:
name: failed-tests-windows-meson-${{ matrix.nr }}
path: ${{env.FAILED_TEST_ARTIFACTS}}

regular:
name: ${{matrix.vector.jobname}} (${{matrix.vector.pool}})
Expand Down
39 changes: 39 additions & 0 deletions Documentation/RelNotes/2.53.0.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ UI, Workflows & Features
in a transaction by default, instead of emitting where each refs
should point at and leaving the actual update to another command.

* "git blame" learns "--diff-algorithm=<algo>" option.


Performance, Internal Implementation, Development Support etc.
--------------------------------------------------------------
Expand Down Expand Up @@ -57,6 +59,43 @@ Fixes since v2.52
corrected.
(merge 7a03a10a3a jx/repo-struct-utf8width-fix later to maint).

* Yet another corner case fix around renames in the "ort" merge
strategy.
(merge a562d90a35 en/ort-rename-another-fix later to maint).

* Test leakfix.
(merge 14b561e768 jk/test-mktemp-leakfix later to maint).

* Update a version of action used at the GitHub Actrions CI.
(merge cd99203f86 js/ci-github-setup-go-update later to maint).

* The "return errno = EFOO, -1" construct, which is heavily used in
compat/mingw.c and triggers warnings under "-Wcomma", has been
rewritten to avoid the warnings.
(merge af3919816f js/mingw-assign-comma-fix later to maint).

* Makefile based build have recently been updated to build a
libgit.a that also has reftable and xdiff objects; CMake based
build procedure has been updated to match.
(merge b0d5c88cca js/cmake-libgit-fix later to maint).

* Under-allocation fix.
(merge d22a488482 js/wincred-get-credential-alloc-fix later to maint).

* "git worktree list" attempts to show paths to worktrees while
aligning them, but miscounted display columns for the paths when
non-ASCII characters were involved, which has been corrected.
(merge 08dfa59835 pw/worktree-list-display-width-fix later to maint).

* "Windows+meson" job at the GitHub Actions CI was hard to debug, as
it did not show and save failed test artifacts, which has been
corrected.
(merge 17bd1108ea jk/ci-windows-meson-test-fix later to maint).

* Emulation code clean-up.
(merge 2367c6bcd6 gf/win32-pthread-cond-wait-err 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).
20 changes: 20 additions & 0 deletions Documentation/diff-algorithm-option.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
`--diff-algorithm=(patience|minimal|histogram|myers)`::
Choose a diff algorithm. The variants are as follows:
+
--
`default`;;
`myers`;;
The basic greedy diff algorithm. Currently, this is the default.
`minimal`;;
Spend extra time to make sure the smallest possible diff is
produced.
`patience`;;
Use "patience diff" algorithm when generating patches.
`histogram`;;
This algorithm extends the patience algorithm to "support
low-occurrence common elements".
--
+
For instance, if you configured the `diff.algorithm` variable to a
non-default value and want to use the default one, then you
have to use `--diff-algorithm=default` option.
21 changes: 1 addition & 20 deletions Documentation/diff-options.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -197,26 +197,7 @@ and starts with _<text>_, this algorithm attempts to prevent it from
appearing as a deletion or addition in the output. It uses the "patience
diff" algorithm internally.

`--diff-algorithm=(patience|minimal|histogram|myers)`::
Choose a diff algorithm. The variants are as follows:
+
--
`default`;;
`myers`;;
The basic greedy diff algorithm. Currently, this is the default.
`minimal`;;
Spend extra time to make sure the smallest possible diff is
produced.
`patience`;;
Use "patience diff" algorithm when generating patches.
`histogram`;;
This algorithm extends the patience algorithm to "support
low-occurrence common elements".
--
+
For instance, if you configured the `diff.algorithm` variable to a
non-default value and want to use the default one, then you
have to use `--diff-algorithm=default` option.
include::diff-algorithm-option.adoc[]

`--stat[=<width>[,<name-width>[,<count>]]]`::
Generate a diffstat. By default, as much space as necessary
Expand Down
2 changes: 2 additions & 0 deletions Documentation/git-blame.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ include::blame-options.adoc[]
Ignore whitespace when comparing the parent's version and
the child's to find where the lines came from.

include::diff-algorithm-option.adoc[]

--abbrev=<n>::
Instead of using the default 7+1 hexadecimal digits as the
abbreviated object name, use <m>+1 digits, where <m> is at
Expand Down
52 changes: 51 additions & 1 deletion builtin/blame.c
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,19 @@ static int git_blame_config(const char *var, const char *value,
}
}

if (!strcmp(var, "diff.algorithm")) {
long diff_algorithm;
if (!value)
return config_error_nonbool(var);
diff_algorithm = parse_algorithm_value(value);
if (diff_algorithm < 0)
return error(_("unknown value for config '%s': %s"),
var, value);
xdl_opts &= ~XDF_DIFF_ALGORITHM_MASK;
xdl_opts |= diff_algorithm;
return 0;
}

if (git_diff_heuristic_config(var, value, cb) < 0)
return -1;
if (userdiff_config(var, value) < 0)
Expand Down Expand Up @@ -824,6 +837,38 @@ static int blame_move_callback(const struct option *option, const char *arg, int
return 0;
}

static int blame_diff_algorithm_minimal(const struct option *option,
const char *arg, int unset)
{
int *opt = option->value;

BUG_ON_OPT_ARG(arg);

*opt &= ~XDF_DIFF_ALGORITHM_MASK;
if (!unset)
*opt |= XDF_NEED_MINIMAL;

return 0;
}

static int blame_diff_algorithm_callback(const struct option *option,
const char *arg, int unset)
{
int *opt = option->value;
long value = parse_algorithm_value(arg);

BUG_ON_OPT_NEG(unset);

if (value < 0)
return error(_("option diff-algorithm accepts \"myers\", "
"\"minimal\", \"patience\" and \"histogram\""));

*opt &= ~XDF_DIFF_ALGORITHM_MASK;
*opt |= value;

return 0;
}

static int is_a_rev(const char *name)
{
struct object_id oid;
Expand Down Expand Up @@ -915,11 +960,16 @@ int cmd_blame(int argc,
OPT_BIT('s', NULL, &output_option, N_("suppress author name and timestamp (Default: off)"), OUTPUT_NO_AUTHOR),
OPT_BIT('e', "show-email", &output_option, N_("show author email instead of name (Default: off)"), OUTPUT_SHOW_EMAIL),
OPT_BIT('w', NULL, &xdl_opts, N_("ignore whitespace differences"), XDF_IGNORE_WHITESPACE),
OPT_CALLBACK_F(0, "diff-algorithm", &xdl_opts, N_("<algorithm>"),
N_("choose a diff algorithm"),
PARSE_OPT_NONEG, blame_diff_algorithm_callback),
OPT_STRING_LIST(0, "ignore-rev", &ignore_rev_list, N_("rev"), N_("ignore <rev> when blaming")),
OPT_STRING_LIST(0, "ignore-revs-file", &ignore_revs_file_list, N_("file"), N_("ignore revisions from <file>")),
OPT_BIT(0, "color-lines", &output_option, N_("color redundant metadata from previous line differently"), OUTPUT_COLOR_LINE),
OPT_BIT(0, "color-by-age", &output_option, N_("color lines by age"), OUTPUT_SHOW_AGE_WITH_COLOR),
OPT_BIT(0, "minimal", &xdl_opts, N_("spend extra cycles to find better match"), XDF_NEED_MINIMAL),
OPT_CALLBACK_F(0, "minimal", &xdl_opts, NULL,
N_("spend extra cycles to find a better match"),
PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, blame_diff_algorithm_minimal),
OPT_STRING('S', NULL, &revs_file, N_("file"), N_("use revisions from <file> instead of calling git-rev-list")),
OPT_STRING(0, "contents", &contents_from, N_("file"), N_("use <file>'s contents as the final image")),
OPT_CALLBACK_F('C', NULL, &opt, N_("score"), N_("find line copies within and across files"), PARSE_OPT_OPTARG, blame_copy_callback),
Expand Down
41 changes: 29 additions & 12 deletions builtin/worktree.c
Original file line number Diff line number Diff line change
Expand Up @@ -975,14 +975,18 @@ static void show_worktree_porcelain(struct worktree *wt, int line_terminator)
fputc(line_terminator, stdout);
}

static void show_worktree(struct worktree *wt, int path_maxlen, int abbrev_len)
struct worktree_display {
char *path;
int width;
};

static void show_worktree(struct worktree *wt, struct worktree_display *display,
int path_maxwidth, int abbrev_len)
{
struct strbuf sb = STRBUF_INIT;
int cur_path_len = strlen(wt->path);
int path_adj = cur_path_len - utf8_strwidth(wt->path);
const char *reason;

strbuf_addf(&sb, "%-*s ", 1 + path_maxlen + path_adj, wt->path);
strbuf_addf(&sb, "%s%*s", display->path, 1 + path_maxwidth - display->width, "");
if (wt->is_bare)
strbuf_addstr(&sb, "(bare)");
else {
Expand Down Expand Up @@ -1016,20 +1020,27 @@ static void show_worktree(struct worktree *wt, int path_maxlen, int abbrev_len)
strbuf_release(&sb);
}

static void measure_widths(struct worktree **wt, int *abbrev, int *maxlen)
static void measure_widths(struct worktree **wt, int *abbrev,
struct worktree_display **d, int *maxwidth)
{
int i;
int i, display_alloc = 0;
struct worktree_display *display = NULL;
struct strbuf buf = STRBUF_INIT;

for (i = 0; wt[i]; i++) {
int sha1_len;
int path_len = strlen(wt[i]->path);
ALLOC_GROW(display, i + 1, display_alloc);
quote_path(wt[i]->path, NULL, &buf, 0);
display[i].width = utf8_strwidth(buf.buf);
display[i].path = strbuf_detach(&buf, NULL);

if (path_len > *maxlen)
*maxlen = path_len;
if (display[i].width > *maxwidth)
*maxwidth = display[i].width;
sha1_len = strlen(repo_find_unique_abbrev(the_repository, &wt[i]->head_oid, *abbrev));
if (sha1_len > *abbrev)
*abbrev = sha1_len;
}
*d = display;
}

static int pathcmp(const void *a_, const void *b_)
Expand Down Expand Up @@ -1075,21 +1086,27 @@ static int list(int ac, const char **av, const char *prefix,
die(_("the option '%s' requires '%s'"), "-z", "--porcelain");
else {
struct worktree **worktrees = get_worktrees();
int path_maxlen = 0, abbrev = DEFAULT_ABBREV, i;
int path_maxwidth = 0, abbrev = DEFAULT_ABBREV, i;
struct worktree_display *display = NULL;

/* sort worktrees by path but keep main worktree at top */
pathsort(worktrees + 1);

if (!porcelain)
measure_widths(worktrees, &abbrev, &path_maxlen);
measure_widths(worktrees, &abbrev,
&display, &path_maxwidth);

for (i = 0; worktrees[i]; i++) {
if (porcelain)
show_worktree_porcelain(worktrees[i],
line_terminator);
else
show_worktree(worktrees[i], path_maxlen, abbrev);
show_worktree(worktrees[i],
&display[i], path_maxwidth, abbrev);
}
for (i = 0; display && worktrees[i]; i++)
free(display[i].path);
free(display);
free_worktrees(worktrees);
}
return 0;
Expand Down
13 changes: 13 additions & 0 deletions ci/run-test-slice-meson.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/sh

# We must load the build options so we know where to find
# things like TEST_OUTPUT_DIRECTORY. This has to come before
# loading lib.sh, though, because it may clobber some CI lib
# variables like our custom GIT_TEST_OPTS.
. "$1"/GIT-BUILD-OPTIONS
. ${0%/*}/lib.sh

group "Run tests" \
meson test -C "$1" --no-rebuild --print-errorlogs \
--test-args="$GIT_TEST_OPTS" --slice "$((1+$2))/$3" ||
handle_failed_tests
48 changes: 28 additions & 20 deletions compat/mingw.c
Original file line number Diff line number Diff line change
Expand Up @@ -491,8 +491,10 @@ static int mingw_open_append(wchar_t const *wfilename, int oflags, ...)
DWORD create = (oflags & O_CREAT) ? OPEN_ALWAYS : OPEN_EXISTING;

/* only these flags are supported */
if ((oflags & ~O_CREAT) != (O_WRONLY | O_APPEND))
return errno = ENOSYS, -1;
if ((oflags & ~O_CREAT) != (O_WRONLY | O_APPEND)) {
errno = ENOSYS;
return -1;
}

/*
* FILE_SHARE_WRITE is required to permit child processes
Expand Down Expand Up @@ -2450,12 +2452,14 @@ static int start_timer_thread(void)
timer_event = CreateEvent(NULL, FALSE, FALSE, NULL);
if (timer_event) {
timer_thread = (HANDLE) _beginthreadex(NULL, 0, ticktack, NULL, 0, NULL);
if (!timer_thread )
return errno = ENOMEM,
error("cannot start timer thread");
} else
return errno = ENOMEM,
error("cannot allocate resources for timer");
if (!timer_thread ) {
errno = ENOMEM;
return error("cannot start timer thread");
}
} else {
errno = ENOMEM;
return error("cannot allocate resources for timer");
}
return 0;
}

Expand Down Expand Up @@ -2488,13 +2492,15 @@ int setitimer(int type UNUSED, struct itimerval *in, struct itimerval *out)
static const struct timeval zero;
static int atexit_done;

if (out)
return errno = EINVAL,
error("setitimer param 3 != NULL not implemented");
if (out) {
errno = EINVAL;
return error("setitimer param 3 != NULL not implemented");
}
if (!is_timeval_eq(&in->it_interval, &zero) &&
!is_timeval_eq(&in->it_interval, &in->it_value))
return errno = EINVAL,
error("setitimer: it_interval must be zero or eq it_value");
!is_timeval_eq(&in->it_interval, &in->it_value)) {
errno = EINVAL;
return error("setitimer: it_interval must be zero or eq it_value");
}

if (timer_thread)
stop_timer_thread();
Expand All @@ -2516,12 +2522,14 @@ int sigaction(int sig, struct sigaction *in, struct sigaction *out)
{
if (sig == SIGCHLD)
return -1;
else if (sig != SIGALRM)
return errno = EINVAL,
error("sigaction only implemented for SIGALRM");
if (out)
return errno = EINVAL,
error("sigaction: param 3 != NULL not implemented");
else if (sig != SIGALRM) {
errno = EINVAL;
return error("sigaction only implemented for SIGALRM");
}
if (out) {
errno = EINVAL;
return error("sigaction: param 3 != NULL not implemented");
}

timer_fn = in->sa_handler;
return 0;
Expand Down
Loading