Skip to content

feat: Add support for merge request from fork#546

Open
Clement-Hue wants to merge 4 commits intoharrisoncramer:developfrom
Clement-Hue:feature-mr-from-fork
Open

feat: Add support for merge request from fork#546
Clement-Hue wants to merge 4 commits intoharrisoncramer:developfrom
Clement-Hue:feature-mr-from-fork

Conversation

@Clement-Hue
Copy link
Copy Markdown

@Clement-Hue Clement-Hue commented Apr 22, 2026

Summary

Add support for choosing and reviewing merge requests originating from forked projects. Previously, the plugin assumed the MR source branch always existed in the local repository, which broke fork-based workflows. This MR makes fork MRs discoverable, fetchable, and reviewable via choose_merge_request.

Problem

When a user selects a merge request that originates from a fork, the plugin fails because:

  1. The MR middleware always filters by SourceBranch, which doesn't exist locally for fork MRs.
  2. The pipeline handler cannot resolve the latest commit because the fork branch isn't on the remote.
  3. Diffview can't display diffs because the fork commits aren't fetched.
  4. The Lua choose_merge_request action tries to switch to a branch that doesn't exist locally.

Changes

  • cmd/app/git/git.go — Add FetchMRHead (fetches refs/merge-requests/<iid>/head) and GetMRHeadCommit (resolves the fetched ref to a SHA) to the GitManager interface and Git implementation; add FetchMrHead helper that skips the fetch when no MR IID is set.
  • cmd/app/git/git_test.go — Add unit tests for FetchMrHead (skip/fetch/error paths) and integration tests for GetMRHeadCommit (success and non-existent ref) using a temporary git repo.
  • cmd/app/middleware.go — When ChosenMrIID is set, filter MRs by IID only (skip SourceBranch) so fork MRs are found.
  • cmd/app/middleware_test.go — Add tests verifying the middleware uses IIDs vs SourceBranch depending on ChosenMrIID.
  • cmd/app/pipeline.go — Fall back to GetMRHeadCommit when the branch doesn't exist on the remote and an MR IID is set.
  • cmd/app/test_helpers.go — Implement GetMRHeadCommit and FetchMRHead on the FakeGitManager to satisfy the updated interface.
  • cmd/main.go — Call FetchMrHead at startup so fork MR commits are available locally for diffview.
  • lua/gitlab/actions/merge_requests.lua — Detect fork MRs (source_project_id ≠ target_project_id) and skip the branch switch; extract activate_mr, select_fork_mr, and select_local_mr helpers for clarity.
  • lua/gitlab/hunks.lua — pass head_sha to parse_hunks_and_diff. The function now accepts and forwards head_sha to the git diff command, ensuring the diff is computed between the correct base and head SHAs of
    the merge request rather than comparing against the working tree. This make diff working with the new strategy

Suggestion

Probably it will be a good idea to use this approach also for local merge request and avoid the fetching of branch and checkout to it. This approach has several benefits

  • No branch switch needed — your working tree stays untouched
  • No clean tree requirement — you can have uncommitted changes
  • Faster — no git switch, no buffer reloads
  • Review any MR from any branch — you don't need the branch locally at all

When a user selects a merge request from choose_merge_request that
originates from a fork, two things previously failed:

1. The Go middleware always filtered by SourceBranch alongside the
   chosen MR IID. The GitLab API source_branch filter does not match
   fork MR branches (they belong to a different project), so the
   query returned zero results and the error 'No MRs Found' was shown.
   Fix: when ChosenMrIID is set, filter only by IID (sufficient to
   uniquely identify the MR) and skip the SourceBranch filter.

2. The Lua code attempted to git checkout the source branch, which
   does not exist locally for fork MRs. Fix: detect fork MRs by
   comparing source_project_id vs target_project_id and skip the
   branch switch, proceeding directly to server restart.
For fork MRs, the head_sha from diff_refs points to commits that
live in the fork repository and are not present locally. Diffview
fails with 'Failed to update files in a diff view' because it cannot
resolve these SHAs.

Fix: at server startup, when ChosenMrIID is set, fetch the MR head
ref from GitLab (refs/merge-requests/:iid/head) and store it as a
local ref. This downloads the fork's commits into the local object
store, allowing diffview to resolve base_sha..head_sha.
The pipeline handler uses GetLatestCommitOnRemote which runs
'git log origin/<branch>' to find the latest commit. For fork MRs,
the source branch does not exist on the origin remote, causing a
failure.

Fix: when GetLatestCommitOnRemote fails and ChosenMrIID is set, fall
back to GetMRHeadCommit which resolves the commit from the locally
fetched refs/merge-requests/:iid/head ref.
@Clement-Hue Clement-Hue changed the title Add support for merge request from fork feat: Add support for merge request from fork Apr 23, 2026
The function now accepts and forwards head_sha to the git diff command,
ensuring the diff is computed between the correct base and head SHAs of
the merge request rather than comparing against the working tree.
@jakubbortlik
Copy link
Copy Markdown
Collaborator

Hi @Clement-Hue, I'm glad to see more contributors to the plugin. Just a note regarding your suggestion to use your new approach also for local merge requests. The benefit of using the local files for a review are that you can use all the benefits of LSP, code navigation, linting, etc. As for the perceived benefits of your approach, you can achieve at least some of them by using git worktrees. With worktrees you can have several versions of the same repo checked out at the same time and you don't worry about switching branches, stashing changes, and a clean tree. I find this a superior workflow for multiple feature branches regardless of merge requests.

The only reason I'm missing the possibility to review a MR without a local branch is for a closed MR where the feature branch has already been deleted.

I think it would be great if gitlab.nvim could support both these workflows.

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.

3 participants