Provide static .patch links for merge request versions
Problem Statement
GitLab currently provides dynamic diff URLs for Merge Requests (e.g., https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18171.diff), but these URLs always return the latest version of the MR diff. This creates issues when teams use these diff URLs in automated pipelines or for applying patches.
Current Issues with Dynamic Diff URLs
-
Lack of Version Consistency: Teams cannot reliably reference a specific version of a patch, making it impossible to ensure that the exact reviewed and tested changes are being applied.
-
Missing Functionality Gap: While GitLab's UI already supports version-specific diff viewing via
diff_idparameters (e.g.,https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18171/diffs?diff_id=24129347), this functionality is not available for downloadable diff files.
Real-World Impact
Communities like Drupal extensively use GitLab diff URLs in their patch management workflows. Without static patch versions, they face deployment inconsistencies and inability to pin specific patch versions for testing and production.
Proposed Solution
Extend the existing diff file generation functionality to accept diff_id query parameters, enabling static patch versions:
https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18171.diff?diff_id=24129347
This approach leverages GitLab's existing diff versioning infrastructure and provides consistency with existing UI patterns while maintaining backward compatibility with current dynamic URLs.
Implementation Approach
The implementation should modify the diff file generation endpoint to:
-
Accept
diff_idparameter: Check for the presence ofdiff_idin query parameters -
Retrieve specific diff version: When
diff_idis provided, fetch the specific diff version instead of the latest -
Maintain backward compatibility: Continue returning latest diff when no
diff_idis specified -
Error handling: Return appropriate errors for invalid or non-existent
diff_idvalues
Possible Implementation
The code right now in Projects::MergeRequestsController#show_merge_request is:
send_git_patch @project.repository, @merge_request.diff_refs
So it can be something like (disclaimer: this isn't tested and only to illustrate the idea):
send_git_patch @project.repository, @merge_request.merge_request_diffs.find_by(id: params[:diff_id])&.diff_refs