Mục lục Git - GitHub

Tạo mới một Repository mới

Trong Git một Repository là một kho chứa (nó chứa các file mã nguồn của bạn, cơ sở liệu Git). Giả sử bạn có một dự án lưu C:\Path\projectcode, chúng ta sẽ chuyển thư mục đó trở thành một Local Repository Git, để giám sát sự thay đổi các file trong thư mục dự án đó. Trước hết ta tìm hiểu về các trạng thái của file trong một Repo

Vòng đời các file trong Git có thể ở một trong các trạng thái được biểu diễn như hình.

Để biết trạng thái các file trong dự án ở trạng thái nào dùng lệnh kiểm tra trạng thái

git status
  • Với vòng đời một File trong Git như trên, ta thấy đầu tiên file mới thì nó ở trạng thái untracked (không được giám sát phiên bản).
  • Từ trạng thái untracked dùng lệnh Git để đưa nó vào trạng thái staged, khi ở staged có nghĩa là file được đưa vào kế hoạch để lưu (mới hoặc cập nhật) vào CSDL của Git (kế hoạch thôi - chưa thực sự có trong CSDL Git) - và bắt đầu theo dõi
  • Ở trạng thái staged (chuẩn bị cho cập nhật vào CSDL - tạo mới hoặc update) dùng lệnh Git để cập nhật vào CSDL Git, gọi là commit - Sau khi cập nhật xong thông tin đầy đủ về File ở phiên bản cuối đã tồn tại trong CSDL Git và File sẽ ở trạng thái là unmodified
  • Ở trạng thái unmodified, nếu File bị sửa đổi nội dung (bạn thêm dòng code chẳng hạn) thì lập tức nó chuyển sang trạng thái modified, từ modified nếu muốn cập nhật sửa đổi vào dữ liệu Git thì lại dùng lệnh Git đưa nó vào trạng thái staged mang ý nghĩa kế hoạch cập nhật. Rồi lại commit để cập nhật vào CSDL và file lại vào trạng thái unmodified
  • Hoặc Ở trạng thái unmodified, file được xóa khỏi CSDL Git để chuyển lại về không theo dõi untracked

Các Video: Sử dụng Git, GitHub

1 Tạo Local Repo

$ cd /c/Path/projectcode/
$ git init
Initialized empty Git repository in C:/Path/projectcode/.git/

Sau lệnh đó thì thư mục projectcode đã trở thành một Local Repo, bên trong nó gồm có các file code mà có thể đưa vào bất ký lúc nào, và một thư mục .git chứa toàn bộ dữ liệu Git về Repo này.

Bắt đầu giám sát các file trong thư mục làm việc

Thời điểm này Git chưa giám sát một file nào chứa trong thư mục làm việc (là thư mục lưu dự án của bạn c:\Path\projectcode\)

Giả sử trong thư mục dự án đang tồn tại các file:

about.html
index.html
abc.tmp

Gõ lệnh xem trạng thái hiện tại:

$ git status
On branch master
No commits yet
Untracked files:
  (use "git add ..." to include in what will be committed)

        abc.tmp
        index.html
        about.html

Qua đó cho biết tình trạng hiện tại như sau: Đang làm việc trên nhánh master, đây là nhánh chính mặc định được tạo ra (ta sẽ tìm hiểu về nhánh sau), các file abc.tmp, index.html trong dự án ở trạng thái untracked có nghĩa là không được Git giám sát.

2 Đưa file mới vào staged giám sát

Để đưa file index.html vào giám sát gõ lệnh sau:

$ git add index.html

Xem lại trạng thái

$ git status
Changes to be committed:
        new file:   index.html
Untracked files:
        abc.tmp
        about.html

Trạng thái hiện tại là file index.html đã được đưa vào khu vực staged là nơi chứa những gì mà sẽ commit ghi dữ liệu vào database của Git. Nhưng file abc.tmp, about.html vẫn là untracked

Những file khác muốn giám sát thực hiện lệnh git add theo cách tương tự. Ngoài ra để đưa vào staged một cách nhanh chóng sử dụng một số trường hợp đặc biệt như:

$ git add *.c       #Thêm tất cả các file có phần mở rộng .c
$ git add .         #Thêm tất cả thay đổi, trừ xóa file
$ git add -A        #Thêm tất cả thay đổi

3 Đánh dấu file bị lờ đi không giám sát

Trong thư mục dự án có thể có những file mà không muốn Git giám sát (phổ biến là các file trong thư mục trình biên dịch sinh ra, các file tạm ...). Nếu muốn lờ đi file nào, thư mục nào thì Git hỗ trợ khai báo chúng trong một file có tên là .gitignore, bạn chỉ việc tạo ra file có tên như vậy ở thư mục dự án vào khai báo bên trong nó những gì muốn lờ đi.

Từ dòng lệnh có thể gõ lệnh sau để tao ra file .gitignore

$ touch .gitignore

Mở file ra: giả sử sẽ lờ đi file abc.tmp, lờ đi các file dạng *.log, lờ đi các file trong thư mục build/Release thì cập nhật nội dung trong file .gitignore như sau:

abc.tmp
*.log
build/Release

4 Đưa tất cả các file vào staged giám sát

Tiếp theo gõ lệnh sau để thêm tất cả các file trong dự án vào staged (có lờ đi các file đánh dấu - đó là abc.tmp)

git add .

Xem lại trạng thái hiện tại:

$ git status
On branch master

Changes to be committed: 
        new file:   .gitignore
        new file:   about.html
        new file:   index.html

Như vậy toàn bộ dự án có 3 file đã đưa hết vào staged để sẵn sàng thực hiện commit đầu tiên.

5 Thực hiện commit đầu tiên

Việc thực commit là thao tác đưa toàn bộ nội dung trong staged vào dữ liệu của Git - nó tạo ra ảnh chụp toàn bộ thư mục làm việc ở thời điểm đó. Như sơ đồ trên nếu đã commit thì nó chuyển file từ trạng thái staged sang unmodified. Thực hiện commit với lệnh như sau:

$ git commit -m"C0 - Khoi tao du an"

6 Xem lịch sử commit

$ git log --oneline
2e276a4 (HEAD -> master) C0 - Khoi tao du an
Nó cho biết trong lịch sử nhánh master bạn có một commit, commit đó có mã hash là 2e276a4 sau này sẽ làm việc nhiều với mã này. HEAD gọi là con trỏ trong Git, bạn tạm hiểu nó cho biết đang đứng ở đâu trong Repo (Như trường hợp này bạn đang ở master, ở commit có mã hash 2e276a4). Ta ký hiệu commit đầu tiên này là C0 - snapshot, thì mô hình hóa Repo hiện tại như hình bên, con trỏ HEAD đang ở nhánh master, và Repo có một snapshot C0

Clone một Remote Repo

Nếu có một Repository đang lưu trữ ở một dịch vụ Git nào đó, ví dụ có Remote Repository - https://github.com/ichte/xtlab, thì có thể sao về máy để thành Local Repo bằng lệnh:

git clone https://github.com/ichte/xtlab.git

Hoặc là (có sử dụng SSH)

git clone git@github.com:ichte/xtlab.git

Làm việc cơ bản Git

Giờ ta sửa đổi nội dung sự án và giám sát nó với Git để tìm hiểu cách làm việc cơ bản

7 Tạo ra một file mới có tên là test.html, sau đó kiểm tra lại trạng thái.

$ git status
On branch master
Untracked files:
        test.html

Git đã phát hiện có một file mới trong dự án, file này chưa được giám sát

8 Đưa file test.html vào giám sát (staged) bằng lệnh git add . hoặc git add test.html

$ git add .
$ git status
Changes to be committed:
        new file:   test.html

Đã đưa file test.html + nội dung của nó vào staged, giờ có thể thực hiện lệnh commit để lưu vào db của Git. Có thể lúc này bạn nhận ra cần thay đổi nội dung của test.html, nên muốn đưa nó ra khỏi staged để sửa đổi nó rồi mới cập nhật lại sau. Thì làm như sau:

$ git reset HEAD test.html

Giờ file lại ở trạng thái như 7, bạn có thể kiểm tra bằng git status, giờ mở file test.html ra cập nhật nội dung gì đó. Ví dụ thêm vào dòng chữ nội dung đầu tiên test.html

Sửa xong thực hiện lại git add . để đưa test.html trở lại sẵn sàng commit

$ git add .

9 Thực hiện commit

$ git commit -m"C1 - them file test.html"

Sau commit xem lại lịch sử commit

$ git log --oneline
8fe842a (HEAD -> master) C1 - them file test.html
2e276a4 C0 - Khoi tao du an

Đến đây Repo có 2 commit, mô hình hóa các snapshot như hình

repo

10 Tiếp tục sửa file test.html, mở file test.html ra, thay thế bằng nội dung mới ví dụ là dòng chữ Học Git và GitHub, sau đó lưu lại. Quay trở lại Git kiểm tra trạng thái hiện tại

$ git status
On branch master
Changes not staged for commit:
        modified:   test.html

Git đã phát hiện ra có sự thay đổi trên test.html, và nó đánh dấu ở trạng thái modified

Lúc này bạn có thể đưa sửa đổi vào staged bằng lệnh git add . và thực hiện commit tiếp theo để cập nhật vào db Git.

11 Tuy nhiên lúc này bạn nhận ra muốn phục hồi lại file về trạng thái ở commit cuối thì làm như sau

$ git checkout -- test.html

File đã phục hồi về trạng thái ở commit cũ (mở ra nội dung nó quay về nội dung đầu tiên test.html)

12 Mở file test.html ra tiếp tục sửa đổi lại ví dụ cho nội dung thành dòng chữ Test for Git and GitHub, sau đó tiến hành commit để lựu lại

$ git add .
$ git commit -m"C2 - update test"
$ git log --oneline
b9542bb (HEAD -> master) C2 - update test
8fe842a C1 - them file test.html
2e276a4 C0 - Khoi tao du an

Sơ đồ Repo hiện tại có 3 commit snapshot như hình bên

13 Tiếp tục mở file test.html thay nội dung thành Test for Git and GitHub 2018 và lưu lại

Tạo ra một file mới test2.html, mở file và chèn nội dung Test2 - Git and GitHub

Kiểm tra trạng thái

$ git status
Changes not staged for commit:
        modified:   test.html

Untracked files:
        test2.html

Nó báo có 1 file ở trạng thái unmodified, 1 file ở trạng thái untracked

Thực hiện đưa hết các file untracked, modified vào staged và tiến hành commit, rồi xem lại log

$ git add .
$ git commit -m"C3 - test2"

$ git log --oneline
de9a8d9 (HEAD -> master) C3 - test2
b9542bb C2 - update test
8fe842a C1 - them file test.html
2e276a4 C0 - Khoi tao du an

Tình trạng hiện tại như hình có 4 snapshot

14 lệnh git diff: giờ dự án đã có 4 commit mà ta ký hiệu các snapshot C0, C1, C2, C3 mỗi khi có nội dung sửa đổi thì trước khi commit phải đưa nó vào kế hoạch commit trước, đó là staged, thao tác commit chính là chuyển nội dung từ staged vào db của Git.

Nếu muốn so sánh sự khác nhau giữa nội dung trong thư mục làm việc, staged với commit cuối thì dùng lệnh:

$ git diff

Ví dụ: mở file test.html nhập nhật nội dung thành Test for Git and GitHub 2018 - 2019

$ git status
        modified:   test.html

Kiểm tra trạng thái thấy file test.html ở trạng thái modified, và trong staged không có bản chụp nào của test.html. Nếu vậy lệnh git diff sẽ so sánh sự khác nhau của bản ở thư mục làm việc và bản commit cuối

$ git diff
diff --git a/test.html b/test.html
index 2361f65..c31ae4c 100644
--- a/test.html
+++ b/test.html
@@ -1 +1 @@
-Test for Git and GitHub 2018
+Test for Git and GitHub 2018 - 2019

Nó cho biết bản có màu đỏ là bản gốc (ở commit cuối), bản có màu xanh là bản đang sửa đổi.

Gọi lệnh git add . để đưa bản sửa đổi test.html vào staged, rồi kiểm tra lại trạng thái thấy như sau

$ git status
On branch master
Changes to be committed: 
        modified:   test.html

Bản sửa đổi test.html đã đưa vào kế hoạch commit trong staged, giờ lệnh git diff sẽ so sánh sự khác nhau của test.html giữa ở thư mục làm việc và bản trong staged. Ngay thời điểm này thấy không có thông báo gì vì 2 bản đó hoàn toàn giống nhau

Mở test.html ra sửa lại nội dung thành Git - GitHub 2018 - 2019, sau đó kiểm tra trạng thái

$ git status
On branch master
Changes to be committed: 
        modified:   test.html

Changes not staged for commit:
        modified:   test.html

Thấy rằng file test.html có một bản trong kế hoạch commit staged và một bản mới sửa đổi khác với bản kế hoạch. Nếu lúc này gõ lệnh git diff sẽ so sánh khác nhau giữa bản đang ở thư mục làm việc và bản kế hoạch commit staged

$ git diff
diff --git a/test.html b/test.html
index c31ae4c..bc0c51b 100644
--- a/test.html
+++ b/test.html
@@ -1 +1 @@
-Test for Git and GitHub 2018 - 2019
+Git - GitHub 2018 - 2019

Thời điểm này test.html có ba bản khác nhau:

  • Bản ở thư mục làm việc
  • Bản trong kế hoạch commit staged
  • Bản ở dữ liệu Git trong commit cuối (snapshot cuối)

Để so sánh khác nhau giữa bản staged và bản commit dùng lệnh

$ git diff --staged
diff --git a/test.html b/test.html
index 2361f65..c31ae4c 100644
--- a/test.html
+++ b/test.html
@@ -1 +1 @@
-Test for Git and GitHub 2018
+Test for Git and GitHub 2018 - 2019

Tóm lại lệnh git diff so sánh sự khác nhau giữa bản trong thư mục làm việc và bản trong staged nếu có, nếu không có thì so sánh với bản commit cuối. Lệnh git diff --staged so sánh giữa bản trong staged và bản commit

15 Khi strong staged đang tồn tại một bản chưa commit của test.html nếu bản ở thư mục làm việc có sửa đổi và gõ lại lệnh git add test.html hoặc git add . thì bản trong kế hoạch commit staged được thay mới từ thư mục làm việc

$ git status
On branch master
Changes to be committed: 
        modified:   test.html

Changes not staged for commit:
        modified:   test.html

$ git add .
$ git status
Changes to be committed: 
        modified:   test.html

16 Tiến hành commit và xem lại log

$ git commit -m"C4"
$ git log --oneline
969cbec (HEAD -> master) C4
de9a8d9 C3 - test2
b9542bb C2 - update test
8fe842a C1 - them file test.html
2e276a4 C0 - Khoi tao du an

17 Nếu muốn xóa một file khỏi Git thì bạn có thể sử dụng lệnh git rm filename hoặc tự xóa trong thư mục làm việc bằng các lệnh xóa file của hệ thống, ví dụ sử dụng File Explore của Windows

Giả sử xóa file test2.html bằng git rm sẽ thấy như sau:

$ git rm test2.html
$ git status
Changes to be committed:
        deleted:    test2.html

File test2.html đã xóa khỏi thư mục làm việc và thông tin xóa đã đưa luôn vào kế hoạch commit staged, nếu tiến hành commit thì sẽ có một snapshot phiên bản mà trong đó file test2.html đã bị xóa.

Tuy nhiên lúc này (chưa commit) nếu muốn phục hồi lại file bị xóa do git rm thì trước tiên phải đưa nó ra khỏi staged bằng lệnh git reset HEAD test2.html, sau đó phục hồi lại bằng lệnh git checkout -- test2.html

Ví dụ phục hồi lại

$ git reset HEAD test2.html
$ git checkout -- test2.html

Nếu xóa file mà không sử dụng git rm thì file xóa đó không tự động đưa vào kế hoạch commit staged mà bạn phải tự đưa sau khi xóa file bằng lệnh git add

Ví dụ giờ bạn lại xóa test2.html bằng cách xóa của hệ thống (ví dụ dùng File Explore). Sau đó kiểm tra trạng thái thấy:

$ git status
Changes not staged for commit:
    deleted:    test2.html

Nếu muốn commit việc này cần đưa vào staged trước

$ git status
Changes to be committed:
    deleted:    test2.html

Tiến hành commit tạo bản snapshot mà file test2.html đã bị xóa

$ git commit -m"C5 - Del test2"
$ git log --oneline
f5e1447 (HEAD -> master) C5 - Del test2
969cbec C4
de9a8d9 C3 - test2
b9542bb C2 - update test
8fe842a C1 - them file test.html
2e276a4 C0 - Khoi tao du an

18 git commit --amend Hiện giờ dự án có 6 snapshot, tương ứng với 6 commit, có thể xem thông tin về commit cuối:

$ git log -1
commit f5e1447053e792ada8f48fff804520bdb503d3ea (HEAD -> master)
Author: XTLAB ≶xtl@xuanthulab.net>
Date:   Mon May 14 16:21:53 2018 +0700

    C5 - Del test2

Nếu tạo ra sự thay đổi, ví dụ mở file index.html cho vào dòng chữ Trang chủ, nếu lúc này tiến hành commit thì hệ thống sẽ tạo ra một snapshot mới. Tuy nhiên bạn muốn không sinh ra thêm một snapshot mới mà sẽ thay thế snapshot cuối cùng thì lúc đó dùng đến lệnh git commit --amend

$ git add .
$ git commit --amend -m"C5 - Update"

Xem lại log

$ git log --oneline
e5d80b6 (HEAD -> master) C5 - Update
969cbec C4
de9a8d9 C3 - test2
b9542bb C2 - update test
8fe842a C1 - them file test.html
2e276a4 C0 - Khoi tao du an

Ta thấy toàn bộ lịch sử vẫn chỉ có 6 snapshot (6 commit), tuy nhiên mã hash của commit cuối cùng thay đổi so với lần commit trước, cho biết là nó mới bị thay thế

19 Khi tra cứu lịch sử commit dùng lệnh git log, ngoài các trường hợp đã sử dụng ở trên, còn có thể sử dụng một số cú pháp để thêm thông tin muốn xem:

  • Muốn xem thêm sự khác nhau (nội dung thay đổi) của từng commit thì thêm vào tham số -p, ví dụ git log -p
  • Muốn giới hạn xem n (số nguyên) commit cuối cùng thì thêm vào tham số -n, ví dụ xem 2 commit cuối cùng git log -p -2
  • Muốn xem sự thay đổi từng từ một qua mỗi commit thêm vào tham số --word-diff, ví dụ $ git log -p -2 --word-diff, khi hiện thị phần nội dung bị loại bỏ hiện thị trong [- -], nội dung thêm vào hiện thị trong {++}

Để xem lịch sử commit trên giao diện đồ họa từ dòng lệnh gõ gitk

Lệnh Git cơ bản làm việc với Repository

Tổng kết lại phần trên, ta đã sử dụng các lệnh Git sau

  • 1 git init khởi tạo một Repository mới
  • 2 git status hiện thị thông tin trạng thái của Repository, git status -s hiện thị thông tin ngắn gọn hơn
  • 3 git add cập nhật nội dung thay đổi của các file, file mới ... vào index, đưa chúng vào staged để chuẩn bị cho việc commit tiếp theo, một số cách sử dụng tham số với lệnh này như:
    • git add filename thêm file có tên chỉ ra trong tham số
    • git add *.c tất cả các file có phần mở rộng .c
    • git add -A thêm mọi thứ có sự thay đổi (file mới, xóa file, nội dung thay đổi ...)
    • git add . thêm mọi thứ trừ loại xóa file
    • git add -u thêm mọi thứ trừ file mới
  • 4 git commit
    • git commit -m "Thông báo ..." thực hiện commit, lưu snapshot vào DB Git
    • git commit --amend -m "Thông báo ..." commit, nhưng cập nhật thông tin vào commit cuối
  • 5 git clone path sao chép một Repository có địa chỉ là path (có thể là địa mạng như https://github.com/ichte/xtlab.git hoặc SSH git@github.com:ichte/xtlab.git, có thể là ở chính máy của bạn như C:\Path\projectcode)
  • 6 git log xem lại lịch sử commit. Nếu muốn hiện thị thông tin 4 commit cuối thôi thì thêm tham số -4 vào git log -4, nếu muốn hiện thị nhưng thông tin gì thay đổi trong từng commit thêm tham số -p, git log --pretty=oneline hiện thị thông tin mỗi commit trên một dòng
  • 7 git diff xem sự thay đổ giữa nội dung ở thư mục làm việc và Staged nếu có, hoặc giữa thư mục làm việc với commit cuối. git diff --staged xem sự thay đổi của nội dung trong staged và commit cuối
  • 8 git rm filename xóa file khỏi thư mục làm việc
  • 9 git reset HEAD filename hủy bỏ việc thay đổi trạng thái của file, ví dụ hủy đưa và Staged
  • 10 git checkout -- filename khôi phục thay đổi nội dung của filename, việc khôi phục ở trạng thái hiện tại có thể là là khôi phục từ Staged nếu có, nếu không thì khôi phục từ commit cuối. Nếu muốn khôi phục file từ một commit cũ có mã hash hash thì làm như sau
    • git checkout [hash] filename khôi phục lại filename
    • git checkout [hash] . khôi phục các file về phiên bản theo commit cũ
Mục lục Git - GitHub

Đăng ký nhận bài viết mới