Chapters ▾ 2nd Edition

2.3 مقدمات گیت (git basics chapter) - مشاهده تاریخچه کامیت‌ها (Viewing the Commit History)

مشاهده تاریخچه کامیت‌ها (Viewing the Commit History)

بعد از این که چندین کامیت ایجاد کردید یا اگر یک مخزن با تاریخچه کامیت‌های موجود را کلون کردید، احتمالاً می‌خواهید به عقب برگردید و ببینید چه اتفاقی افتاده است. ابزار اصلی و قدرتمند برای انجام این کار دستور git log است.

در این مثال‌ها از یک پروژه بسیار ساده به نام simplegit استفاده شده است. برای دریافت این پروژه، دستور زیر را اجرا کنید:

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

وقتی در این پروژه دستور git log را اجرا می‌کنید، باید خروجی‌ای شبیه به این مشاهده کنید:

$ 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

به طور پیش‌فرض و بدون هیچ آرگومانی، git log فهرست کامیت‌های انجام شده در آن مخزن را به ترتیب معکوس زمانی نمایش می‌دهد؛ یعنی جدیدترین کامیت‌ها ابتدا نشان داده می‌شوند. همان‌طور که می‌بینید، این دستور هر کامیت را با چک‌سام SHA-1، نام و ایمیل نویسنده، تاریخ ثبت و پیام کامیت نشان می‌دهد.

گزینه‌های بسیار زیاد و متنوعی برای دستور git log وجود دارد که دقیقاً آنچه را که به دنبالش هستید به شما نشان می‌دهد. در اینجا، برخی از محبوب‌ترین آن‌ها را به شما معرفی می‌کنیم.

یکی از گزینه‌های بسیار مفید، -p یا --patch است که تغییرات (خروجی پچ) وارد شده در هر کامیت را نمایش می‌دهد. همچنین می‌توانید تعداد ورودی‌های لاگ نمایش داده شده را محدود کنید، مثلاً با استفاده از -2 فقط دو ورودی آخر را نشان دهید.

$ 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

این گزینه همان اطلاعات را نمایش می‌دهد اما با یک دیف (تغییرات) مستقیماً پس از هر ورودی. این برای مرور کد یا بررسی سریع آنچه در یک سری کامیت که همکار شما اضافه کرده، بسیار مفید است. شما همچنین می‌توانید از مجموعه‌ای از گزینه‌های خلاصه‌سازی با git log استفاده کنید. برای مثال، اگر بخواهید آمار مختصری از هر کامیت ببینید، می‌توانید گزینه --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(+)

همان‌طور که می‌بینید، گزینه --stat زیر هر ورودی کامیت فهرستی از فایل‌های تغییر یافته، تعداد فایل‌های تغییر کرده و تعداد خطوط اضافه یا حذف شده در آن‌ها را چاپ می‌کند. همچنین در پایان، خلاصه‌ای از این اطلاعات را ارائه می‌دهد.

گزینه مفید دیگر --pretty است. این گزینه خروجی لاگ را به قالب‌های دیگری غیر از پیش‌فرض تغییر می‌دهد. چند مقدار پیش‌ساخته برای این گزینه موجود است که می‌توانید استفاده کنید. مقدار oneline برای این گزینه هر کامیت را در یک خط نمایش می‌دهد که وقتی تعداد زیادی کامیت دارید، کاربردی است. علاوه بر این، مقادیر short، full و fuller خروجی را تقریباً در همان قالب اما به ترتیب با اطلاعات کمتر یا بیشتر نشان می‌دهند:

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

مهم‌ترین گزینه‌ی مقدار format است که به شما اجازه می‌دهد قالب خروجی لاگ خود را مشخص کنید. این گزینه به‌ویژه زمانی مفید است که خروجی را برای پردازش ماشینی تولید می‌کنید — زیرا قالب را به‌طور صریح تعیین می‌کنید، می‌دانید که با به‌روزرسانی‌های گیت تغییر نخواهد کرد:

$ 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

Useful specifiers for git log --pretty=format بخشی از مشخصه‌های مفیدتری را که گزینه format می‌پذیرد فهرست کرده است.

جدول 1. Useful specifiers for git log --pretty=format
Specifier Description 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

شاید برایتان سؤال باشد تفاوت بین نویسنده و ثبت‌کننده چیست. نویسنده کسی است که در اصل کار را نوشته، در حالی که ثبت‌کننده کسی است که آخرین بار تغییرات را اعمال کرده است. پس اگر شما یک پچ به پروژه ارسال کنید و یکی از اعضای اصلی آن پچ را اعمال کند، هر دو اعتبار می‌گیرید — شما به عنوان نویسنده و آن عضو اصلی به عنوان ثبت‌کننده. این تمایز را در گیت توزیع‌شده (Distributed git) بیشتر توضیح خواهیم داد.

مقادیر oneline و format به‌ویژه همراه با گزینه دیگری از log به نام --graph مفید هستند. این گزینه یک نمودار ASCII زیبا نشان می‌دهد که تاریخچه شاخه و ادغام شما را به تصویر می‌کشد:

$ git log --pretty=format:"%h %s" --graph
* 2d3acf9 Ignore errors from SIGCHLD on trap
*  5e3ee11 Merge branch 'master' of https://github.com/dustin/grit.git
|\
| * 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

این نوع خروجی در فصل بعدی که به شاخه‌بندی و ادغام می‌پردازیم، جذاب‌تر خواهد شد.

این‌ها تنها چند گزینه ساده برای قالب‌بندی خروجی git log بودند — گزینه‌های بسیار بیشتری وجود دارد. Common options to git log فهرستی از گزینه‌هایی که تا کنون بررسی کرده‌ایم به همراه برخی گزینه‌های رایج دیگر و نحوه تغییر خروجی دستور log ارائه می‌دهد.

جدول 2. Common options to git log
Option Description

-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. Option values include oneline, short, full, fuller, and format (where you specify your own format).

--oneline

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

محدود کردن خروجی لاگ (Limiting Log Output)

علاوه بر گزینه‌های فرمت‌بندی خروجی، دستور git log چندین گزینه محدودکننده مفید دارد؛ یعنی گزینه‌هایی که به شما اجازه می‌دهند تنها زیرمجموعه‌ای از کامیت‌ها را نمایش دهید. شما قبلاً یکی از این گزینه‌ها را دیده‌اید — گزینه -2 که فقط دو کامیت آخر را نشان می‌دهد. در واقع، می‌توانید از -<n> استفاده کنید، که n عدد صحیحی است و آخرین n کامیت را نمایش می‌دهد. اما در عمل، به ندرت از این گزینه زیاد استفاده می‌شود، چون به‌طور پیش‌فرض گیت تمام خروجی را از طریق یک صفحه‌بندی‌کننده (pager) عبور می‌دهد تا فقط یک صفحه از خروجی لاگ را در یک زمان ببینید.

با این حال، گزینه‌های محدودکننده زمانی مانند --since و --until بسیار کاربردی هستند. برای مثال، این دستور فهرستی از کامیت‌هایی که در دو هفته گذشته انجام شده‌اند را دریافت می‌کند:

$ git log --since=2.weeks

این دستور با فرمت‌های زیادی کار می‌کند — می‌توانید یک تاریخ خاص مانند "2008-01-15" یا یک تاریخ نسبی مانند "2 years 1 day 3 minutes ago" مشخص کنید.

همچنین می‌توانید لیست را به کامیت‌هایی که با برخی معیارهای جستجو مطابقت دارند، فیلتر کنید. گزینه --author به شما امکان می‌دهد روی نویسنده خاصی فیلتر کنید، و گزینه --grep اجازه می‌دهد کلمات کلیدی را در پیام‌های کامیت جستجو کنید.

یادداشت

می‌توانید بیش از یک نمونه از هر دو معیار جستجو --author و --grep را مشخص کنید، که خروجی کامیت را به کامیت‌هایی محدود می‌کند که با هر یک از الگوهای --author و هر یک از الگوهای --grep مطابقت دارند؛ اما افزودن گزینه --all-match خروجی را بیشتر محدود می‌کند تا فقط کامیت‌هایی که با تمام الگوهای --grep مطابقت دارند نمایش داده شوند.

یکی دیگر از فیلترهای بسیار مفید، گزینه -S است (که به طور غیررسمی به آن گزینه “pickaxe” گیت گفته می‌شود)، که یک رشته می‌گیرد و فقط آن کامیت‌هایی را نشان می‌دهد که تعداد وقوع آن رشته را تغییر داده‌اند. برای مثال، اگر بخواهید آخرین کامیتی که اشاره‌ای به یک تابع خاص را اضافه یا حذف کرده است پیدا کنید، می‌توانید این دستور را اجرا کنید:

$ git log -S function_name

آخرین گزینه واقعاً مفید برای عبور به git log به عنوان فیلتر، مسیر است. اگر یک دایرکتوری یا نام فایل را مشخص کنید، می‌توانید خروجی لاگ را به کامیت‌هایی محدود کنید که تغییری در آن فایل‌ها ایجاد کرده‌اند. این همیشه آخرین گزینه است و معمولاً با دو خط تیره (--) پیش از آن می‌آید تا مسیرها را از گزینه‌ها جدا کند:

$ git log -- path/to/file

در بخش Options to limit the output of git log این گزینه‌ها و چند گزینه رایج دیگر برای مرجع شما فهرست شده‌اند.

جدول 3. Options to limit the output of git log
Option Description

-<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.

برای مثال، اگر بخواهید ببینید کدام کامیت‌ها که فایل‌های تست را در تاریخچه سورس کد گیت تغییر داده‌اند، توسط جونیو هامانو در ماه اکتبر ۲۰۰۸ انجام شده‌اند و کامیت‌های ادغام (merge) نیستند، می‌توانید چیزی شبیه به این را اجرا کنید:

$ 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

از تقریباً ۴۰,۰۰۰ کامیت در تاریخچه کد منبع گیت، این دستور ۶ کامیت مطابق با این معیارها را نشان می‌دهد.

نکته
Preventing the display of merge commits

بسته به روند کاری که در مخزن شما استفاده می‌شود، ممکن است درصد قابل توجهی از کامیت‌های تاریخچه لاگ شما فقط کامیت‌های ادغام (merge commits) باشند که معمولاً اطلاعات زیادی ارائه نمی‌دهند. برای جلوگیری از نمایش کامیت‌های ادغام که باعث شلوغی تاریخچه لاگ می‌شوند، کافی است گزینه --no-merges را به دستور log اضافه کنید.

scroll-to-top