Tổng quan và git status

Xem thử

Vấn đề cần giải quyết

Bạn quay lại dự án sau một kỳ nghỉ và không nhớ mình đang làm gì: tệp nào đã sửa, cái nào đã add, nhánh nào đang mở, và tuần trước đã commit những gì. Trước khi thay đổi bất cứ thứ gì, bạn cần "nhìn" được kho. Hai lệnh chỉ đọc làm việc đó: git status trả lời "tôi đang có gì chưa lưu?" còn git log trả lời "kho đã đi qua những gì?".

Sau bài này, bạn có thể

  • Đọc mã hai ký tự của git status -s và suy ra vị trí của từng tệp.
  • Đọc git log như phép đi ngược theo commit cha và lọc nó theo tác giả, tệp hoặc nhánh.
  • Phân biệt git status (trạng thái hiện tại) với git log (lịch sử).

Tiên quyết: chương Lưu thay đổi.

git status

bash
git status
git status -s

Dạng ngắn -s hiện mỗi tệp một dòng với mã hai ký tự. Cột bên trái so Staging Area với HEAD, cột bên phải so Working Directory với Staging Area:

MãÝ nghĩa
??Tệp chưa theo dõi (untracked)
A Tệp mới đã staged
MĐã sửa, chưa staged
M Đã sửa và đã staged
MMĐã staged một phần, rồi sửa thêm chưa staged
D / D Đã xóa chưa staged / đã xóa và đã staged

Thử và quan sát

Hãy dự đoán: một tệp đã commit, bạn sửa rồi add, rồi sửa tiếp lần nữa. git status -s hiện mã gì và vì sao có hai chữ cái? Chạy mô phỏng và thử biến thể tệp bị xóa.

Đang tải Animation…

Bảng bước (bản đọc tĩnh của mô phỏng)

BướcLệnhĐiều xảy ra
1echo "// ghi chú" > notes.txtTạo tệp mới, Git chưa theo dõi.
2git status -sMã ?? báo tệp chưa theo dõi (untracked).
3git add notes.txtAdd tệp mới: nó vào Staging Area.
4git status -sChữ A ở cột bên trái nghĩa là tệp mới đã staged (added).
5echo "thêm" >> app.jsSửa tệp đã commit: Working Directory có v2, hai vùng còn lại giữ v1.
6git status -sChữ M ở cột bên phải nghĩa là đã sửa nhưng chưa staged.
7git add app.js && echo "nữa" >> app.jsAdd v2 rồi sửa tiếp thành v3: tệp vừa có phần staged, vừa có phần chưa staged.
8git status -sMã MM: cột trái là phần đã staged so với HEAD, cột phải là phần sửa thêm chưa staged.

Biến thể: Tệp bị xóa

BướcLệnhĐiều xảy ra
1rm old.jsXóa tệp đã theo dõi khỏi Working Directory.
2git status -sChữ D ở cột bên phải: đã xóa nhưng chưa staged.
3git rm old.jsgit rm ghi nhận việc xóa vào Staging Area (tệp đã không còn ở Working Directory).
4git status -sChữ D ở cột bên trái: việc xóa đã staged và sẽ vào commit kế tiếp.

Giải đáp. Mã MM: chữ M bên trái là phần đã staged so với HEAD, chữ M bên phải là phần sửa thêm chưa staged. Hai chữ cái đến từ hai phép so sánh khác nhau, nên một tệp có thể vừa có thay đổi đã staged vừa có thay đổi chưa staged. git status chỉ đọc nên bạn chạy bao nhiêu lần cũng không đổi trạng thái nào.

git log: đọc lịch sử

bash
git log
git log --oneline
git log --graph --oneline --decorate --all
git log -p
git log --stat

Log bắt đầu từ commit mà HEAD đang trỏ tới rồi đi ngược theo quan hệ cha, nên commit mới nhất hiện đầu tiên. Hãy dự đoán: lịch sử có nhánh feature tách từ C2. git log --oneline trên main có liệt kê commit của feature không?

Đang tải Animation…

Bảng bước (bản đọc tĩnh của mô phỏng)

BướcLệnhĐiều xảy ra
1git log --onelineLog bắt đầu từ commit HEAD trỏ tới (C3) rồi đi ngược theo cha: C3, C2, C1. Commit của feature không nằm trên đường này.
2git log --oneline --graph --allCờ --all bắt đầu từ mọi nhánh, nên thấy cả feature. Đồ thị cho thấy chỗ lịch sử tách ra.
3git log --oneline --author="An"Cờ --author chỉ giữ commit của một tác giả. Các commit khác vẫn có trong kho, chỉ bị ẩn khỏi kết quả.
4git log --oneline -- login.jsDấu -- giới hạn vào lịch sử của một tệp: chỉ những commit đã chạm tới tệp đó.

Biến thể: So hai nhánh bằng main..feature

BướcLệnhĐiều xảy ra
1git log --oneline main..featureCú pháp A..B liệt kê commit có trong B mà không có trong A: đây là phần feature đã làm thêm so với main.
2git log --oneline feature..mainChiều ngược lại: commit main đã có mà feature chưa có.
3git log --oneline main...featureBa dấu chấm cho commit chỉ nằm ở một trong hai phía.

Giải đáp. Không, vì log mặc định chỉ đi từ HEAD ngược theo cha, và commit của feature không nằm trên đường đó. Cờ --all đổi điểm bắt đầu thành mọi nhánh. Các bộ lọc không đổi kho, chỉ chọn một phần của chuỗi commit.

Lọc lịch sử

bash
git log --author="An"
git log --since="2 weeks ago"
git log --grep="bugfix"
git log -- src/app.js
git log main..feature

main..feature liệt kê commit có trên feature mà main chưa có, rất hữu ích để xem một nhánh sẽ mang vào gì trước khi merge.

Hiểu lầm thường gặp

  • "git log cho thấy mọi commit trong kho." Mặc định nó chỉ cho thấy các commit đi tới được từ HEAD; thêm --all mới thấy mọi nhánh.
  • "git status cho biết tệp khác gì." Nó chỉ nói tệp nào đã đổi; muốn thấy đổi gì, dùng git diff.
  • "Chữ M ở cột nào cũng như nhau." Cột trái nói về staged, cột phải nói về chưa staged.

Tự kiểm tra

  1. Mã A và AM khác nhau thế nào về những gì sẽ vào commit kế tiếp?
  2. Lệnh nào liệt kê commit của nhánh feature mà main chưa có?
  3. Bạn muốn xem chỉ những commit của một người về một tệp. Kết hợp những tùy chọn nào?

Đáp án gợi ý. (1) A đưa nguyên bản đã add vào commit; AM có phần sửa thêm chưa staged và phần này sẽ không vào commit. (2) git log main..feature. (3) git log --author="An" -- tên-tệp.

Điều cần nhớ

  • git status đọc trạng thái hiện tại; git log đọc lịch sử; cả hai chỉ đọc.
  • Mã hai ký tự: cột trái so với HEAD, cột phải so với Staging Area.
  • Log đi ngược theo cha từ HEAD; --all, --author, -- và A..B đổi điểm bắt đầu hoặc bộ lọc.
  • Bài sau: git tag, đánh dấu cố định một điểm trong lịch sử.

Nguồn tham khảo

Pro Git, chương 2.3 "Viewing the Commit History" (git-scm.com/book); tài liệu git-status và git-log (git-scm.com/docs).