- Thứ tự:
git init -b main,git add .,git commit, tạo kho trống trên GitHub,git remote add origin <URL>,git push -u origin main. - Tài liệu GitHub khuyên không tạo README, giấy phép hay
.gitignorekhi tạo kho để đẩy code có sẵn lên; nếu đã lỡ tạo,git pull --rebase origin mainrồi đẩy lại. - GitHub đã bỏ xác thực bằng mật khẩu cho Git. Khi được hỏi mật khẩu, dùng personal access token, hoặc dùng SSH hay trình quản lý thông tin đăng nhập.
Bài này theo tài liệu của GitHub về đưa code có sẵn lên GitHub và về kho từ xa, đọc ngày 11/11/2026. Đoạn code trong bài chạy Git thật (phiên bản 2.55) với một kho "từ xa" giả lập trong thư mục tạm, nên bạn tập được mà không cần mạng. Chưa cài Git hay chưa hiểu commit là gì thì đọc trước Git và GitHub là gì.
Chuẩn bị trước khi đẩy
Ba việc làm một lần trên máy:
- Cài Git từ git-scm.com và kiểm tra bằng
git --version. - Khai tên và email cho commit, theo sách Pro Git:
git config --global user.name "Tên bạn"vàgit config --global user.email "email@cua-ban". - Tạo tài khoản GitHub nếu chưa có.
Và một việc làm cho mỗi dự án, trước lần commit đầu tiên: tạo tệp .gitignore liệt kê thứ không được đưa lên, tối thiểu .venv/, __pycache__/ và .env. Tài liệu GitHub nhắc rõ: không bao giờ thêm, commit hay đẩy dữ liệu nhạy cảm như mật khẩu hay khóa API lên kho từ xa. Xem giữ khóa API an toàn.
Bước 1: biến thư mục dự án thành kho Git
Mở terminal (trên Windows dùng Git Bash), vào thư mục gốc của dự án và chạy:
git init -b main
git add .
git commit -m "First commit"
Lệnh đầu tạo kho Git với nhánh chính tên main. Theo tài liệu, cú pháp -b main cần Git 2.28.0 trở lên; với Git cũ hơn, dùng git init rồi git symbolic-ref HEAD refs/heads/main. Nếu thư mục đã là kho Git rồi thì bỏ qua lệnh này. Lệnh thứ hai chọn mọi tệp (trừ những gì .gitignore loại ra) để đưa vào commit; lệnh thứ ba lưu commit đầu tiên.
Trước khi commit, chạy git status để xem danh sách tệp sắp lưu. Nếu thấy .env, thư mục .venv hay tệp dữ liệu lớn trong danh sách, dừng lại và sửa .gitignore trước.
Bước 2: tạo kho trống trên GitHub
Trên trang GitHub, tạo kho mới, đặt tên, chọn công khai hay riêng tư. Điều quan trọng nhất ở bước này, theo tài liệu GitHub: không khởi tạo kho mới với README, giấy phép hay tệp .gitignore, để tránh lỗi. Các tệp đó bạn thêm sau khi đã đẩy code lên.
Lý do: nếu kho trên web có sẵn một commit (README), còn kho trên máy có commit của bạn, hai lịch sử không nối với nhau, và lần đẩy đầu bị từ chối. Mục "Lỗi bị từ chối" bên dưới tái hiện đúng tình huống này.
Sau khi tạo, GitHub hiện trang Quick Setup có địa chỉ của kho, dạng https://github.com/ten-ban/ten-kho.git. Chép địa chỉ đó.
Bước 3: nối kho trên máy với kho trên GitHub
git remote add origin https://github.com/ten-ban/ten-kho.git
git remote -v
origin là tên gọi quy ước cho kho từ xa chính. Lệnh thứ hai in ra địa chỉ để bạn kiểm tra đã nối đúng chưa.
Bước 4: đẩy code lên
git push -u origin main
Tùy chọn -u ghi nhớ rằng nhánh main trên máy đi cùng nhánh main trên GitHub, nên từ lần sau chỉ cần gõ git push. Tài liệu GitHub ghi lệnh trên cho macOS và Linux, còn trên Windows ghi git push origin main. Mở lại trang kho trên GitHub, bạn sẽ thấy các tệp của mình.
Cách khác: dùng GitHub CLI
Nếu đã cài GitHub CLI, tài liệu cho phép làm bước 2 tới 4 bằng một lệnh. Chạy gh repo create, chọn đẩy một kho có sẵn trên máy lên GitHub và làm theo lời nhắc; hoặc bỏ qua lời nhắc bằng:
gh repo create --source=. --public --push
Thay --public bằng --private nếu muốn kho riêng tư.
Lỗi 1: bị hỏi mật khẩu, nhập đúng vẫn không được
Theo tài liệu GitHub về kho từ xa, xác thực bằng mật khẩu cho Git đã bị bỏ để chuyển sang các cách an toàn hơn. Khi dùng địa chỉ HTTPS và Git hỏi mật khẩu, bạn nhập personal access token (mã truy cập cá nhân tạo trong phần cài đặt tài khoản GitHub) thay cho mật khẩu. Hai cách đỡ phải nhập lại mỗi lần:
- dùng trình quản lý thông tin đăng nhập như Git Credential Manager để lưu token;
- dùng địa chỉ SSH (dạng
git@github.com:ten-ban/ten-kho.git): tạo cặp khóa SSH trên máy và thêm khóa công khai vào tài khoản GitHub.
Token cũng là một loại khóa bí mật: không dán vào code, không gửi cho người khác, và đặt thời hạn hết hiệu lực khi tạo.
Lỗi 2: bị từ chối (rejected) vì kho đã có README
Đoạn Python dưới đây tái hiện cả hai trường hợp bằng Git thật. "GitHub" ở đây là một kho bare trong thư mục tạm, nên chạy được không cần mạng. Phần 1 đẩy lên kho trống; phần 2 đẩy lên một kho đã có sẵn commit README, giống khi bạn tích chọn "thêm README" lúc tạo kho trên web.
"""Tập đưa code lên kho từ xa mà không cần mạng: "kho từ xa" là một kho bare trong thư mục tạm, đóng vai GitHub.
Cần đã cài Git. Mọi thứ nằm trong thư mục tạm và bị xóa khi chạy xong.
Phần 1: đẩy lên kho trống (đúng cách tài liệu GitHub khuyên).
Phần 2: tái hiện lỗi khi kho trên web đã có sẵn README, rồi sửa bằng git pull --rebase.
"""
import os
import subprocess
import tempfile
TEN = ["-c", "user.name=Hoc Vien", "-c", "user.email=hocvien@example.com", "-c", "init.defaultBranch=main"]
def git(thu_muc, *ts, kiem=True):
p = subprocess.run(["git", *TEN, *ts], cwd=thu_muc, capture_output=True, text=True, encoding="utf-8")
if kiem and p.returncode != 0:
raise RuntimeError(p.stderr)
return p
def tao_du_an(goc, ten):
duan = os.path.join(goc, ten)
os.makedirs(duan)
with open(os.path.join(duan, "bai_tap.py"), "w", encoding="utf-8", newline="\n") as f:
f.write("print('Xin chào GitHub')\n")
git(duan, "init", "-q", "-b", "main")
git(duan, "add", ".")
git(duan, "commit", "-q", "-m", "Thêm bài tập đầu tiên")
return duan
def chay_thu():
with tempfile.TemporaryDirectory() as goc:
# Phần 1: kho từ xa trống.
git(goc, "init", "-q", "--bare", "kho_trong.git")
duan = tao_du_an(goc, "du_an_1")
git(duan, "remote", "add", "origin", os.path.join(goc, "kho_trong.git"))
p = git(duan, "push", "-u", "origin", "main", kiem=False)
print("1. Đẩy lên kho trống:", "thành công" if p.returncode == 0 else "thất bại")
git(goc, "clone", "-q", os.path.join(goc, "kho_trong.git"), "may_khac")
print("2. Clone về máy khác, thấy:", ", ".join(sorted(f for f in os.listdir(os.path.join(goc, "may_khac")) if f != ".git")))
# Phần 2: kho từ xa đã có README do trang web tạo sẵn.
git(goc, "init", "-q", "--bare", "kho_co_readme.git")
tam = os.path.join(goc, "tao_readme")
git(goc, "clone", "-q", os.path.join(goc, "kho_co_readme.git"), "tao_readme")
with open(os.path.join(tam, "README.md"), "w", encoding="utf-8", newline="\n") as f:
f.write("# Dự án\n")
git(tam, "add", ".")
git(tam, "commit", "-q", "-m", "Initial commit")
git(tam, "push", "-q", "origin", "main")
duan2 = tao_du_an(goc, "du_an_2")
git(duan2, "remote", "add", "origin", os.path.join(goc, "kho_co_readme.git"))
p = git(duan2, "push", "-u", "origin", "main", kiem=False)
bi_tu_choi = p.returncode != 0 and "rejected" in p.stderr
print("3. Đẩy lên kho đã có README:", "bị từ chối (rejected)" if bi_tu_choi else "không như dự kiến")
git(duan2, "pull", "-q", "--rebase", "origin", "main")
p = git(duan2, "push", "-u", "origin", "main", kiem=False)
print("4. Sau git pull --rebase rồi đẩy lại:", "thành công" if p.returncode == 0 else "thất bại")
print(" Lịch sử:", " <- ".join(git(duan2, "log", "--format=%s").stdout.split("\n")[:2]))
if __name__ == "__main__":
chay_thu()
Kết quả:
1. Đẩy lên kho trống: thành công
2. Clone về máy khác, thấy: bai_tap.py
3. Đẩy lên kho đã có README: bị từ chối (rejected)
4. Sau git pull --rebase rồi đẩy lại: thành công
Lịch sử: Thêm bài tập đầu tiên <- Initial commit
Dòng 3 là lỗi bạn sẽ gặp nếu tạo kho có README rồi đẩy code từ máy lên. Cách sửa ở dòng 4: git pull --rebase origin main kéo commit README về và đặt commit của bạn lên trên nó, rồi đẩy lại bình thường. Dòng lịch sử cho thấy kết quả: commit của bạn nằm sau commit "Initial commit" mà trang web đã tạo.
Một số hướng dẫn trên mạng khuyên dùng git push -f (ép đẩy) cho nhanh. Lệnh đó ghi đè lịch sử trên GitHub và xóa mất README đã có; với kho làm chung thì xóa luôn việc của người khác. Đừng dùng -f khi chưa hiểu rõ nó làm gì.
Kiểm tra trước mỗi lần đẩy
Đẩy lên rồi thì ai có quyền xem kho cũng thấy, nên dành nửa phút kiểm tra trước:
git status: có tệp nào lạ trong danh sách sắp commit không (tệp.env, thư mụcdata/hàng trăm MB, tệp tạm của trình soạn thảo).git diff --staged: đọc lướt những dòng sắp lưu. Đây là lúc bắt được một dòng in mật khẩu ra màn hình hay một khóa API dán tạm để thử.- Chạy lại chương trình hoặc bộ test một lần. Kho của bạn là thứ người khác sẽ tải về chạy thử; một commit làm hỏng chương trình là ấn tượng đầu tiên không tốt.
Nếu lỡ git add một tệp không muốn đưa lên, bỏ nó khỏi khu chuẩn bị bằng git restore --staged <tệp> rồi thêm tên tệp vào .gitignore.
Làm việc trên nhiều máy
Khi bạn code ở cả máy trường lẫn máy nhà, GitHub là nơi đồng bộ hai máy. Trên máy thứ hai, tải kho về bằng git clone <địa chỉ kho>. Từ đó, quy tắc đơn giản là: kéo về trước khi bắt đầu, đẩy lên khi xong. Mở máy là chạy git pull để lấy các commit từ máy kia; xong việc thì commit và git push. Nếu quên kéo về và hai máy cùng có commit mới, lần đẩy sẽ bị từ chối giống lỗi ở trên, và cách sửa vẫn là git pull --rebase rồi đẩy lại. Nếu hai máy sửa cùng một dòng, Git sẽ báo xung đột và đánh dấu chỗ đó trong tệp để bạn chọn bản giữ lại.
Sau lần đẩy đầu: vòng làm việc hằng ngày
Từ giờ, mỗi khi làm xong một phần việc:
git add .
git commit -m "Mô tả ngắn điều vừa làm"
git push
Ba thói quen giúp kho của bạn trông chuyên nghiệp và dễ dùng lại:
- Commit nhỏ, mỗi commit một ý, với lời mô tả nói rõ đã làm gì ("Thêm hàm tính điểm trung bình" thay vì "update").
- Thêm README mô tả dự án làm gì, cài và chạy thế nào. Bài đọc README và LICENSE có gợi ý.
- Không đẩy tệp lớn. Theo tài liệu GitHub, Git cảnh báo khi tệp lớn hơn 50 MiB và GitHub chặn tệp lớn hơn 100 MiB. Tệp trọng số mô hình hay bộ dữ liệu nên để nơi khác, ví dụ Hugging Face.
- Tích chọn "thêm README" khi tạo kho để đẩy code có sẵn lên, rồi gặp lỗi rejected.
- Dùng
git push -fđể "sửa" lỗi rejected, xóa mất lịch sử trên GitHub. - Nhập mật khẩu GitHub khi Git hỏi: phải dùng personal access token hoặc SSH.
- Commit trước khi có
.gitignore, đưa cả.venv,__pycache__và.envlên. - Dán token hay khóa API vào code hoặc lời mô tả commit.
- Quên
-uở lần đẩy đầu, rồi lần saugit pushbáo nhánh chưa có upstream.
Câu hỏi thường gặp
Nên chọn kho công khai hay riêng tư?
Bài tập và dự án muốn đưa vào portfolio thì công khai. Đồ án chưa nộp, code có dữ liệu riêng hay dự án của công ty thì riêng tư. Đổi được sau, nhưng tài liệu GitHub lưu ý chuyển về riêng tư không xóa được các bản fork hay bản sao người khác đã tải.
Lỡ đẩy tệp .env lên GitHub thì làm sao?
Coi khóa trong tệp đã lộ: thu hồi và tạo khóa mới ngay ở trang của nhà cung cấp. Xóa tệp ở commit sau không xóa được khỏi lịch sử. Bài giữ khóa API an toàn hướng dẫn đầy đủ.
Có cần dùng dòng lệnh không, dùng GitHub Desktop được không?
Được. GitHub Desktop là ứng dụng có giao diện để làm cùng các việc. Nên biết thêm các lệnh cơ bản vì hướng dẫn của dự án và công cụ AI lập trình đều dùng lệnh.
main và master khác gì nhau?
Chỉ là tên nhánh chính. Kho mới trên GitHub dùng main; nếu kho của bạn dùng tên khác, thay main trong các lệnh bằng tên đó.
Học tiếp
- Ôn lại ba trạng thái của tệp trong Git: Git và GitHub là gì.
- Trước khi đẩy dự án có gọi API: giữ khóa API an toàn.
- Xem lộ trình đầy đủ: GitHub cho người học AI.
Nếu bạn muốn học lập trình và AI bài bản cùng giảng viên, tham khảo khóa học AI của Big-O Coding.
Khóa AI – Introduction to Machine Learning: nền tảng Máy học từ thuật toán cơ bản đến Neural Networks và LLM, học bằng Python. Học thử buổi 1 miễn phí.


