Git Pro: Những thao tác cơ bản khi làm việc với Git (P2) – Commit History & Undo

Chúng ta đã tìm hiểu những lệnh cơ bản khi sử dụng Git ở bài trước . Trong bài này chúng ta sẽ tiếp tục tìm hiểu kỹ hơn với các thao tác: xem lại lịch sử commit và hoàn tác những gì bạn đã làm.

2.3 Xem Lịch sử Commit

Xem lịch sử commit

Sau khi bạn đã tạo một số commit hoặc nếu bạn đã clone một kho lưu trữ với lịch sử commit hiện có, nếu bạn sẽ muốn nhìn lại xem những việc gì đã diễn ra. Công cụ cơ bản và mạnh mẽ nhất để làm điều này là git log .

Ví dụ này sử dụng một dự án rất đơn giản có tên là “simplegit”. Để có được dự án, thực hiện lệnh:

$ git clone https://github.com/schacon/simplegit-progit

Khi bạn chạy git log bạn sẽ nhận được output như sau:

$ git log
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Mon Mar 17 21:52:11 2008 -0700

    Change version number

commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 16:40:33 2008 -0700

    Remove unnecessary test

commit a11bef06a3f659402fe7563abf99ad00de2209e6
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 10:31:28 2008 -0700

    Initial commit

Theo mặc định, git log liệt kê các commit được thực hiện trong repo đó theo thứ tự thời gian đảo ngược; nghĩa là, các commit gần đây nhất xuất hiện đầu tiên. Lệnh này liệt kê từng commit với SHA-1, tên và email của tác giả, ngày commit và thông điệp commit.

Có nhiều tùy chọn có sẵn với git log để hiển thị những gì bạn đang tìm kiếm. Chúng ta cùng đi đến một số tuỳ chọn phổ biến nhất:

Đầu tiên là -p hoặc --patch , cho thấy sự khác biệt (output patch ) được đặt trong trong mỗi commit. Bạn có thể giới hạn số lượng mục được hiển thị, chẳng hạn như sử dụng -2 để chỉ hiển thị hai mục nhập cuối cùng.

$ git log -p -2
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Mon Mar 17 21:52:11 2008 -0700

    Change version number

diff --git a/Rakefile b/Rakefile
index a874b73..8f94139 100644
--- a/Rakefile
+++ b/Rakefile
@@ -5,7 +5,7 @@ require 'rake/gempackagetask'
 spec = Gem::Specification.new do |s|
     s.platform  =   Gem::Platform::RUBY
     s.name      =   "simplegit"
-    s.version   =   "0.1.0"
+    s.version   =   "0.1.1"
     s.author    =   "Scott Chacon"
     s.email     =   "schacon@gee-mail.com"
     s.summary   =   "A simple gem for using Git in Ruby code."

commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 16:40:33 2008 -0700

    Remove unnecessary test

diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index a0a60ae..47c6340 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -18,8 +18,3 @@ class SimpleGit
     end

 end
-
-if $0 == __FILE__
-  git = SimpleGit.new
-  puts git.show
-end

Tùy chọn này hiển thị sự khác biết sau mỗi mục.

Bạn cũng có thể sử dụng một loạt các tùy chọn tóm tắt với git log . Ví dụ: nếu muốn xem một số thông tin rút gọn cho mỗi commit, bạn có thể sử dụng tùy chọn --stat :

$ git log --stat
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Mon Mar 17 21:52:11 2008 -0700

    Change version number

 Rakefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 16:40:33 2008 -0700

    Remove unnecessary test

 lib/simplegit.rb | 5 -----
 1 file changed, 5 deletions(-)

commit a11bef06a3f659402fe7563abf99ad00de2209e6
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 10:31:28 2008 -0700

    Initial commit

 README           |  6 ++++++
 Rakefile         | 23 +++++++++++++++++++++++
 lib/simplegit.rb | 25 +++++++++++++++++++++++++
 3 files changed, 54 insertions(+)

Như bạn thấy, tùy chọn --stat in bên dưới mỗi mục commit một danh sách các tệp đã sửa đổi, có bao nhiêu tệp đã được thay đổi và có bao nhiêu dòng trong các tệp đó đã được thêm và xóa. Cuối cùng là tóm tắt thông tin ở cuối.

Tuỳ chọn --pretty . Tùy chọn này thay đổi đầu ra log thành các định dạng khác. Tùy chọn oneline in mỗi commit trên một dòng, nó rất hữu ích khi bạn xem nhiều commit. Ngoài ra, các tùy chọn short , full và fuller output hiển thị cùng định dạng nhưng có ít hoặc nhiều thông tin hơn:

$ git log --pretty=oneline
ca82a6dff817ec66f44342007202690a93763949 Change version number
085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 Remove unnecessary test
a11bef06a3f659402fe7563abf99ad00de2209e6 Initial commit

Một tuỳ chọn hay ho hơn mà bạn có thể chọn là format , cho phép bạn chỉ định định dạng đầu ra theo ý của  bạn. Như sau:

$ git log --pretty=format:"%h - %an, %ar : %s"
ca82a6d - Scott Chacon, 6 years ago : Change version number
085bb3b - Scott Chacon, 6 years ago : Remove unnecessary test
a11bef0 - Scott Chacon, 6 years ago : Initial commit

Các tùy chọn hữu ích cho git log --pretty=format

OptionDescription of Output

%H

Commit hash

%h

Abbreviated commit hash

%T

Tree hash

%t

Abbreviated tree hash

%P

Parent hashes

%p

Abbreviated parent hashes

%an

Author name

%ae

Author email

%ad

Author date (format respects the –date=option)

%ar

Author date, relative

%cn

Committer name

%ce

Committer email

%cd

Committer date

%cr

Committer date, relative

%s

Subject


oneline
format rất có ích với tùy chọn log khác như --graph .
 Tùy chọn này thêm một biểu đồ ASCII nhỏ hiển thị lịch sử nhánh của bạn:

$ git log --pretty=format:"%h %s" --graph
* 2d3acf9 Ignore errors from SIGCHLD on trap
*  5e3ee11 Merge branch 'master' of git://github.com/dustin/grit
|\
| * 420eac9 Add method for getting the current branch
* | 30e367c Timeout code and tests
* | 5a09431 Add timeout protection to grit
* | e1193f8 Support for heads with slashes in them
|/
* d6016bc Require time for xmlschema
*  11d191e Merge branch 'defunkt' into local

Đó chỉ là một số tùy chọn định dạng đầu ra đơn giản cho git log . Các tùy chọn phổ biến cho git log được liệt kê dưới đây:

OptionDescription

-p

Show the patch introduced with each commit.

--stat

Show statistics for files modified in each commit.

--shortstat

Display only the changed/insertions/deletions line from the –stat command.

--name-only

Show the list of files modified after the commit information.

--name-status

Show the list of files affected with added/modified/deleted information as well.

--abbrev-commit

Show only the first few characters of the SHA-1 checksum instead of all 40.

--relative-date

Display the date in a relative format (for example, “2 weeks ago”) instead of using the full date format.

--graph

Display an ASCII graph of the branch and merge history beside the log output.

--pretty

Show commits in an alternate format. Options include oneline, short, full, fuller, and format (where you specify your own format).

--oneline

Shorthand for --pretty=oneline --abbrev-commit used together.

Giới hạn của output log

Ngoài các tùy chọn format output, git log có một số tùy chọn khác cho phép bạn chỉ hiển thị số lượng nhỏ commit. Ví dụ như  -2 , chỉ hiển thị hai lần commit cuối cùng. Bạn có thể áp dụng tương tự với -<n> , n là bất kỳ số nguyên nào để hiển thị n lần commit cuối cùng. Bạn không nên sử dụng lệnh này thường xuyên, vì Git mặc định tất cả các output đều thông qua một pager để bạn chỉ nhìn thấy một trang log output.

Tuy nhiên, vẫn có các tuỳ chọn khác như  --since và --until. Ví dụ: lệnh này đưa ra danh sách các commit được thực hiện trong hai tuần qua:

$ git log --since=2.weeks

Lệnh trên hoạt động với nhiều định dạng – bạn có thể chỉ định một ngày cụ thể như "2008-01-15" hoặc tương đối như "2 years 1 day 3 minutes ago" .

Bạn cũng có thể lọc để commit phù hợp với một số tiêu chí tìm kiếm, như –author cho phép bạn lọc theo một author cụ thể và tùy chọn --grep cho phép bạn tìm kiếm từ khóa trong thông điệp commit.

Tùy chọn -S (được gọi chung là tùy chọn Pickitaxe của Git). Ví dụ: nếu bạn muốn tìm commit cuối cùng đã thêm hoặc xóa tham chiếu đến một chức năng cụ thể, bạn có thể gọi:

$ git log -S function_name

Tùy chọn cuối cùng là một đường dẫn. Nếu bạn chỉ định một thư mục hoặc tên tệp, bạn có thể giới hạn đầu ra log commit. Đây luôn là tùy chọn cuối cùng và thường được bắt đầu bằng dấu gạch ngang kép ( -- ) để tách các đường dẫn khỏi các tùy chọn.

Một vài tùy chọn phổ biến khác để bạn tham khảo.

OptionDescription

-<n>

Show only the last n commits

--since--after

Limit the commits to those made after the specified date.

--until--before

Limit the commits to those made before the specified date.

--author

Only show commits in which the author entry matches the specified string.

--committer

Only show commits in which the committer entry matches the specified string.

--grep

Only show commits with a commit message containing the string

-S

Only show commits adding or removing code matching the string

Ví dụ: nếu bạn muốn xem trong lịch sử commit Git, commit nào được tạo bởi “Junio C Hamano”  trong thời gian từ “2008-10-01” đến “2008-11-01” sửa đổi các tệp test. Bạn có thể chạy một lệnh như:

$ git log --pretty="%h - %s" --author='Junio C Hamano' --since="2008-10-01" \
   --before="2008-11-01" --no-merges -- t/
5610e3b - Fix testcase failure when extended attributes are in use
acd3b9e - Enhance hold_lock_file_for_{update,append}() API
f563754 - demonstrate breakage of detached checkout with symbolic link HEAD
d1a43f2 - reset --hard/read-tree --reset -u: remove unmerged new paths
51a94af - Fix "checkout --track -b newbranch" on detached HEAD
b0ad11e - pull: allow "git pull origin $something:$current_branch" into an unborn branch

Trong số gần 40.000 commit trong lịch sử, lệnh này hiển thị 6 kết quả phù hợp với các tiêu chí đó.

2.4 Hoàn tác

Undoing

Ở bất kỳ stage nào, bạn có thể muốn hoàn tác( undo) một cái gì đó. Trong mục này, chúng tôi sẽ giới thiệu một vài công cụ cơ bản để hoàn tác các thay đổi mà bạn đã thực hiện. Nhưng hãy chú ý nhé, bởi vì không phải tất cả mọi thứ đều có thể hoàn tác.

Một trong những lần undo phổ biến diễn ra khi bạn commit quá sớm và khi đó bạn quên add một số tệp hoặc thông điệp commit của bạn bị sai. Nếu bạn muốn làm lại commit đó, hãy thực hiện các thay đổi mà bạn đã quên, thực hiện chúng và commit lại bằng tùy chọn --amend :

$ git commit --amend

Lệnh này lấy stage và dùng cho commit. Nếu bạn không thực hiện thay đổi nào kể từ lần commit cuối cùng (ví dụ: bạn chạy lệnh này ngay sau lần commit trước đó), thì snapshot của bạn sẽ giống hệt nhau, và tất cả những gì bạn thay đổi chỉ là thông điệp của commit.

Với cùng một commit trình chỉnh sửa thông điệp được kích hoạt, nó vẫn chứa thông điệp của commit trước đó của bạn. Bạn có thể chỉnh sửa thông điệp giống như mọi khi, nhưng nó sẽ ghi đè lên commit trước đó của bạn.

Ví dụ: nếu bạn commit và sau đó nhớ ra rằng bạn đã quên thực hiện các thay đổi trong một vài tệp bạn muốn thêm vào commit này, bạn có thể thực hiện như sau:

$ git commit -m 'Initial commit'
$ git add forgotten_file
$ git commit --amend

Nó thể hiện rằng, bạn kết thúc với một commit – commit thứ hai thay thế kết quả của lần commit đầu tiên.

Unstaging một tập tin Staged

Có một điều thú vị là khi bạn sử dụng lệnh lệnh git status output của lệnh cũng nhắc bạn cách hoàn tác các thay đổi. Ví dụ: giả sử bạn đã thay đổi hai tệp và muốn commit chúng là hai thay đổi riêng biệt, nhưng bạn lại vô tình nhập git add * . Làm thế nào bạn có thể bỏ qua một trong hai thay đổi trên? Lệnh git status có nhắc bạn:

$ git add *
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    README.md -> README
    modified:   CONTRIBUTING.md

Ngay bên dưới dòng “Changes to be committed” nói rằng hãy sử dụng git reset HEAD <file>... để unstage. Vì vậy, hãy sử dụng lời khuyên đó để bỏ qua tệp CONTRIBUTING.md :

$ git reset HEAD CONTRIBUTING.md
Unstaged changes after reset:
M	CONTRIBUTING.md
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    README.md -> README

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:   CONTRIBUTING.md

Tệp CONTRIBUTING.md được sửa đổi nhưng unstaged.

Unmodifying một tập tin Modified

Nếu bạn không muốn giữ lại các thay đổi đối với tệp CONTRIBUTING.md ? Vậy bạn phải làm thế nào? – làm sao để đưa file của bạn chở lại như trước khi bạn commit (hoặc như khi bạn vừa thực hiện clone)? Rất may mắn git status cũng cho biết ta cần làm gì trong trường hợp này. Trong output ở ví dụ trên, unstaged được liệt kê như sau:

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:   CONTRIBUTING.md

Output trên cho bạn biết khá rõ cách để loại bỏ những thay đổi mà bạn đã thực hiện. Chúng ta làm theo đề nghị:

$ git checkout -- CONTRIBUTING.md
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    README.md -> README

Bạn có thể thấy rằng những thay đổi đã được hoàn nguyên.

Các bạn hãy nhớ rằng, bất kỳ thứ gì được commit trong Git hầu như luôn có thể được phục hồi. Cả các commit trên các nhánh đã bị xóa hoặc các commit được ghi đè bằng một commit --amend cũng vậy. Tuy nhiên, bất cứ thứ gì bạn không commit thì sẽ không bao giờ tìm lại được.

 

Add a Comment

Scroll Up