Skip to content

Conversation

@estebank
Copy link
Contributor

@estebank estebank commented Dec 21, 2025

When detecting "diff markers", inspect the current git repo's state to see if there is an active rebase. If that is the case, we try to identify whether the rebase is caused by git rebase or implicitly by git pull. In order to do that we query git to ask for the path of .git/rebase-merge and then inspect the files orig-head (the commit we are rebasing from), onto (the commit we are rebasing onto) and head-name (the branch being rebased). We modify the labels pointing at the markers to be clear on where each section of code is coming from.

git rebase case:

error: encountered diff marker
 --> src/main.rs:2:1
  |
2 | <<<<<<< HEAD
  | ^^^^^^^ between this marker and `=======` is the code that you're rebasing onto
3 |     println!("Hello, main!");
4 | =======
  | ------- between this marker and `>>>>>>>` is the code from branch 'branch-2' that you are rebasing
5 |     println!("Hello, branch!");
6 | >>>>>>> e644375 (branch)
  | ^^^^^^^ this marker concludes the conflict region
  |
  = note: conflict markers indicate that a merge was started but could not be completed due to merge conflicts
          to resolve a conflict, keep only the code you want and then delete the lines containing conflict markers
  = note: for an explanation on these markers from the `git` documentation:
          visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts>

git merge case:

error: encountered diff marker
 --> src/main.rs:2:1
  |
2 | <<<<<<< HEAD
  | ^^^^^^^ between this marker and `=======` is the code from branch 'branch-2'
3 |     println!("Hello, branch!");
4 | =======
  | ------- between this marker and `>>>>>>>` is the code from branch 'master'
5 |     println!("Hello, main!");
6 | >>>>>>> master
  | ^^^^^^^ this marker concludes the conflict region
  |
  = note: conflict markers indicate that a merge was started but could not be completed due to merge conflicts
          to resolve a conflict, keep only the code you want and then delete the lines containing conflict markers
  = note: for an explanation on these markers from the `git` documentation:
          visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts>

git pull --rebase case:

error: encountered diff marker
 --> src/main.rs:2:1
  |
2 | <<<<<<< HEAD
  | ^^^^^^^ between this marker and `=======` is the code from branch 'main'
3 |     println!("Hello, 2!");
4 | =======
  | ------- between this marker and `>>>>>>>` is the code from remote branch 'main' of github.com:estebank/pull-merge-conflict
5 |     println!("Hello, 1!");
6 | >>>>>>> 8191e7e4f9f82be45bdd4e71c37d2adcf4f88aa2
  | ^^^^^^^ this marker concludes the conflict region
  |
  = note: conflict markers indicate that a merge was started but could not be completed due to merge conflicts
          to resolve a conflict, keep only the code you want and then delete the lines containing conflict markers
  = note: for an explanation on these markers from the `git` documentation:
          visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts>

git pull --no-rebase case:

error: encountered diff marker
 --> src/main.rs:2:1
  |
2 | <<<<<<< HEAD
  | ^^^^^^^ between this marker and `=======` is the code from branch 'main' of github.com:estebank/pull-merge-conflict
3 |     println!("Hello, 1!");
4 | =======
  | ------- between this marker and `>>>>>>>` is the code from local branch 'main' before `git pull`
5 |     println!("Hello, 2!");
6 | >>>>>>> ebbeec7 (second)
  | ^^^^^^^ this marker concludes the conflict region
  |
  = note: conflict markers indicate that a merge was started but could not be completed due to merge conflicts
          to resolve a conflict, keep only the code you want and then delete the lines containing conflict markers
  = note: for an explanation on these markers from the `git` documentation:
          visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts>

Also, the generic help description is now removed.

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Dec 21, 2025
@rustbot
Copy link
Collaborator

rustbot commented Dec 21, 2025

r? @petrochenkov

rustbot has assigned @petrochenkov.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@estebank
Copy link
Contributor Author

estebank commented Dec 21, 2025

I'll push a run-make test for the different cases being handled shortly.

This is what it looks like in my two test repos

git rebase case:

Screenshot 2025-12-21 at 1 13 24 PM

git pull case:
Screenshot 2025-12-21 at 1 13 30 PM

and the current output:
Screenshot 2025-12-21 at 1 15 57 PM

Edit: done.

format!("code you had in commit `{orig_head_sha}` that you are rebasing");
}
if let Ok(output) =
Command::new("git").args(["branch", "--points-at", onto_sha.trim()]).output()
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Both calls to git branch --points-at (locals only and remotes) will incur a linear cost on the number of branches that exist in the repo. This can be a problem as there are some projects with lots of branches. We have the time cost of filtering them and the potential of lots branches pointing to the same tip, which is handled somewhat already.

The decision on whether the risk is acceptable, or we should not even try, is one I am flip-flopping and keep arguing with myself.

I reached out to the git mailing list to see if they could add the equivalent of branch-name so that this is unnecessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed to work only if the current directory cargo was invoked from is the root git repo and git has a default path configuration.

@Noratrieb Noratrieb added S-waiting-on-MCP Status: PR has a compiler MCP and is waiting for the compiler MCP to complete. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Dec 23, 2025
@rustbot rustbot added the A-run-make Area: port run-make Makefiles to rmake.rs label Dec 23, 2025
@rust-log-analyzer

This comment has been minimized.

// conflict might not have been caused by a git rebase, and we'll fall-back on the default
// diagnostic.
let git = |path: &str| {
std::fs::read_to_string(format!(".git/{path}"))
Copy link
Member

@jyn514 jyn514 Dec 25, 2025

Choose a reason for hiding this comment

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

now this is definitely broken, certainly on worktrees and submodules and likely in other cases too. the fallback is to just not emit the diagnostic, which is ok i guess, but it will make UI tests very fragile and generally i don’t think this behaves how you expect.

i would rather you run git —rev-parse tbh.

Copy link
Contributor Author

@estebank estebank Dec 25, 2025

Choose a reason for hiding this comment

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

i would rather you run git —rev-parse tbh

I'll look into potentially using the appropriate sub-crate from gitoxide for this (if not just taking the appropriate logic), given how unlikely it will be for people to accept us shelling out to git.

Edit: it looks like it'd be https://crates.io/crates/gix-discover.

Edit 2: the list of new deps this would add is not ideal:

byteorder@1.5.0
gix-actor@0.36.1
gix-hashtable@0.11.0
gix-date@0.11.1
same-file@1.0.6
dunce@1.0.5
hash32@0.3.1
gix-object@0.53.0
gix-lock@20.0.0
walkdir@2.5.0
gix-utils@0.3.1
winapi-util@0.1.11
jiff-tzdb-platform@0.1.3
gix-validate@0.10.1
gix-trace@0.1.16
winnow@0.7.14
gix-fs@0.18.0
sha1-checked@0.10.0
prodash@30.0.1
gix-discover@0.44.0
faster-hex@0.10.0
gix-ref@0.56.0
gix-features@0.45.0
heapless@0.8.0
jiff-tzdb@0.1.5
gix-hash@0.21.0
gix-path@0.10.22
gix-sec@0.12.2
gix-tempfile@20.0.0

When detecting "diff markers", inspect the current `git` repo's state to see if there is an active rebase. If that is the case, we try to identify whether the rebase is caused by `git rebase` or implicitly by `git pull`. In order to do that we query `git` to ask for the path of `.git/rebase-merge` and then inspect the files `orig-head` (the commit we are rebasing from), `onto` (the commit we are rebasing onto) and `head-name` (the branch being rebased). We modify the labels pointing at the markers to be clear on where each section of code is coming from.

`git rebase` case:

```
error: encountered diff marker
 --> src/main.rs:2:1
  |
2 | <<<<<<< HEAD
  | ^^^^^^^ between this marker and `=======` is the code from branch `master` we're rebasing onto
3 |     println!("Hello, main!");
4 | =======
  | ------- between this marker and `>>>>>>>` is the code you had in branch `branch-2` that you are rebasing
5 |     println!("Hello, branch!");
6 | >>>>>>> e644375 (branch)
  | ^^^^^^^ this marker concludes the conflict region
  |
  = note: conflict markers indicate that a merge was started but could not be completed due to merge conflicts
          to resolve a conflict, keep only the code you want and then delete the lines containing conflict markers
  = note: for an explanation on these markers from the `git` documentation:
          visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts>
```

`git pull` case:

```
error: encountered diff marker
 --> src/main.rs:2:1
  |
2 | <<<<<<< HEAD
  | ^^^^^^^ between this marker and `=======` is the code from the remote branch `origin/main` we're rebasing onto
3 |     println!("Hello, 1!");
4 | =======
  | ------- between this marker and `>>>>>>>` is the code you had in branch `main` that you are rebasing
5 |     println!("Hello, 2!");
6 | >>>>>>> ebbeec7 (second)
  | ^^^^^^^ this marker concludes the conflict region
  |
  = note: conflict markers indicate that a merge was started but could not be completed due to merge conflicts
          to resolve a conflict, keep only the code you want and then delete the lines containing conflict markers
  = note: for an explanation on these markers from the `git` documentation:
          visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts>
```

Also, the generic `help` description had the `git pull` case flipped from what it should have been.
The logic now only works if `cargo` is called from the git root, otherwise it won't find where the git metadata is. We rely purely on inspecting the files with rebase metadata and don't attempt to resolve a rebase target SHA to a branch name.

Reword slightly the labels.
@rustbot
Copy link
Collaborator

rustbot commented Dec 26, 2025

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@bors
Copy link
Collaborator

bors commented Jan 2, 2026

☔ The latest upstream changes (presumably #150575) made this pull request unmergeable. Please resolve the merge conflicts.

@bors bors added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Jan 2, 2026
@rust-bors
Copy link
Contributor

rust-bors bot commented Jan 2, 2026

☔ The latest upstream changes made this pull request unmergeable. Please resolve the merge conflicts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-run-make Area: port run-make Makefiles to rmake.rs S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. S-waiting-on-MCP Status: PR has a compiler MCP and is waiting for the compiler MCP to complete. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants