git init

Xem thử

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

Bạn có thư mục ung-dung/ với vài chục tệp mã nguồn nhưng chưa có lịch sử nào. Bạn muốn bắt đầu theo dõi thay đổi, và cả đội cũng cần một kho trung tâm để push lên. Hai nhu cầu này dùng hai dạng kho khác nhau.

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

  • Dùng git init để biến một thư mục thành kho và giải thích nó thêm gì vào thư mục.
  • Phân biệt kho thường với kho bare và biết khi nào dùng loại nào.
  • Nói được vai trò của HEAD, refs và objects trong .git.

Tiên quyết: bài Tổng quan thiết lập kho.

Dùng cơ bản

bash
cd duong-dan/du-an
git init

Sau lệnh này thư mục hiện tại trở thành kho. Các tệp của bạn không đổi; chỉ có thêm thư mục ẩn .git. Chưa có commit nào, nên lịch sử còn trống. Để khởi tạo vào một thư mục mới: git init ten-du-an.

Hai dạng kho

Cách đọc hình. Khung bên trái là kho thường: có Working Directory để bạn sửa tệp và thư mục .git chứa dữ liệu. Khung bên phải là kho bare (git init --bare): chỉ có dữ liệu Git, không có thư mục làm việc, nên không thể sửa code trực tiếp trong đó. Vì vậy kho bare phù hợp làm điểm trung tâm mà mọi người push và pull, đúng cách máy chủ Git hoạt động. Theo quy ước, tên kho bare kết thúc bằng .git.

bash
git init --bare /srv/git/du-an.git

Năm thành phần chính trong .git: HEAD trỏ tới nhánh hiện tại; config là cấu hình riêng của kho; objects/ chứa toàn bộ nội dung (blob, tree, commit); refs/ chứa con trỏ nhánh và tag; hooks/ chứa script chạy theo sự kiện. Chuỗi HEAD, nhánh trong refs, commit trong objects giải thích vì sao đổi nhánh rất nhẹ: chỉ đổi con trỏ.

Thử và quan sát

Hãy dự đoán: ngay sau git init, nhưng trước khi có commit nào, git status báo gì và thư mục objects/ đã có gì chưa? Chạy mô phỏng, rồi thử biến thể kho bare để thấy vì sao nó không có Working Directory.

Đ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 init demoGit tạo thư mục .git với bộ khung rỗng. HEAD trỏ tới nhánh main nhưng nhánh này chưa có commit nào.
2git statusKho tồn tại nhưng lịch sử còn trống.
3echo "hello" > a.txtTạo tệp trong Working Directory. Chưa gì được ghi vào .git.
4git add a.txtAdd ghi nội dung tệp thành một đối tượng blob trong objects/ và cập nhật Staging Area.
5git commit -m "Commit đầu tiên"Commit tạo thêm tree và commit trong objects/, rồi nhánh main trong refs/ trỏ tới C1.

Biến thể: Thử với kho bare

BướcLệnhĐiều xảy ra
1git init --bare demo.gitKho bare chỉ có dữ liệu Git, không có thư mục làm việc. Theo quy ước tên kết thúc bằng .git.
2git add a.txtTrong kho bare không có Working Directory nên các lệnh cần bản làm việc đều bị từ chối.
3git push /srv/git/demo.git mainMuốn có nội dung, người dùng push từ một kho thường lên. Commit đến qua push chứ không sửa trực tiếp.

Giải đáp. git status báo "No commits yet": kho có nhưng lịch sử trống, và objects/ chưa chứa đối tượng nào. Chỉ khi add, nội dung tệp mới thành blob; khi commit mới có tree và commit, và nhánh main trong refs/ trỏ tới commit đó. Trong biến thể bare, lệnh cần bản làm việc như git add bị từ chối; nội dung đến kho bare qua push.

Hiểu lầm và giới hạn

  • "git init tự đưa các tệp vào lịch sử." Không. Bạn vẫn phải add rồi commit.
  • "Có thể xóa .git cho gọn." Xóa .git nghĩa là biến kho trở lại thư mục thường và mất toàn bộ lịch sử, trừ khi bạn còn một bản clone.
  • "Chạy git init hai lần sẽ xóa dữ liệu." Chạy lại trong kho có sẵn chỉ báo "Reinitialized" và không xóa lịch sử, nhưng không cần thiết.

Tự kiểm tra

  1. Sau git init, thư mục có thêm gì và các tệp cũ có đổi không?
  2. Vì sao máy chủ Git thường dùng kho bare?
  3. Vì sao trong kho bare lệnh git add thất bại?

Đáp án gợi ý. (1) Có thêm thư mục .git; tệp cũ giữ nguyên. (2) Nó không có Working Directory nên không ai sửa trực tiếp, chỉ nhận và phát lịch sử qua push và pull. (3) Vì add cần một bản làm việc để lấy nội dung, mà kho bare không có.

Điều cần nhớ

  • git init thêm .git, không đụng tới tệp của bạn.
  • Kho thường có bản làm việc, kho bare chỉ giữ dữ liệu Git để làm điểm trung tâm.
  • HEAD, refs, objects tạo thành chuỗi trỏ từ nhánh tới nội dung.
  • Bài sau: git clone, lấy một kho đã có về máy.

Nguồn tham khảo

Tài liệu git-init (git-scm.com/docs/git-init); Pro Git, chương 10.2 "Git Internals - Plumbing and Porcelain" (git-scm.com/book).