پالت فرمان

دنبال فرمانی برای اجرا بگردید…

ZarynZaryn
میزبانی کد و کنترل نسخه·۱۳ دقیقه مطالعه·

مهاجرت از Git

یک مخزن Git را با سه دستور به zev بیاورید. اول ببینید چه می‌آید، بعد آن را در همان پوشه یا مستقیم از نشانی‌اش بیاورید و اثبات بگیرید که همهٔ کامیت‌ها و فایل‌ها با Git یکی است. با مثال‌های واقعی برای یک پروژهٔ متن‌باز، مخزن یک شرکت با LFS و زیرماژول و هوک، و تیمی که کم‌کم جابه‌جا می‌شود.

جابه‌جایی سه دستور است و لازم نیست همه‌چیز در یک روز عوض شود. zev تاریخچهٔ Git شما را می‌خواند و در zev می‌نویسد. به `.git` هیچ دستی نمی‌خورد، پس Git و zev کنار هم کار می‌کنند تا تیمتان آماده شود. ```bash zev import-git --check # ۱. پیش‌نمایش: چه می‌آید و چه کاری اول با شماست. چیزی نمی‌نویسد zev import-git --verify # ۲. آوردن، سپس اثبات اینکه هر کامیت و هر فایل با Git یکی است zev new && zev push # ۳. گذاشتن روی Zaryn ``` ```diagram type: flow title: سه دستور، و در آخر اثبات --- پیش‌نمایش | `--check` تاریخچه را می‌خواند و می‌گوید چه می‌آید و چه کاری اول با شماست. چیزی نوشته نمی‌شود | accent | 🔍 ~ آماده آوردن | همهٔ شاخه‌ها و برچسب‌ها، نویسنده‌ها، تاریخ‌ها، پیام‌ها، فایل‌های LFS، نام شما و هوک‌هایتان | | 📥 ~ --verify اثبات | هر کامیت و هر فایل سر هر شاخه، بایت به بایت با Git مقایسه می‌شود | good | ✓ ~ zev push اشتراک | روی Zaryn. هم‌تیمی‌ها zev clone می‌زنند و به Git نیازی ندارند | | ☁️ ``` ## پیش‌نمایش در هر مخزن Git اجرایش کنید. تاریخچه را می‌خواند و هیچ چیزی نمی‌نویسد، حتی پوشهٔ `.zev` را: ```bash cd web-app zev import-git --check ``` ```text Moving this folder from Git to zev (a preview: nothing is written) History 10 commits · 2 branch(es) · 1 tag(s) · 2 author(s) · 2021 → 2026 Size 200 KiB in Git Files 8 at the current commit Biggest design/hero.psd 2.3 MiB ✓ Every branch and tag comes over, with each commit's author, date and full message ✓ 1 Git LFS file(s) come over whole: zev keeps big files itself, no LFS server ✓ Your name carries over: commits you make with zev say Sara Kim <sara@example.com> ✓ Git hooks carry over to zev: pre-commit ✓ CI files stay where they are: .github/workflows/ci.yml ✓ .git isn't touched: Git keeps working while your team switches · Submodule vendor/ui-kit: after import, zev sub add <its zev address> vendor/ui-kit pins it (https://github.com/example/ui-kit.git) · 1 commit(s) that only exist inside merges arrive as part of their merge commit Ready. Run zev import-git --verify: it imports, then proves every file matches Git. ``` نشانه‌ها را این‌طور بخوانید: ```diagram type: cards title: نشانه‌های ‎--check چه می‌گویند --- ✓ | می‌آید | کاری با شما نیست | good ! | اول این را انجام دهید | کلون کم‌عمق، یا فایل‌های LFS که فقط اشاره‌گرشان هست. دستور دقیق در همان خط آمده | warn · | خوب است بدانید | به شکل دیگری می‌آید، مثل زیرماژول که زیرمخزن می‌شود | ``` ## آوردن در پوشهٔ مخزن Git، آن را در یک گام بیاورید و اثبات کنید: ```bash zev import-git --verify ``` ```text Reading the Git history of this folder… ✓ Brought in 10 commit(s), 15 file version(s) and 1 tag(s) from Git. feature/search new main new 1 Git LFS file(s) brought in whole: zev stores large files itself, no LFS server needed Your Git name carries over: zev commits will say Sara Kim <sara@example.com> Git hooks carried over to .zev/hooks: pre-commit Proving the import against Git… ✓ Verified: 3 branch(es) and tag(s) checked against Git 10 commit(s): same Git commit, author, date, message and order 9 file version(s) at the tips: Git's SHA-1 recomputed from zev's own copy, all identical 1 Git LFS file(s): zev has the whole file, its SHA-256 matches the pointer ``` اثبات به خود آوردن تکیه نمی‌کند. zev هر فایل را دوباره از انبار خودش می‌خواند، همان SHA-1 که Git به آن می‌دهد را از نو حساب می‌کند و با Git مقایسه می‌کند. بیشتر ابزارهای مهاجرت از شما می‌خواهند به آن‌ها اعتماد کنید؛ این یکی نتیجه را نشانتان می‌دهد. ```diagram type: sequence title: ‎--verify چطور آوردن را اثبات می‌کند lanes: Git | zev alt: برای هر شاخه و برچسب، zev تاریخچهٔ Git و تاریخچهٔ خودش را کنار هم پیمایش می‌کند و شناسهٔ Git، نویسنده، تاریخ و پیام هر کامیت را مقایسه می‌کند؛ سر هر شاخه هر فایل را از انبار خودش می‌خواند، SHA-1 گیت را از نو حساب می‌کند و مقایسه می‌کند، و برای فایل‌های LFS هش SHA-256 را با اشاره‌گر می‌سنجد --- Git -> zev : کامیت‌های هر شاخه و برچسب، از تازه‌ترین note zev : همان شناسهٔ Git، نویسنده، تاریخ و پیام، به همان ترتیب؟ | accent Git -> zev : هر فایل سر شاخه: مسیر، حالت، SHA-1 note zev : نسخهٔ خودش را بخوان و مثل Git هش کن: یکی است؟ | good Git -> zev : اشاره‌گر LFS (هش SHA-256 فایل واقعی) note zev : SHA-256 فایل کاملی که دارد: همان است؟ | good ``` اگر چیزی نخواند، دقیقاً می‌گوید چه چیزی و کجا، با کد ۱ خارج می‌شود، و `zev undo` آوردن را برمی‌گرداند: ```text ✗ 2 difference(s) from Git: branch main: zev commit 7c01d2e9aa stands for Git 4f2a9c1e0b, expected 9b3e77a1c2 zev undo takes the import back. ``` ## گذاشتن روی Zaryn ```bash zev new # روی Zaryn می‌سازد و به‌عنوان origin وصل می‌کند zev push ``` هم‌تیمی‌هایتان `zev clone owner/name` می‌زنند و اصلاً به Git نیاز ندارند. ## یا مستقیم از نشانی‌اش لازم نیست اول کلونش کنید. نشانی را به `zev import-git` بدهید: با Git کلون می‌کند، اگر پروژه از Git LFS استفاده کند فایل‌هایش را هم می‌گیرد، و می‌آوردشان، همه در یک گام: ```bash zev import-git https://github.com/example/web-app.git --verify zev import-git git@gitlab.com:team/api.git api-service # در پوشه‌ای که خودتان نام می‌برید zev import-git https://git.example.com/infra.git --check # فقط کلون و پیش‌نمایش ``` همهٔ شاخه‌های روی سرور می‌آیند، حتی آن‌هایی که هیچ‌وقت checkout نکرده‌اید. Git در کلون فقط شاخهٔ فعلی را می‌سازد، اما zev هر شاخهٔ `origin/…` را هم با نام خودش می‌آورد. اگر پوشه‌ای ندهید، نام پوشه از نام مخزن گرفته می‌شود، و zev هیچ‌وقت روی پوشه‌ای که از قبل هست کلون نمی‌کند. ## همچنان Git تایپ کنید سال‌ها کار با Git در دست‌هایتان است. `zev` را جلویش بگذارید: zev می‌گوید دستور Git شما در zev چیست، و همان را اجرا می‌کند: ```bash zev git commit -am "Fix login" ``` ```text git commit -am "Fix login" → zev add . → zev commit -m "Fix login" zev add . also stages new files; git commit -a only takes files Git already tracks. Commits are signed automatically. ``` با `-n` فقط شکل zev را ببینید، و خود `zev git` به‌تنهایی دستورهایی را که بیشتر به کار می‌روند فهرست می‌کند: ```bash zev git -n commit --amend -m "Fix the login form" ``` ```text git commit --amend -m "Fix the login form" → zev undo → zev commit -m "Fix the login form" zev undo takes the last commit back and keeps its changes staged; then it commits again with the new message. ``` ```diagram type: cards title: zev git با دستور Git شما چه می‌کند --- = | یکسان | zev آن را با همان نام دارد: git status → zev status | good ≈ | نزدیک | همان دستور با گزینه‌های zev: git checkout -b x → zev switch -c x | good → | دستوری دیگر | zev آن را جور دیگری انجام می‌دهد: git reset --soft HEAD~1 → zev undo | accent ! | اول می‌پرسد | کاری را دور می‌ریزد (git reset --hard، git checkout -- file). با y اجرا می‌شود، یا در اسکریپت با ‎--yes | warn × | لازم نیست | zev می‌گوید چرا: git lfs، git rebase --continue. چیزی اجرا نمی‌شود | ``` دستورهایی که کاری را دور می‌ریزند پیش از اجرا می‌پرسند: ```text git checkout -- login.js → zev restore login.js Throws away your unsaved changes to these files (zev recover can bring them back). Run it? [y/N] ``` اگر دستوری را که فقط در Git هست مستقیم در zev تایپ کنید هم به‌جای «دستور ناشناخته» جواب می‌گیرید: ```text $ zev reset --hard HEAD~1 zev has no 'reset'. git reset --hard HEAD~1 in zev: zev undo zev restore . Or let zev do it: zev git reset --hard HEAD~1 ``` ### git تایپ کنید، zev بگیرید یک خط در `~/.bashrc` یا `~/.zshrc`، و `git` در مخزن‌های zev هم کار می‌کند. در پوشه‌ای که `.zev` دارد (و `.git` ندارد)، `git` همان `zev git` را اجرا می‌کند؛ هر جای دیگر مثل قبل Git است: ```bash eval "$(zev git --shell-setup)" ``` ```diagram type: flow title: بعد از ‎--shell-setup، git کجا می‌رود --- مخزن Git | ‎.git اینجاست (حتی وقتی در حال جابه‌جایی هستید): Git است | | 🌿 ~ مخزن zev | فقط ‎.zev: git همان zev git را اجرا می‌کند، که شکل zev را می‌گوید و اجرایش می‌کند | accent | ⚡ ~ هر جای دیگر | مثل قبل Git است | | 📁 ``` برای اسکریپت‌ها و عامل‌های هوش مصنوعی، `zev git --json <command>` شکل zev را به‌صورت داده می‌دهد و چیزی اجرا نمی‌کند: ```bash zev git --json commit -am "Fix login" ``` ```json {"git":["commit","-am","Fix login"],"kind":"close","zev":["zev add .","zev commit -m \"Fix login\""], "argv":[["add","."],["commit","-m","Fix login"]],"note":"zev add . also stages new files; …"} ``` ## مثال‌ها ### یک پروژهٔ متن‌باز از GitHub یک نگه‌دارنده پروژهٔ عمومی را جابه‌جا می‌کند و از مشارکت‌کننده‌ها می‌خواهد از Zaryn کلون کنند: ```bash zev import-git https://github.com/example/parser.git --verify cd parser zev new # می‌پرسد: عمومی یا خصوصی zev push ``` شناسه‌های قدیمی کامیت Git در issueها، تغییرنامه‌ها و نوشته‌های وبلاگ همچنان کار می‌کنند: ```bash zev show 4f2a9c1 # شناسهٔ کامیت Git، کوتاه یا کامل zev log --json -n 1 # روی هر کامیت آورده‌شده: "git": "4f2a9c1e…" ``` ### مخزن یک شرکت با LFS، زیرماژول و هوک مخزن یک تیم طراحی فایل‌های فتوشاپ را در Git LFS نگه می‌دارد، یک کیت رابط کاربری را به‌صورت زیرماژول دارد و هوک‌های Husky اجرا می‌کند. هر کدام از این‌ها در zev شکلی دارد: ```diagram type: flow title: هر افزونهٔ Git در zev شکلی دارد --- Git LFS | فایل‌های بزرگ کامل می‌آیند. zev خودش نگهشان می‌دارد، پس به سرور یا سهمیهٔ LFS نیازی نیست | good | 🗄️ ~ زیرماژول‌ها | کیت رابط کاربری را هم بیاورید، سپس zev sub add آن را به‌عنوان زیرمخزن سنجاق می‌کند | | 🧩 ~ هوک‌ها | pre-commit، commit-msg، post-commit، pre-push و post-merge می‌آیند. پوشهٔ ‎.husky همچنان کار می‌کند | good | 🪝 ``` ```bash git lfs fetch --all # فقط اگر ‎--check بگوید بعضی فایل‌های LFS فقط اشاره‌گرند zev import-git --verify cd vendor/ui-kit && zev import-git && zev new && zev push && cd ../.. zev sub add acme/ui-kit vendor/ui-kit zev commit -m "UI kit as a subrepository" ``` هوکی که در `.git/hooks` است در `.zev/hooks` کپی می‌شود. هوکی که در پوشه‌ای است که کامیتش می‌کنید، مثل `.husky` در Husky، یک فایل دوخطی در `.zev/hooks` می‌گیرد که آن را از همان‌جا اجرا می‌کند؛ پس تغییر `.husky/pre-commit` برای Git و zev هر دو اعمال می‌شود. هوکی که خودش `git` را صدا می‌زند، مثل `lint-staged`، هنوز به staging گیت نگاه می‌کند؛ وقتی Git را کنار گذاشتید، نسخهٔ zev آن را بنویسید. ### تیمی که کم‌کم جابه‌جا می‌شود دو هفته، نیمی از تیم هنوز در Git کامیت می‌کند. یک نفر هر وقت خواست آوردن را اجرا می‌کند و فقط کامیت‌های تازهٔ Git می‌آیند: ```diagram type: sequence title: دو هفته Git و zev کنار هم lanes: کاربران Git | مخزن | کاربران zev --- کاربران Git -> مخزن : git commit و git push مخزن -> کاربران zev : zev import-git (فقط کامیت‌های تازه) کاربران zev -> مخزن : zev commit و zev push note مخزن : شاخه‌ای که کامیت‌های zev خودش را دارد هیچ‌وقت بازنویسی نمی‌شود | warn note کاربران zev : همه روی zev: ‎.git را پاک کنید | good ``` ```bash zev import-git --check # "Imported before: 12 new Git commit(s) to bring in" zev import-git --verify ``` هر اجرا می‌گوید کدام شاخه‌ها `updated` شدند، کدام `up to date` هستند و کدام `kept: it has zev commits of its own` ماندند. zev هیچ‌وقت شاخه‌ای را که در zev رویش کامیت کرده‌اید بازنویسی نمی‌کند. `zev undo` هر آوردنی را برمی‌گرداند. ### در یک اسکریپت یا کار CI `--check` و `--verify` هر دو `--json` می‌گیرند، پس یک pipeline می‌تواند به آن‌ها مشروط شود: ```bash zev import-git --check --json | jq -e .ready # تا وقتی کاری اول مانده، شکست می‌خورد zev import-git --verify --json | jq -e .verified # اگر چیزی با Git فرق کند، شکست می‌خورد ``` ```json {"ready":true,"commits":10,"all_commits":11,"new_commits":null,"branches":2,"tags":1, "authors":2,"lfs_whole":1,"lfs_pointer_only":[],"submodules":[{"path":"vendor/ui-kit", "url":"https://github.com/example/ui-kit.git"}],"shallow":false,"hooks":["pre-commit"]} ``` ## وقتی ‎--check می‌گوید «اول این را انجام دهید» ```text ! This is a shallow clone, so only the recent history is here. First: git fetch --unshallow ! 1 Git LFS file(s) have only a pointer here. First: git lfs fetch --all design/hero.psd 2 thing(s) to do first (marked !), then zev import-git --verify. ``` | می‌گوید | چرا | این کار را بکنید | |---|---|---| | shallow clone | `git clone --depth` فقط کامیت‌های اخیر را گرفته | `git fetch --unshallow`، سپس آوردن | | فایل LFS فقط اشاره‌گر دارد | فایل واقعی هیچ‌وقت دانلود نشده | `git lfs fetch --all`، سپس آوردن | | kept: it has zev commits of its own | کسی در zev روی آن شاخه کامیت کرده | هیچ. هر وقت آماده بودید کار Git را با `zev merge` بیاورید | | Git hooks zev doesn't run | هوکی مثل `prepare-commit-msg` در zev شکلی ندارد | کارش را به `commit-msg` یا `pre-commit` ببرید | ## چه می‌آید و چه نمی‌آید | | | |---|---| | **شاخه‌ها و برچسب‌ها** | همه‌شان، حتی شاخه‌هایی که فقط روی `origin` هستند. برچسب‌های annotated به کامیت خودشان اشاره می‌کنند | | **کامیت‌ها** | نویسنده، تاریخ و پیام کامل. تاریخچهٔ هر شاخه خط first-parent آن است، پس یک merge در Git یک کامیت می‌شود که همهٔ کاری را که آن merge کرده می‌آورد (پایین‌تر را ببینید) | | **فایل‌ها** | بایت به بایت، با بیت اجرایی، از جمله نام‌هایی که فاصله دارند | | **نام و ایمیل شما** | `user.name` و `user.email` گیت هویت zev این مخزن می‌شوند | | **هوک‌ها** | pre-commit، commit-msg، post-commit، pre-push و post-merge، از `.git/hooks` یا `core.hooksPath` (Husky) | | **.gitignore** | همان‌طور که هست خوانده می‌شود. اگر `.zevignore` اضافه کنید، جایش را می‌گیرد | | **Git LFS** | فایل‌هایی که محتوایشان در `.git/lfs` است کامل می‌آیند: zev خودش فایل‌های بزرگ را نگه می‌دارد، پس سرور LFS لازم نیست. برای آن‌هایی که فقط اشاره‌گر دارند، `git lfs fetch --all` بزنید و دوباره بیاورید؛ zev نامشان را می‌گوید | | **زیرماژول‌ها** | zev هر کدام را با نشانی‌اش نام می‌برد. مخزنش را هم بیاورید، سپس `zev sub add <address> <folder>` آن را [زیرمخزن](/docs/fa/subrepos) می‌کند | | **پیوندهای نمادین** | به‌صورت پیوند می‌آیند، همان‌طور که Git نگهشان می‌دارد: مقصد پیوند، نه فایلی که به آن اشاره می‌کند | | **فایل‌های CI** | به‌صورت فایل، سر جای خودشان می‌مانند | | **امضاها** | کامیت‌های آورده‌شده امضا ندارند: امضا می‌گوید چه کسی کامیت را ساخته، و آوردن آن را نساخته. هر چه بعد از آن کامیت کنید خودکار امضا می‌شود ([کامیت‌های امضاشده](/docs/fa/signed-commits)) | ## چه چیزی متفاوت کار می‌کند **تاریخچه یک خط صاف می‌ماند.** zev کامیت merge ندارد. `zev merge` کامیت‌های شما را روی شاخهٔ دیگر دوباره اجرا می‌کند، پس `zev log` همیشه از بالا به پایین خوانده می‌شود و چیزی برای باز کردن ندارد. همان تاریخچه‌ای است که کاربران Git از `git pull --rebase` می‌گیرند. وقتی آوردن به یک merge در Git می‌رسد، شاخه‌ای را دنبال می‌کند که merge روی آن انجام شده، و merge یک کامیت می‌شود که هر چه آورده را در خود دارد. `--check` می‌گوید این کار چند کامیت را در خود جمع می‌کند. **برگرداندن یک دستور است.** نه `commit --amend` هست، نه دستورالعمل `reset`، نه reflog که به خاطر بسپارید: `zev undo` آخرین commit، merge، rebase یا آوردن را برمی‌گرداند و `zev op log` هر کاری که کرده‌اید را فهرست می‌کند ([برگرداندن هر چیز](/docs/fa/undo)). **هنوز همه‌چیز اینجا نیست.** worktreeها و checkoutهای sparse و shallow هنوز در zev شکلی ندارند. همهٔ دستورهای روزمره همان نام را دارند: [دستورهای Git شما در zev](/docs/fa/zev-vs-git#دستورهای-git-شما-در-zev). ## CI و ابزارهای شما اسکریپت‌هایی که `git status --porcelain` را می‌خوانند می‌توانند `zev status --brief` را بخوانند، که همان دو حرف را به کار می‌برد. برای بقیه، همهٔ دستورهای روزمره `--json` دارند ([اسکریپت‌نویسی و عامل‌های هوش مصنوعی](/docs/fa/automation-and-agents)). Zaryn با هر push، CI را اجرا می‌کند ([شروع با CI](/docs/fa/get-started-ci)). ## دستورها | دستور | چه می‌کند | |---|---| | `zev import-git --check` | پیش‌نمایش: تاریخچه، اندازه، بزرگ‌ترین فایل‌ها، چه می‌آید و چه کاری اول با شماست. چیزی نمی‌نویسد | | `zev import-git` | تاریخچهٔ Git این پوشه را در همین‌جا می‌آورد | | `zev import-git <folder>` | تاریخچهٔ Git پوشه‌ای دیگر را می‌آورد | | `zev import-git <address> [<folder>]` | با Git کلون می‌کند (و فایل‌های LFS را می‌گیرد)، سپس می‌آورد | | `zev import-git --verify` | می‌آورد، سپس اثبات می‌کند هر کامیت و هر فایل سر هر شاخه با Git یکی است | | `zev git <a git command>` | شکل zev آن را می‌گوید و اجرا می‌کند؛ `-n` فقط می‌گوید، `--json` آن را به‌صورت داده می‌دهد | | `eval "$(zev git --shell-setup)"` | در مخزن zev، `git` تایپ کنید و zev بگیرید | | `--json`، `--brief` | خروجی ماشین‌خوان برای هر کدام از این‌ها | همچنین ببینید: [zev و Git](/docs/fa/zev-vs-git)، [زیرمخزن‌ها](/docs/fa/subrepos)، [چرا zev](/docs/fa/why-zev).