Làm web (05) - Git: thao tác với kho chứa (tt)

Bài học trước: Làm web (04) - Git: thao tác với kho chứa
-----

3.2.7     Xem các thay đổi staged và unstaged


Khi sử dụng lệnh git status, thông tin có được chỉ là tập tin nào đã bị thay đổi, mà không thể biết được nội dung bên trong đã bị thay đổi như thế nào (ví dụ hàng nào đã được thêm, hàng nào đã bị xóa). Để biết được điều này, cần sử dụng lệnh git diff (chữ diff là viết tắt của diffirence).

Có thể sử dụng lệnh git diff để biết được “những thông tin đã bị thay đổi nhưng chưa được staged” và “những thông tin đã được staged mà chưa được commit”. Nghĩa là so sánh nội dung tập tin ở ba vùng làm việc: working directory <> staging area <> git directory.

Giả sử bạn thực hiện sửa và staged tập tin readme.txt một lần nữa, sau đó sửa tập tin tailieu.txt mà không stage nó. Chạy lệnh git status sẽ có kết quả sau,

$ git status
On branch master
Your branch is ahead of 'origin/master' by 3 commits.
  (use "git push" to publish your local commits)

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   readme.txt

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   tailieu.txt

Để xem chính xác bạn đã thực hiện thay đổi, nhưng chưa staged những nội dung gì trong tailieu.txt, sử dụng lệnh git diff, xem kết quả,

$ git diff
diff --git a/tailieu.txt b/tailieu.txt
index c387b19..7f46f78 100644
--- a/tailieu.txt
+++ b/tailieu.txt
@@ -1 +1,2 @@
-Tài liệu trên remote repository.
+Tài liệu trên remote repository.
+tai liệu 3/3/2019

Lệnh git diff đã thực hiện so sánh nội dung của tập tin ở thư mục làm việc (working directory) với nội dung của chính tập tin đó nhưng ở khu vực staging (những nội dung sẽ được commit). Kết quả của lệnh này sẽ cho bạn biết những nội dung nào đã bị thay đổi nhưng chưa được stage.

Nếu muốn biết những nội dung nào đã được staged để commit, thì sử dụng lệnh git diff với tham số là --cached hoặc --staged. Lệnh này sẽ thực hiện so sánh nội dung của tập tin trong staging với tập tin đã được commit lần trước đó.

Ví dụ, thực hiện commit tập tin tailieu.txt, sau đó thêm một dòng thông tin vào nội dung của tailieu.txt, thực hiện stage, gõ lệnh git diff --staged để xem kết quả,

$ git diff --staged
diff --git a/tailieu.txt b/tailieu.txt
index 7f46f78..e278a02 100644
--- a/tailieu.txt
+++ b/tailieu.txt
@@ -1,2 +1,3 @@
 Tài liệu trên remote repository.
 tai liệu 3/3/2019
+Test diff --staged

Một tình huống sử dụng khác là: giả sử bạn đã staged một tập tin, sau đó bạn lại sửa tập tin đó, trong tình huống này, bạn có thể sử dụng lệnh git diff để xem nội dung nào chưa được staged, sử dụng lệnh git diff --staged để xem nội dung nào đã được staged. Xem ví dụ,

Kết quả của lệnh git diff,

$ git diff
diff --git a/tailieu.txt b/tailieu.txt
index 7dba564..9671700 100644
--- a/tailieu.txt
+++ b/tailieu.txt
@@ -2,3 +2,4 @@
 tai liệu 3/3/2019
 Test diff --staged
 10:53 staged
+10:56 unstaged
\ No newline at end of file

Kết quả của lệnh git diff --staged,

$ git diff --staged
diff --git a/tailieu.txt b/tailieu.txt
index e278a02..7dba564 100644
--- a/tailieu.txt
+++ b/tailieu.txt
@@ -1,3 +1,4 @@
 Tài liệu trên remote repository.
 tai liệu 3/3/2019
 Test diff --staged
+10:53 staged

3.2.8     Commit thay đổi


Sau khi đã tổ chức các tập tin theo ý muốn(stage), có thể thực hiện commit các tập tin, nghĩa là tạo một phiên bản mới, một “ảnh” hay một snapshot cho dự án. Lưu ý: mọi thay đổi thực hiện sau lệnh git add sẽ không được commit.

Cách đơn giản nhất để commit là gõ lệnh git commit. Sau khi chạy lệnh này, một trình soạn thảo sẽ mở lên. Đây là trình soạn thảo bạn đã cấu hình bằng lệnh git config --global core.editor trước đây.

[Khi gõ lệnh git commit, có thể gặp lỗi như sau:

$ git commit
hint: Waiting for your editor to close the file... This command is not supported by the help utility.  Try "D:/Liv/TuHoc/IT/chuyennganh/CNPM/gitlearning/langbiang/.git/COMMIT_EDITMSG /?".
Aborting commit due to empty commit message.

Lỗi này xảy ra do trong tập tin .git\config có cấu hình như sau:

[core]
            repositoryformatversion = 0
            filemode = false
            bare = false
            logallrefupdates = true
            symlinks = false
            ignorecase = true
            editor = help

Để ý dòng tô đậm đã thiết lập editor là help, dòng này được ưu tiên hơn giá trị editor trong tập tin .gitconfig nên Git không thể mở được editor, dẫn đến không thể thực hiện commit.

Cách sửa: cấu hình lại editor trong .git\config hoặc xóa dòng cấu hình editor=help để sử dụng cấu hình của tập tin .gitconfig.]

Sau khi gõ lệnh commit, giả sử cửa sổ Sublime Text sẽ mở ra với nội dung như sau:

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch master
# Your branch is ahead of 'origin/master' by 8 commits.
#   (use "git push" to publish your local commits)
#
# Changes to be committed:
#          modified:   tailieu.txt
#

Bắt đầu là một dòng trống để bạn nhập thông điệp, sau đó là nội dung của lệnh git status cuối cùng (đã được chú thích). Bạn có thể xóa nội dung được chú thích hoặc giữ nguyên để dễ theo dõi, nhập thông điệp riêng của bạn. Lưu và đóng Sublime text, lệnh commit sẽ được thực hiện.

Bạn cũng có thể sử dụng lệnh git commit -v để đưa nội dung của lệnh git diff --staged vào trong cửa sổ soạn thảo.

Ví dụ,

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch master
# Your branch is ahead of 'origin/master' by 9 commits.
#   (use "git push" to publish your local commits)
#
# Changes to be committed:
#          modified:   tailieu.txt
#
# ------------------------ >8 ------------------------
# Do not modify or remove the line above.
# Everything below it will be ignored.
diff --git a/tailieu.txt b/tailieu.txt
index 94ba15c..d0620f8 100644
--- a/tailieu.txt
+++ b/tailieu.txt
@@ -3,4 +3,5 @@ tai liệu 3/3/2019
 Test diff --staged
 10:53 staged
 10:56 unstaged
-3:23 4/3/2019
\ No newline at end of file
+3:23 4/3/2019
+3:48 4/3/2019
\ No newline at end of file

Khi commit, nội dung của lệnh git diff --staged  và các chú thích sẽ bị gỡ đi.

Ngoài ra, cũng có thể nhập trực tiếp thông điệp của mỗi commit bằng tham số -m. Ví dụ,
git commit -m “Issue số 2, có sửa hàm abc()”

Sau khi thực hiện, nếu thành công, lệnh commit sẽ hiển thị, nhánh bạn vừa commit, mã SHA-1, bao nhiêu tập tin đã thay đổi, số dòng đã thêm hoặc xóa.


Mỗi commit là một phiên bản của dự án, vì vậy sau này, bạn sẽ dựa vào đó để so sánh hoặc khôi phục các phiên bản.

3.2.9     Bỏ qua khu vực tổ chức


Ở các phần trên, trước khi commit, bạn thường phải thực hiện một bước chuẩn bị là “tổ chức” (stage) tập tin (dùng lệnh git add). Tuy nhiên, đôi khi cách làm này làm cho công việc trở nên phức tạp. Git cho phép bạn thực hiện commit mà không cần phải stage các tập tin.

Để thực hiện, bạn sử dụng thêm tham số -a trong lệnh commit, Git sẽ tự động thêm tất cả các tập tin đã được theo dõi, trước khi thực hiện commit.

Ví dụ,

$ git status
On branch master
Your branch is ahead of 'origin/master' by 11 commits.
  (use "git push" to publish your local commits)

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   readme.txt

no changes added to commit (use "git add" and/or "git commit -a")

$ git commit -a -m "test commit khong can git add"
[master a45d045] test commit khong can git add
 1 file changed, 0 insertions(+), 0 deletions(-)
Để ý sẽ thấy, bạn chưa chạy lệnh git add để stage tập tin readme.txt, tuy nhiên vẫn có thể thực hiện commit được với tham số -a.

3.2.10      Xóa tập tin


Để xóa tập tin, sử dụng lệnh git rm để gỡ bỏ tập tin ra khỏi khu vực stage (không theo dõi tập tin đó nữa), sau đó thực hiện commit. Lệnh git rm cũng xóa luôn tập tin đó trong thư mục làm việc, vì vậy bạn sẽ không thấy tập tin đó như là một tập tin chưa được theo dõi (untracked).

Ví dụ,

$ git rm code.php
rm 'code.php'

$ git status
On branch master
Your branch is ahead of 'origin/master' by 12 commits.
  (use "git push" to publish your local commits)

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        deleted:    code.php

$ git commit -m "xóa tập tin code.php"
[master 32d4243] xóa tập tin code.php
 1 file changed, 0 insertions(+), 0 deletions(-)
 delete mode 100644 code.php

Vậy, nếu dùng File Explorer (hay Windows Explorer) để xóa (delete) một tập tin thì chuyện gì sẽ xảy ra?

$ git status
On branch master
Your branch is ahead of 'origin/master' by 13 commits.
  (use "git push" to publish your local commits)

Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        deleted:    readme.txt

no changes added to commit (use "git add" and/or "git commit -a")

Git sẽ thông báo là vừa có hành động xóa một tập tin trong thư mục làm việc, và việc làm đó chưa được đưa vào stage (changes not staged for commit). Lúc này, nếu bạn thực hiện tiếp lệnh git rm thì tập tin sẽ bị xóa khỏi khu vực tổ chức. Ngược lại, nếu bạn không thực hiện tiếp lệnh git rm thì tập tin đó chỉ không xuất hiện trong thư mục làm việc, mà nó vẫn tồn tại trong khu vực tổ chức, và Git vẫn duy trì tập tin (nghĩa là Git xem việc xóa tập tin chưa hề xảy ra), nếu bạn thực hiện commit thì tập tin đó vẫn tồn tại trong dự án như chưa có hành động xóa.

$ git rm readme.txt
rm 'readme.txt'

$ git status
On branch master
Your branch is ahead of 'origin/master' by 13 commits.
  (use "git push" to publish your local commits)

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        deleted:    readme.txt

Lần commit tiếp theo, tập tin readme.txt sẽ bị xóa và không còn được theo dõi nữa.

Ở phần trên đã hướng dẫn xóa các tập tin đã được Git theo dõi và đã được commit ít nhất một lần.
Vậy với các tập tin chưa được Git theo dõi thì sao? Giả sử bạn vừa tạo một tập tin trong thư mục làm việc, sau đó xóa luôn bằng chức năng delete của File Explorer? Trong trường hợp này, Git xem như không có chuyện gì xảy ra, vì thực tế Git chưa theo dõi tập tin bạn vừa tạo rồi lại xóa luôn.

Một trường hợp khác: giả sử bạn tạo mới một tập tin, đã đưa nó vào stage (đã theo dõi), nhưng chưa commit lần nào hoặc bạn đã modified một tập tin. Trong trường hợp này Git không cho bạn xóa bằng lệnh git rm, vì Git sợ bạn sẽ vô tình xóa mất dữ liệu quan trọng mà không thể khôi phục lại được. Nếu bạn chắc chắn muốn xóa tập tin, thì phải sử dụng thêm tham số -f. (f là viết tắt của force).

Ví dụ,

– Tạo một tập tin trong thư mục làm việc (ví dụ: xoa.txt)

– Stage tập tin này bằng lệnh git add

$ git status
On branch master
Your branch is ahead of 'origin/master' by 14 commits.
  (use "git push" to publish your local commits)

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        new file:   xoa.txt

– Sử dụng lệnh git rm để xóa, Git sẽ thông báo lỗi

$ git rm xoa.txt
error: the following file has changes staged in the index:
    xoa.txt
(use --cached to keep the file, or -f to force removal)

– Thêm tham số -f để xóa

$ git rm -f xoa.txt
rm 'xoa.txt'

Ví dụ cho trường hợp modified một tập tin đã được Git theo dõi,

$ git status
On branch master
Your branch is ahead of 'origin/master' by 14 commits.
  (use "git push" to publish your local commits)

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   tailieu.txt

no changes added to commit (use "git add" and/or "git commit -a")

$ git rm tailieu.txt
error: the following file has local modifications:
    tailieu.txt
(use --cached to keep the file, or -f to force removal)

$ git rm -f tailieu.txt
rm 'tailieu.txt'

Trường hợp cuối cùng là bạn đã stage một tập tin, nhưng bạn chỉ muốn Git không theo dõi nó nữa, nhưng vẫn để nó tồn tại trên thư mục làm việc (trên đĩa cứng). Ngoài cách sử dụng .gitignore, bạn cũng có thể sử dụng lệnh git rm với tham số --cached.

Ví dụ,

$ git status
On branch master
Your branch is ahead of 'origin/master' by 15 commits.
  (use "git push" to publish your local commits)

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        new file:   cached.txt

$ git rm --cached cached.txt
rm 'cached.txt'

Sử dụng lệnh git rm, bạn có thể xóa tập tin, thư mục (thêm tham số -r) và các tập tin khớp với mẫu (pattern). Ví dụ,

Ví dụ xóa thư mục,

$ git rm -r thumuc/
rm 'thumuc/tm1.txt'

Ví dụ xóa tập tin khớp mới mẫu (xóa toàn bộ các tập tin có phần mở rộng là .log trong thư mục log):

$ git rm log/*.log

Ví dụ xóa toàn bộ các tập tin kết thúc bằng ~.

$ git rm \*~

Để xóa một tập tin trong thư mục làm việc, sử dụng lệnh $ rm tentaptin. Để xóa thư mục trong thư mục làm việc, sử dụng lệnh $ rm –r tenthumuc

Lab 15. Hiểu về các tình huống xóa tập tin.

Thực hiện tạo thư mục và tập tin tùy ý, sau đó thực hiện xóa tập tin/thư mục theo các trường hợp sau (ghi lại nội dung màn hình kết quả của mỗi trường hợp):

– Xóa tập tin từ khu vực stage, sau đó thực hiện commit

– Xóa tập tin (đã được theo dõi) tại thư mục làm việc (bằng File Explorer), sau đó thực hiện xóa trong khu vực stage, và commit

– Tạo tập tin trong thư mục làm việc, chạy lệnh git status để xem kết quả, xóa tập tin vừa tạo bằng File Explorer, chạy lệnh git status để xem kết quả

– Xóa một tập tin đã được theo dõi, đang trong stage

– Xóa một tập tin đang ở trạng thái modified

– Xóa một tập tin trong stage nhưng không xóa nó tại thư mục làm việc

– Xóa một thư mục

– Xóa toàn bộ các tập tin có phần mở rộng là .log

3.2.11     Đổi tên tập tin


Trong Git, việc di chuyển tập tin từ thư mục này qua thư mục khác cũng được xem như là đổi tên tập tin. Git không theo dõi việc đổi tên tập tin một cách tường minh. Nếu bạn thực hiện đổi tên trong Git không có thông tin nào ghi lại quá trình này.

Để thực hiện việc đổi tên, sử dụng lệnh git mv ten_cu ten_moi.

Ví dụ,

$ git mv taptin1.doc taptin2.doc

$ git status
On branch master
Your branch is ahead of 'origin/master' by 21 commits.
  (use "git push" to publish your local commits)

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        renamed:    taptin1.doc -> taptin2.doc

Lệnh $ git mv taptin1.doc taptin2.doc tương đương với 3 lệnh sau,

$ mv taptin1.doc taptin2.doc
$ git rm taptin1.doc

$ git add taptin2.doc

</////05
-----------
Cập nhật [08/10/2019]
-----------
Xem thêm: Tổng hợp các bài viết về Làm web
Xem thêm: Làm web (06) - Git: xem lịch sử commit