Skip to content

SOP: GitLab Merge Request - Developer Role

Purpose

This guide provides a step-by-step workflow for creating and managing merge requests in GitLab. It is designed for developers of all experience levels, from those new to Git/GitLab to seasoned contributors.

Quick Reference Workflow

Issue > Branching > Merging

  1. Create Issue
  2. Discuss Issue in comments and summarise off-line discussions
  3. Assign Issue to Assignee (Implementer)
  4. Create MR from Issue (create branch + draft MR)
  5. Prepare to make changes (locally or Web IDE)
  6. Make changes (commit frequently)
  7. Push to branch
  8. Monitor CI (fix failures, push again)
  9. Prepare MR (description, verify settings)
  10. Remove Draft status
  11. Request review (assign reviewer/assignee)
  12. Engage with review comments
  13. Make changes > Push > Request re-review
  14. Reviewer(s) approve
  15. Maintainer merges
  16. Celebrate the merge!

Full Workflow

This section describes the workflow for Developers who make changes to the content of the project in GitLab. The workflow used has a larger number of steps. The main points in the workflow are:

  • Create an Issue and discuss
  • Assign person to implement solution
  • Create Merge Request + Branch from the issue
  • Work
  • Initiate Merge Request review
  • Celebrate merge of the branch into development

Step 1: Create an Issue

What: Document the bug, feature, or task before making any changes.

Why: Creating an issue first ensures that every piece of work is documented, visible to everyone, and properly discussed before any changes are made. It helps us track what we’re doing, why we’re doing it, and how we decided on the solution - making it easier for anyone, present and future, to understand the context later. Skipping this step makes it harder to follow the project’s progress and can lead to duplicated or misaligned work.

How:

  1. Navigate to the relevant project in GitLab
  2. Go to Issues > New Issue
  3. Select an appropriate template from the drop down menu under the word 'Description'
  4. We have 4 Issue templates and one merge request template
    • Bug Report Schema: Used to describe a problem with the metadata schema
    • Bug Report Service: Used to describe a problem with a service or other piece of software
    • EPIC Issue: Used to describe large multitask issues
    • Feature Request: Used to describe a new feature
  5. Templates for issues and merge requests are maintained at NFDI4Immuno / Utilities / project-templates.
  6. Fill in:
  7. Title: Clear, concise and action oriented description -- is required
    • Think of the title as a headline - it enables others to understand what the specific task is about
    • See below for examples
  8. Description: Detailed explanation of what needs to be done and why. Use the template as a guide and feel free to add additional information as needed for greater clarity
    • The Issue description is important as is the seed for the following discussion and ultimately resolution
    • Write the description as explaining the issue to someone unfamiliar with the bug or feature
  9. Labels: Add relevant labels
  10. Assignee: Leave empty or assign to yourself (only one assignee per issue in free tier GitLab)
  11. Click Create Issue

Examples of title forms to avoid and to strive for:

Vague titles (Avoid) Descriptive & Action-Oriented (Preferred)
Error on page 404 Error when clicking 'Submit' on Metadata form
Layout broken Search bar overlaps navigation menu on mobile view
Add export Add 'Export to JSON' button to Schema Viewer
Update README Update installation instructions for macOS users in README
Clean up code Refactor authentication logic to use environment variables

Tips:

  • Write issues as if explaining to someone unfamiliar with the context
  • Reference related issues if applicable
  • Add screenshots or examples when helpful
  • Include acceptance criteria: "This is done when..." if applicable

Avoid:

  • Skipping issue creation - even for "quick fixes"
  • Vague titles like "Fix bug" or "Update code"

Step 2: Discuss the Issue

What: Engage with others to clarify requirements and approach.

Why: Discussing the issue upfront helps us align on the goal, avoid misunderstandings, and agree on the best way to solve the problem. It gives everyone a chance to ask questions, suggest alternatives, and catch potential issues early - before any changes are made. This saves time later and ensures we’re all on the same page, especially when multiple people might be involved. Decisions and reasoning for a particular suggestion is documented.

How:

  1. Team members comment on the issue
  2. Discuss:
  3. Implementation approach
  4. Potential challenges
  5. Scope and boundaries
  6. Testing requirements
  7. Reach consensus before starting development

Tips:

  • Use @<name> to notify specific people
  • Ask questions early rather than making assumptions
  • Document decisions in the issue comments for future reference

Step 3: Assign Issue to Assignee

What: Identify and assign the person who can implement the changes.

Why: Assigning an issue to a person makes it clear who is responsible for coordinating the implementation of the changes.

How:

  1. Open the issue in GitLab
  2. In the right-hand sidebar, click Edit next to "Assignee"
  3. Select the person who will implement the changes - the assignee is automatically notified

Tips:

  • Only one person can be assigned per issue (due to limitations in GitLab Free tier)
  • If the work is complex or spans multiple areas additional people can be included by mentioning them in a comment

Avoid:

  • Using assignment as a mean of notifying people - use @<name> a comment instead

Step 4: Create Merge Request from Issue

What: Create a feature branch and draft merge requests directly from the issue.

Why:

  • Creating the merge request directly from the issue links the work to the original discussion, keeping everything in one place. It automatically creates a dedicated feature branch, so there is no development work on stable branches like development or main.
  • Setting a 'Draft' status signals that the work is still in progress - this prevents premature reviews and keeps the workflow clean and intentional.
  • Changing the label of the issue or task makes it easy to exclude or include these in searches.

How:

  1. Open the issue you're working on
  2. Click the Create merge request button near the top right
  3. This automatically creates:
  4. A new branch named {issue-number}-{issue-title} (e.g., 42-add-user-authentication)
  5. A draft merge request linked to the issue
  6. Sets the source branch (your new branch) and target branch
  7. IMPORTANT: In the merge request creation page, verify:
  8. Target branch is set to development (NOT main)
  9. The merge request is marked as Draft
  10. Click Create merge request at the bottom
  11. Change the label of issue or task to status::in-process
  12. Go to the task or issue handled by the merge request
  13. Go to ‘Labels’ in the side bar, click ‘Edit’, unselect status::to-do and select status::in-process

Tips:

  • Always branch from development unless you have a specific reason not to
  • The auto-generated branch name keeps naming consistent
  • Draft status prevents accidental early reviews

Step 5: Prepare to Make Changes

What: Get the code locally or prepare to use GitLab's Web IDE.

Why: This step ensures that work is done on the right branch and has the latest state. This prevents mistakes like accidentally making changes on the wrong branch or missing recent updates. Starting from the correct branch (always development) keeps work aligned with the current state of the project and limits merge conflicts later.

Option A - For developers with Git access (Command Line or IDE):

Clone the project repository if it does not exist locally:

# Clone the repository (only needed once)
git clone <repository-url>
cd <project-directory>

Fetch the new branch from the server and check it out for work:

# Fetch the latest changes
git fetch origin

# Switch to your new branch
git checkout {issue-number}-{issue-title}

Option B - For developers using GitLab Web IDE:

  1. Open the merge request you created
  2. Click Code > Open in Web IDE
  3. The Web IDE opens with your branch already selected

Tips:

  • Verify you're on the correct branch before making changes
  • Keep your local development branch updated regularly

Step 6: Make Changes

What: Implement the changes discussed in the issue.

Why: Breaking work into small, focused changes makes it easier to review, test, and understand. Commit messages help the reviewer to understand the intent. See Git Commit Messages for the use of prefixes and commit message structure.

How:

  1. Make changes to the necessary files
  2. Run unit tests to test changes (if possible)
  3. Document functions and complex steps
  4. Add unit tests for new functions and other additions
  5. Commit work regularly using the structure and prefixes described in Git Commit Messages

Good Practices for Commits:

  • One logical change = One commit
  • Small, focused commits are better than large, monolithic ones
  • Example progression:
    • Commit 1: "feat: Add user model"
    • Commit 2: "feat: Add user validation logic"
    • Commit 3: "feat: Add user authentication endpoint"
    • Commit 4: "test: Add user authentication tests"

Commit Commands (for CLI/IDE users):

# Stage your changes`
git add <file1> <file2>

# Or stage all changes`
git add .

# Commit with a message
git commit -m "feat: Add user model with email and password fields"

Pre-commit hooks:

Pre-commit hooks are automated checks done before a commit is created. These checks enforce coding standards and help identifying issues before the code is integrated in the code base (CI).

Once you run the git commit -m ... command, the pre-commit framework in our repository will do the following:

  • Format the code
  • Lint the code
  • Check types
  • Ensure dependencies are up to date

If any hook fails, the commit will be blocked until all identified fixes are made. This will help you integrate clean and validated code. As a team, it will help building a unified code base with consistent quality.

Tips:

  • Commit frequently - it's easier to review smaller chunks
  • A commit is stored only locally at first. To make it visible on GitLab, see next step.
  • Commits will be squashed on merge, meaning all commits on the feature branch will be merged into one when merging into development
  • Use pre-commit hooks to help you commit clean code, e.g. read well error and warning messages.

Avoid:

  • Committing commented-out code or debugging statements
  • Committing configuration files with personal settings, e.g. usernames, secrets and passwords
  • Committing unrelated changes in the same commit
  • Ignoring the suggested corrections made by pre-commit hooks. You won't be able to finalize your commit until these are solved
  • Disabling pre-commit hooks

Step 7: Push Changes

What: Add commits to GitLab so they're visible in the merge request.

Why: Pushing changes to the remote branch on GitLab makes them visible to others and triggers the CI pipeline automatically. Pushing regularly also means that the work is safely backed up and not lost if something goes wrong locally.

How: Command Line:

git push origin {issue-number}-{issue-title}

VS Code/IDE:

  • Click the Push button in your Git interface

GitLab Web IDE:

  • Click Commit > Write commit message > Commit & Push

Tips:

  • Push regularly, not just when finished - this helps preventing loss of changes
  • Each push automatically triggers a CI pipeline, which runs unit tests
  • Pushing early lets others see your progress

Step 8: Monitor CI Pipeline

What: Automated tests and checks run on every push. Ensure they pass.

Why: The CI pipeline runs automated tests and checks to ensure the changes don’t break existing functionality.

How:

  1. Go to the merge request in GitLab
  2. Scroll down to see the Pipeline status
  3. Click on the pipeline to see individual job results
  4. If any jobs fail:
  5. Click on the failed job to see the error log
  6. Fix the issues locally
  7. Commit and push the fixes
  8. CI will run again automatically
  9. For unit tests
  10. Go to Test summary, click on downward arrow (show details)
  11. Inspect failed tests individually

What Must Pass:

  • All unit tests
  • Documentation building jobs, if present
  • Some jobs (like external publishing) may be allowed to fail if due to external factors

Tips:

  • Don't move to the next step until CI has passed
  • Read error messages carefully - they indicate exactly what's wrong, even when it is hard to read
  • If stuck, ask a maintainer for help

Avoid:

  • Ignoring CI failures hoping they'll "work in production"
  • Asking for review while tests are failing

Step 9: Prepare the Merge Request

What: Write a clear description and verify settings before requesting review.

Why: A well-written merge request description gives reviewers the context they need to quickly and thoroughly understand the changes. It explains what changed and why. This also ensures the work is properly documented for future reference, even after the MR is merged.

How:

  1. Click Edit on the merge request
  2. Update the Description with:
  3. What changed: Summary of the implementation
  4. Why: Reference the issue and explain your approach
  5. How to test: Steps reviewers can follow to verify
  6. Screenshots: If UI changes, add before/after images
  7. Verify settings:
  8. Target branch is development (check below MR header)
  9. "Delete source branch after merge" is checked (default)
  10. CI pipeline passed
  11. The original issue is linked (should show "Closes #XX")
  12. Apply applicable labels

Example MR Descriptions

A simple solution:

## Merge Request Checklist

Before merging, ensure you have completed the following:

- [x] Code/Schema is thoroughly tested locally.
- [x] Documentation (internal/external) is updated, if necessary.
- [x] All new code/definitions are covered by tests.
- [x] This MR targets the correct branch (e.g., `development`, or a specific feature branch).

## Summary

Added a new `email` slot to the Person class to support contact information requirements. This change enables downstream applications to store and validate email addresses for person records.

## Implementation Details

- Added `email` slot to `Person` class in `schema/core.yaml`
- Set slot as optional with pattern validation for email format
- Added example usage in inline documentation
- Updated `examples/person_example.yaml` to demonstrate email field

### Type of Change (Select one or more)

- [ ] Feature / Enhancement
- [x] Bug Fix
- [x] Metadata/Schema Change
- [ ] Refactoring / Technical Debt
- [ ] Documentation Update

## Related Issues

Closes #123

MR for a more complex problem:

## Merge Request Checklist

Before merging, ensure you have completed the following:

- [x] Code/Schema is thoroughly tested locally.
- [x] Documentation (internal/external) is updated, if necessary.
- [x] All new code/definitions are covered by tests.
- [x] This MR targets the correct branch (e.g., `development`, or a specific feature branch).

## Summary

Implemented batch processing endpoint for data ingestion with validation, deduplication, and error handling. This replaces the single-item POST endpoint which caused performance issues when processing large datasets, reducing ingestion time from ~30 minutes to ~2 minutes for 10k records.

## Implementation Details

- Created new `/api/v1/batch/ingest` POST endpoint in `routers/batch.py`
- Implemented chunked processing (configurable batch size, default 100 items)
- Added async processing with progress tracking via job ID
- Added comprehensive error handling for database connection failures and timeouts
- Added integration tests covering success cases, partial failures, and edge cases
- Added unit tests for deduplication logic and validation rules
- Updated `docs/api-reference.md` with batch endpoint usage examples
- Added monitoring metrics for batch size, processing time, and failure rates

### Type of Change (Select one or more)

- [x] Feature / Enhancement
- [ ] Bug Fix
- [ ] Metadata/Schema Change
- [ ] Refactoring / Technical Debt
- [x] Documentation Update

## Related Issues

Closes #123, #456, #789

The merge request template can be found under NFDI4Immuno / Utilities / project-templates / merge_request_templates.

Tips:

  • A good description helps reviewers understand context quickly
  • Include anything unusual or tricky about the implementation
  • If there are deviations from the original issue discussion, explain why

Step 10: Remove Draft Status and Change Label of Issue or Task

What: Signal that the merge request is ready for review.

Why: Removing the draft status signals that your work is complete, tested, and ready for formal review. Changing the label of the issue or task makes it easy to exclude these from searches.

How:

  1. At the top of the merge request, click Mark as ready
  2. The "Draft:" prefix is removed from the title
  3. The MR is now visible to reviewers as ready for review
  4. Change the label of issue or task to status::in-review
  5. Go to the task or issue handled by the merge request
  6. Go to ‘Labels’ in the side bar, click ‘Edit’, unselect status::in-process and select status::in-review

Tips:

  • A good description helps reviewers understand context quickly

Include anything unusual or tricky about the implementation

If there are deviations from the original issue discussion, explain why

  • Only remove Draft when:
  • All changes are complete
  • CI pipeline has passed
  • MR description is complete
  • The Draft status can be reenabled if larger changes are needed - or the MR cannot be completed before other changes have been merged

Step 11: Request Review

What: Assign reviewers to examine the changes. Because of the limitations in the GitLab Free tier, only one reviewer can be assigned. If an additional reviewer is needed add this as assignee.

Why: Review brings in fresh eyes to check the changes, legibility, and documentation and is a key part of the quality process.

How:

For single reviewer:

  1. In the merge request, find the Reviewers section
  2. Click Edit and select one reviewer
  3. GitLab notifies them automatically

For two reviewers:

  1. Assign one person as Reviewer
  2. Assign the other as Assignee
  3. Add a comment: "@reviewer1 @reviewer2 - Ready for review, please coordinate approval"
  4. Both reviewers work together and use the Approve button to signal completion

Tips:

  • Choose reviewers based on:
  • Expertise in the affected area
  • Complexity (simple changes: 1 reviewer, complex: 2 reviewers)

Step 12: Engage with Review Comments

What: Respond to feedback from reviewers.

Why: Different views and opinions are opportunities to improve the code, to clarify decisions, and to learn.

How:

  1. GitLab notifies you when reviewers leave comments
  2. For each comment, it is possible to:
  3. Reply with explanations or questions
  4. Make the requested change > commit > push
  5. Start a discussion if there is disagreement or questions
  6. After addressing a comment:
  7. Click Resolve discussion (or ask the reviewer to resolve it)
  8. If you made changes, mention which commit addressed it

Types of Comments:

  • Suggestions: Reviewer may propose specific code changes you can apply directly
  • Questions: Answer clearly; they help improve understanding
  • Required changes: Must be addressed before approval
  • Optional/Nit-picks: Nice to have but not blocking

Tips:

  • Don't take feedback personally - it's about the code, not you
  • Ask for clarification if you don't understand a comment
  • Explain your reasoning if you disagree with a suggestion

Avoid:

  • Resolve discussions without addressing them
  • Ignore comments hoping they'll be forgotten

Step 13: Request Re-Review

What: After making changes based on feedback, ask reviewers to check again.

How:

  1. After pushing your changes, click the circle-arrow icon ⟲ by the reviewers name to return the merge request to the reviewer.
  2. Alternatively, add a comment mentioning the reviewers:
  3. "@reviewer @assignee - I've addressed your comments in commits. Ready for another look!"

Tips:

  • Summarize what changed since the last review
  • Point to specific commits that addressed feedback
  • If changes were significant, explain your approach

Step 14: Approval

What: Reviewers formally approve the merge request.

Why: An approval from a reviewer means they’ve reviewed and accepted the changes.

How:

  1. Once reviewers are satisfied, they click the Approve button
  2. The approval appears on the merge request
  3. This signals to maintainers that the MR is ready to merge

For multiple reviewers (workaround):

  • Both the assigned reviewer and assignee should agree to approve
  • This gives maintainers clear signal that both have signed off

Tips:

  • Approval means "I've reviewed this and it meets our quality standards"
  • It doesn't mean the code is perfect - just that it's good enough to merge

Step 15: Maintainer Merges

What: A maintainer performs the final merge into development.

Why: Only maintainers can merge changes into development to protect the stability of the codebase. They ensure that all checks are passed, approvals are in place, and no unresolved issues remain.

Who: Only users with a Maintainer role can merge.

How (for maintainers):

  1. Verify:
  2. MR is approved
  3. CI pipeline is green
  4. No unresolved discussions
  5. Target branch is development
  6. Click Merge
  7. Confirm CI passes all jobs
  8. Confirm the merge
  9. The MR is merged, and:
  10. The branch is automatically deleted
  11. The linked issue is automatically closed
  12. Changes are now in development

Step 16: Celebrate

What: Changes are now part of the project! Time to party!

Why: Because we can and it is a good reason.

Good Practices Summary

Do

  • Create issues before writing code
  • Branch from development (unless exceptional circumstances)
  • Commit frequently with clear messages
  • Push regularly to trigger CI
  • Respond to review comments promptly and professionally
  • Test changes thoroughly

Do not

  • Skip issue creation for "quick fixes"
  • Push directly to development or main
  • Request review while CI is failing
  • Ignore review comments
  • Take feedback personally
  • Resolve discussions without addressing them

Additional Resources