رفتن به محتوا
LoopX

آزمون بخش ۳: کار با GitHub

این آزمون پنج درس بخش «کار با GitHub» را می‌سنجد. جواب هر سؤال همان لحظه با توضیح نشان داده می‌شود و نتیجه‌ات در همین مرورگر ذخیره می‌شود (پیشرفت من).

؟ آزمون بخش ۳
  1. git push -u origin main علاوه بر ارسال چه می‌کند؟

  2. origin/main چیست؟

  3. فرق git fetch و git pull؟

  4. push تو با «rejected (fetch first)» رد شد. بهترین کار؟

  5. git fetch --prune چه می‌کند؟

  6. کدام فایل را به GitHub (Settings ← SSH keys) می‌دهی؟

  7. در آدرس git@github.com:user/repo.git قسمت «git@» چیست؟

  8. ssh -T git@github.com با «Connection timed out» تمام می‌شود. محتمل‌ترین علت و راه‌حل؟

  9. remote پروژه‌ای که با HTTPS کلون کرده‌ای را چطور به SSH تغییر می‌دهی؟

  10. مخزن را در GitHub با «Add a README file» ساخته‌ای و پروژه‌ی محلی با تاریخچه‌ی خودت داری. git pull چه می‌گوید؟

  11. در پیام commit نوشته‌ای «Fixes #12». چه می‌شود؟

  12. پروژه‌ی عمومی بدون فایل LICENSE چه وضعیتی دارد؟

  13. برگه‌ی «Files changed» یک PR معادل کدام دستور است؟

  14. در «Squash and merge»، با PR ای که ۵ commit دارد چه می‌شود؟

  15. در fork-based workflow، origin و upstream چه هستند؟

  16. پیام «feat(api)!: remove v1 endpoints» در Conventional Commits نسخه را چطور بالا می‌برد؟

  17. چرا hook های `.git/hooks` برای اعمال قاعده‌ی تیمی کافی نیستند؟

  18. گزینه‌ی «Require a pull request before merging» در branch protection چه می‌کند؟

🏁 چالش: یک روز کاری دو برنامه‌نویسسخت

با آنچه در این بخش آموختی، یک روز کاری دو برنامه‌نویس را شبیه‌سازی کن. «سرور» یک مخزن bare محلی است:

۱. یک مخزن bare به نام team.git و دو کلون sara و reza بساز (هر کدام با نام و ایمیل خودشان). سارا یک commit اولیه با پیام chore: init روی main می‌فرستد. ۲. سارا شاخه‌ی feature/search را با دو commit (feat: add search، docs: describe search) می‌سازد و push می‌کند. رضا همان موقع روی main یک commit (fix: typo in README) می‌فرستد. ۳. سارا برای PR: با git diff --stat main...origin/feature/search فایل‌های PR را نشان دهد؛ بعد main را بگیرد و شاخه‌اش را روی آن rebase کند و با --force-with-lease push کند. ۴. ادغام را به‌روش squash (معادل محلی «Squash and merge») روی main انجام بده، main را push کن و شاخه‌ی راه دور را حذف کن. ۵. رضا git fetch --prune بزند، main را بگیرد و ثابت کند شاخه‌ی راه دور دیگر در فهرستش نیست و main هر دو یکی است. ۶. نسخه‌ی v1.0.0 را با یک tag annotated بزن، push کن و tag های سرور را با git ls-remote --tags ثابت کن. ۷. همه‌چیز را پاک کن.

راهنمایی

برای ۳: git fetch origin، git rebase origin/main (اگر هر دو یک خط README را عوض کرده باشند conflict می‌شود: حلش کن، git add و git rebase --continue)، git push --force-with-lease. برای ۴: git switch main، git pull، git merge --squash feature/search، git commit -m "feat: add search (#1)"، git push و git push origin --delete feature/search. برای ۵: git fetch --prune، git branch -r، git rev-parse main origin/main.

راه‌حل
Terminal window
git config --global init.defaultBranch main
mkdir -p ~/gitlab && cd ~/gitlab
git init -q --bare team.git
git clone -q team.git sara 2>/dev/null; git clone -q team.git reza 2>/dev/null
(cd sara && git config user.name Sara && git config user.email sara@example.com)
(cd reza && git config user.name Reza && git config user.email reza@example.com)
cd sara && echo "# Team" > README.md && git add README.md && git commit -qm "chore: init" && git push -q origin main
cd ../reza && git pull -q
echo "== ۲) شاخه‌ی سارا و commit رضا"
cd ../sara && git switch -qc feature/search
echo "def search(q): return q" > search.py && git add search.py && git commit -qm "feat: add search"
echo "search docs" >> README.md && git commit -qam "docs: describe search"
git push -q -u origin feature/search
cd ../reza && sed -i 's/Team/Team project/' README.md && git commit -qam "fix: typo in README" && git push -q
echo "== ۳) فایل‌های PR، rebase و push"
cd ../sara
git fetch -q origin
git diff --stat main...origin/feature/search
git rebase origin/main 2>&1 | tail -3
printf '# Team project\nsearch docs\n' > README.md && git add README.md && GIT_EDITOR=true git rebase --continue 2>&1 | tail -1
git push --force-with-lease 2>&1 | tail -1
echo "== ۴) squash و پاک‌سازی شاخه"
git switch -q main && git pull -q
git merge -q --squash feature/search && git commit -qm "feat: add search (#1)"
git push -q origin main && git push -q origin --delete feature/search
git log --oneline
echo "== ۵) از دید رضا"
cd ../reza && git fetch -q --prune && git pull -q
git branch -r
git rev-parse main origin/main
echo "== ۶) tag"
git tag -a v1.0.0 -m "Release 1.0.0" && git push -q origin v1.0.0
git ls-remote --tags origin | awk '{print $2}'
echo "== ۷) پاک‌سازی"
cd ~ && rm -rf ~/gitlab ~/.gitconfig
خروجی
== ۲) شاخه‌ی سارا و commit رضا
== ۳) فایل‌های PR، rebase و push
README.md | 1 +
search.py | 1 +
2 files changed, 2 insertions(+)
hint: You can instead skip this commit: run "git rebase --skip".
hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply f6471db... docs: describe search
Successfully rebased and updated refs/heads/feature/search.
+ f6471db...5b1e06e feature/search -> feature/search (forced update)
== ۴) squash و پاک‌سازی شاخه
Squash commit -- not updating HEAD
96ed8ca feat: add search (#1)
fba8935 fix: typo in README
c01a9bd chore: init
== ۵) از دید رضا
origin/main
96ed8cabfeab4c11c38ef861d3655fb36c7a7f2a
96ed8cabfeab4c11c38ef861d3655fb36c7a7f2a
== ۶) tag
refs/tags/v1.0.0
refs/tags/v1.0.0^{}
== ۷) پاک‌سازی