</>Học Dev
Bài học

Tuần 1 - Ngày 4: Remote Repository — Làm Việc với Team

Tuần 1 – Ngày 4

Tuần 1 - Ngày 4: Remote Repository — Làm Việc với Team

Mục tiêu học tập

  • Cấu hình và quản lý remote với git remote
  • Phân biệt fetch, pull, push và khi nào dùng cái nào
  • Hiểu tracking branches và upstream
  • Nắm rõ pull --rebase vs pull mặc định
  • Biết khi nào dùng --force-with-lease thay vì --force

1. Remote là gì?

Remote là tên đặt cho URL của một repository khác — thường là GitHub, GitLab, hoặc Bitbucket. Khi clone, Git tự động tạo remote tên origin.

LocalrepositoryRemote(GitHub)mainpush/fetchorigin/mainfeature/authorigin/feature/...refs/remotes/origin/mainorigin/feature/Remote-trackingbranches(origin/main,origin/feature/...)làbnsaolocalcaremotebranchescpnhtkhifetch.

2. Quản lý remotes

# Xem các remotes đã cấu hình
git remote -v
# origin  https://github.com/user/repo.git (fetch)
# origin  https://github.com/user/repo.git (push)

# Thêm remote
git remote add origin https://github.com/user/repo.git
git remote add upstream https://github.com/original/repo.git

# Đổi URL remote (ví dụ: chuyển từ HTTPS sang SSH)
git remote set-url origin git@github.com:user/repo.git

# Xoá remote
git remote remove upstream

# Đổi tên remote
git remote rename origin github

# Xem chi tiết một remote
git remote show origin

3. git fetch — Tải về nhưng không merge

# Fetch tất cả branches từ origin
git fetch origin

# Fetch branch cụ thể
git fetch origin main

# Fetch tất cả remotes
git fetch --all

# Fetch và xoá remote-tracking branches đã bị xoá trên remote
git fetch --prune origin
# hoặc cấu hình auto-prune
git config --global fetch.prune true

Sau git fetch:

  • Remote-tracking branches (origin/main) được cập nhật
  • Branches local của bạn không thay đổi
  • Bạn có thể xem diff trước khi merge: git diff main origin/main
# Sau fetch, xem remote main khác local main thế nào
git fetch origin
git log main..origin/main --oneline    # commits trên remote chưa có local
git log origin/main..main --oneline    # commits local chưa push lên remote
git diff main origin/main              # xem full diff

4. git push — Đẩy lên remote

# Push branch hiện tại lên remote, set upstream
git push -u origin main
git push -u origin feature/auth
# -u = --set-upstream: lần sau chỉ cần gõ git push

# Push sau khi đã set upstream
git push

# Push và xoá branch remote
git push origin --delete feature/old-branch

# Push tag
git push origin v1.0.0
git push origin --tags   # push tất cả tags

# Push tất cả branches (ít dùng)
git push --all origin

--force-with-lease — Cách push an toàn hơn --force

# Tình huống: bạn đã rebase và cần push lên remote branch
# (remote branch và local không còn cùng history)

# NGUY HIỂM: --force ghi đè không kiểm tra
git push --force origin feature/auth
# Nếu đồng nghiệp push trong lúc bạn đang rebase → commits của họ bị mất!

# AN TOÀN HƠN: --force-with-lease
git push --force-with-lease origin feature/auth
# Git kiểm tra: remote-tracking ref (origin/feature/auth) có khớp với
# remote thực không? Nếu ai push trước → Git từ chối, bạn phải fetch trước

# Quy tắc:
# - KHÔNG BAO GIỜ force push lên main/master/develop (shared branches)
# - force-with-lease chỉ dùng trên PERSONAL branches (feature/ branches)
# - Sau rebase cá nhân → force-with-lease

5. git pull — Fetch + merge

git pull là shortcut cho git fetch + git merge (hoặc git rebase).

# Pull mặc định = fetch + merge
git pull origin main
git pull   # nếu đã set upstream

# Pull với rebase thay vì merge
git pull --rebase origin main
git pull --rebase

# Xem sẽ pull gì trước khi pull
git fetch && git log ..origin/main --oneline

pull mặc định vs pull --rebase

Tìnhhung:BncócommitC,remotecócommitD(khôngbiết)Statetrưcpull:ABClocalmainDorigin/mainSaugitpull(mcđnhmerge):ABCMlocalmain(M=mergecommit)DSaugitpull--rebase:ABDC'localmain(CrebasedontopofD)^Hashkhácvìparentkhác

Khi nào dùng --rebase?

# Dùng --rebase khi:
# - Làm việc một mình trên feature branch
# - Muốn lịch sử tuyến tính (không có merge commits vô nghĩa)
# - CI/CD yêu cầu linear history

# Cấu hình mặc định pull --rebase
git config --global pull.rebase true
# Hoặc chỉ cho repo hiện tại
git config pull.rebase true

# Dùng merge khi:
# - Muốn lưu lại context "merge từ upstream vào feature branch"
# - Branch shared (nhiều người cùng push)

6. Tracking Branches

Tracking branch là liên kết giữa local branch và remote branch. Khi set tracking, git push/git pull biết remote nào và branch nào để sync.

# Khi clone, main tự động track origin/main

# Set upstream khi push lần đầu
git push -u origin feature/auth
# Sau đó: git push và git pull hoạt động không cần chỉ định

# Xem tracking info
git branch -vv
# main         abc1234 [origin/main] feat: add user login
# feature/auth def5678 [origin/feature/auth: ahead 2] feat: auth WIP

# Set tracking cho branch đã tồn tại
git branch --set-upstream-to=origin/feature/auth feature/auth
# hoặc ngắn hơn
git branch -u origin/feature/auth

# Tạo local branch track remote branch
git switch --track origin/feature/auth
# tạo local feature/auth tracking origin/feature/auth

7. Workflow với remote thực tế

Bắt đầu feature mới

# 1. Sync main trước
git switch main
git pull --rebase origin main

# 2. Tạo branch
git switch -c feature/payment-gateway

# 3. Làm việc, commit
git add . && git commit -m "feat: add Stripe integration"

# 4. Push lần đầu với -u
git push -u origin feature/payment-gateway

# 5. Push tiếp theo
git push

# 6. Sau khi PR merge, dọn dẹp
git switch main
git pull
git branch -d feature/payment-gateway
git push origin --delete feature/payment-gateway

Nhận thay đổi của đồng đội

# Đồng nghiệp đã merge PR vào main
git switch main
git fetch origin
git log ..origin/main --oneline   # xem có gì mới
git merge origin/main             # hoặc git pull

# Cập nhật feature branch của bạn sau khi main có thay đổi
git switch feature/my-feature
git rebase main   # rebase lên main mới nhất

Câu hỏi ôn tập

  1. git fetchgit pull khác nhau ở bước nào?

    Xem đáp án

    git fetch chỉ tải về remote objects và cập nhật remote-tracking branches (origin/main...) — không thay đổi local branches. git pull = git fetch + git merge (hoặc git rebase). Fetch cho phép xem sự khác biệt (git diff main origin/main) trước khi quyết định merge — an toàn hơn khi làm việc trên shared branches.

  2. Tracking branch là gì? Lợi ích của nó?

    Xem đáp án

    Tracking branch là liên kết giữa local branch và remote branch tương ứng (upstream). Set khi dùng git push -u origin feature/x hoặc git switch --track origin/feature/x. Lợi ích: sau khi set, chỉ cần gõ git pushgit pull mà không cần chỉ định remote/branch. git branch -vv hiển thị tracking info và số commits ahead/behind.

  3. Tại sao --force-with-lease an toàn hơn --force?

    Xem đáp án

    --force ghi đè remote branch bất kể có ai push thêm gì không. --force-with-lease kiểm tra remote-tracking ref local (origin/feature/x) có khớp với remote thực hay không trước khi push. Nếu đồng nghiệp đã push lên branch đó trong lúc bạn đang rebase → Git từ chối, bảo vệ commits của họ. Luôn dùng --force-with-lease trên feature branches cá nhân.

  4. git pull --rebase tạo ra lịch sử khác gì so với git pull mặc định?

    Xem đáp án

    git pull mặc định (merge) tạo một merge commit khi cả hai branches đều có commits riêng — lịch sử có nhánh rẽ. git pull --rebase đặt commits local của bạn lên trên commits remote, tạo lịch sử tuyến tính không có merge commit thừa. Phù hợp hơn cho feature branches cá nhân; cấu hình global bằng git config --global pull.rebase true.

  5. Khi chạy git push mà Git báo The current branch has no upstream branch, phải làm gì?

    Xem đáp án

    Branch chưa được set tracking upstream. Chạy git push -u origin <tên-branch> để push lên remote và set upstream cùng lúc. Sau đó git pushgit pull sẽ hoạt động mà không cần chỉ định thêm. Có thể cấu hình auto-setup: git config --global push.autoSetupRemote true để không cần gõ -u mỗi lần.

Bài tập thực hành

# Cần có GitHub account để thực hành bài này

# 1. Tạo repo trên GitHub, sau đó clone
git clone https://github.com/YOUR_USER/test-repo.git
cd test-repo

# 2. Xem remote đã được cấu hình tự động
git remote -v

# 3. Tạo file và push
echo "# Test" > README.md
git add README.md
git commit -m "docs: add README"
git push -u origin main   # set upstream lần đầu

# 4. Trên GitHub: tạo một file qua UI (simulate đồng đội push)

# 5. Fetch về xem
git fetch origin
git log ..origin/main --oneline  # thấy commit từ GitHub

# 6. Merge
git merge origin/main
git log --oneline

# 7. Tạo feature branch và push
git switch -c feature/test
echo "feature content" > feature.txt
git add feature.txt && git commit -m "feat: test feature"
git push -u origin feature/test

# 8. Xem tracking
git branch -vv

Tài liệu tham khảo chính thức


Tiếp theo: Ngày 5 — Merge vs Rebase