feat: Handle `glab mr checkout` failure when there are non fast-forwarding conflicts

Description

  • feat: Handle glab mr checkout failure when there are non fast-forwarding conflicts

When in interactive mode, checkout will ask whether to discard local changes

Optionally --force flag can be used to discard changes by default

No change is made if there are uncommited changes in the work tree.

Resolves #1379 (closed)

How has this been tested?

$ glab repo clone gitlab-org/cli glab

Cloning into 'glab'...
remote: Enumerating objects: 58179, done.
remote: Counting objects: 100% (1268/1268), done.
remote: Compressing objects: 100% (174/174), done.
remote: Total 58179 (delta 1183), reused 1093 (delta 1093), pack-reused 56911 (from 1)
Receiving objects: 100% (58179/58179), 31.01 MiB | 13.38 MiB/s, done.
Resolving deltas: 100% (39787/39787), done.

$ cd glab

$ glab mr checkout 3345

remote: Enumerating objects: 13, done.
remote: Counting objects: 100% (13/13), done.
remote: Compressing objects: 100% (10/10), done.
remote: Total 13 (delta 3), reused 11 (delta 3), pack-reused 0 (from 0)
Unpacking objects: 100% (13/13), 13.70 KiB | 1.25 MiB/s, done.
From gitlab.com:gitlab-org/cli
 * [new branch]        brodock/mr-checkout-non-fastfoward-handling -> brodock/mr-checkout-non-fastfoward-handling
Switched to branch 'brodock/mr-checkout-non-fastfoward-handling'

$ git commit --amend --no-edit --date=now

[brodock/mr-checkout-non-fastfoward-handling be242e25] feat: Handle `glab mr checkout` failure when there are non fast-forwarding conflicts
 Date: Tue Jun 2 12:07:09 2026 +0200
 4 files changed, 577 insertions(+), 2 deletions(-)

# Use the following command to retrieve the amended commit hash and compare after any of the reset operations performed by the checkout command
$ git rev-parse HEAD

# This tests the default behavior from before the change introduced by this MR
$ glab mr checkout 3345

fatal: refusing to fetch into branch 'refs/heads/brodock/mr-checkout-non-fastfoward-handling' checked out at '/private/tmp/glab'
From gitlab.com:gitlab-org/cli
 * branch              brodock/mr-checkout-non-fastfoward-handling -> FETCH_HEAD
Already on 'brodock/mr-checkout-non-fastfoward-handling'

$ cd /path/to/project

$ make build

$ cd /tmp/glab

# This tests the behavior introduced by this MR (a prompt is introduced when using it in a TTY interactive mode)
$ /path/to/project/bin/glab mr checkout 3345

fatal: refusing to fetch into branch 'refs/heads/brodock/mr-checkout-non-fastfoward-handling' checked out at '/private/tmp/glab'
From gitlab.com:gitlab-org/cli
 * branch              brodock/mr-checkout-non-fastfoward-handling -> FETCH_HEAD
┃ Local branch "brodock/mr-checkout-non-fastfoward-handling" has diverged from remote. Reset to remote (discards local commits on this branch)?

┃                                                                 Yes!     No.

# Selected yes, compare the commit with `git rev-parse HEAD`, it should now match the one in `FETCH_HEAD`. 

$ git commit --amend --no-edit --date=now

[brodock/mr-checkout-non-fastfoward-handling 7188dfe4] feat: Handle `glab mr checkout` failure when there are non fast-forwarding conflicts
 Date: Tue Jun 2 12:35:13 2026 +0200
 4 files changed, 577 insertions(+), 2 deletions(-)

# This should be a different hash again
$ git rev-parse HEAD 

$ /path/to/project/bin/glab mr checkout 3345 --force

fatal: refusing to fetch into branch 'refs/heads/brodock/mr-checkout-non-fastfoward-handling' checked out at '/private/tmp/glab'
From gitlab.com:gitlab-org/cli
 * branch              brodock/mr-checkout-non-fastfoward-handling -> FETCH_HEAD
HEAD is now at a6d14c15 feat: Handle `glab mr checkout` failure when there are non fast-forwarding conflicts
Already on 'brodock/mr-checkout-non-fastfoward-handling'

# This should match 'FETCH_HEAD' again
$ git rev-parse HEAD 

Screenshots (if appropriate):

Edited by Gabriel Mazzetto

Merge request reports

Loading