---
id: git-gitlab
title: "GitLab"
shortTitle: "GitLab"
track: git
trackTitle: "Git & VCS Hosting"
order: 7
level: important
status: published
estimatedMinutes: 30
prerequisites:
  - git-hooks
next: git-monorepo
reviewedAgainst: 2026-10-12
sources:
  - title: "Merge requests"
    url: https://docs.gitlab.com/user/project/merge_requests/
  - title: "Protected branches"
    url: https://docs.gitlab.com/user/project/repository/branches/protected/
---

# GitLab

GitLab gom Git remote, merge request và CI vào một chỗ. Bài này chỉ nói phần hosting; file `.gitlab-ci.yml` nằm ở bài GitLab CI.

## Để làm gì

Sau bài này, bạn đọc được một merge request, biết nhánh nào đang được bảo vệ, và quy đổi được thuật ngữ GitLab sang GitHub khi tài liệu nội bộ dùng lẫn lộn.

## Gồm những gì

- Project, merge request, protected branch, role.
- Merge request chỉ khác pull request ở tên gọi; bản chất vẫn là review trước khi vào `main`.
- Bản self-managed và GitLab.com dùng cùng các khái niệm này.

Bài này không nói về Runner, job hay `script:`; phần đó thuộc bài GitLab CI.

## Dùng khi nào

Bạn sẽ cần bài này khi team đang dùng GitLab, hoặc khi khách hàng đưa cho bạn một remote `gitlab.com`. Thao tác Git vẫn là `git push` và `git pull`. Thứ khác đi là quyền trên server và cách mở request để merge.

Đừng duy trì hai quy trình khác nhau chỉ vì tên gọi khác nhau. Protected branch trên GitLab và ruleset trên GitHub phục vụ cùng một mục đích: không ai push thẳng vào `main`.

## Kiến thức cốt lõi

Mỗi project GitLab chứa một repo Git. Merge request (MR) là đề nghị merge nhánh nguồn vào nhánh đích. Reviewer comment ngay trên diff, và sau khi merge thì nhánh đích có các commit đó.

Protected branch chặn những người không đủ role. Trên project mới, `main` thường được bảo vệ sẵn: không cho force-push, và muốn merge thì cần quyền Maintainer hoặc một rule đã cấu hình. Hãy xem trang Protected branches của project trước khi giả định ai cũng merge được.

Role xếp theo quyền tăng dần: Guest, Planner, Reporter, Developer, Maintainer, Owner. Developer push được lên nhánh thường, nhưng không sửa được protected branch nếu rule không cho phép.

Issue, wiki và container registry cũng nằm trong GitLab, nhưng bạn không cần chúng để push code.

## Lệnh và code mẫu

Thêm remote không khác gì GitHub:

```bash
git remote add origin git@gitlab.com:group/app.git
git push -u origin main
```

Nếu đã cài CLI chính thức `glab` và chạy `glab auth login`, bạn mở MR được ngay từ terminal:

```bash
glab mr create --target-branch main --title "lab: sua health" --description "Khong doi API"
```

Chưa có `glab` thì mở MR trên web cũng được. Bạn không cần tạo tài khoản chỉ để làm bài này.

## Thực hành

1. Ghi ra giấy hoặc file nháp: remote của team là GitHub hay GitLab, nhánh mặc định tên gì, ai được merge.
2. Nếu đang có project GitLab, mở Settings, Protected branches, rồi ghi lại role nào được push và được merge vào `main`.
3. Nếu chưa có project, đọc bảng dưới và đối chiếu với phần pull request đã học.

| Việc | GitHub | GitLab |
| --- | --- | --- |
| Đề nghị merge | Pull request | Merge request |
| Nhánh bị khóa | Ruleset, branch protection | Protected branch |
| CLI chính thức | `gh` | `glab` |

## Kết quả mong đợi

Bạn giải thích được MR và PR là cùng một cửa review, và protected branch là cấu hình trên server chứ không phải một file trong `.git` trên máy bạn.

## Checklist

- [ ] Nhánh `main` không nhận push thẳng từ Developer nếu team đã bật protected branch.
- [ ] MR mô tả thay đổi gì và kiểm tra bằng cách nào, không chỉ ghi tên nhánh.
- [ ] Tách CI của GitLab (bài sau) khỏi chuyện quyền merge.

## Thẻ ôn

### git-gitlab-protected
kind: distinguish
cue: Có `.gitlab-ci.yml` chưa có nghĩa là `main` đã bị khóa. Protected branch là cấu hình trên server. File CI chỉ nói Runner chạy job nào.

Q: Repo GitLab đã có `.gitlab-ci.yml` và pipeline chạy xanh. Một developer vẫn push thẳng commit vào `main`. File CI có khóa nhánh không, và thứ nào mới chặn push thẳng?

A: File đó chỉ khai job để Runner chạy khi có sự kiện phù hợp. Nó không quyết định ai được ghi vào nhánh nào. Khóa nhánh là protected branch, cấu hình trên server GitLab, không phải một file nằm trong `.git` trên máy bạn. Khi `main` được protect, developer không push thẳng. Thay đổi đi qua merge request, cửa review cùng vai với pull request. Quyền merge và chuyện CI có chạy là hai việc khác nhau.

### git-gitlab-force
kind: trap
cue: Force-push vào `main` bị protected branch từ chối là đúng. Fetch, pull cho khớp history, rồi mở merge request. Đừng xin tắt protection.

Q: `main` trên máy bạn lệch so với server. Bạn force-push và GitLab từ chối vì protected branch. Có nên xin Owner tắt protection một lần để đẩy cho xong không?

A: Đừng. Lệnh bị từ chối vì server đang giữ history của nhánh dùng chung, không phải vì Git hỏng. Tắt protection để force-push sẽ viết đè lịch sử mà người khác và pipeline đang dựa vào. `git fetch` rồi `git pull` để máy bạn khớp `main`, xử lý phần lệch ở local, rồi mở merge request cho thay đổi mới.

## Lỗi thường gặp

**Force-push vào `main` vì máy local bị lệch.** Protected branch từ chối là đúng. Hãy đồng bộ lại history bằng `git fetch` và `git pull`, rồi mở MR. Đừng xin Owner tắt protection chỉ cho một lần push.

**Tưởng có `.gitlab-ci.yml` là nhánh đã được bảo vệ.** File đó chỉ định nghĩa job để Runner chạy. Việc khóa nhánh do protected branch đảm nhận, tách hẳn khỏi CI.

## Nguồn

1. [Merge requests](https://docs.gitlab.com/user/project/merge_requests/) — MR, review, và merge.
2. [Protected branches](https://docs.gitlab.com/user/project/repository/branches/protected/) — ai được push và merge.

## Tiếp theo

[Monorepo](./08-monorepo.md)
