Git
Chapters ▾ 2nd Edition

2.3 پایه‌های گیت - دیدن تاریخچهٔ کامیت‌ها

دیدن تاریخچهٔ کامیت‌ها

پس از اینکه چندین کامیت انجام دادید، یا شاید یک مخزن را که خود تارخچه‌ای از کامیت‌ها را در بر دارد، کلون کردید، شاید بخواهید ببینید که در کامیت‌های پیشین چه پیش آمده است. یک ابزار بسیار اساسی و قدرتمند برای این کار دستور 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، نام و ایمیل نویسنده، تاریخ کامیت و پیام کامیت لیست می‌کند.

گستردگی آپشن‌ها و فلگ(flag)های موجود برای دستور 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

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

آپشن‌های مفید برای`git log --pretty=format` لیستی از آپشن مفید بیشتری که فلگ format اختیار می‌کند.

Table 1. آپشن‌های مفید برای`git log --pretty=format`
‌آپشن توضیحات

%H

هش کد کامیت

%h

خلاصه شده هش کد کامیت

%T

درخت هش

%t

خلاصه شده درخت هش

%P

هش کد پدر

%p

خلاصه شده هش کد پدر

%an

نام نویسنده

%ae

ایمیل نویسنده

%ad

تاریخ اصلی کامیت (با توجه به فرمت date--)

%ar

تاریخ اصلی کامیت و وابستگی‌ها

%cn

نام کامیت‌کننده

%ce

ایمیل کامیت‌کننده

%cd

تاریخ آخرین تغییر کامیت ثبت‌شده

%cr

تاریخ اخرین کامیت ثبت‌شده و وابستگی‌ها

%s

موضوع

شاید اول درباره author و committer متعجب شید و تفاوت آن دو را به خوبی درک نکنید.

نویسنده یا author در واقع شخصی اصلی بوده است که کار را انجام داده به طور مثال کد برنامه را نوشته، در حالی که کامیت‌کننده یا committer شخصی است که فعل کامیت را انجام داده و تغییرات را تایید کرده است این دو می‌توانند هر کدام شخص متفاوتی باشند و یا هر دو یک نفر باشند. پس اگر شما یک تیکه کد جدید به پروژه اضافه کنید و یکی از اعضای هسته پروژه آن قسمت را تایید کند هر دوی شما دارای اعتبار می‌شوید. شما به عنوان نویسنده آن و عضو هسته به عنوان شخص کامیت کننده. درمورد تشخیص بهتر فرق آن دو در قسمت گیت توزیع‌شده به طور مفصل بحث شده است.

آپشن oneline و format به طور ویژه‌ای با آپشنی دیگری از فعل ‍log مورد استفاده قرار می‌گیرد به نام graph--. این آپشن یک گراف ASCII کوچک و تمیز و زیبا برای نمایش شاخه‌ها و تاریخچه مرج نشان می‌دهد:

$ 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

مادامی که وارد فصل بعدی که درباره برنچ‌ها و مرج ست این نوع خروجی بیشتر مورد پسند واقع خواهد شد.

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

Table 2. آپشن‌های معمول دستور git log
آپشن‌ها توضیحات

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

محدود کردن خروجی لاگ

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

در واقعیت شما معمولاً از دستور استفاده نمی‌کنید چرا که خود گیت به صورت پیش‌فرض همه‌ٔخروجی‌ها را صفحه‌بندی می‌کند که شما فقط یک صفحه خروجی لاگ را در لحظه می‌بینید در حالی لاگ لیست بلند‌ بالایی است. با این حال، آپشن‌های محدود کردن زمان مانند since-- و until-- بسیار مورد استفاده و مفید هستند. — برای مثال، این دستور لیست کامیت‌های ساخته شده در دو هفته‌ی گذشته را نشان می‌دهد.

$ git log --since=2.weeks

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

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

Note

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

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

$ git log -S function_name

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

در بخش آپشن‌های مختلف برای خروجی git log ما به عنوان رفرنس شما بخشی کمی از آپشن‌های معمول را برای شما لیست خواهیم کرد.

Table 3. آپشن‌های مختلف برای خروجی 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

به عنوان مثال، می‌خواهیم کامیت‌های اصلاحیات فایل‌های تست در تاریخچه سورس کد گیت که توسط Junio Hamano در تاریخ October 2008 و مرج کامیت نیستند را ببینیم. شما می‌توانید با اجرای دستوری مانند دستور پایین چنین نتیجه‌آی را ببینید.

$ 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

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

Tip
جلوگیری از نمایش مرج کامیت‌ها

بسته به وضعیت روند کاری مورد استفاده در مخزن شما، این امکان وجود دارد که درصد قابل توجهی از کامیت‌ها فقط مرج کامیت باشند واقعاً نیاز به نمایش آنها نیست. برای جلوگیری از نمایش مرج کامیت‌ها به سادگی یک آپشن، --no-merges را به دستور اضافه کنید تا مرج کامیت‌ها را نمایش ندهد.