Kho lưu trữ Git: cách tạo bằng git init và kết nối remote
Kho lưu trữ Git là thư mục dự án cùng thư mục ẩn .git, nơi Git lưu toàn bộ lịch sử commit, nhánh, thẻ và cấu hình. Tạo bằng lệnh git init trong thư mục dự án, hoặc tải kho có sẵn bằng git clone. Kho từ xa được kết nối bằng git remote add origin địa-chỉ.
Kho lưu trữ Git (repository, hay repo) là dự án mà Git theo dõi thay đổi. Về mặt vật lý, đó là một thư mục bình thường chứa các tệp của bạn cùng một thư mục ẩn .git, nơi lưu toàn bộ lịch sử: commit, nhánh, thẻ và cấu hình. Xóa .git đi, và chỉ còn lại các tệp không có phiên bản nào trong quá khứ.
Kho lưu trữ gồm những gì
Khi làm việc với Git, nên hình dung ba khu vực mà các thay đổi di chuyển qua:
- thư mục làm việc (working tree) — các tệp bạn thấy và chỉnh sửa;
- index (staging area) — bản nháp của commit tiếp theo, nơi thay đổi đi vào qua
git add; - lịch sử — cơ sở dữ liệu commit bên trong
.git, nơi thay đổi đi vào quagit commit.
Nói chính xác, chính kho lưu trữ là nội dung của .git. Thư mục làm việc chỉ là một bản «bung ra» của dự án mà Git lấy từ lịch sử.
Cách tạo kho lưu trữ Git bằng git init
Chuyển vào thư mục dự án và chạy một lệnh:
cd ~/projects/my-app
git init
Initialized empty Git repository in /home/user/projects/my-app/.git/
Có thể tạo kho trong thư mục trống, cũng như trong thư mục đã có sẵn tệp. Trong trường hợp sau, không có gì bị mất: các tệp hiện có chỉ trở thành chưa được theo dõi (untracked), cho đến khi bạn thêm chúng bằng git add.
Một số biến thể hữu ích của lệnh:
# Tạo thư mục và kho luôn trong đó
git init my-app
# Đặt tên cho nhánh đầu tiên (nếu không sẽ là master hoặc giá trị trong cấu hình)
git init -b main
# Đặt main làm nhánh mặc định cho mọi kho mới
git config --global init.defaultBranch main
Commit đầu tiên
Kho trống không có commit thì gần như vô dụng. Ngay sau git init, thường làm như sau:
git config --global user.name "Nguyễn Văn An"
git config --global user.email "an@example.com"
git status
git add .
git commit -m "Cấu trúc ban đầu của dự án"
Tên và email chỉ cần đặt một lần trên máy — chúng được ghi vào mỗi commit. Không có chúng, Git sẽ từ chối commit và yêu cầu bạn giới thiệu bản thân.
Thêm .gitignore ngay từ đầu
Trước lần git add . đầu tiên, hãy tạo tệp .gitignore liệt kê những thứ không được đưa vào kho: phụ thuộc, sản phẩm build, bí mật, tệp của IDE.
node_modules/
dist/
.env
.idea/
.vscode/
*.log
__pycache__/
Nếu tệp đã lọt vào commit, .gitignore không tự gỡ nó. Cần ngừng theo dõi tệp nhưng giữ nó trên đĩa: git rm --cached .env, rồi commit.
Bên trong thư mục .git
Trong công việc hằng ngày không cần mở thư mục này, nhưng hiểu cấu trúc sẽ giải đáp nhiều thắc mắc:
| Phần tử | Nội dung |
|---|---|
objects/ | Các đối tượng nén: nội dung tệp (blob), cấu trúc thư mục (tree), commit |
refs/heads/ | Các nhánh — tệp chứa hash của commit mới nhất |
refs/tags/ | Các thẻ |
HEAD | Con trỏ tới nhánh hiện tại, ví dụ ref: refs/heads/main |
config | Cấu hình riêng của kho này, bao gồm danh sách remote |
index | Trạng thái của staging area |
hooks/ | Script chạy khi có sự kiện (pre-commit, pre-push) |
Từ đây có kết luận quan trọng: nhánh trong Git là một tệp nhỏ chứa một hash. Vì vậy tạo nhánh diễn ra tức thì và không tốn gì.
Làm sao biết một thư mục là kho Git
git status
# hoặc chính xác hơn
git rev-parse --is-inside-work-tree
Bên ngoài kho, bạn sẽ nhận được fatal: not a git repository (or any of the parent directories): .git. Chú ý cụm «parent directories»: Git tìm .git ở các thư mục cha, đi ngược lên cây thư mục. Nếu vô tình chạy git init trong thư mục home, cả thư mục đó sẽ trở thành kho — và thư mục .git đó cần được xóa.
Kho cục bộ và kho từ xa
Kho tạo bằng git init chỉ tồn tại trên máy bạn. Để chia sẻ mã và có bản sao lưu, người ta kết nối kho từ xa (remote) — một bản sao trên máy chủ: GitHub, GitLab, Bitbucket hoặc máy chủ Git riêng.
Kho từ xa không phải là «kho chính» theo nghĩa của Git: mỗi bản sao đều đầy đủ và chứa toàn bộ lịch sử. Chỉ có thỏa thuận của nhóm mới khiến nó trở thành trung tâm.
git remote: kết nối kho từ xa
Remote là tên ngắn cho địa chỉ máy chủ. Theo quy ước, tên chính là origin.
# Thêm remote
git remote add origin git@github.com:username/my-app.git
# Xem danh sách kèm địa chỉ
git remote -v
origin git@github.com:username/my-app.git (fetch)
origin git@github.com:username/my-app.git (push)
Sau đó gửi nhánh và liên kết nó với nhánh từ xa:
git push -u origin main
Các lệnh git remote cơ bản
| Lệnh | Tác dụng |
|---|---|
git remote -v | Danh sách remote và địa chỉ |
git remote add <tên> <url> | Kết nối kho từ xa mới |
git remote set-url origin <url> | Đổi địa chỉ, ví dụ từ HTTPS sang SSH |
git remote rename origin cu | Đổi tên remote |
git remote remove cu | Xóa remote (bản thân máy chủ không bị ảnh hưởng) |
git remote show origin | Chi tiết: nhánh, theo dõi, nhánh nào đang tụt lại |
Các dạng địa chỉ
https://github.com/user/repo.git— HTTPS, chạy được ở mọi nơi, khi ghi cần token;git@github.com:user/repo.git— SSH, cần khóa, sau khi cấu hình sẽ không hỏi mật khẩu;/srv/git/repo.githoặcfile:///srv/git/repo.git— đường dẫn cục bộ, tiện cho thử nghiệm.
Lỗi thường gặp
«error: remote origin already exists». Remote có tên đó đã tồn tại. Nếu cần đổi địa chỉ, dùng git remote set-url origin <url>, đừng chạy add lại.
«failed to push some refs» / «Updates were rejected». Trên máy chủ có commit mà bạn chưa có — thường là README được tạo khi lập kho trên trang web. Chạy git pull --rebase origin main rồi thử push lại. Nếu hai lịch sử hoàn toàn không liên quan, Git báo «refusing to merge unrelated histories» — khi đó với git pull cần cờ --allow-unrelated-histories. Đơn giản hơn là tạo kho trên trang web ở trạng thái trống.
«src refspec main does not match any». Bạn cố gửi một nhánh không tồn tại: hoặc chưa có commit nào, hoặc nhánh tên là master. Kiểm tra bằng git branch.
Máy chủ Git riêng: kho bare
GitHub không bắt buộc. Kho từ xa có thể là bất kỳ máy nào mà bạn có quyền SSH. Trên máy chủ người ta tạo kho «trần» (bare) — không có thư mục làm việc, chỉ có nội dung của .git:
# Trên máy chủ
ssh user@server
git init --bare /srv/git/my-app.git
# Trên máy của bạn
git remote add origin user@server:/srv/git/my-app.git
git push -u origin main
Để làm việc với máy chủ như vậy cùng ba người, chỉ cần cấp cho đồng nghiệp quyền SSH vào thư mục kho và một nhóm chung có quyền ghi. Nhưng để phân quyền theo nhánh và theo dự án thì như thế là không đủ — lúc đó cần một nền tảng Git đầy đủ.
Không thể «vào kho bare rồi sửa tệp» — nó chỉ dùng để trao đổi qua push và fetch. Đó chính là cách các kho trên mọi nền tảng Git hoạt động. Nếu cần giao diện web, review và quản lý công việc, người ta cài các giải pháp tự host như GitLab, Gitea hoặc Forgejo.
Nhánh theo dõi: máy cục bộ nhìn thấy máy chủ như thế nào
Sau khi kết nối remote và chạy git fetch hoặc git push lần đầu, trong kho xuất hiện các nhánh từ xa dạng origin/main. Đây không phải nhánh trên máy chủ, mà là bản «chụp» cục bộ của những gì bạn đã thấy trên máy chủ lần đồng bộ cuối. Chúng chỉ được cập nhật khi chạy fetch, pull và push.
Vì vậy phân biệt ba lệnh trao đổi là điều quan trọng:
| Lệnh | Thay đổi gì |
|---|---|
git fetch | Cập nhật origin/*, không đụng tới nhánh và tệp của bạn |
git pull | fetch + gộp origin/main vào nhánh hiện tại |
git push | Gửi commit của bạn và cập nhật nhánh trên máy chủ |
Để xem nhánh của bạn tụt lại hay vượt lên bao nhiêu:
git fetch
git status -sb
## main...origin/main [ahead 2, behind 1]
Ở đây có hai commit của bạn mà máy chủ chưa có, và một commit trên máy chủ mà bạn chưa có. Trước khi push, cần lấy commit đó về.
Liên kết giữa nhánh cục bộ và nhánh từ xa (upstream) được thiết lập bằng cờ -u ở lần push đầu tiên. Nếu quên, có thể đặt riêng: git branch --set-upstream-to=origin/main. Xem tất cả liên kết bằng git branch -vv.
Nhiều kho: monorepo hay mỗi dự án một kho
Câu hỏi thường gặp của người mới: nên tạo bao nhiêu kho Git. Quy tắc đơn giản: một kho cho một đơn vị được phát triển và phát hành độc lập. Bài tập, dự án cá nhân và các dịch vụ riêng biệt — mỗi cái một kho. Đừng tạo một kho cho cả thư mục «Dự án của tôi»: lịch sử sẽ lẫn lộn, và khó đưa riêng một dự án vào portfolio.
Các công ty lớn đôi khi giữ toàn bộ mã trong một monorepo để dễ thay đổi chung và build thống nhất, nhưng đó là quyết định kiến trúc có kèm công cụ riêng. Người mới nên bắt đầu với nguyên tắc «một dự án — một kho», và không bao giờ đặt một kho bên trong kho khác mà không dùng submodule.
git init hay git clone
| Tình huống | Lệnh |
|---|---|
| Bắt đầu dự án mới từ đầu | git init |
| Có thư mục mã chưa được quản lý phiên bản | git init trong thư mục đó |
| Dự án đã có trên GitHub hoặc máy chủ | git clone <url> |
| Cần kho trung tâm trên máy chủ riêng | git init --bare |
Sau git clone, remote origin đã được cấu hình sẵn, không cần thêm thủ công.
Quy trình từng bước: từ thư mục đến kho trên GitHub
- Tạo thư mục dự án và chạy
git init -b main. - Thêm
.gitignorevà README. - Tạo commit đầu tiên:
git add .vàgit commit -m "Initial commit". - Trên GitHub, tạo kho trống — không có README, giấy phép hay .gitignore.
- Kết nối:
git remote add origin <địa-chỉ>. - Gửi code:
git push -u origin main. - Sau đó làm việc theo vòng: sửa →
git add→git commit→git push.
Tóm lại
Kho lưu trữ Git là dự án của bạn cộng với thư mục .git chứa toàn bộ lịch sử. Kho được tạo bằng git init, còn kết nối với máy chủ được thiết lập qua git remote add origin và lần git push -u đầu tiên. Kho từ xa có thể là GitHub, GitLab hoặc máy chủ Git riêng với kho bare. Tạo kho đầu tiên, vùng index và kết nối remote được thực hành trong khóa học Git.
Câu hỏi thường gặp
Làm sao xóa kho Git nhưng giữ lại các tệp?
Xóa thư mục ẩn .git ở gốc dự án: rm -rf .git trên Linux và macOS. Các tệp vẫn còn, nhưng toàn bộ lịch sử phiên bản sẽ mất.
Chạy git init trong thư mục đã có kho có sao không?
Không sao: Git báo Reinitialized existing Git repository và không đụng tới lịch sử. Lệnh chỉ bổ sung các tệp hệ thống còn thiếu.
Có thể kết nối bao nhiêu remote với một kho?
Bao nhiêu cũng được. Ví dụ origin cho fork của bạn và upstream cho dự án gốc — đây là cách làm phổ biến khi đóng góp cho mã nguồn mở.
Cấu hình riêng của kho được lưu ở đâu?
Trong tệp .git/config. Cấu hình người dùng toàn cục nằm ở ~/.gitconfig và được đặt bằng git config --global.
Kho bare khác kho thông thường ở điểm nào?
Kho bare không có thư mục làm việc với các tệp, chỉ có dữ liệu nội bộ của Git. Nó được dùng làm kho trung tâm trên máy chủ, nơi người ta push tới.
Chủ đề này được giảng chi tiết kèm thực hành trong khóa học “Git с нуля до уверенного разработчика”.
- Первый репозиторий: init, add, commit и магия индекса
- GitHub и удалённые репозитории: ваш код в облаке