Danh sách bài viết

Bài 6: GitHub — push code, branch, pull request cơ bản

GitHub workflow cho AI Engineer: setup SSH, tạo repo, push code, branch, pull request, GitHub Actions CI cơ bản, PR template, Issue tracking và best practice repo public.

27/05/2026
0 lượt xem
1

Mục Tiêu Bài Học

Sau khi hoàn thành bài này, bạn sẽ:

  • Setup SSH key và xác thực với GitHub
  • Tạo repo và push code theo 3 cách khác nhau
  • Hiểu branch protection rules và cách áp dụng cho portfolio repo
  • Mở PR, self-review diff, chọn merge strategy phù hợp
  • Viết PR template và Issue template để repo trông professional
  • Cấu hình GitHub Actions CI chạy pytest tự động
  • Dùng gh CLI để thao tác nhanh hơn UI

Bài này tiếp nối bài 5 (Git workflow). Phần Git basics (init, add, commit, branch, merge) đã được đề cập ở đó và không lặp lại ở đây.

2

GitHub Là Gì

GitHub là web platform host git repository, thuộc sở hữu của Microsoft từ năm 2018. Đây là nơi phần lớn open-source code được host: PyTorch, Transformers (Hugging Face), scikit-learn, NumPy, FastAPI... đều có repo trên GitHub.

Free tier (2026)

  • Public và private repo không giới hạn số lượng
  • GitHub Actions: 2000 phút/tháng cho private repo (không giới hạn cho public)
  • GitHub Packages: 500 MB storage
  • GitHub Pages: host static site miễn phí
  • Codespaces: 120 core-hours/tháng (free cho cá nhân)

Alternatives

GitLab và Bitbucket là 2 lựa chọn phổ biến nhất. GitLab có self-hosted option và CI/CD mạnh hơn out-of-the-box. Bitbucket tích hợp tốt với Jira. Bài này tập trung vào GitHub vì đây là nơi portfolio AI/ML project thường được đặt và recruiter tra cứu.

3

Setup Tài Khoản Và SSH

Chọn username

Username xuất hiện trong URL repo (github.com/username/repo), trên CV, và trong mọi commit từ GitHub UI. Chọn tên professional và ngắn gọn. Tên dạng nguyenvana hay vanadev ổn; hacker9999 hay codemonkey_lol không phù hợp nếu dùng để xin việc.

SSH key setup

SSH cho phép push/pull mà không cần nhập password mỗi lần. Dùng ed25519 thay vì RSA (ngắn hơn, bảo mật hơn):

# Tạo SSH key mới
ssh-keygen -t ed25519 -C "[email protected]"
# Khi hỏi file location: Enter để dùng default (~/.ssh/id_ed25519)
# Khi hỏi passphrase: khuyến nghị đặt passphrase để bảo mật thêm

# Copy public key
cat ~/.ssh/id_ed25519.pub

Vào GitHub Settings → SSH and GPG keys → New SSH key, paste nội dung public key vào. Title đặt tên máy để dễ quản lý, ví dụ: "MacBook Pro M3".

Verify kết nối:

ssh -T [email protected]
# Output mong muốn:
# Hi username! You've successfully authenticated, but GitHub does not provide shell access.

HTTPS vs SSH

HTTPS yêu cầu Personal Access Token (PAT) thay vì password (GitHub đã tắt password auth từ 2021). SSH không cần token mỗi lần push — phù hợp hơn cho personal machine. Nếu làm trên CI/CD server, HTTPS với token được dùng phổ biến hơn vì dễ rotate.

4

Tạo Repository

Cách 1: GitHub UI

Vào github.com → dấu + → New repository. Điền:

  • Repository name: tên ngắn gọn, lowercase, dùng - thay khoảng trắng. Ví dụ: rag-chatbot, churn-prediction.
  • Visibility: Public nếu đây là portfolio project; Private nếu chứa data nhạy cảm hoặc đang prototype.
  • Initialize with README: tick nếu tạo repo mới. Không tick nếu đã có local repo muốn push lên.
  • .gitignore template: chọn Python để có template cơ bản (sẽ cần bổ sung thêm cho AI project — xem bài 5).
  • License: MIT phổ biến nhất cho open source cá nhân. Apache 2.0 nếu muốn patent protection rõ ràng hơn.

Cách 2: gh CLI

# Cài gh (macOS)
brew install gh

# Đăng nhập (chọn SSH protocol khi được hỏi)
gh auth login

# Tạo repo public với README
gh repo create rag-chatbot --public --add-readme

# Tạo repo private, clone về luôn
gh repo create churn-prediction --private --clone

Cách 3: Từ local repo đã có

cd existing-project

# Khởi tạo git nếu chưa có
git init -b main

# Tạo remote repo và push cùng lúc
gh repo create my-ai-project --public --source=. --push

# Hoặc tạo remote repo trước rồi add remote thủ công
git remote add origin [email protected]:username/my-ai-project.git
git branch -M main
git push -u origin main
5

Push Code Lần Đầu

Push lần đầu (set upstream)

# Thêm remote nếu chưa có
git remote add origin [email protected]:username/repo.git

# Đặt tên branch chính là main (Git 2.28+)
git branch -M main

# Push và set upstream tracking
git push -u origin main
# Flag -u = --set-upstream, chỉ cần làm 1 lần cho mỗi branch mới

Push các lần tiếp theo

git add src/data_loader.py
git commit -m "feat(data): add preprocessing pipeline for text data"
git push
# Không cần -u nữa vì đã set upstream

Push branch mới lên remote

git checkout -b feature/add-rag
# ... develop, commit ...
git push -u origin feature/add-rag
# GitHub sẽ hiển thị banner "Compare & pull request" ngay sau push

Kiểm tra remote

# Xem danh sách remote
git remote -v
# origin  [email protected]:username/repo.git (fetch)
# origin  [email protected]:username/repo.git (push)

# Xem tracking info của branch hiện tại
git branch -vv
# * main  abc1234 [origin/main] feat: initial project structure
6

Branch Trên GitHub

Default branch

Tên mặc định là main (GitHub đổi từ master sang main từ tháng 10/2020). Nếu repo cũ vẫn dùng master, đổi ở Settings → Branches → Default branch.

Branch protection rules

Với portfolio repo, bật branch protection cho main để tránh push trực tiếp lên main và bắt buộc qua PR. Settings → Branches → Add branch protection rule, nhập main:

Rule Tác dụng Nên bật?
Require a pull request before merging Chặn push trực tiếp lên main Có — cho portfolio repo
Require status checks to pass CI phải pass trước khi merge Có — nếu đã có CI
Require linear history Không cho phép merge commit — bắt buộc squash hoặc rebase Tuỳ preference
Include administrators Rule áp dụng cả cho owner Có — tránh bypass vô tình

Tạo branch và push

git checkout -b feature/vector-store-integration
# ... develop ...
git add src/retrieval/vector_store.py tests/test_vector_store.py
git commit -m "feat(retrieval): integrate ChromaDB vector store"
git push -u origin feature/vector-store-integration

Sau khi push, GitHub hiển thị banner vàng "Compare & pull request" trên trang repo. Click vào đó để mở PR.

Xem branch trên GitHub

Tab branches (cạnh dropdown branch selector, hiện số branch đang có) liệt kê tất cả branch kèm trạng thái: ahead/behind main bao nhiêu commit, ngày commit cuối, author.

7

Pull Request — Quy Trình Chi Tiết

Pull Request (PR) là request merge code từ branch này vào branch khác, kèm theo UI để review diff, comment, chạy CI, và track history thay đổi. Dù làm solo, mở PR thay vì merge trực tiếp có giá trị thực tế.

Quy trình từng bước

Bước 1 — Push branch:

git push -u origin feature/add-rag

Bước 2 — Mở PR trên GitHub:
Click "Compare & pull request" từ banner, hoặc vào tab Pull requests → New pull request → chọn base branch (main) và compare branch (feature/add-rag).

Bước 3 — Điền thông tin PR:

  • Title: ngắn gọn theo Conventional Commits format. Ví dụ: feat: add RAG retrieval module with ChromaDB.
  • Description: dùng PR template (xem mục 8). Mô tả what + why, cách test, link issue liên quan.
  • Reviewers: với solo project, assign chính mình để self-review.
  • Labels: enhancement, feature, bug... Tạo label custom nếu cần: ml, data.
  • Linked issues:Closes #12 trong description — issue #12 sẽ tự đóng khi PR được merge.

Bước 4 — CI chạy (nếu đã cấu hình):
Tab Checks trong PR hiển thị status của tất cả workflow. CI fail → nên fix trước khi merge vào main.

Bước 5 — Review diff:
Tab Files changed hiển thị toàn bộ diff. Scroll qua từng file để phát hiện: debug print bỏ quên, hardcoded path, logic sai, thiếu error handling. Có thể add comment trực tiếp vào dòng code.

Bước 6 — Merge:
Chọn merge strategy phù hợp:

Strategy Kết quả Khi nào dùng
Create a merge commit Giữ nguyên history graph, tạo merge commit Muốn thấy rõ khi nào merge nhánh
Squash and merge Gom tất cả commit thành 1 trên main Branch có nhiều WIP commit muốn clean up
Rebase and merge Linear history, không có merge commit Muốn main log thẳng tắp

Với portfolio project, Squash and merge thường là lựa chọn tốt nhất: main history sạch, mỗi entry = 1 feature hoàn chỉnh.

Bước 7 — Xóa branch sau merge:
GitHub hiện nút "Delete branch" ngay sau khi merge. Click vào để dọn sạch remote branch. Local branch xóa bằng:

git checkout main
git pull
git branch -d feature/add-rag
8

PR Template

Tạo file .github/PULL_REQUEST_TEMPLATE.md trong repo. GitHub tự động điền nội dung file này vào description mỗi khi tạo PR mới.

## Summary
<!-- Mô tả ngắn gọn thay đổi trong PR này -->

## Changes
-

## Tests
- [ ] Unit tests pass (`pytest tests/`)
- [ ] Manual test

## Screenshots / Demo
<!-- Nếu có thay đổi UI hoặc output -->

## Notes for reviewer
<!-- Chỉ ra phần cần review kỹ, decision đã đưa ra, trade-off -->

Closes #

Commit file này vào repo:

mkdir -p .github
# tạo nội dung file ở trên
git add .github/PULL_REQUEST_TEMPLATE.md
git commit -m "chore: add pull request template"
git push

Multiple PR templates

Nếu cần nhiều template cho các loại PR khác nhau (feature, bugfix, hotfix), đặt vào .github/PULL_REQUEST_TEMPLATE/ thay vì file đơn. Khi tạo PR, thêm query param ?template=feature.md vào URL.

9

Issue Tracking

Tab Issues là nơi track bug, feature request, và task trong project. Với portfolio repo, Issues dùng để document các việc cần làm và link với PR — recruiter có thể thấy project management workflow của bạn.

Issue templates

Tạo thư mục .github/ISSUE_TEMPLATE/ với 2 file:

bug_report.md:

---
name: Bug report
about: Report a bug
labels: bug
---

## Describe the bug

## Steps to reproduce
1.
2.

## Expected behavior

## Environment
- OS:
- Python version:
- Library versions (`pip freeze | grep -E "torch|transformers|langchain"`):

## Logs / Traceback
```
```

feature_request.md:

---
name: Feature request
about: Suggest an improvement
labels: enhancement
---

## Problem / Motivation

## Proposed solution

## Alternatives considered

Reference issue trong PR và commit

GitHub nhận diện các từ khoá sau trong PR description hoặc commit message và tự đóng issue khi merge:

  • Closes #12, Fixes #12, Resolves #12 — đóng issue #12 khi PR merge vào default branch
  • Refs #12 — mention issue mà không đóng

Labels hữu ích

GitHub tạo sẵn: bug, documentation, duplicate, enhancement, good first issue, help wanted, invalid, question, wontfix. Thêm label custom cho AI project: model, data, experiment, ci.

10

GitHub Actions — CI Cơ Bản

GitHub Actions chạy workflow tự động khi có sự kiện (push, PR, schedule...). Workflow định nghĩa bằng YAML trong .github/workflows/.

Workflow CI cơ bản cho Python AI project

Tạo file .github/workflows/ci.yml:

name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: "3.11"
          cache: "pip"

      - name: Install dependencies
        run: pip install -r requirements.txt

      - name: Run tests
        run: pytest tests/ -v --tb=short

Sau khi push file này, mỗi khi có push lên main hoặc mở PR vào main, GitHub tự động chạy workflow. Kết quả hiển thị ở tab Actions trên repo và trong phần Checks của PR (dấu ✅ / ❌).

Thêm lint check

      - name: Lint with ruff
        run: |
          pip install ruff
          ruff check src/ tests/

Cache dependencies đúng cách

cache: "pip" trong actions/setup-python@v5 cache thư mục pip dựa trên hash của requirements.txt. Khi requirements.txt không thay đổi, step install skip cache hit — tiết kiệm 1-2 phút mỗi run.

Giới hạn free tier

2000 phút/tháng cho private repo. ubuntu-latest tính 1x, windows-latest tính 2x, macos-latest tính 10x. Với public repo không có giới hạn phút.

GitHub Actions cho ML pipeline (training job, model evaluation, Docker build, deploy) được đề cập chi tiết trong Series 6 — MLOps (bài về CI/CD cho ML).

11

GitHub Pages

GitHub Pages host static site miễn phí từ content trong repo. URL mặc định: https://username.github.io/repo-name. Với repo đặt tên username.github.io, URL là https://username.github.io (không có path).

Bật GitHub Pages

Settings → Pages → Source: chọn branch (thường là main hoặc gh-pages) và folder (/root hoặc /docs). Save. GitHub deploy trong vài phút.

Use cases phổ biến

  • Portfolio website: HTML/CSS tĩnh hoặc build từ framework (Astro, Next.js static export). Đặt tên repo là username.github.io.
  • Project documentation: MkDocs (dùng mkdocs gh-deploy), Docusaurus, hoặc Sphinx với make html → push vào gh-pages branch.
  • Demo notebook: Build HTML từ Jupyter với jupyter nbconvert, push vào docs/ folder.

Auto-deploy với GitHub Actions

name: Deploy docs

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.11"
      - run: pip install mkdocs mkdocs-material
      - run: mkdocs gh-deploy --force
12

Releases Và Tags

Tag đánh dấu 1 commit là version cụ thể. GitHub Release thêm lớp thông tin lên trên tag: changelog, binary artifact, download link.

Tạo tag và push

# Annotated tag (khuyến nghị — có message và author)
git tag -a v1.0.0 -m "Initial release: RAG chatbot v1 with ChromaDB"

# Push tag lên GitHub
git push origin v1.0.0

# Hoặc push tất cả tag cùng lúc
git push --tags

# Liệt kê tag
git tag -l

# Checkout về 1 version cụ thể
git checkout v1.0.0

Tạo GitHub Release từ tag

Vào tab ReleasesDraft a new release → chọn tag → điền:

  • Release title: v1.0.0 — RAG Chatbot Initial Release
  • Description: changelog: tính năng có, breaking change, upgrade guide.
  • Attach binaries: requirements.txt snapshot, model config, exported ONNX nếu có.

Dùng Semantic Versioning (semver.org): MAJOR.MINOR.PATCH. MAJOR tăng khi có breaking change, MINOR khi thêm feature backward-compatible, PATCH khi fix bug.

13

GitHub CLI

gh CLI (GitHub CLI 2.x) cho phép thao tác với GitHub trực tiếp từ terminal mà không cần mở browser. Hữu ích cho automation script và workflow nhanh.

Cài đặt

# macOS
brew install gh

# Linux (Debian/Ubuntu)
sudo apt install gh

# Windows
winget install --id GitHub.cli

# Đăng nhập
gh auth login

Các lệnh thường dùng

# Repo
gh repo clone username/repo
gh repo view --web              # mở repo trong browser

# Pull Request
gh pr create --title "feat: add vector store" --body "..."
gh pr list                      # xem danh sách PR đang mở
gh pr checkout 42               # checkout về branch của PR #42
gh pr view 42 --web             # mở PR #42 trong browser
gh pr merge 42 --squash --delete-branch

# Issue
gh issue create --title "Bug: empty input crash" --label bug
gh issue list
gh issue close 12

# Actions
gh workflow list
gh run list --workflow=ci.yml
gh run watch                    # stream log của run đang chạy
gh run view 1234567 --log-failed  # xem log của step fail

# Release
gh release create v1.0.0 --notes "Initial release"
gh release list

Tạo PR từ CLI

git checkout -b feature/add-rag
# ... commit code ...
git push -u origin feature/add-rag

gh pr create \
  --title "feat: add RAG retrieval with ChromaDB" \
  --body "Implements vector search using ChromaDB. Closes #8" \
  --label enhancement
14

README Badges

Badges hiển thị status của project ngay đầu README — CI pass/fail, license, version Python. Đặt ở dòng đầu README ngay sau title.

![CI](https://github.com/username/repo/actions/workflows/ci.yml/badge.svg)
![License](https://img.shields.io/github/license/username/repo)
![Python](https://img.shields.io/badge/python-3.11-blue)
![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen)

Badge CI link trực tiếp đến GitHub Actions workflow. Khi CI pass, badge hiển thị nền xanh; khi fail, hiển thị nền đỏ. Thay username/repoci.yml bằng giá trị thực của repo.

shields.io cung cấp thêm nhiều loại badge: last commit, code size, open issues, stars... Không cần thêm nhiều — 3–4 badge là đủ để truyền đạt thông tin quan trọng. Quá nhiều badge làm README trông cluttered.

15

Best Practice Repo Public

Checklist cho một portfolio repo đạt tiêu chuẩn:

File / Setting Mục đích Bắt buộc?
README.md Giải thích project, quick start, architecture
LICENSE Điều khoản sử dụng code Có (MIT hoặc Apache 2.0)
.gitignore Chặn data, model, secret, cache
requirements.txt hoặc pyproject.toml Reproducible environment
.github/workflows/ci.yml Tự động test khi push/PR Khuyến nghị
.github/PULL_REQUEST_TEMPLATE.md Chuẩn hoá PR description Khuyến nghị
CONTRIBUTING.md Hướng dẫn đóng góp (nếu open cho contributor) Nếu public cần contributor
SECURITY.md Cách report security issue Nếu user upload data

GitHub Profile README

Tạo repo có tên trùng với username (ví dụ: repo nguyenvana/nguyenvana) và thêm README.md — nội dung file này hiển thị ngay trên trang profile. Đây là nơi brief introduction, link các project nổi bật, tech stack. Không cần hoa mỹ — thông tin rõ ràng là đủ.

Stars, Forks, Watchers

Star là bookmark + appreciation. Fork là copy repo về account của mình để develop độc lập. Watch là subscribe notification. Số star nhiều phản ánh mức độ hữu ích của repo với cộng đồng — không nên tự farm star bằng spam vì không có giá trị thực.

16

Common Pitfalls

  • Push token hoặc API key vào repo. GitHub Secret Scanning tự detect một số pattern (OpenAI, AWS, Stripe...) và alert ngay. Nhưng phát hiện sau vẫn muộn — phải revoke ngay lập tức và rewrite history (xem bài 5 mục "Khi lỡ commit secret"). Phòng ngừa bằng pre-commit hook detect-secrets.
  • Public repo có .env lỡ commit. Ngay cả sau khi xóa file và push lại, file vẫn tồn tại trong git history và có thể clone về. Xử lý tương tự: revoke credential trước, rewrite history sau.
  • PR description rỗng. Reviewer (kể cả bản thân sau 2 tuần) không có context để hiểu tại sao thay đổi này được làm. Tối thiểu 1–2 câu mô tả là đủ.
  • Merge PR khi CI fail. GitHub cho phép merge dù CI fail nếu không bật branch protection. Nếu có rule "Require status checks to pass", nút Merge bị khóa. Không bypass trừ khi CI fail do flaky test không liên quan đến code change.
  • Force push lên main trong repo public có fork. Người đã fork và đang develop trên fork của họ sẽ bị mất commit khi history diverge. Chỉ force push lên branch của chính mình khi thực sự cần thiết.
  • Quên --global khi config git user.email trên máy mới. Commit hiển thị author email lạ (hoặc empty), không link được với GitHub account — contribution graph không tính.
  • Branch tích tụ sau merge. Remote branch sau khi merge không tự xóa. Theo thời gian, tab Branches hiển thị hàng chục branch cũ. Bật auto-delete ở Settings → Pull Requests → "Automatically delete head branches".
  • Dùng HTTPS thay SSH nhưng không lưu credential. Mỗi push yêu cầu nhập PAT. Dùng Git Credential Manager (Windows/macOS) hoặc chuyển sang SSH để tránh phải nhập token mỗi lần.
17

Tóm Tắt

  • SSH key ed25519 là cách xác thực phù hợp cho personal machine — không phải nhập password mỗi lần push.
  • Tạo repo qua UI, gh CLI, hoặc từ local repo với gh repo create --source=. --push. Push lần đầu cần git push -u origin main để set upstream.
  • Branch protection rules cho main: yêu cầu PR và CI pass trước khi merge — áp dụng cho portfolio repo để demonstrate workflow có tổ chức.
  • PR workflow: push branch → mở PR → CI chạy → self-review Files Changed → merge (squash thường là lựa chọn tốt cho solo project) → xóa branch.
  • PR template (.github/PULL_REQUEST_TEMPLATE.md) và Issue template chuẩn hoá thông tin và làm repo trông professional.
  • .github/workflows/ci.yml với actions/checkout@v4 + actions/setup-python@v5 + pytest: CI cơ bản đủ để block broken code merge vào main.
  • GitHub Pages host static site miễn phí từ repo — dùng cho portfolio website hoặc project docs.
  • gh CLI 2.x: gh pr create, gh pr checkout, gh run watch... — nhanh hơn mở browser cho các thao tác thường gặp.
  • Secret vào repo: revoke credential ngay, rewrite history bằng git filter-repo.