| GIT-PUSH(1) | دستورات عمومی کاربر | GIT-PUSH(1) |
نام (NAME)
git-push - بهروزرسانی ارجاعهای دوردست همراه با اشیاء مرتبط
خلاصه دستور (SYNOPSIS)
git push [--all | --branches | --mirror | --tags] [--follow-tags] [--atomic] [-n | --dry-run] [--receive-pack=<git-receive-pack>]
[--repo=<repository>] [-f | --force] [-d | --delete] [--prune] [-q | --quiet] [-v | --verbose]
[-u | --set-upstream] [-o <string> | --push-option=<string>]
[--[no-]signed | --signed=(true|false|if-asked)]
[--force-with-lease[=<refname>[:<expect>]] [--force-if-includes]]
[--no-verify] [<repository> [<refspec>...]]
توضیحات (DESCRIPTION)
یک یا چند شاخه، برچسب یا سایر ارجاعها را در یک یا چند مخزن دوردست از مخزن محلی شما بهروزرسانی میکند و تمام دادههای لازم را که از قبل روی مخزن دوردست وجود ندارند ارسال مینماید.
سادهترین روش برای ارسال، استفاده از دستور git push <remote> <branch> است. دستور git push origin main شاخه محلی main را به شاخه main در مخزن دوردست با نام origin ارسال میکند.
همچنین میتوانید با استفاده از یک گروه مخزن دوردست (remote group)، بهطور همزمان به چندین مخزن دوردست ارسال انجام دهید. یک گروه مخزن دوردست، فهرستی نامگذاریشده از مخازن دوردست است که از طریق remotes.<name> در پیکربندی گیت شما تنظیم میشود:
$ git config remotes.all-remotes "origin gitlab backup"
سپس دستور git push all-remotes به نوبت به origin، gitlab و backup ارسال انجام میدهد، گویی که git push را برای هر یک به صورت جداگانه اجرا کرده باشید. ارسال به هر مخزن دوردست بهطور مستقل با استفاده از پیکربندی نگاشت ارسال (push mapping) مخصوص به خود انجام میشود. یک مدخل remotes.<group> در فایل پیکربندی وجود دارد. (به git-config(1) مراجعه کنید).
مقدار پیشفرض آرگومان <repository>، مخزن بالادست (upstream) برای شاخه جاری است، یا اگر بالادستی پیکربندی نشده باشد، برابر با origin خواهد بود.
برای تصمیمگیری درباره اینکه کدام شاخهها، برچسبها یا سایر ارجاعها ارسال شوند، Git به ترتیب اولویت از موارد زیر استفاده میکند:
بسته به اینکه push.default روی چه مقداری تنظیم شده باشد، اگر بالادست (upstream) را برای شاخه جاری تنظیم نکرده باشید ممکن است اجرای git push با شکست مواجه شود. برای اطلاعات بیشتر در مورد نحوه تنظیم و استفاده از بالادستها به بخش «شاخههای بالادست (UPSTREAM BRANCHES)» در زیر مراجعه کنید.
میتوانید با تنظیم قلابها (hooks) در یک مخزن، کاری کنید که با هر بار ارسال (push) به آن، رویدادهای سفارشی مدنظرتان اجرا شوند. به مستندات git-receive-pack(1) مراجعه کنید.
گزینهها (OPTIONS)
<repository>
<refspec>...
قالب یک مشخصه ارجاع (refspec) بهصورت [+]<src>[:<dst>] است، برای مثال main، main:other، یا HEAD^:refs/heads/main.
بخش <src> اغلب نام شاخهٔ محلی برای ارسال است، اما میتواند هر «عبارت SHA-1» دلخواهی باشد (ببینید gitrevisions(7)).
بخش <dst> مشخص میکند چه ارجاعی در سمت دوردست بهروزرسانی شود. این مقدار باید نام یک شاخه، برچسب، یا ارجاع دیگری باشد، نه یک عبارت دلخواه.
علامت + اختیاری است و عملکردی مشابه --force دارد.
میتوانید یک مشخصه ارجاع را با استفاده از شکل کاملاً بسطیافته بنویسید (برای مثال refs/heads/main:refs/heads/main) که دقیقاً منبع و مقصد را مشخص میکند، یا با شکلی کوتاهتر (برای مثال main یا main:other). در ادامه قوانینی برای چگونگی بسط مشخصههای ارجاع و همچنین سایر شکلهای ویژه مختلف مشخصه ارجاع آورده شده است:
همهٔ بهروزرسانیها مجاز نیستند: برای جزئیات بخش PUSH RULES را در زیر ببینید.
--all, --branches
--prune
--mirror
-n, --dry-run
--porcelain
-d, --delete
--tags
--follow-tags
--signed, --no-signed, --signed=(true|false|if-asked)
false, --no-signed
true, --signed
if-asked
--atomic, --no-atomic
-o <option>, --push-option=<option>
--receive-pack=<git-receive-pack>, --exec=<git-receive-pack>
--force-with-lease, --no-force-with-lease, --force-with-lease=<refname>, --force-with-lease=<refname>:<expect>
این گزینه در صورتی که مقدار فعلی ارجاع دوردست همان مقدار مورد انتظار باشد، این محدودیت را لغو میکند. در غیر این صورت git push با شکست مواجه میشود.
تصور کنید باید چیزی را که قبلاً منتشر کردهاید بازپایهریزی (rebase) کنید. برای جایگزین کردن تاریخچهای که قبلاً منتشر کردهاید با تاریخچه بازپایهریزیشده، باید قانون «الزام به جلوبردن سریع» (must fast-forward) را دور بزنید. اگر در زمان بازپایهریزی شما، فرد دیگری کارهای خود را بر روی تاریخچه اصلی شما بنا کرده باشد، نوک شاخه در دوردست ممکن است با کامیت آنها به جلو رفته باشد، و ارسال کورکورانه با --force باعث از دست رفتن کار آنها خواهد شد.
این گزینه به شما امکان میدهد اعلام کنید انتظار دارید تاریخچهای که در حال بهروزرسانی آن هستید همان چیزی باشد که بازپایهریزی کردهاید و میخواهید جایگزین کنید. اگر ارجاع دوردست همچنان به کامیتی اشاره میکند که شما مشخص کردهاید، میتوانید مطمئن باشید که هیچ فرد دیگری تغییری در ارجاع ایجاد نکرده است. این مانند گرفتن یک «اجاره / پیمان» (lease) روی ارجاع بدون قفل کردن صریح آن است، و ارجاع دوردست تنها در صورتی بهروزرسانی میشود که «اجاره / پیمان» همچنان معتبر باشد.
--force-with-lease بهتنهایی و بدون مشخص کردن جزئیات، با الزام به اینکه مقدار فعلی ارجاعهای دوردست برابر با شاخه ردیاب دوردستی (remote-tracking branch) باشد که برای آنها داریم، از تمام ارجاعهای دوردستی که قرار است بهروزرسانی شوند محافظت میکند.
--force-with-lease=<refname>، بدون مشخص کردن مقدار مورد انتظار، در صورتی که <refname> قرار باشد بهروزرسانی شود، (بهتنهایی) از آن محافظت میکند؛ با الزام به اینکه مقدار فعلی آن برابر با شاخه ردیاب دوردستی باشد که برای آن داریم.
--force-with-lease=<refname>:<expect> در صورتی که <refname> قرار باشد بهروزرسانی شود، (بهتنهایی) از آن محافظت میکند؛ با الزام به اینکه مقدار فعلی آن برابر با مقدار مشخصشده <expect> باشد (که مجاز است با شاخه ردیاب دوردستی که برای refname داریم متفاوت باشد، یا حتی هنگام استفاده از این قالب نیازی به داشتن چنین شاخه ردیاب دوردستی نداریم). اگر <expect> رشته خالی باشد، در این صورت ارجاع نامبردهشده نباید از قبل وجود داشته باشد.
توجه داشته باشید که تمام حالتها به جز --force-with-lease=<refname>:<expect> که مقدار فعلی مورد انتظار ارجاع را صراحتاً مشخص میکند، همچنان آزمایشی هستند و با کسب تجربه بیشتر از این ویژگی، ممکن است معناشناسی آنها تغییر کند.
--no-force-with-lease تمام موارد قبلی --force-with-lease در خط فرمان را لغو خواهد کرد.
یک نکته کلی درباره ایمنی: ارائه این گزینه بدون مقدار مورد انتظار، یعنی به صورت --force-with-lease یا --force-with-lease=<refname>، با هر چیزی که به طور ضمنی git fetch را در پسزمینه روی مخزن دوردستِ مقصد اجرا میکند (برای نمونه اجرای git fetch origin روی مخزن شما در یک cronjob)، تداخل بسیار نامناسبی ایجاد میکند.
محافظتی که این گزینه نسبت به --force ارائه میدهد این است که اطمینان حاصل میکند تغییرات بعدی که کار شما بر پایه آنها نبوده است پایمال (clobber) نشوند، اما اگر فرآیندی در پسزمینه در حال بهروزرسانی ارجاعها باشد، این حفاظت به سادگی بیاثر میشود. ما هیچ چیزی جز اطلاعات ردیابی دوردست نداریم که به عنوان معیار اکتشافی برای ارجاعهایی که انتظار میرود دیدهاید و مایل به بازنویسی آنها هستید به آن اتکا کنیم.
اگر ویرایشگر شما یا سامانه دیگری git fetch را در پسزمینه برای شما اجرا میکند، یک راه برای کاهش این اثر این است که صرفاً یک دوردست (remote) دیگر تنظیم کنید:
git remote add origin-push $(git config remote.origin.url) git fetch origin-push
اکنون هنگامی که فرآیند پسزمینه git fetch origin را اجرا میکند، ارجاعها روی origin-push بهروزرسانی نخواهند شد، و بنابراین دستوراتی مانند:
git push --force-with-lease origin-push
با شکست مواجه خواهند شد مگر اینکه بهصورت دستی git fetch origin-push را اجرا کنید. البته این روش نیز در صورت اجرای چیزی که git fetch --all را اجرا کند کاملاً بیاثر میشود؛ در آن صورت باید یا آن را غیرفعال کنید یا کار خستهکنندهتری مانند این انجام دهید:
git fetch # update 'master' from remote git tag base master # mark our base point git rebase -i master # rewrite some commits git push --force-with-lease=master:base master:master
یعنی یک تگ base برای نسخههایی از کد بالادست که دیدهاید و مایل به بازنویسی آنها هستید ایجاد کنید، سپس تاریخچه را بازنویسی نمایید، و در نهایت در صورتی که نسخه دوردست همچنان روی base باشد، تغییرات را با اجبار به master ارسال کنید، صرفنظر از اینکه remotes/origin/master محلی شما در پسزمینه به چه چیزی بهروزرسانی شده است.
به عنوان روش جایگزین، مشخص کردن --force-if-includes به عنوان یک گزینه کمکی همراه با --force-with-lease[=<refname>] (یعنی بدون مشخص کردن اینکه ارجاع در سمت دوردست دقیقاً باید به چه کامیتی اشاره کند، یا از کدام ارجاعها در سمت دوردست محافظت میشود) در زمان «ارسال» (push)، قبل از اجازه دادن به بهروزرسانی اجباری بررسی خواهد کرد که آیا بهروزرسانیهای ارجاعهای ردیاب دوردست که ممکن است به طور ضمنی در پسزمینه بهروز شده باشند، به صورت محلی ادغام شدهاند یا خیر.
-f, --force
این فلگ آن بررسی، سایر بررسیهای ایمنی در PUSH RULES در زیر، و بررسیهای --force-with-lease را غیرفعال میکند. این گزینه میتواند باعث شود مخزن دوردست کامیتهایی را از دست بدهد؛ با احتیاط از آن استفاده کنید.
توجه داشته باشید که --force برای تمام ارجاعهای در حال ارسال اعمال میشود، بنابراین استفاده از آن هنگامی که push.default روی matching تنظیم شده باشد یا با چندین مقصد ارسال که با remote.<name>.push پیکربندی شدهاند، ممکن است ارجاعهایی غیر از شاخه جاری را بازنویسی کند (از جمله ارجاعهای محلی که کاملاً عقبتر از همتای دوردست خود هستند). برای اجبار ارسال تنها به یک شاخه، از یک + در ابتدای مشخصه ارجاع (refspec) برای ارسال استفاده کنید (به عنوان مثال git push origin +master برای اجبار ارسال به شاخه master). برای جزئیات بیشتر بخش <refspec>... در بالا را ببینید.
--force-if-includes, --no-force-if-includes
این گزینه بررسیای را فعال میکند که بررسی مینماید آیا نوک ارجاع ردیابی دوردست از یکی از مدخلهای «reflog» شاخه محلی که برای بازنویسی بر پایه آن بوده قابل دستیابی است یا خیر. این بررسی با رد کردن بهروزرسانی اجباری در صورتی که چنین نباشد، تضمین میکند که هرگونه بهروزرسانی از سمت دوردست بهصورت محلی ادغام شده باشد.
اگر این گزینه بدون تعیین --force-with-lease ارسال شود، یا همراه با --force-with-lease=<refname>:<expect> مشخص شود، یک «no-op» (بیاثر) خواهد بود.
مشخص کردن --no-force-if-includes این رفتار را غیرفعال میکند.
--repo=<repository>
-u, --set-upstream
--thin, --no-thin
-q, --quiet
-v, --verbose
--progress
--no-recurse-submodules, --recurse-submodules=(check|on-demand|only|no)
check
on-demand
only
no
هنگام استفاده از on-demand یا only، اگر یک زیرماژول دارای پیکربندی push.recurseSubmodules=(on-demand|only) یا submodule.recurse باشد، بازگشت بیشتری رخ خواهد داد. در این حالت، با only مانند on-demand رفتار میشود.
--verify, --no-verify
-4, --ipv4
-6, --ipv6
نشانیهای وب گیت (GIT URLS)
بهطور کلی، نشانیها (URL) حاوی اطلاعاتی درباره پروتکل انتقال، نشانی سرور دوردست و مسیر مخزن هستند. بسته به پروتکل انتقال، ممکن است برخی از این اطلاعات وجود نداشته باشند.
گیت از پروتکلهای ssh، git، http و https پشتیبانی میکند (علاوه بر این، ftp و ftps میتوانند برای واکشی استفاده شوند، اما این کار ناکارآمد و منسوخ است؛ از آنها استفاده نکنید).
انتقال بومی (یعنی نشانی git://) هیچگونه احراز هویتی انجام نمیدهد و باید در شبکههای ناامن با احتیاط استفاده شود.
نحوهای زیر میتوانند با آنها استفاده شوند:
همچنین میتوان یک نحو جایگزین شبیه scp را با پروتکل ssh استفاده کرد:
این نحو تنها در صورتی تشخیص داده میشود که هیچ اسلشی قبل از اولین دونقطه نباشد. این امر به تمایز مسیر محلی که حاوی دونقطه است کمک میکند. برای نمونه، مسیر محلی foo:bar میتواند بهصورت یک مسیر مطلق یا ./foo:bar مشخص شود تا از تفسیر نادرست آن بهعنوان یک نشانی ssh جلوگیری شود.
پروتکلهای ssh و git علاوه بر این از بسط ~<username> پشتیبانی میکنند:
برای مخازن محلی، که بهطور بومی توسط گیت نیز پشتیبانی میشوند، میتوان از نحوهای زیر استفاده کرد:
این دو نحو عمدتاً معادل هستند، به جز هنگام کلون کردن که اولی متضمن گزینه --local است. برای جزئیات به git-clone(1) مراجعه کنید.
دستورهای git clone، git fetch و git pull (اما نه git push) یک فایل باندل مناسب را نیز میپذیرند. به git-bundle(1) مراجعه کنید.
هنگامی که گیت روش کار با یک پروتکل انتقال معین را نمیداند، تلاش میکند از دستیار دوردست remote-<transport> در صورت وجود استفاده کند. برای درخواست صریح یک دستیار دوردست، میتوان از نحو زیر استفاده کرد:
که در آن <address> میتواند یک مسیر، یک سرور و مسیر، یا یک رشته دلخواه شبیه نشانی باشد که توسط دستیار دوردست مربوطه فراخوانیشده شناسایی میشود. برای جزئیات به gitremote-helpers(7) مراجعه کنید.
اگر تعداد زیادی مخزن دوردست با نامهای مشابه وجود دارد و میخواهید قالب متفاوتی برای آنها استفاده کنید (به گونهای که نشانیهای مورداستفاده شما به نشانیهایی که کار میکنند بازنویسی شوند)، میتوانید یک بخش پیکربندی به این شکل بسازید:
[url "<actual-url-base>"]
insteadOf = <other-url-base>
برای نمونه، با این تنظیم:
[url "git://git.host.xz/"]
insteadOf = host.xz:/path/to/
insteadOf = work:
یک نشانی مانند "work:repo.git" یا مانند "host.xz:/path/to/repo.git" در هر زمینهای که یک نشانی میپذیرد به "git://git.host.xz/repo.git" بازنویسی خواهد شد.
اگر میخواهید نشانیها را فقط برای ارسال (push) بازنویسی کنید، میتوانید یک بخش پیکربندی به این شکل بسازید:
[url "<actual-url-base>"]
pushInsteadOf = <other-url-base>
برای نمونه، با این تنظیم:
[url "ssh://example.org/"]
pushInsteadOf = git://example.org/
یک نشانی مانند "git://example.org/path/to/repo.git" برای ارسالها به "ssh://example.org/path/to/repo.git" بازنویسی میشود، اما دریافتها (pull) همچنان از نشانی اصلی استفاده خواهند کرد.
مخازن دوردست (REMOTES)
نام یکی از موارد زیر میتواند به عنوان آرگومان <repository> بهجای نشانی (URL) استفاده شود:
همه این موارد همچنین به شما این امکان را میدهند که مشخصه ارجاع (refspec) را از خط فرمان حذف کنید زیرا هر یک از آنها حاوی یک مشخصه ارجاع هستند که گیت بهطور پیشفرض از آن استفاده خواهد کرد.
مخزن دوردست نامگذاریشده در فایل پیکربندی
میتوانید نام یک مخزن دوردست را که پیشتر با استفاده از git-remote(1)، git-config(1) یا حتی با ویرایش دستی فایل $GIT_DIR/config پیکربندی کردهاید، مشخص کنید. نشانی (URL) این مخزن دوردست برای دسترسی به مخزن استفاده خواهد شد. اگر در خط فرمان مشخصه ارجاعی را ارائه ندهید، مشخصه ارجاع این مخزن دوردست بهطور پیشفرض استفاده خواهد شد. مدخل مربوطه در فایل پیکربندی به این صورت خواهد بود:
[remote "<name>"]
url = <URL>
pushurl = <pushurl>
push = <refspec>
fetch = <refspec>
پارامتر <pushurl> فقط برای ارسالها (push) استفاده میشود. این پارامتر اختیاری است و مقدار پیشفرض آن <URL> میباشد. ارسال (push) به یک مخزن دوردست بر تمام pushurlهای تعریفشده یا تمام urlهای تعریفشده (در صورت عدم تعریف هیچ pushurl) اعمال میشود. با این حال، fetch در صورتی که چندین url تعریف شده باشد، تنها از اولین url تعریفشده دریافت خواهد کرد.
فایل نامگذاریشده در $GIT_DIR/remotes
میتوانید نام فایلی را در $GIT_DIR/remotes مشخص کنید. نشانی (URL) موجود در این فایل برای دسترسی به مخزن استفاده خواهد شد. اگر در خط فرمان مشخصه ارجاعی را ارائه ندهید، مشخصه ارجاع موجود در این فایل به عنوان پیشفرض استفاده خواهد شد. این فایل باید قالب زیر را داشته باشد:
URL: one of the above URL formats Push: <refspec> Pull: <refspec>
خطوط Push: توسط git push و خطوط Pull: توسط git pull و git fetch استفاده میشوند. برای نگاشتهای شاخه اضافی میتوان چندین خط Push: و Pull: تعیین کرد.
فایل نامگذاریشده در $GIT_DIR/branches
میتوانید نام فایلی را در $GIT_DIR/branches مشخص کنید. نشانی (URL) موجود در این فایل برای دسترسی به مخزن استفاده خواهد شد. این فایل باید دارای قالب زیر باشد:
<URL>#<head>
پارامتر <URL> الزامی است؛ #<head> اختیاری است.
بسته به عملیات، اگر مشخصه ارجاعی را در خط فرمان ارائه ندهید، گیت از یکی از مشخصههای ارجاع زیر استفاده خواهد کرد. <branch> نام این فایل در $GIT_DIR/branches است و مقدار پیشفرض <head> برابر با master میباشد.
git fetch استفاده میکند از:
refs/heads/<head>:refs/heads/<branch>
git push استفاده میکند از:
HEAD:refs/heads/<head>
شاخههای بالادست (UPSTREAM BRANCHES)
شاخهها در گیت میتوانند بهطور اختیاری دارای یک شاخه دوردست بالادست باشند. گیت بهطور پیشفرض برای عملیاتهای دوردست از شاخه بالادست استفاده میکند، به عنوان مثال:
شاخه بالادست در .git/config، در فیلدهای "remote" و "merge" ذخیره میشود. به عنوان مثال، اگر شاخه بالادستِ main برابر با origin/main باشد:
[branch "main"] remote = origin merge = refs/heads/main
شما میتوانید با استفاده از git push --set-upstream <remote> <branch> یک شاخه بالادست را صریحاً تنظیم کنید، اما گیت در اغلب موارد بهطور خودکار شاخه بالادست را برای شما تنظیم میکند؛ برای مثال:
نکته
گاهی اوقات از شاخههای بالادست به عنوان "اطلاعات ردگیری" (tracking information) یاد میشود، مانند عبارت "set the branch’s tracking information".
گروههای دوردست (REMOTE GROUPS)
یک گروه دوردست، فهرستی نامگذاریشده از مخازن دوردست است که از طریق remotes.<name> در پیکربندی گیت شما تنظیم میشود:
$ git config remotes.all-remotes "r1 r2 r3"
هنگامی که یک نام گروه به عنوان آرگومان <repository> داده میشود، ارسال به نوبت برای هر یک از مخازن دوردستِ عضو گروه انجام میگیرد. اصل حاکم این است که:
git push <options> all-remotes <args>
دقیقاً معادل است با:
git push <options> r1 <args> git push <options> r2 <args> ... git push <options> rN <args>
که در آن r1، r2، ...، rN اعضای all-remotes هستند. هیچ رفتار خاصی اضافه یا حذف نمیشود — گروه صرفاً یک میانبر برای اجرای جداگانه همان دستور push در برابر هر مخزن دوردست عضو است.
هنگام ارسال به گروهی متشکل از بیش از یک مخزن دوردست، گیت به ترتیب برای هر مخزن دوردست عضو یک زیرفرآیند مجزای git push ایجاد میکند. هر زیرفرآیند همان پرچمها و مشخصههای ارجاع مربوط به فراخوانی اولیه را دریافت میکند. این بدان معناست که نگاشتهای ارسال اختصاصی هر مخزن دوردست که از طریق remote.<name>.push پیکربندی شدهاند و حالت آینهای (remote.<name>.mirror) بهطور مستقل برای هر مخزن دوردست ارزیابی میشوند، و یک مخزن دوردست آینهای در گروه نمیتواند بر رفتار ارسال سایر مخازن دوردست غیرآینهای در همان گروه تأثیر بگذارد.
گزینه --atomic برای ارسالهای گروهی پشتیبانی نمیشود، زیرا اتمیک بودن (اتمام یکپارچه) تنها در قالب یک اتصال انتقال واحد به یک مخزن دوردست منفرد قابل تضمین است. اگر --atomic همراه با یک نام گروه ترکیب شود، گیت فراخوانی را با یک خطا رد خواهد کرد.
اگر هر یک از مخازن دوردستِ عضو با شکست مواجه شود، خواه به دلیل رد شدن ارسال (مانند یک بهروزرسانی غیر fast-forward یا هوک سمت سرور که یک ارجاع را رد میکند) یا خطای اتصال (مانند عدم وجود مخزن، شکست در احراز هویت، یا در دسترس نبودن شبکه)، گیت خطا را گزارش داده و به ارسال به باقی مخازن دوردست در گروه ادامه میدهد. در صورتی که ارسال به هر یک از اعضا ناموفق باشد، کد خروج کلی غیرصفر خواهد بود.
این بدان معناست که کاربر مسئول اطمینان از معقول بودن توالی ارسالهای جداگانه است. اگر git push r1 برای مجموعهای معین از گزینهها و آرگومانها با شکست مواجه شود، آنگاه git push all-remotes نیز هنگام رسیدن به r1 به همان شیوه با شکست مواجه خواهد شد. ارسال گروهی کار خاصی برای به موفقیت رساندن یک ارسالِ انفرادیِ ناموفق انجام نمیدهد.
خروجی (OUTPUT)
خروجی «git push» به روش انتقال مورد استفاده بستگی دارد؛ این بخش خروجی را هنگام ارسال بر روی پروتکل گیت (چه به صورت محلی و چه از طریق ssh) توضیح میدهد.
وضعیت ارسال به صورت جدولی خروجی داده میشود، به طوری که هر خط نشاندهنده وضعیت یک ارجاع منفرد است. هر خط به این صورت است:
<flag> <summary> <from> -> <to> (<reason>)
اگر از --porcelain استفاده شود، آنگاه هر خط از خروجی به این صورت خواهد بود:
<flag> \t <from>:<to> \t <summary> (<reason>)
وضعیت ارجاعهای بهروز تنها در صورتی نمایش داده میشود که گزینه --porcelain یا --verbose استفاده شده باشد.
<flag>
(space)
+
-
*
!
=
<summary>
برای یک بهروزرسانی ناموفق، جزئیات بیشتری ارائه میشود:
rejected
remote rejected
remote failure
from
to
reason
قوانین ارسال (PUSH RULES)
به عنوان یک قابلیت ایمنی، دستور git push تنها انواع خاصی از بهروزرسانیها را مجاز میداند تا از دست رفتن تصادفی دادهها در مخزن دوردست جلوگیری شود.
از آنجا که شاخهها و برچسبها برای کاربردهای متفاوتی در نظر گرفته شدهاند، قوانین ایمنی برای ارسال به یک شاخه با قوانین ارسال به یک برچسب متفاوت است. در قوانین زیر «بهروزرسانی» به معنای هرگونه تغییر به جز حذف و ایجاد است. حذف و ایجاد همیشه مجاز است، مگر زمانی که توسط پیکربندی یا قلابها ممنوع شده باشد.
شما میتوانید این قوانین را با ارسال --force یا با افزودن + اختیاری در ابتدای یک مشخصه ارجاع (refspec) نادیده بگیرید. تنها استثناها این است که هیچ مقداری از اجبار کردن باعث نخواهد شد یک شاخه شیئی غیر از کامیت را بپذیرد، و اجبار کردن باعث نخواهد شد مخزن دوردست ارسالی را بپذیرد که برای رد آن پیکربندی شده است.
قلابها و پیکربندی نیز میتوانند این قوانین را لغو کرده یا اصلاح کنند؛ برای نمونه receive.denyNonFastForwards و receive.denyDeletes را در git-config(1) و pre-receive و update در githooks(5) ببینید.
نکتهای درباره جلوبردنهای سریع (NOTE ABOUT FAST-FORWARDS)
هنگامی که یک بهروزرسانی، شاخهای (یا بهطور کلیتر، یک ارجاع) را که به کامیت A اشاره میکرد تغییر میدهد تا به کامیت دیگری مانند B اشاره کند، این عملیات اگر و تنها اگر B نوادهای از A باشد، یک بهروزرسانی جلوبردن سریع (fast-forward) نامیده میشود.
در یک بهروزرسانی جلوبردن سریع از A به B، مجموعه کامیتهایی که کامیت اولیه A بر پایه آنها ساخته شده بود، زیرمجموعهای از کامیتهایی است که کامیت جدید B بر روی آنها بنا شده است. از این رو، هیچ تاریخچهای از دست نمیرود.
در مقابل، یک بهروزرسانی جلوبردن غیرسریع (non-fast-forward) تاریخچه را از بین خواهد برد. برای نمونه، فرض کنید شما و فرد دیگری کار را از کامیت یکسان X آغاز کردهاید، و شما تاریخچهای ساختهاید که به کامیت B میرسد، در حالی که فرد دیگر تاریخچهای منتهی به کامیت A ساخته است. این تاریخچه به این شکل است:
B
/
---X---A
همچنین فرض کنید آن فرد دیگر پیشتر تغییرات منتهی به A را به مخزن اصلی که شما دو نفر کامیت اولیه X را از آن دریافت کرده بودید، ارسال (push) کرده است.
ارسالِ انجامشده توسط فرد دیگر، شاخهای را که به کامیت X اشاره میکرد بهروزرسانی کرده تا به کامیت A اشاره کند. این یک جلوبردن سریع (fast-forward) است.
اما اگر شما برای ارسال تلاش کنید، سعی خواهید کرد شاخه را (که اکنون به A اشاره دارد) با کامیت B بهروزرسانی نمایید. این عملیات جلوبردن سریع نخواهد بود. اگر چنین کاری میکردید، تغییرات ایجادشده توسط کامیت A از دست میرفت، زیرا از این پس همگان کار را بر پایه B ادامه میدادند.
این دستور بهطور پیشفرض اجازه بهروزرسانی غیرسریع را نمیدهد تا از چنین از دست رفتن تاریخچهای جلوگیری کند.
اگر نمیخواهید کار خودتان (تاریخچه از X به B) یا کار فرد دیگر (تاریخچه از X به A) را از دست بدهید، باید ابتدا تاریخچه را از مخزن واکشی (fetch) کنید، تاریخچهای بسازید که شامل تغییرات انجامشده توسط هر دو طرف باشد، و سپس نتیجه را ارسال (push) کنید.
میتوانید دستور "git pull" را اجرا کنید، تداخلهای احتمالی را برطرف نمایید، و نتیجه را با "git push" ارسال کنید. دستور "git pull" یک کامیت ادغام C بین کامیتهای A و B ایجاد خواهد کرد.
B---C
/ /
---X---A
بهروزرسانی A با کامیت ادغام حاصلشده، بهصورت جلوبردن سریع خواهد بود و ارسال (push) شما پذیرفته میشود.
به عنوان روش دیگر، میتوانید با استفاده از git pull --rebase تغییرات خود بین X و B را بر روی A بازپایهریزی (rebase) کرده و نتیجه را ارسال (push) نمایید. این بازپایهریزی یک کامیت جدید D ایجاد میکند که تغییرات بین X و B را بر روی A بنا میسازد.
B D
/ /
---X---A
مجدداً، بهروزرسانی A با این کامیت یک جلوبردن سریع خواهد بود و ارسال شما پذیرفته میشود.
وضعیت رایج دیگری نیز وجود دارد که ممکن است هنگام تلاش برای ارسال (push) با رد شدن به دلیل جلوبردن غیرسریع مواجه شوید، و این حالت حتی زمانی که به مخزنی ارسال میکنید که هیچکس دیگری به آن ارسال نمیکند نیز امکانپذیر است. پس از اینکه خودتان کامیت A را ارسال کردید (در تصویر نخست این بخش)، آن را با git commit --amend جایگزین میکنید تا کامیت B تولید شود، و سپس تلاش میکنید آن را ارسال کنید چون فراموش کردهاید که پیشتر A را ارسال کرده بودید. در چنین حالتی، و تنها اگر مطمئن هستید که در این فاصله هیچکس کامیت قبلی شما یعنی A را واکشی (fetch) نکرده است (و ساخت کار خود را بر روی آن آغاز نکرده است)، میتوانید git push --force را برای رونویسی روی آن اجرا کنید. به عبارت دیگر، git push --force روشی است که برای مواردی در نظر گرفته شده که شما واقعاً قصد دارید تاریخچه را از دست بدهید.
مثالها (EXAMPLES)
git push
git push origin
رفتار پیشفرض این دستور هنگامی که هیچ <refspec> (مشخصه ارجاع) مشخص نشده باشد را میتوان با تنظیم گزینه push مربوط به ریموت، یا متغیر پیکربندی push.default تعیین کرد.
برای نمونه، جهت تعیین رفتار پیشفرض برای ارسال تنها شاخه فعلی به origin از دستور زیر استفاده کنید: git config remote.origin.push HEAD. هر <refspec> معتبری (مانند موارد موجود در مثالهای زیر) میتواند بهعنوان مقدار پیشفرض برای git push origin پیکربندی شود.
git push origin :
git push origin master
git push origin HEAD
git push mothership master:satellite/master dev:satellite/dev
برای بررسی مفاهیم تطبیق، به بخش شرحدهنده <refspec>... در بالا مراجعه کنید.
این کار برای شبیهسازی اجرای git fetch روی mothership با استفاده از git push است که در جهت معکوس اجرا میشود تا کارهای انجامشده روی satellite ادغام شوند، و اغلب زمانی لازم است که فقط امکان برقراری ارتباط یکطرفه را دارید (یعنی satellite میتواند با ssh به mothership متصل شود اما mothership نمیتواند اتصال به satellite را آغاز کند زیرا دومی پشت فایروال قرار دارد یا sshd را اجرا نمیکند).
پس از اجرای این دستور git push روی دستگاه satellite، شما با ssh به mothership متصل میشوید و در آنجا git merge را اجرا میکنید تا شبیهسازی اجرای git pull روی mothership جهت دریافت تغییرات ایجادشده روی satellite کامل شود.
git push origin HEAD:master
git push origin master:refs/heads/experimental
git push origin :experimental
git push origin +dev:master
o---o---o---A---B origin/master
\
X---Y---Z dev
دستور فوق مخزن origin را به صورت زیر تغییر میدهد:
A---B (unnamed branch)
/
o---o---o---X---Y---Z master
کامیتهای A و B دیگر به شاخهای با نام نمادین تعلق نخواهند داشت و بنابراین غیرقابل دسترس خواهند بود. به این ترتیب، این کامیتها با اجرای دستور git gc در مخزن origin حذف خواهند شد.
امنیت (SECURITY)
پروتکلهای fetch و push برای جلوگیری از سرقت دادههایی از مخزن طرف مقابل که قصد بهاشتراکگذاری آنها نبوده است طراحی نشدهاند. اگر دادههای خصوصی دارید که باید از یک همتای مخرب محافظت شوند، بهترین گزینه شما ذخیره آنها در یک مخزن دیگر است. این امر هم برای کلاینتها و هم برای سرورها صدق میکند. بهویژه، فضاهای نام (namespaces) روی یک سرور برای کنترل دسترسی خواندن کارآمد نیستند؛ شما فقط باید دسترسی خواندن به یک فضای نام را به کلاینتهایی اعطا کنید که برای دسترسی خواندن به کل مخزن به آنها اعتماد دارید.
بردارهای حمله شناختهشده به شرح زیر هستند:
پیکربندی (CONFIGURATION)
تمام موارد زیر این خط در این بخش بهطور گزینشی از مستندات git-config(1) گنجانده شدهاند. محتوا همان چیزی است که در آنجا یافت میشود:
push.autoSetupRemote
push.default
nothing
current
upstream
tracking
simple
این حالت مستلزم آن است که مخزن دوردستی که باید به آن push شود شناختهشده باشد. هنگام push کردن مجدد به همان دوردستی که از آن pull میکنید، شاخه جاری باید یک شاخه ردیابی بالادست با همان نام نیز داشته باشد.
این حالت از نسخه گیت ۲.۰ حالت پیشفرض است، و امنترین گزینه مناسب برای مبتدیان است.
matching
برای استفاده مؤثر از این حالت، باید مطمئن شوید که قبل از اجرای git push، همه شاخههایی که قصد ارسالشان را دارید آماده push شدن باشند، زیرا هدف اصلی این حالت این است که به شما امکان دهد تمام شاخهها را یکباره push کنید. اگر معمولاً کار روی یک شاخه را تمام کرده و نتیجه را push میکنید، در حالی که شاخههای دیگر ناتمام هستند، این حالت برای شما مناسب نیست. همچنین این حالت برای push کردن به یک مخزن متمرکز مشترک مناسب نیست، چرا که افراد دیگر ممکن است شاخههای جدیدی در آنجا اضافه کنند، یا نوک شاخههای موجود را خارج از کنترل شما بهروزرسانی نمایند.
این گزینه قبلاً پیشفرض بود، اما از گیت ۲.۰ به بعد چنین نیست (simple پیشفرض جدید است).
push.followTags
push.gpgSign
push.pushOption
این یک متغیر چندمقداری است، و از یک مقدار خالی میتوان در یک فایل پیکربندی با اولویت بالاتر (مانند .git/config در یک مخزن) برای پاک کردن مقادیر به ارث رسیده از فایلهای پیکربندی با اولویت پایینتر (مانند $HOME/.gitconfig) استفاده کرد.
مثال: /etc/gitconfig push.pushoption = a push.pushoption = b ~/.gitconfig push.pushoption = c repo/.git/config push.pushoption = push.pushoption = b این تنظیم تنها منجر به b خواهد شد (a و c پاک میشوند).
push.recurseSubmodules
push.useForceIfIncludes
push.negotiate
push.useBitmaps
گیت (GIT)
بخشی از مجموعه git(1)
| 2026-06-29 | Git 2.55.0 |