| GIT-SVN(1) | Git Manual | GIT-SVN(1) |
نام (NAME)
git-svn - پل ارتباطی دومنظوره میان مخازن سابورژن و گیت
خلاصه دستور (SYNOPSIS)
git svn <command> [<options>] [<arguments>]
توضیحات (DESCRIPTION)
ابزار git svn مجرایی ساده برای انتقال مجموعهتغییرات (changesetها) میان سابورژن و گیت است. این ابزار جریانی دوطرفه از تغییرات را میان یک مخزن سابورژن و یک مخزن گیت فراهم میکند.
git svn میتواند با استفاده از گزینه --stdlayout یک مخزن استاندارد سابورژن را که از ساختار رایج "trunk/branches/tags" پیروی میکند، ردگیری کند. همچنین با استفاده از گزینههای -T/-t/-b میتواند شاخهها و برچسبها را در هر ساختار و چیدمانی دنبال کند (گزینههای زیر برای init و همچنین دستور clone را ببینید).
پس از ردگیری یک مخزن سابورژن (با هر یک از روشهای فوق)، میتوان مخزن گیت را با استفاده از دستور fetch از سابورژن بهروزرسانی کرد و سابورژن را نیز با استفاده از دستور dcommit از طریق گیت بهروز نمود.
دستورها (COMMANDS)
init
-T<trunk-subdir>, --trunk=<trunk-subdir>, -t<tags-subdir>, --tags=<tags-subdir>, -b<branches-subdir>, --branches=<branches-subdir>, -s, --stdlayout
--no-metadata
--use-svm-props
--use-svnsync-props
--rewrite-root=<URL>
--rewrite-uuid=<UUID>
--username=<user>
--prefix=<prefix>
نکته
پیش از نگارش ۲.۰ گیت، پیشوند پیشفرض "" (بدون پیشوند) بود. این بدان معنا بود که ارجاعات ردگیری SVN در "refs/remotes/*" قرار میگرفتند که با نحوه سازماندهی ارجاعات ردگیری ریموت در خود گیت ناسازگار بود. اگر همچنان همان پیشفرض قدیمی را میخواهید، میتوانید با پاس دادن --prefix "" در خط فرمان به آن برسید (اگر Getopt::Long پرل شما نسخهای کمتر از ۲.۳۷ باشد ممکن است --prefix="" کار نکند).
--ignore-refs=<regex>
--ignore-paths=<regex>
--include-paths=<regex>
--no-minimize-url
fetch
این دستور در صورت نیاز به طور خودکار rev_map را بهروزرسانی میکند (برای جزئیات بیشتر به $GIT_DIR/svn/**/.rev_map.* در بخش FILES در ادامه مراجعه کنید).
--localtime
این گزینه تداخلی در تعامل با مخزن Subversion که از آن کلون گرفتهاید ایجاد نمیکند، اما اگر میخواهید مخزن محلی Git شما بتواند با مخزن محلی Git شخص دیگری تعامل داشته باشد، یا نباید از این گزینه استفاده کنید یا باید هر دو نفر در یک منطقه زمانی محلی یکسان از آن استفاده نمایید.
--parent
--ignore-refs=<regex>
config key: svn-remote.<name>.ignore-refs
اگر کلید پیکربندی ignore-refs تنظیم شده باشد و گزینه خط فرمان نیز داده شود، هر دو عبارت باقاعده استفاده خواهند شد.
--ignore-paths=<regex>
config key: svn-remote.<name>.ignore-paths
اگر کلید پیکربندی ignore-paths تنظیم شده باشد و گزینه خط فرمان نیز داده شود، هر دو عبارت باقاعده استفاده خواهند شد.
مثالها:
نادیدهگرفتن دایرکتوری "doc*" برای هر واکشی
--ignore-paths="^doc"
نادیدهگرفتن "branches" و "tags" در دایرکتوریهای سطح اول
--ignore-paths="^[^/]+/(?:branches|tags)"
--include-paths=<regex>
config key: svn-remote.<name>.include-paths
--log-window-size=<n>
clone
--preserve-empty-dirs
--placeholder-filename=<filename>
rebase
این دستور مشابه svn update یا git pull عمل میکند، با این تفاوت که جهت سهولت در اجرای dcommit با git svn، تاریخچه خطی را با git rebase بهجای git merge حفظ میکند.
این دستور تمام گزینههایی را که git svn fetch و git rebase میپذیرند قبول میکند. با این حال، --fetch-all تنها از [svn-remote] جاری واکشی میکند، نه از تمامی تعاریف [svn-remote].
مشابه git rebase؛ این دستور مستلزم آن است که درخت کاری تمیز باشد و هیچ تغییر کامیتنشدهای نداشته باشد.
این دستور در صورت نیاز به طور خودکار rev_map را بهروزرسانی میکند (برای جزئیات بیشتر به $GIT_DIR/svn/**/.rev_map.* در بخش FILES در ادامه مراجعه کنید).
-l, --local
dcommit
هنگامی که نام اختیاری یک شاخه Git (یا نام یک شیء کامیت Git) به عنوان آرگومان مشخص شود، این زیردستور روی شاخه مشخصشده کار میکند، نه روی شاخه جاری.
استفاده از dcommit بر set-tree (در ادامه) ترجیح داده میشود.
--no-rebase
--commit-url <URL>
config key: svn-remote.<name>.commiturl config key: svn.commiturl (overwrites all svn-remote.<name>.commiturl options)
توجه داشته باشید که نشانی وب (URL) سابورژن در کلید پیکربندی commiturl شامل شاخه SVN نیز میشود. اگر ترجیح میدهید نشانی کامیت را برای کل یک مخزن SVN تنظیم کنید، بهجای آن از svn-remote.<name>.pushurl استفاده نمایید.
استفاده از این گزینه برای هر هدف دیگری (نپرسید چرا) اکیداً منع شده است.
--mergeinfo=<mergeinfo>
config key: svn.pushmergeinfo
این گزینه باعث میشود git-svn تلاش کند در صورت امکان، ویژگی svn:mergeinfo را بهطور خودکار در مخزن SVN مقداردهی نماید. در حال حاضر، این کار تنها هنگام dcommit کردن ادغامهای غیر رو به جلو (non-fast-forward) که در آنها همه والدین به جز والد اول قبلاً در SVN ارسال (push) شدهاند، امکانپذیر است.
--interactive
اگر پاسخ "no" یا "quit" باشد، git svn dcommit بدون کامیت کردن چیزی در SVN، بلافاصله خاتمه مییابد.
branch
-m, --message
-t, --tag
-d<path>, --destination=<path>
git config --get-all svn-remote.<name>.branches git config --get-all svn-remote.<name>.tags
که در آن <name> نام مخزن SVN است که توسط گزینه -R در دستور init مشخص شده است (یا بهطور پیشفرض "svn").
--username
--commit-url
git config --get-all svn-remote.<name>.commiturl
--parents
tag
log
ویژگیهای زیر از ‘svn log’ پشتیبانی میشوند:
-r <n>[:<n>], --revision=<n>[:<n>]
-v, --verbose
--limit=<n>
--incremental
قابلیتهای جدید:
--show-commit
--oneline
نکته
خود SVN زمانها را تنها بر حسب UTC و نه چیز دیگری ذخیره میکند. کلاینت استاندارد svn زمان UTC را به زمان محلی (یا بر اساس متغیر محیطی TZ=) تبدیل میکند. این دستور نیز رفتار مشابهی دارد.
blame
--git-format
find-rev
-B, --before
-A, --after
set-tree
create-ignore
show-ignore
mkdirs
commit-diff
پیام کامیت یا مستقیماً از طریق گزینه -m یا -F فراهم میشود، یا بهصورت غیرمستقیم از برچسب یا کامیت هنگامی که شبهدرخت دوم چنین شیئی را نشان میدهد، یا با فراخوانی یک ویرایشگر درخواست میشود (گزینه --edit در زیر را ببینید).
-m <msg>, --message=<msg>
-F <filename>, --file=<filename>
info
proplist
propget
propset
مثال:
git svn propset svn:keywords "FreeBSD=%H" devel/py-tipper/Makefile
این دستور ویژگی svn:keywords را برای فایل devel/py-tipper/Makefile برابر با FreeBSD=%H قرار میدهد.
show-externals
gc
reset
تنها rev_map و refs/remotes/git-svn تغییر میکنند (برای جزئیات بیشتر به $GIT_DIR/svn/**/.rev_map.* در بخش فایلها (FILES) در ادامه مراجعه کنید). پس از reset یک fetch و سپس git reset یا git rebase را اجرا کنید تا شاخههای محلی به درخت جدید منتقل شوند.
-r <n>, --revision=<n>
-p, --parent
مثال:
r1---r2---r3 remotes/git-svn
\
A---B master
مشکل ignore-paths یا مجوزهای دسترسی SVN را که از ابتدا باعث ناقص بودن "r2" شده بود برطرف کنید. سپس:
git svn reset -r2 -p git svn fetch
r1---r2'--r3' remotes/git-svn \ r2---r3---A---B master
سپس "master" را با git rebase اصلاح کنید. از git merge استفاده نکنید، در غیر این صورت تاریخچه شما با dcommit آینده سازگار نخواهد بود!
git rebase --onto remotes/git-svn A^ master
r1---r2'--r3' remotes/git-svn
\
A'--B' master
گزینهها (OPTIONS)
--shared[=(false|true|umask|group|all|world|everybody)], --template=<template-directory>
-r <arg>, --revision <arg>
این گزینه پشتیبانی از بازههای ویرایش (revision ranges) را برای تاریخچه جزئی/کوتاهشده فراهم میکند. بازههای $NUMBER، $NUMBER1:$NUMBER2 (بازههای عددی)، $NUMBER:HEAD، و BASE:$NUMBER همگی پشتیبانی میشوند.
این گزینه به شما اجازه میدهد هنگام اجرای واکشی (fetch)، یک آینه (mirror) جزئی بسازید؛ اما عموماً توصیه نمیشود زیرا بخشهایی از تاریخچه نادیده گرفته شده و از دست خواهد رفت.
-, --stdin
فهرستی از کامیتها را از ورودی استاندارد (stdin) میخواند و آنها را به ترتیب معکوس کامیت میکند. از هر سطر تنها مقدار ابتدایی sha1 خوانده میشود، بنابراین میتوان از خروجی git rev-list --pretty=oneline استفاده کرد.
--rmdir
در صورتی که هیچ فایلی باقی نمانده باشد، پوشهها را از درخت SVN حذف میکند. سامانه SVN میتواند پوشههای خالی را نسخهبندی کند و به صورت پیشفرض در صورت خالی ماندن از فایل، آنها را حذف نمیکند. گیت قادر به نسخهبندی پوشههای خالی نیست. فعال کردن این فلگ باعث میشود کامیت به SVN همانند گیت رفتار کند.
config key: svn.rmdir
-e, --edit
پیام کامیت را پیش از کامیت کردن به SVN ویرایش میکند. این ویژگی برای اشیایی که کامیت هستند به صورت پیشفرض غیرفعال است و هنگام کامیت اشیاء درختی (tree objects) اجباراً فعال میشود.
config key: svn.edit
-l<num>, --find-copies-harder
هر دوی آنها مستقیماً به git diff-tree پاس داده میشوند؛ برای اطلاعات بیشتر git-diff-tree(1) را ببینید.
config key: svn.l config key: svn.findcopiesharder
-A<filename>, --authors-file=<filename>
loginname = Joe User <user@example.com>
اگر این گزینه مشخص شود و git svn با نام ثبتکنندهای در SVN برخورد کند که در authors-file وجود ندارد، git svn عملیات را لغو خواهد کرد. سپس کاربر باید مدخل مربوطه را اضافه کند. اجرای مجدد دستور قبلی git svn پس از تغییر authors-file باید عملیات را ادامه دهد.
config key: svn.authorsfile
--authors-prog=<filename>
به دلایل تاریخی، یک filename نسبی برای init و clone ابتدا نسبت به پوشه جاری جستجو میشود و برای fetch نسبت به ریشه درخت کاری جستجو میگردد. اگر filename پیدا نشود، همانند هر دستور دیگری در $PATH جستجو میشود.
config key: svn.authorsProg
-q, --quiet
-m, --merge, -s<strategy>, --strategy=<strategy>, -p, --rebase-merges
هنگام استفاده از dcommit، در صورتی که امکان استفاده از git reset وجود نداشته باشد، مستقیماً به git rebase پاس داده میشوند (توضیحات dcommit را ببینید).
-n, --dry-run
برای dcommit، مجموعه آرگومانهای Git را چاپ میکند که نشان میدهد کدام diffها در SVN کامیت خواهند شد.
برای rebase، شاخه محلی مرتبط با مخزن svn بالادستی متصل به شاخه جاری و نشانی URL مخزن svn که واکشی از آن انجام خواهد شد را نمایش میدهد.
برای branch و tag، نشانیهای URL را که هنگام ایجاد شاخه یا برچسب جهت کپی کردن استفاده خواهند شد نمایش میدهد.
--use-log-author
config key: svn.useLogAuthor
--add-author-from
config key: svn.addAuthorFrom
گزینههای پیشرفته (ADVANCED OPTIONS)
-i<GIT_SVN_ID>, --id <GIT_SVN_ID>
-R<remote-name>, --svn-remote <remote-name>
--follow-parent
config key: svn.followparent
گزینههای فقط-فایل-پیکربندی (CONFIG FILE-ONLY OPTIONS)
svn.noMetadata, svn-remote.<name>.noMetadata
این گزینه فقط برای درونریزیهای یکباره قابل استفاده است زیرا git svn بدون متادیتا قادر به واکشی دوباره نخواهد بود. علاوه بر این، در صورت از دست رفتن فایلهای $GIT_DIR/svn/**/.rev_map.* شما، git svn نمیتواند آنها را دوباره بسازد.
دستور git svn log نیز روی مخازنی که از این گزینه استفاده میکنند کار نخواهد کرد. همچنین استفاده از این گزینه به دلایلی (امیدواریم) کاملاً مشخص، با گزینه useSvmProps تداخل دارد.
استفاده از این گزینه توصیه نمیشود زیرا پیگیری ارجاعات قدیمی به شماره ویرایشهای SVN را در مستندات موجود، گزارشهای اشکال و بایگانیها دشوار میسازد. اگر قصد دارید در نهایت از SVN به Git مهاجرت کنید و از کنار گذاشتن تاریخچه SVN مطمئن هستید، در عوض استفاده از git-filter-repo[1] را در نظر بگیرید. همچنین filter-repo امکان قالببندی مجدد متادیتا برای خوانایی بهتر و بازنویسی اطلاعات پدیدآورنده را برای کاربرانی که از "svn.authorsFile" استفاده نمیکنند، فراهم میکند.
svn.useSvmProps, svn-remote.<name>.useSvmProps
اگر یک ویرایش SVN دارای ویژگی "svm:headrev" باشد، احتمالاً آن ویرایش توسط SVN::Mirror (که توسط SVK نیز به کار میرود) ایجاد شده است. این ویژگی حاوی یک شناسه یکتای مخزن (UUID) و یک شماره ویرایش است. ما میخواهیم چنین به نظر برسد که در حال آینهسازی نشانی URL اصلی هستیم، بنابراین یک تابع کمکی معرفی میشود که نشانی URL هویتی و UUID اصلی را بازمیگرداند و هنگام تولید متادیتا در پیامهای کامیت از آن استفاده میکند.
svn.useSvnsyncProps, svn-remote.<name>.useSvnsyncprops
svn-remote.<name>.rewriteRoot
svn-remote.<name>.rewriteUUID
svn-remote.<name>.pushurl
svn.brokenSymlinkWorkaround
svn.pathnameencoding
svn-remote.<name>.automkdirs
از آنجا که گزینههای noMetadata، rewriteRoot، rewriteUUID، useSvnsyncProps و useSvmProps همگی بر متادیتای تولیدشده و استفادهشده توسط git svn اثر میگذارند؛ آنها باید پیش از درونریزی هرگونه تاریخچه در فایل پیکربندی تنظیم شوند و این تنظیمات پس از مشخص شدن هرگز نباید تغییر یابند.
علاوه بر این، در هر بخش svn-remote فقط از یکی از این گزینهها میتوان استفاده کرد زیرا آنها بر خط متادیتای git-svn-id: اثر میگذارند، به استثنای rewriteRoot و rewriteUUID که میتوانند با هم استفاده شوند.
مثالهای پایه (BASIC EXAMPLES)
ردیابی و مشارکت در تنه (trunk) پروژهای که با Subversion مدیریت میشود (با نادیده گرفتن برچسبها و شاخهها):
# Clone a repo (like git clone):
git svn clone http://svn.example.com/project/trunk
# Enter the newly cloned directory:
cd trunk
# You should be on master branch, double-check with 'git branch'
git branch
# Do some work and commit locally to Git:
git commit ...
# Something is committed to SVN, rebase your local changes against the
# latest changes in SVN:
git svn rebase
# Now commit your changes (that were committed previously using Git) to SVN,
# as well as automatically updating your working HEAD:
git svn dcommit
# Append svn:ignore and svn:global-ignores settings to the default Git exclude file:
git svn show-ignore >> .git/info/exclude
ردیابی و مشارکت در کل پروژهای که با Subversion مدیریت میشود (همراه با یک تنه، برچسبها و شاخهها):
# Clone a repo with standard SVN directory layout (like git clone):
git svn clone http://svn.example.com/project --stdlayout --prefix svn/
# Or, if the repo uses a non-standard directory layout:
git svn clone http://svn.example.com/project -T tr -b branch -t tag --prefix svn/
# View all branches and tags you have cloned:
git branch -r
# Create a new branch in SVN
git svn branch waldo
# Reset your master to trunk (or any other branch, replacing 'trunk'
# with the appropriate name):
git reset --hard svn/trunk
# You may only dcommit to one branch/tag/trunk at a time. The usage
# of dcommit/rebase/show-ignore should be the same as above.
فرآیند اولیه git svn clone میتواند بسیار زمانبر باشد (بهویژه برای مخازن بزرگ Subversion). اگر چندین نفر (یا یک نفر با چندین دستگاه) بخواهند از git svn برای تعامل با همان مخزن Subversion استفاده کنند، میتوانید کلون اولیه git svn clone را روی مخزنی در یک سرور انجام دهید و از هر نفر بخواهید آن مخزن را با git clone کلون کند:
# Do the initial import on a server
ssh server "cd /pub && git svn clone http://svn.example.com/project [options...]"
# Clone locally - make sure the refs/remotes/ space matches the server
mkdir project
cd project
git init
git remote add origin server:/pub/project
git config --replace-all remote.origin.fetch '+refs/remotes/*:refs/remotes/*'
git fetch
# Prevent fetch/pull from remote Git server in the future,
# we only want to use git svn for future updates
git config --remove-section remote.origin
# Create a local branch from one of the branches just fetched
git checkout -b master FETCH_HEAD
# Initialize 'git svn' locally (be sure to use the same URL and
# --stdlayout/-T/-b/-t/--prefix options as were used on server)
git svn init http://svn.example.com/project [options...]
# Pull the latest changes from Subversion
git svn rebase
بازسازی در برابر واکشی/ادغام (REBASE VS. PULL/MERGE)
ترجیحاً برای همگامسازی کامیتهای ادغامنشده با یک شاخه git svn، به جای git pull یا git merge از git svn rebase یا git rebase استفاده کنید. انجام این کار تاریخچه کامیتهای ادغامنشده را نسبت به مخزن بالادست SVN به صورت خطی حفظ میکند و امکان استفاده از زیرفرمان ترجیحی git svn dcommit را برای ارسال مجدد کامیتهای ادغامنشده به SVN فراهم میسازد.
در ابتدا، git svn توصیه میکرد توسعهدهندگان از شاخه git svn عملیات pull یا merge را انجام دهند. علت این امر آن بود که پدیدآورنده، دستور git svn set-tree B را برای کامیت کردن یک سرشاخه (head) منفرد، به نگارش git svn set-tree A..B جهت اعمال چندین کامیت ترجیح میداد. استفاده از git pull یا git merge همراه با git svn set-tree A..B هنگام کامیت در SVN باعث هموارسازی (flatten شدن) تاریخچه غیرخطی میشود و این موضوع میتواند به این بینجامد که کامیتهای ادغام به طور غیرمنتظرهای کامیتهای قبلی را در SVN معکوس و بیاثر کنند.
ردیابی ادغام (MERGE TRACKING)
اگرچه git svn میتواند تاریخچه کپیها (از جمله شاخهها و برچسبها) را برای مخازنی با ساختار استاندارد ردیابی کند، اما هنوز قادر نیست تاریخچه ادغامهای انجامشده درون گیت را به کاربران بالادست در SVN منعکس کند. بنابراین به کاربران توصیه میشود برای تسهیل سازگاری با SVN، تاریخچه را درون گیت تا حد امکان خطی نگه دارند (بخش «هشدارها و نکات مهم» را در زیر ببینید).
مدیریت شاخههای اسویان (HANDLING OF SVN BRANCHES)
اگر git svn برای واکشی شاخهها پیکربندی شده باشد (و گزینه --follow-branches برقرار باشد)، گاهی برای یک شاخه SVN چندین شاخه گیت ایجاد میکند، که این شاخههای اضافی نامهایی به صورت branchname@nnn (که در آن nnn شماره بازبینی SVN است) خواهند داشت. این شاخههای اضافی زمانی ایجاد میشوند که git svn نتواند برای نخستین کامیت در یک شاخه SVN یک کامیت والد پیدا کند تا شاخه را به تاریخچه شاخههای دیگر متصل نماید.
به طور معمول، نخستین کامیت در یک شاخه SVN شامل یک عملیات کپی است. git svn این کامیت را میخواند تا شماره بازبینی SVN را که شاخه از آن ایجاد شده است به دست آورد. سپس تلاش میکند کامیت گیت متناظر با این بازبینی SVN را پیدا کرده و از آن به عنوان والد شاخه استفاده کند. با این حال، ممکن است کامیت گیت مناسبی برای ایفای نقش والد وجود نداشته باشد. این حالت از جمله زمانی رخ میدهد که شاخه SVN رونوشتی از بازبینیای باشد که توسط git svn واکشی نشده است (برای نمونه به این دلیل که بازبینی قدیمی بوده و با --revision نادیده گرفته شده است)، یا در SVN دایرکتوریای کپی شده باشد که توسط git svn ردیابی نمیشود (مانند شاخهای که اصلاً ردیابی نمیشود، یا زیردایرکتوریای از یک شاخه ردیابیشده). در چنین مواردی، git svn همچنان شاخه گیت را ایجاد خواهد کرد، اما به جای استفاده از یک کامیت گیت موجود به عنوان والد شاخه، تاریخچه SVN دایرکتوریای را که شاخه از آن کپی شده میخواند و کامیتهای گیت مناسب را میسازد. این وضعیت با پیام «Initializing parent: <branchname>» نشان داده میشود.
علاوه بر این، یک شاخه ویژه به نام <branchname>@<SVN-Revision> ایجاد میکند که در آن <SVN-Revision> شماره بازبینی SVN است که شاخه از روی آن کپی شده است. این شاخه به کامیت والد تازهساختهشده شاخه اشاره خواهد کرد. اگر شاخه در SVN حذف شده و بعداً از نسخه متفاوتی دوباره ایجاد شود، چندین شاخه از این دست با کاراکتر @ وجود خواهد داشت.
توجه داشته باشید که این ممکن است به این معنا باشد که برای یک بازبینی منفرد در SVN، چندین کامیت گیت ایجاد میشود.
یک مثال: در یک مخزن SVN با ساختار استاندارد trunk/tags/branches، دایرکتوری trunk/sub در r.100 ایجاد میشود. در r.200، دایرکتوری trunk/sub با کپی شدن درون branches/ شاخهبندی میشود. سپس دستور git svn clone -s یک شاخه به نام sub ایجاد میکند. همچنین کامیتهای گیت جدیدی برای r.100 تا r.199 میسازد و از آنها به عنوان تاریخچه شاخه sub استفاده میکند. بدین ترتیب برای هر بازبینی از r.100 تا r.199 دو کامیت گیت وجود خواهد داشت (یکی حاوی trunk/ و دیگری حاوی trunk/sub/). در نهایت، شاخهای به نام sub@200 ایجاد میکند که به کامیت والد جدید شاخه sub (یعنی کامیت مربوط به r.200 و trunk/sub/) اشاره دارد.
هشدارها و نکات مهم (CAVEATS)
به منظور سادگی و تعاملپذیری با Subversion، توصیه میشود که همه کاربران git svn عملیاتهای clone، fetch و dcommit را مستقیماً از سرور SVN انجام دهند و از تمامی عملیاتهای git clone/pull/merge/push میان مخازن و شاخههای گیت پرهیز کنند. روش توصیهشده برای تبادل کد میان شاخهها و کاربران گیت، استفاده از git format-patch و git am، یا صرفاً اجرای 'dcommit’ بر روی مخزن SVN است.
اجرای git merge یا git pull روی شاخهای که قصد دارید از آن dcommit کنید توصیه «نمیشود»، زیرا کاربران Subversion نمیتوانند هیچیک از ادغامهایی را که انجام دادهاید مشاهده کنند. افزون بر این، اگر از یک شاخه گیت که آینهای از یک شاخه SVN است merge یا pull کنید، ممکن است dcommit تغییرات را به اشتباه روی شاخه دیگری کامیت کند.
اگر اقدام به ادغام میکنید، به این قاعده توجه داشته باشید: git svn dcommit تلاش خواهد کرد کامیتها را بر روی کامیت SVN ذکرشده در خروجی دستور زیر ثبت کند:
git log --grep=^git-svn-id: --first-parent -1
بنابراین شما باید اطمینان حاصل کنید که تازهترین کامیت شاخهای که میخواهید به آن dcommit کنید، والد نخست (first parent) ادغام باشد. در غیر این صورت آشفتگی رخ خواهد داد، بهویژه اگر والد نخست یک کامیت قدیمیتر در همان شاخه SVN باشد.
دستور git clone شاخههای موجود در سلسلهمراتب refs/remotes/ یا متادیتا و پیکربندیهای git svn را کلون نمیکند. بنابراین مخازنی که با استفاده از git svn ایجاد و مدیریت میشوند، در صورتی که نیاز به کلونسازی داشته باشند، باید از rsync برای کلون کردن استفاده کنند.
از آنجا که dcommit در لایه درونی خود از rebase استفاده میکند، هر شاخه گیتی که پیش از اجرای dcommit دستور git push را روی آن اجرا کرده باشید، نیازمند بازنویسی اجباری (force) ارجاع موجود در مخزن دوردست خواهد بود. این کار عموماً یک شیوه نامناسب تلقی میشود؛ برای جزئیات به مستندات git-push(1) مراجعه کنید.
از گزینه --amend در دستور git-commit(1) روی تغییری که قبلاً آن را dcommit کردهاید استفاده نکنید. بازنویسی با --amend برای کامیتهایی که پیشتر برای سایر کاربران به یک مخزن دوردست push شدهاند کاری نادرست به شمار میرود و dcommit در SVN نیز مشابه همان است.
هنگام کلون کردن یک مخزن SVN، اگر از هیچیک از گزینههای تعیین ساختار مخزن (--trunk، --tags، --branches، --stdlayout) استفاده نشود، git svn clone یک مخزن گیت با تاریخچهای کاملاً خطی ایجاد خواهد کرد که در آن شاخهها و برچسبها به صورت دایرکتوریهای جداگانه در کپی کاری ظاهر میشوند. اگرچه این آسانترین راه برای به دست آوردن رونوشتی از کل مخزن است، اما در پروژههایی با شاخههای متعدد به ایجاد کپی کاری چندین برابر بزرگتر از صرفاً شاخه trunk میانجامد. بنابراین برای پروژههایی که از ساختار دایرکتوری استاندارد (trunk/branches/tags) استفاده میکنند، توصیه میشود کلون کردن با گزینه --stdlayout انجام پذیرد. اگر پروژه از ساختاری غیراستاندارد پیروی میکند، و/یا نیازی به شاخهها و برچسبها نیست، سادهترین کار این است که تنها یک دایرکتوری (معمولاً trunk) بدون هیچگونه گزینه ساختار مخزن کلون شود. اگر به کل تاریخچه به همراه شاخهها و برچسبها نیاز است، باید گزینههای --trunk / --branches / --tags به کار روند.
هنگام استفاده از چندین --branches یا --tags، ابزار git svn تداخل نامها را به طور خودکار مدیریت نمیکند (به عنوان مثال، اگر دو شاخه از مسیرهای گوناگون نام یکسانی داشته باشند، یا اگر یک شاخه و یک برچسب دارای نام یکسان باشند). در این موارد، ابتدا از init برای راهاندازی مخزن گیت خود استفاده کنید و سپس پیش از نخستین fetch، فایل $GIT_DIR/config را ویرایش نمایید تا شاخهها و برچسبها با فضاهای نام (namespaces) متفاوتی مرتبط شوند. به عنوان مثال:
branches = stable/*:refs/remotes/svn/stable/* branches = debug/*:refs/remotes/svn/debug/*
پیکربندی (CONFIGURATION)
ابزار git svn اطلاعات پیکربندی [svn-remote] را در فایل $GIT_DIR/config مخزن ذخیره میکند. این بخش شبیه به بخشهای [remote] در هسته گیت است، به جز اینکه کلیدهای fetch آرگومانهای الگوی تطبیق (glob) را نمیپذیرند؛ بلکه در عوض توسط کلیدهای branches و tags مدیریت میشوند. از آنجا که برخی مخازن SVN به شیوهای غیرمعمول با چندین پروژه پیکربندی شدهاند، گسترشهای glob مانند مواردی که در ادامه آمده مجاز هستند:
[svn-remote "project-a"]
url = http://server.org/svn
fetch = trunk/project-a:refs/remotes/project-a/trunk
branches = branches/*/project-a:refs/remotes/project-a/branches/*
branches = branches/release_*:refs/remotes/project-a/branches/release_*
branches = branches/re*se:refs/remotes/project-a/branches/*
tags = tags/*/project-a:refs/remotes/project-a/tags/*
به خاطر داشته باشید که نویسه عام * (ستاره) در ارجاع محلی (سمت راست :) باید راستترین جزء مسیر باشد؛ با این حال نویسه عام دوردست میتواند در هر کجایی قرار گیرد تا زمانی که یک جزء مسیر مستقل باشد (که توسط / یا انتهای خط احاطه شده باشد). این نوع پیکربندی به صورت خودکار توسط init ایجاد نمیشود و باید به طور دستی با یک ویرایشگر متنی یا با استفاده از git config درج گردد.
همچنین توجه داشته باشید که در هر کلمه تنها یک ستاره مجاز است. برای مثال:
branches = branches/re*se:refs/remotes/project-a/branches/*
با شاخههای release، rese و re123se مطابقت خواهد داشت، در حالی که
branches = branches/re*s*e:refs/remotes/project-a/branches/*
باعث ایجاد خطا خواهد شد.
همچنین میتوان زیرمجموعهای از شاخهها یا برچسبها را با استفاده از فهرستی از نامهای جداشده با کاما درون آکولاد واکشی کرد. به عنوان مثال:
[svn-remote "huge-project"]
url = http://server.org/svn
fetch = trunk/src:refs/remotes/trunk
branches = branches/{red,green}/src:refs/remotes/project-a/branches/*
tags = tags/{1.0,2.0}/src:refs/remotes/project-a/tags/*
استفاده از چندین کلید fetch، branches و tags پشتیبانی میشود:
[svn-remote "messy-repo"]
url = http://server.org/svn
fetch = trunk/project-a:refs/remotes/project-a/trunk
fetch = branches/demos/june-project-a-demo:refs/remotes/project-a/demos/june-demo
branches = branches/server/*:refs/remotes/project-a/branches/*
branches = branches/demos/2011/*:refs/remotes/project-a/2011-demos/*
tags = tags/server/*:refs/remotes/project-a/tags/*
ایجاد یک شاخه در چنین پیکربندیای مستلزم رفع ابهام از این است که با بهرهگیری از فلگ -d یا --destination از کدام مکان استفاده شود:
$ git svn branch -d branches/server release-2-3-0
توجه داشته باشید که git-svn بالاترین بازبینیای را که یک شاخه یا برچسب در آن ظاهر شده است ردیابی میکند. اگر زیرمجموعه شاخهها یا برچسبها پس از واکشی تغییر یابد، آنگاه فایل $GIT_DIR/svn/.metadata باید به صورت دستی ویرایش شود تا branches-maxRev و/یا tags-maxRev در صورت لزوم حذف (یا بازنشانی) شوند.
فایلها (FILES)
$GIT_DIR/svn/**/.rev_map.*
git svn fetch و git svn rebase در صورت مفقود بودن یا بهروز نبودن rev_map، آن را به طور خودکار بهروزرسانی میکنند. git svn reset به طور خودکار آن را به عقب بازمیگرداند.
باگها (BUGS)
ما تمامی ویژگیهای SVN را به جز svn:executable نادیده میگیریم. هر ویژگی مدیریتنشده در فایل $GIT_DIR/svn/<refname>/unhandled.log ثبت میشود.
دایرکتوریهای تغییرنامیافته و کپیشده توسط Git شناسایی نمیشوند و در نتیجه هنگام کامیت کردن در SVN ردیابی نخواهند شد. من برنامهای برای افزودن پشتیبانی از این قابلیت ندارم، چرا که پیادهسازی آن برای تمامی حالتهای مرزی (corner cases) ممکن بسیار دشوار و زمانبر است (خود گیت هم این کار را انجام نمیدهد). کامیت کردن فایلهای تغییرنامیافته و کپیشده در صورتی که به اندازه کافی شبیه باشند تا Git بتواند آنها را تشخیص دهد، به طور کامل پشتیبانی میشود.
در SVN این امکان وجود دارد (اگرچه توصیه نمیشود) که تغییرات روی یک برچسب کامیت شوند (زیرا یک برچسب صرفاً رونوشتی از یک دایرکتوری است و از نظر فنی با یک شاخه یکسان است). هنگام کلون کردن یک مخزن SVN، ابزار git svn نمیتواند پیشبینی کند که آیا چنین کمیتی روی یک برچسب در آینده رخ خواهد داد یا خیر. بنابراین محافظهکارانه عمل کرده و تمام برچسبهای SVN را به عنوان شاخه وارد میکند و نام برچسب را با پیشوند tags/ قرار میدهد.
همچنین ببینید (SEE ALSO)
گیت (GIT)
بخشی از مجموعه git(1)
یادداشتها (NOTES)
- 1.
- git-filter-repo
| 2026-06-29 | Git 2.55.0 |