Skip to content

fix(git): retry force pushes as force pushes, and read git's output in English - #90

Merged
noahbclarkson merged 3 commits into
mainfrom
fix/push-retry-and-git-locale
Oct 19, 2026
Merged

noahbclarkson merged 3 commits into
mainfrom
fix/push-retry-and-git-locale

Conversation

@noahbclarkson

Copy link
Copy Markdown
Owner

Two bugs on main, found while reviewing #89. Neither depends on the i18n work.

Force-push retry

retry_git_operation decided whether to force by checking the failure summary for "force push" (workspace/operations.rs:210). On failure the summary is always "Push to '<remote>' failed", so a failed force push was retried as a plain push, and the remote rejects that as non-fast-forward.

  • New GitOperationKind::ForcePush, chosen by GitOperationKind::push(force) in all three push entry points, including the "could not start" paths.
  • The retry reads the kind instead of the text.
  • The toolbar's pushing state uses kind.is_push(), so it covers both kinds.
  • The failure summary now says "Force push to '' failed".

git's output language

Several outcomes are recognised by matching git's output, and a localized git translates every one of them:

Where Match
network.rs (pull) Already up to date., CONFLICT, Automatic merge failed
rebase.rs CONFLICT, could not apply
auth.rs Permission denied (publickey) and the other SSH failures that trigger the HTTPS fallback
mod.rs [ahead N, behind M] from %(upstream:track)

git_command(), which every CLI call goes through, now sets LC_MESSAGES=C. LC_ALL overrides every category, so when it is set its value moves to LANG and the per-category variables it was overriding are removed. Only the message language changes: dates, collation and character encoding resolve exactly as before, and hooks see the same locale apart from messages.

Trade-off: git's stderr shown in failure toasts is now English for users with a localized git.

Verification

  • cargo clippy --workspace --all-targets -- -D warnings: clean.
  • cargo test -p rgitui_git -p rgitui_workspace: 414 + 769 passed.
  • New unit tests cover the environment changes: no LC_ALL, LC_ALL with other LC_* set, and an empty LC_ALL.
  • Not verified live: neither Git for Windows nor WSL Ubuntu on the test machine has git's translations installed, so the effect on a localized git wasn't observed directly. It relies on gettext's documented precedence (LC_ALL > LC_MESSAGES > LANG, and LANGUAGE ignored when the message locale is C).

🤖 Generated with Claude Code

…n English

Retrying a failed push decided whether to force by searching the failure
summary for "force push". The summary on failure is always "Push to '<remote>'
failed", so a failed force push was retried as a plain push. Force pushes now
carry their own GitOperationKind::ForcePush, the retry reads the kind, and the
toolbar's pushing state covers both.

Several outcomes are recognised by matching git's output: CONFLICT and
"Automatic merge failed" after a pull, "could not apply" during a rebase,
"Already up to date.", the SSH auth failures that trigger the HTTPS fallback,
and the "[ahead N, behind M]" of %(upstream:track). A localized git translates
all of them. git_command() now sets LC_MESSAGES=C. When LC_ALL is set it
overrides every category, so its value moves to LANG and the per-category
variables it was overriding are removed, which changes the message language
and nothing else. git's stderr shown in failure toasts is English as a result.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-19T08:53:38.377222Z 5a6afa8 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b434398fc0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/rgitui_git/src/project/mod.rs Outdated
let mut lc_all = None;
let mut categories = Vec::new();
for (key, value) in vars {
if key == "LC_ALL" {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Match locale environment names case-insensitively on Windows

On Windows, environment-variable names are case-insensitive, but these comparisons are case-sensitive. If rgitui is launched with a mixed/lowercase variable such as lc_all=de_DE.UTF-8, Git still treats it as LC_ALL, while this function leaves it inherited; it consequently overrides the newly added LC_MESSAGES=C, so the output remains localized and the parsing failures this change intends to fix persist. Mixed-case LC_* variables likewise escape removal and can change the supposedly preserved non-message categories after LC_ALL is moved to LANG.

Useful? React with 👍 / 👎.

…tle a failed push

- Windows reads environment names without regard to case, so a
  lowercase `lc_all` is `LC_ALL` to git there. The exact-case check
  missed it, `LC_MESSAGES=C` lost to it, and git kept answering in the
  user's language. Names now match case-insensitively where the platform
  does (`cfg!(windows)`), and the variable is removed under the name it
  was found with.
- Splitting `ForcePush` from `Push` meant a plain push succeeding after
  a failed force push (or the reverse) no longer cleared the failure:
  the success handler compared kinds for equality, so the stale banner
  came back and still offered a retry that force-pushes.
  `GitOperationKind::settles` treats both pushes as one for this.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@noahbclarkson

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep them coming!

Reviewed commit: 562e46fe65

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@noahbclarkson

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Nice work!

Reviewed commit: 5a6afa8c63

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@noahbclarkson
noahbclarkson merged commit c132dfc into main Oct 19, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant