محتوای کامیتهای Claude Code چیست؟
ابزار Claude Code تریلر Co-authored-by و لینک نشستهای ابری را به تاریخچه گیت اضافه میکند. پیش از push کردن، با دستور git log -1 بررسی کنید چه متنی در کامیت شما ثبت شده است.
محتوای کامیتهای Claude Code
ابزار Claude Code یک تریلر Co-authored-by: به انتهای پیامهای کامیتی که مینویسد اضافه میکند و یک خط انتساب (attribution) نیز در توضیحات Pull Requestهایی که باز میکند قرار میدهد. نشستهایی (sessions) که در فضای ابری یا از طریق Remote Control اجرا میشوند، لینکی به آن نشست در claude.ai نیز ضمیمه میکنند. تمام این موارد متن سادهای هستند که در تاریخچه git شما ذخیره میشوند. هنگامی که این موارد را به یک مخزن عمومی push میکنید، اطلاعات عمومی میشوند و تا زمانی که شخصی تاریخچه را بازنویسی نکند، در آنجا باقی میمانند.
عبارت دقیق این متنها در نسخههای مختلف تغییر کرده است، بنابراین به کپی تریلر چاپشده در هیچ راهنمایی، از جمله همین راهنما، اعتماد نکنید. در عوض، کامیتهای خود را بررسی کنید. دستورات git زیر بخش پایدار این مبحث هستند: نحوه مدیریت تریلر در git سالهاست که به همین شکل کار میکند و پس از تغییر متن در نسخه بعدی نیز به همین روال به کار خود ادامه خواهد داد.
تریلر در Git چیست
تریلر خطی به شکل Token: value در آخرین بلوک از پیام commit است. Git هیچ فهرست ثابتی از توکنها ارائه نمیدهد. Signed-off-by:، Reviewed-by:، Fixes: و Co-authored-by: قراردادهایی هستند که بر پایه یک مکانیزم واحد بنا شدهاند و یک forge، یعنی سایتی که مخزن را میزبانی میکند (مانند GitHub یا GitLab)، آنها را میخواند تا تصمیم بگیرد چه چیزی را در صفحه commit نمایش دهد.
Git در مورد محل قرارگیری این بلوک سختگیر است. مستندات git interpret-trailers بیان میکند که این گروه باید با یک یا چند خط خالی پیشزمینه شود، در انتهای پیام یا بلافاصله قبل از خطی که با --- شروع میشود قرار گیرد، و یا باید تماماً شامل تریلر باشد یا «حداقل شامل یک تریلر تولید شده توسط Git یا پیکربندیشده توسط کاربر باشد و حداقل 25 درصد آن را تریلرها تشکیل دهند».
آن قانون آخر در اینجا اهمیت دارد. یک URL ساده یا یک خط متن عادی در داخل بلوک نهایی، تریلر محسوب نمیشود و وجود تعداد کافی از خطوط غیرتریلر باعث میشود کل بلوک به عنوان تریلر شناسایی نشود. به همین دلیل است که یک commit ممکن است به نظر برسد که دارای یک خط Co-authored-by: است، در حالی که تمام ابزارهایی که تریلرها را به درستی میخوانند، چیزی در آن نمیبینند.
چگونه میتوانم تریلرهای موجود در تاریخچه خود را بخوانم؟
با پیام خام آخرین کامیت شروع کنید.
git log -1 --format=%B%B موضوع و بدنه را دقیقاً همانطور که ذخیره شدهاند، بدون شکستن خطوط یا تغییر فرمت چاپ میکند. این خروجی، حقیقت محض است. هر چیزی که یک پلتفرم مدیریت کد (forge) به شما نشان میدهد، صرفاً یک رندر از آن است.
حالا از git بپرسید کدامیک از آن خطوط را به عنوان تریلر میشناسد.
git log -1 --format=%B | git interpret-trailers --parse--parse مخفف --only-trailers --only-input --unfold است، بنابراین خروجی فقط شامل بلوک تریلر است و هیچ چیز دیگری ندارد. نتیجه مطلوب، یک خط برای هر تریلر است. اگر با وجود مشاهده واضح یک خط Co-authored-by:، خروجی خالی باشد، به این معناست که بلوک تریلر از قوانین جایگذاری ذکر شده در بالا پیروی نمیکند.
برای اسکن کل تاریخچه، تریلر را بر اساس کلید آن جستجو کنید.
git log --format='%h %(trailers:key=Co-authored-by,valueonly)'نسخههای قدیمیتر git از گزینه key= در %(trailers) پشتیبانی نمیکنند. جستجو در متن پیام در همه نسخهها کار میکند.
git log -i --grep='^Co-authored-by:' --format='%h %an %s'--grep پیام کامیت را مطابقت میدهد و -i جستجو را نسبت به حروف کوچک و بزرگ حساس نمیکند؛ این موضوع مهم است زیرا حروفنویسی این تریلر در ابزارهای مختلف یکسان نبوده است. پیش از push کردن، دامنه جستجو را به مواردی که هنوز ارسال نکردهاید محدود کنید.
git log origin/main..HEAD --format=%Bآن کامیتها هنوز محلی هستند، به این معنی که هنوز میتوانید آنها را بهسادگی تغییر دهید.
دستور Co-authored-by: چه تأثیری بر انتساب (attribution) در GitHub دارد؟
GitHub این تریلر (trailer) را میخواند و نویسنده دوم را در صفحه commit نمایش میدهد. این کار تنها زمانی نویسنده را به یک پروفایل لینک میکند که آدرس ایمیل متعلق به یک حساب کاربری باشد. مستندات خود GitHub بیان میکند که commitها زمانی در نمودار مشارکت (contributions graph) ظاهر میشوند که «با آدرس ایمیلی انجام شده باشند که به حساب کاربری شما در GitHub متصل است»؛ بنابراین، آدرسی که متعلق به هیچکس نیست، نمیتواند به یک پروفایل متصل شود. برای یک جفت انسانی، هدف دقیقاً همین است: آدرس همکار شما در حساب کاربری او وجود دارد و commit برای هر دوی شما محاسبه میشود. برای آدرسی که هیچ حسابی مالک آن نیست، این تریلر تنها چیزی را که صفحه commit نمایش میدهد تغییر میدهد و لیست مشارکتکنندگان (contributor list) مخزن را دستنخورده باقی میگذارد.
خود Git این تریلر را کاملاً نادیده میگیرد. دستورات git shortlog -sn و git log --author هدر نویسنده را میخوانند که شامل نام و ایمیل شماست، بنابراین هیچ شمارش محلی (local count) هرگز نویسنده همکار (co-author) را نشان نخواهد داد. انتساب در اینجا یک قابلیت پلتفرم (forge) است که بر روی یک قرارداد متنی ساده لایهبندی شده است؛ قراردادی که در تفاوت بین خود git و پلتفرمی که آن را روی آن میزبانی میکنید نهفته است.
لینک نشست مسئله متفاوتی است
تریلر (trailer) نام یک نویسنده همکار را ذکر میکند. URL نشست، اشارهگری به یک رونوشت (transcript) است. تنظیمات Claude Code به سند attribution.sessionUrl به عنوان کلیدی اشاره دارد که «لینک نشست claude.ai را از کامیتهای ابری و Remote Control حذف میکند»؛ این موضوع همچنین منبع لینک را مشخص میکند: نشستهای تحت وب و نشستهایی که از طریق Remote Control هدایت میشوند.
این لینک یک اعتبارنامه (credential) نیست. اینکه آیا کسی میتواند آن نشست را باز کند یا خیر، توسط دسترسی به حساب کاربری تعیین میشود، نه با مخفی ماندن URL. دلیل دور نگه داشتن آن از مخازن عمومی سادهتر است. این لینک یک متن عمومی دائمی است که یک شناسه نشست داخلی را نام میبرد و به رونوشتی کاری اشاره دارد که هرگز برای مخاطب نوشته نشده است. در یک مخزن خصوصی، استدلال معکوس صادق است، زیرا بازبین (reviewer) میتواند لینک را دنبال کند و بخواند که چگونه تغییر حاصل شده است. اینکه آن رونوشتها کجا ذخیره میشوند و چه مدت باقی میمانند، در نحوه ذخیرهسازی و ازسرگیری نشستها توسط Claude Code پوشش داده شده است.
تنظیماتی که انتساب (attribution) کامیتهای Claude Code را کنترل میکنند
این کلیدها که در تاریخ 1 سپتامبر 2026 بر اساس مرجع تنظیمات Claude Code بررسی شدهاند، در بخش "Git and attribution" مستند شدهاند:
attribution: "سفارشیسازی انتسابی که Claude Code به کامیتها و pull requestها اضافه میکند"attribution.commit: "تغییر یا مخفیسازی trailer که Claude Code به کامیتها میافزاید"attribution.pr: "تغییر یا مخفیسازی خط انتساب در توضیحات pull request"attribution.sessionUrl: "حذف لینک نشست claude.ai از کامیتهای cloud و Remote Control"includeGitInstructions: "حذف دستورالعملهای پیشفرض کامیت و PR از system prompt"includeCoAuthoredBy: منسوخ شده است، با این یادداشت که "برای مخفیسازی یا تغییر انتساب کامیت و PR ازattributionاستفاده کنید"
مقدار قابلقبول برای هر کلید را از ورودی مربوط به آن در مرجع تنظیمات دریافت کنید و نه از راهنماها. نام کلیدها ثابت هستند. مقادیر پذیرفتهشده و پیشفرضها بخشهای متغیر هستند و اگر فایل تنظیمات دارای کلیدی با املای صحیح اما مقداری با املای نادرست باشد، بدون نمایش خطا از کار میافتد.
محل نوشتن تنظیمات تعیین میکند که چه کسی آن را دریافت میکند. ~/.claude/settings.json برای هر پروژهای که باز میکنید اعمال میشود. یک .claude/settings.json که در ریشه مخزن (repository) کامیت شده باشد، به دست هر کسی که آن را clone کند میرسد. .claude/settings.local.json مختص شما در همان پروژه است و Claude Code اولین باری که فایل را مینویسد، آن را به git excludes سراسری شما اضافه میکند تا در کامیتهایتان قرار نگیرد. اولویت اجرا به این صورت است: تنظیمات مدیریتشده، سپس خط فرمان، سپس تنظیمات محلی پروژه، سپس تنظیمات اشتراکی پروژه و در نهایت تنظیمات کاربر. بنابراین، فایل محلی یک همتیمی بر فایلی که شما کامیت کردهاید ارجحیت دارد؛ پس با یک تنظیم کامیتشده به عنوان یک پیشفرض برخورد کنید، نه یک تضمین.
سپس آن را تأیید کنید، زیرا اعتقاد شما به یک تنظیم، مدرک درستی آن نیست. اجازه دهید Claude Code کامیت بعدی را به روال معمول انجام دهد، سپس نتیجه را بررسی کنید.
git log -1 --format=%B
git log -1 --format=%B | git interpret-trailers --parseاگر trailer همچنان چاپ میشود، به این معنی است که تغییرات به نشست (session) اعمال نشده است. پیش از آنکه نتیجه بگیرید کلید خراب است، فایلی که ویرایش کردهاید و ترتیب اولویتهای ذکر شده در بالا را بررسی کنید.
کنترلهایی که به تنظیمات وابسته نیستند
یک تنظیمات، تنها یک ابزار را پیکربندی میکند. قانون مخزن (repository rule) باید در برابر مشارکتکنندهای که از ابزار متفاوتی استفاده میکند یا اصلاً از هیچ عاملی (agent) بهره نمیبرد، پایدار بماند. Git مکانی برای قرار دادن این قانون در اختیار شما میگذارد: هوک commit-msg با مسیر فایل پیام به عنوان اولین آرگومان اجرا میشود و میتواند آن فایل را ویرایش کرده یا commit را بهطور کامل رد کند.
#!/bin/sh
# .githooks/commit-msg
grep -qi '^co-authored-by: claude' "$1" || exit 0
grep -vi '^co-authored-by: claude' "$1" > "$1.new" && mv "$1.new" "$1"chmod +x .githooks/commit-msg
git config core.hooksPath .githooksاولین grep زمانی که کاری برای انجام دادن وجود ندارد، سریعاً خارج میشود، بنابراین یک commit معمولی تقریباً هیچ هزینهای ندارد. دومی، پیام را بدون خط منطبق بازنویسی میکند. به جای حذف تمام trailerها، یک توکن دقیق را مطابقت دهید، زیرا فیلتری که به صورت «حذف آخرین بلوک» نوشته شده باشد، ممکن است خط Signed-off-by: مورد نیاز پروژه را نیز حذف کند.
.git/hooks بخشی از مخزن نیست، بنابراین هوکی که در آنجا قرار میدهید هرگز به دست دیگران نمیرسد. core.hooksPath، گیت را به دایرکتوریای اشاره میدهد که میتوانید آن را commit کنید و هر شخص همچنان باید آن یک خط git config را خودش اجرا کند. گیت این کار را برای آنها انجام نمیدهد که این یک تصمیم عمدی است: مخزنی که بتواند هنگام clone کردن، فایلهای اجرایی خود را نصب کند، راهی برای اجرای کد روی دستگاه شما خواهد بود.
برای رد کردن commit به جای بازنویسی آن، پیامی را در standard error چاپ کرده و از هوک با exit 1 خارج شوید. رد کردن، انتخاب صادقانهتری در یک مخزن اشتراکی است، زیرا ویرایش بیسروصدای پیام commit دیگران، به جای آموزش قانون، آن را پنهان میکند. این لایه با هوکهای خودِ عامل (agent) متفاوت است؛ هوکهای عامل پیش از آنکه گیت درگیر شود و هنگام فراخوانی ابزار اجرا میشوند، و نحوه تطبیق و مسدودسازی ابزار توسط هوک Claude Code به آن بخش میپردازد.
هیچکدام از این موارد برای pull requestهای ارسالی از forkها کمکی نمیکنند، زیرا هوک روی دستگاهی قرار دارد که شما کنترلی بر آن ندارید. بررسی در CI (یکپارچهسازی مداوم) تنها لایهای است که هر commit را پیش از ادغام (merge) مشاهده میکند.
if git log --format=%B "origin/${BASE_BRANCH:-main}..HEAD" | grep -qi '^co-authored-by: claude'; then
echo "Attribution trailer found. Rewrite the branch before merging." >&2
exit 1
fiقانون را علاوه بر اعمال کردن، مکتوب کنید. فایل AGENTS.md در کنار فایل CONTRIBUTING.md که برای انسان قابل خواندن است، یک پیام واحد را هم به عامل و هم به شخص منتقل میکند و بررسی CI همان چیزی است که این قانون را به واقعیت تبدیل میکند.
حذف trailer پیش از push کردن
برای commit که بهتازگی انجام دادهاید:
git log -1 --format=%B | grep -vi '^co-authored-by: claude' | git commit --amend -F -دستور -F - پیام جدید را از standard input میخواند. Git خطوط خالی ابتدا و انتهای پیامی که به این روش ارسال شده باشد را حذف میکند، بنابراین خط خالی باقیمانده پس از حذف trailer، بهطور خودکار از بین میرود. پیش از ادامه کار، نتیجه را با git log -1 --format=%B بررسی کنید.
برای چندین commit روی یک branch، یک interactive rebase نسبت به branch مقصد (که قرار است merge در آن انجام شود) اجرا کنید و هر پیامی که قصد تغییر آن را دارید با reword علامتگذاری کنید.
git rebase -i origin/mainهر commit از اولین commit ویرایششده به بعد، یک hash جدید دریافت میکند؛ زیرا hash یک commit شامل پیام آن و parent آن است. این عملیات تا زمانی که commitها محلی (local) هستند رایگان است، اما پس از push شدن، هزینهبر خواهد بود.
حذف trailer پس از push کردن
در شاخهای که فقط شما از آن استفاده میکنید، آن را مطابق روش بالا بازنویسی کرده و سپس با force push جایگزین کنید.
git push --force-with-leaseدستور --force-with-lease در صورتی که remote از آخرین fetch شما تغییر کرده باشد، push را رد میکند تا نتواند commitهایی که شخص دیگری اضافه کرده است را بیسروصدا حذف کند. دستور ساده --force چنین بررسیای ندارد.
برای trailerهایی که در طول تاریخچه طولانی پخش شدهاند، git filter-repo تمام پیامها را در یک مرحله بازنویسی میکند. clone را از داخل کپی کاری فعلی خود اجرا کنید تا URL از همان remote که از قبل دارید، دریافت شود.
pip install git-filter-repo
git clone "$(git remote get-url origin)" ../project-rewrite
cd ../project-rewrite
git filter-repo --message-callback '
return b"\n".join(l for l in message.split(b"\n") if not l.lower().startswith(b"co-authored-by: claude"))
'callback هر پیام را به صورت بایت دریافت میکند و پیام نهایی را برای ذخیرهسازی بازمیگرداند؛ به همین دلیل است که هر رشته در آن دارای پیشوند b است. دستور filter-repo از اجرا روی مخزنی که یک clone تازه نیست خودداری میکند، مگر اینکه پرچم --force را ارسال کنید. همچنین این دستور پس از پایان کار، remote با نام origin را حذف میکند تا بهطور تصادفی بازنویسی را push نکنید. remote را دوباره بهصورت دستی اضافه کنید، force-push انجام دهید و سپس به همه اطلاع دهید که مخزن را دوباره clone کنند، زیرا تمام hashهایی که در اختیار دارند اکنون نامعتبر است.
در مورد کارهایی که بازنویسی نمیتواند انجام دهد شفاف باشید. این کار فقط کپی مخزن شما را تغییر میدهد. این عملیات به forkها، cloneهای موجود، mirrorها، صفحات pull request که قبلاً پیام را نقلقول کردهاند، یا ایندکس جستجوی کدی که هفته گذشته شما را crawl کرده است، دسترسی ندارد. برای یک secret لو رفته، راه حل اصلی چرخاندن (rotate) آن secret است و بازنویسی فقط نقش پاکسازی را دارد. یک trailer افشاگرانه، secret محسوب نمیشود؛ بنابراین بازنویسی کل تاریخچه را در برابر هزینههای آن، یعنی نیاز به بازسازی تمام pull requestهای باز، بسنجید.
آنچه بازبین در سمت دیگر انتظار دارد
نگهدارندگان پروژهها در این مورد اتفاقنظر ندارند و همین اختلافنظر، دلیل اصلی برای بررسی پیش از حذف هرگونه اطلاعات است. برخی پروژهها خواهان افشای اطلاعات هستند و از شما میخواهند آن را بازگردانید، زیرا بازبین، یک پچِ تولیدشده توسط ماشین را با دید متفاوتی بررسی میکند. برخی دیگر آن را ممنوع میکنند که اغلب به دلیل پرسش درباره هویت قانونی نویسنده تغییرات است. پروژههایی که از DCO (گواهی مبدأ توسعهدهنده) استفاده میکنند، به یک خط Signed-off-by: نیاز دارند؛ این خط بیانیهای است که شما درباره حق خود برای ارسال کد ارائه میدهید و یک فیلتر پیامِ بیدقت، آن را به همراه اطلاعات انتساب حذف میکند.
ابتدا فایل CONTRIBUTING.md را بخوانید. اگر پروژه در این باره چیزی نگفته است، یک قانون برای مخزن انتخاب کرده و آن را یادداشت کنید، زیرا تریلری که تنها در نیمی از کامیتها ظاهر شود، از هر دو حالت دیگر بدتر است: این کار باعث میشود تاریخچه پروژه مانند دو پروژه مجزا به نظر برسد.
اگر عامل (agent) را بهجای لپتاپ خود روی یک سرور اجرا کنید، همین پرسش یک لایه عمیقتر مطرح میشود. اجرای Claude Code روی یک VPS با حساب کاربری اختصاصی تعیین میکند که این عامل به کدام مخازن دسترسی دارد و آنچه یک عامل کدنویسی از دستگاه خارج میکند ترافیکی را پوشش میدهد که هرگز در پیام کامیت ظاهر نمیشود.
FAQ
آیا تریلر Co-authored-by برای Claude در آمار مشارکتکنندگان مخزن من محاسبه میشود؟
خیر. GitHub یک کامیت را از طریق آدرس ایمیل متصل به یک حساب کاربری GitHub به پروفایل شخص نسبت میدهد و مشارکتها را بر این اساس میشمارد. آدرسی که متعلق به هیچ حسابی نباشد قابل لینکشدن نیست، بنابراین تریلر صفحه کامیت را تغییر میدهد اما لیست مشارکتکنندگان بدون تغییر باقی میماند. خود Git هرگز تریلرها را برای این منظور نمیخواند. git shortlog -sn فقط هدر نویسنده (author) را میشمارد، بنابراین نویسنده همکار (co-author) هرگز در آنجا ظاهر نمیشود.
چگونه تمام کامیتهایی که از قبل دارای این تریلر هستند را پیدا کنم؟
git log -i --grep='^Co-authored-by:' --format='%h %an %s' آنها را در کل تاریخچه و بدون حساسیت به حروف بزرگ و کوچک لیست میکند. در نسخههای اخیر git، دستور git log --format='%h %(trailers:key=Co-authored-by,valueonly)' مقدار را از طریق پارسر تریلر خودِ git میخواند و به جای تطبیق متن خام، از آن استفاده میکند. برای مشاهده فقط مواردی که هنوز push نکردهاید، یک محدوده اضافه کنید: git log origin/main..HEAD --format=%B.
آیا میتوانم تریلر را از کامیتهایی که قبلاً push کردهام حذف کنم؟
بله، با بازنویسی تاریخچه، اما این کار هزینه واقعی دارد. در شاخهای که فقط خودتان از آن استفاده میکنید، از amend یا rebase استفاده کنید و سپس git push --force-with-lease را اجرا کنید. در یک شاخه اشتراکی، هر کامیت از اولین مورد ویرایششده به بعد، هش (hash) جدیدی دریافت میکند، بنابراین هر clone و هر pull request باز باید دوباره ساخته شود. همچنین بازنویسی هرگز به forkها، mirrorها یا cloneهایی که شخص دیگری دیروز ایجاد کرده است، نمیرسد.
آیا لینک نشست claude.ai در پیام کامیت یک ریسک امنیتی است؟
این لینک یک اعتبارنامه (credential) نیست و دسترسی به نشست توسط حساب کاربری تعیین میشود، نه با حدس زدن URL. مشکل اینجاست که این یک متن عمومی دائمی است که به یک رونوشت (transcript) به عنوان یادداشتهای کاری اشاره دارد. اسناد مرجع تنظیمات Claude Code، گزینه attribution.sessionUrl را به عنوان کلیدی معرفی میکند که آن لینک را از کامیتهای cloud و Remote Control حذف میکند، و یک هوک commit-msg آن را از هر چیزی که تنظیمات پوشش نمیدهد، پاکسازی میکند.
آیا باید انتساب (attribution) را کلاً غیرفعال کنم؟
این موضوع به مخزن بستگی دارد، نه به سلیقه شخصی. در یک پروژه عمومی، از فایل CONTRIBUTING.md پیروی کنید، زیرا نگهدارندهای (maintainer) که خواهان افشای این موضوع باشد، دوباره آن را درخواست خواهد کرد. در مخزن یک شرکت، نگه داشتن تریلر اغلب مفید است، زیرا به بازبین (reviewer) در یک سال بعد میگوید که چرا یک تغییر به آن شکل خاص است. یک بار برای کل مخزن تصمیم بگیرید و آن را در CI اعمال کنید تا تاریخچه ثابت بماند.