Chapterبەش 2 · Lectureوانە 2.2
Branches and Merging: Working on Many Things at Onceلقەکان و بەیەککردن: کارکردن لەسەر چەند شتێک لە یەک کاتدا
How a team works on several things at once without breaking main. With Bazaar Cart's delivery fee and a honey-price bug, the lesson shows that a branch is a movable name and HEAD marks where you are, creates and switches branches, deals with unfinished work (commit or stash), merges by fast-forward and by a three-way merge commit, resolves a real merge conflict and the SyntaxError that leftover markers cause, and covers avoiding conflicts, deleting and naming branches, tags as fixed names, and the GitHub flow and trunk-based strategies, with a word on rebase.
تیمێک چۆن لە یەک کاتدا لەسەر چەند شتێک کار دەکات بێ ئەوەی main تێک بدات. بە کرێی گەیاندنی Bazaar Cart و نرخی هەنگوین، وانەکە پیشان دەدات ناوێکی جووڵاوە و نیشانی دەدات لە کوێیت، دروست دەکات و لە نێوانیاندا دەگوازێتەوە، کاری تەواونەکراو ( یان stash) چارەسەر دەکات، بە و بە سێلایەنە دەکات، ڕاستەقینە و ئەو نیشانە بەجێماوەکان دروستی دەکەن چارەسەر دەکات و باس لە دوورکەوتنەوە لە ناکۆکی، سڕینەوە و ناونانی ، وەک ناوی جێگیر و ستراتیژییەکانی GitHub flow و trunk-based دەکات، لەگەڵ وشەیەک لەبارەی rebase.
What you will learnچی فێر دەبیت
- Explain what a branch and HEAD are, and create and switch branches.
- Handle unfinished work before switching with a commit or git stash.
- Tell a fast-forward merge from a three-way merge and read the merge commit in git log --graph.
- Resolve a merge conflict and find leftover conflict markers.
- Keep conflicts small, delete and name branches, mark a version with a tag and choose a branching strategy.
- ڕوون بکەیتەوە و چین و دروست بکەیت و لە نێوانیاندا بگوازیتەوە.
- پێش گواستنەوە کاری تەواونەکراو بە یان git stash چارەسەر بکەیت.
- لە سێلایەنە جیا بکەیتەوە و لە git log --graph بخوێنیتەوە.
- چارەسەر بکەیت و نیشانە بەجێماوەکانی ناکۆکی بدۆزیتەوە.
- ناکۆکییەکان بچووک بهێڵیتەوە، بسڕیتەوە و ناویان لێ بنێیت، بە نیشان بکەیت و هەڵبژێریت.
Two jobs at the same timeدوو کار لە یەک کاتدا
Bazaar Cart works, and two jobs arrive at once (prices in this lesson are made up, in IQD). Karwan must add the delivery fee, rule R4; it will take him a day or two. Meanwhile Dilan, the tester, finds a bug: honey costs 30,000 IQD per kilogram, but prices.py says 3000 — a zero has been missing since the very first commit. Shilan must fix it today. Neither job may break main, the code Soran's shop uses every day.
Bazaar Cart کار دەکات و دوو کار پێکەوە دێن (نرخەکانی ئەم وانەیە دەستکردن و بە دینارن). کاروان دەبێت کرێی گەیاندن زیاد بکات، ڕێسای R4؛ ڕۆژێک یان دوو ڕۆژی پێدەچێت. لەو کاتەدا دیلان، ، دەدۆزێتەوە: هەنگوین کیلۆی بە 30,000 دینارە، بەڵام prices.py دەڵێت 3000 — سفرێک لە یەکەم ونە. شیلان دەبێت ئەمڕۆ چاکی بکات. هیچ کامیان نابێت main تێک بدەن، ئەو کۆدەی دوکانەکەی سۆران هەموو ڕۆژێک بەکاری دەهێنێت.
The answer is branches: separate lines of work inside one repository. Each person works on their own branch; when the work is ready and checked, it is merged back into main.
وەڵامەکە : هێڵی جیای کار لە ناو یەک . هەر کەسێک لەسەر خۆی کار دەکات؛ کاتێک کارەکە ئامادە و پشکنراو بوو، دەگەڕێتەوە ناو main ().
Hana's family keeps a recipe book. When she wants to try a new dolma recipe, she writes it on a separate page and cooks it a few times. Only when the family likes it does she copy it into the book. The book — like main — is never spoiled by an experiment.
خێزانەکەی هانا کتێبێکی ڕێچەتەی خواردنیان هەیە. کاتێک دەیەوێت ڕێچەتەیەکی نوێی دۆڵمە تاقی بکاتەوە، لەسەر پەڕەیەکی جیا دەینووسێت و چەند جارێک لێی دەنێت. تەنیا کاتێک خێزانەکە حەزیان لێ بوو، دەیگوازێتەوە ناو کتێبەکە. کتێبەکە — وەک main — هەرگیز بە تاقیکردنەوەیەک تێک ناچێت.
Where the analogy stops workingسنووری ئەم نموونەیە
Git does not copy the book for a branch: a branch is only a name, so it costs almost nothing. And Git usually joins the pages by itself; a person decides only when two people changed the same line.
Git کتێبەکە بۆ کۆپی ناکات: تەنیا ناوێکە، بۆیە نزیکەی هیچی تێناچێت. هەروەها Git زۆرجار خۆی پەڕەکان بەیەک دەگەیەنێت؛ تەنیا کاتێک دوو کەس هەمان دێڕیان گۆڕیبێت کەسێک بڕیار دەدات.
A branch is a movable nameلق ناوێکی جووڵاوە
Remember that every commit points to its parent (Git basics). A branch is simply a name that points to one commit — in Git it is a tiny file of 41 bytes holding a commit hash, so making one is instant and copies nothing. main is an ordinary branch that git init -b main made. When you commit, the branch you are on moves forward to the new commit.
لەبیرت بێت هەر ئاماژە بە دایکەکەی دەکات (بنەماکانی Git). تەنیا ناوێکە کە ئاماژە بە یەک دەکات — لە Gitـدا بچکۆلەیە بە قەبارەی 41 کە هەڵدەگرێت، بۆیە دروستکردنی یەکسەرییە و هیچ شتێک کۆپی ناکات. main ئاساییە کە git init -b main دروستی کرد. کاتێک دەکەیت، ئەو لەسەریتی دەچێتە پێش بۆ نوێیەکە.
HEAD is Git's marker for where you are: it points to your current branch. git branch lists the branches and marks HEAD's branch with *; git branch <name> makes a new branch but does not switch to it.
نیشانەی Gitـە بۆ ئێستا لە کوێیت: ئاماژە بە ئێستات دەکات. git branch لیست دەکات و بە * نیشان دەکات؛ git branch <name> نوێ دروست دەکات بەڵام ناتباتە سەری.
git branch* main
Make a branch and switch to itلقێک دروست بکە و بچۆ سەری
git switch -c feature/delivery-fee creates the branch and switches to it (-c = create; older tutorials write git checkout -b). Karwan adds one line, DELIVERY_FEE = 2500 — Soran's price at that time — and commits:
git switch -c feature/delivery-fee دروست دەکات و دەچێتە سەری (-c = create؛ فێرکارییە کۆنەکان git checkout -b دەنووسن). کاروان یەک دێڕ زیاد دەکات، DELIVERY_FEE = 2500 — نرخی سۆران لەو کاتەدا — و دەکات:
git switch -c feature/delivery-fee
git branch
git add prices.py
git commit -m "Add a delivery fee of 2,500 IQD"
git log --oneline --graph --all$ git switch -c feature/delivery-fee Switched to a new branch 'feature/delivery-fee' $ git branch * feature/delivery-fee main $ git add prices.py $ git commit -m "Add a delivery fee of 2,500 IQD" [feature/delivery-fee 07af517] Add a delivery fee of 2,500 IQD 1 file changed, 2 insertions(+) $ git log --oneline --graph --all * 07af517 (HEAD -> feature/delivery-fee) Add a delivery fee of 2,500 IQD * 463271a (main) Revert "List the order lines in alphabetical order" * 5c71c96 List the order lines in alphabetical order * 2ff6abe Add cart.py to total an order * 4fc0f01 Ignore Python cache files, virtual environments and .env * 903e816 Check that grams are between 100 and 10,000 * 08d3d64 Add line price calculation
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 5
--graph --alldraws every branch as a text graph; each*is a commit. Heremainis still one commit behind.--graph --allهەموو وەک دەقی دەکێشێت؛ هەر*ـێک . لێرەداmainهێشتا یەک لە دواوەیە.
Switching with unfinished workگواستنەوە بە کاری تەواونەکراوەوە
Karwan has started writing delivery_fee() but has not committed it. Now Shilan needs main. Switching would replace prices.py with main's version and destroy his edit, so Git refuses:
کاروان دەستی کردووە بە نووسینی delivery_fee() بەڵام هێشتا نەکردووە. ئێستا شیلان پێویستی بە main هەیە. گواستنەوە prices.py بە وەشانەکەی main دەگۆڕێت و دەستکارییەکەی لەناو دەبات، بۆیە Git ڕەتی دەکاتەوە:
git status --short
git switch main$ git status --short M prices.py $ git switch main error: Your local changes to the following files would be overwritten by checkout: prices.py Please commit your changes or stash them before you switch branches. Aborting
Two ways out. Usually simplest: commit the unfinished work on the branch (you can improve it in later commits). For a short break there is git stash: it puts your uncommitted changes in a drawer and makes the working tree clean; later, on the same branch, git stash pop brings them back:
دوو ڕێگە هەیە. زۆرجار سادەترینیان: کارە تەواونەکراوەکە لەسەر بکە (دەتوانیت لە دواتردا باشتری بکەیت). بۆ پشوویەکی کورت git stash هەیە: گۆڕانکارییە دەخاتە چەکمەجەیەکەوە و پاک دەکاتەوە؛ دواتر، لەسەر هەمان ، git stash pop دەیانگەڕێنێتەوە:
git stash
git status --short
git switch main$ git stash Saved working directory and index state WIP on feature/delivery-fee: 07af517 Add a delivery fee of 2,500 IQD $ git status --short $ git switch main Switched to branch 'main'
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 1
WIP= work in progress. New, untracked files are not stashed unless you add-u.WIP= کاری بەردەوام. نوێی چاودێرینەکراو stash ناکرێن مەگەر-uزیاد بکەیت.
Fast-forward: the name just movesبەیەککردنی بەپێشخستن: تەنیا ناوەکە دەجووڵێت
Shilan makes her own branch from main, fixes the honey price and commits. Then she switches back to main and merges her branch into it — git merge always brings the named branch into the branch you are on:
شیلان خۆی لە main دروست دەکات، نرخی هەنگوین چاک دەکات و دەکات. پاشان دەگەڕێتەوە سەر main و خۆی تێکەڵی دەکات — git merge هەمیشە ئەو ناوی دەبەیت دەهێنێتە ناو ئەو لەسەریتی:
git switch -c fix/honey-price
git diff
git add prices.py
git commit -m "Fix the price of honey: 30,000 IQD per kg"
git switch main
git merge fix/honey-price$ git switch -c fix/honey-price
Switched to a new branch 'fix/honey-price'
$ git diff
diff --git a/prices.py b/prices.py
index 719b474..26e26e1 100644
--- a/prices.py
+++ b/prices.py
@@ -6,7 +6,7 @@ PRICES = {
"sumac": 8000,
"dried figs": 12000,
"black tea": 14000,
- "honey": 3000,
+ "honey": 30000,
}
$ git add prices.py
$ git commit -m "Fix the price of honey: 30,000 IQD per kg"
[fix/honey-price 2f5c2b5] Fix the price of honey: 30,000 IQD per kg
1 file changed, 1 insertion(+), 1 deletion(-)
$ git switch main
Switched to branch 'main'
$ git merge fix/honey-price
Updating 463271a..2f5c2b5
Fast-forward
prices.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 6
Updating 463271a..2f5c2b5+Fast-forward: main simply moved from its old commit to Shilan's.Updating 463271a..2f5c2b5+Fast-forward: main تەنیا لە کۆنەکەی خۆیەوە چوو بۆ شیلان.
Nothing new had happened on main since Shilan's branch started, so there was nothing to combine. Git only moved the name main forward to her commit: a fast-forward merge. No new commit is made, and the history stays one straight line.
لەو کاتەوەی شیلان دەستی پێکرد، هیچ شتێکی نوێ لەسەر main ڕووی نەدابوو، بۆیە هیچ شتێک نەبوو تا پێکەوە ببەسترێت. Git تەنیا ناوی mainـی بۆ ئەو برد: . هیچ نوێ دروست ناکرێت و مێژووەکە وەک هێڵێکی ڕاست دەمێنێتەوە.
Three-way merge: a commit with two parentsبەیەککردنی سێلایەنە: کۆمیتێک بە دوو دایک
Karwan goes back to his branch, takes his work out of the stash and finishes it: delivery_fee() in prices.py and a delivery line in cart.py:
کاروان دەگەڕێتەوە سەر ، کارەکەی لە stash دەردەهێنێت و تەواوی دەکات: delivery_fee() لە prices.py و دێڕێکی گەیاندن لە cart.py:
git switch feature/delivery-fee
git stash pop
git add prices.py cart.py
git commit -m "Add delivery_fee() and show the fee in cart.py"$ git switch feature/delivery-fee
Switched to branch 'feature/delivery-fee'
$ git stash pop
On branch feature/delivery-fee
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: prices.py
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (3039c3cabef668d1fe80c787be084784f3e3465b)
$ git add prices.py cart.py
$ git commit -m "Add delivery_fee() and show the fee in cart.py"
[feature/delivery-fee fadb817] Add delivery_fee() and show the fee in cart.py
2 files changed, 9 insertions(+), 1 deletion(-)Now main has a commit his branch does not have (Shilan's fix), and his branch has two commits main does not have: the two lines of work have diverged. Git compares three snapshots — the common ancestor and the two branch tips — joins both sets of changes and records the result in a merge commit with two parents:
ئێستا main هەیە کە ئەو نییەتی (چاککردنەکەی شیلان) و ئەویش دوو هەیە کە main نییەتی: هەردوو هێڵی کارەکە لێک جیا بوونەتەوە. Git سێ وێنەی تەواو بەراورد دەکات — هاوبەشەکەی پێشوو و دوایین هەردوو — هەردوو کۆمەڵە گۆڕانکارییەکە پێکەوە دەبەستێت و ئەنجامەکە لە بە دوو دایک تۆمار دەکات:
git switch main
git merge feature/delivery-fee
git log -1
python3 cart.py$ git switch main
Switched to branch 'main'
$ git merge feature/delivery-fee
Auto-merging prices.py
Merge made by the 'ort' strategy.
cart.py | 5 ++++-
prices.py | 7 +++++++
2 files changed, 11 insertions(+), 1 deletion(-)
$ git log -1
commit 58bc993147a7f2f1a53eea20af03828bcb0b22e5 (HEAD -> main)
Merge: 2f5c2b5 fadb817
Author: Karwan <karwan@example.com>
Date: Wed Nov 4 11:40:00 2026 +0300
Merge branch 'feature/delivery-fee'
$ python3 cart.py
walnuts 500 g 9,000 IQD
sumac 350 g 3,000 IQD
black tea 250 g 3,500 IQD
Goods total 15,500 IQD
Delivery 2,500 IQD
To pay 18,000 IQDExplain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 2
Merge made by the 'ort' strategy.'ort' has been Git's default since 2021; older books still print 'recursive'.Merge made by the 'ort' strategy.لە ساڵی 2021ـەوە 'ort' ڕێگەی بنەڕەتیی Gitـە؛ کتێبە کۆنەکان هێشتا 'recursive' دەنووسن.- Lineدێڕی 3
Merge: 2f5c2b5 fadb817— the two parents.Merge: 2f5c2b5 fadb817— هەردوو دایکەکە.
The whole story in motionهەموو چیرۆکەکە بە جووڵە
Here is everything so far, first as an animation, then as Git draws it in text. Read the text graph from the bottom up: each * is a commit, |/ is where a branch started, and the * where two lines meet again is a merge commit.
ئەمە هەموو ئەوەیە کە تا ئێستا ڕوویدا، سەرەتا وەک ئەنیمەیشن، پاشان وەک ئەوەی Git بە دەق دەیکێشێت. دەقییەکە لە خوارەوە بۆ سەرەوە بخوێنەرەوە: هەر *ـێک ، |/ ئەو شوێنەیە کە دەستی پێکرد و ئەو *ـەی دوو هێڵ تێیدا دیسان دەگەنەوە یەک .


git log --oneline --graph --all* 58bc993 (HEAD -> main) Merge branch 'feature/delivery-fee' |\ | * fadb817 (feature/delivery-fee) Add delivery_fee() and show the fee in cart.py | * 07af517 Add a delivery fee of 2,500 IQD * | 2f5c2b5 (fix/honey-price) Fix the price of honey: 30,000 IQD per kg |/ * 463271a Revert "List the order lines in alphabetical order" * 5c71c96 List the order lines in alphabetical order * 2ff6abe Add cart.py to total an order * 4fc0f01 Ignore Python cache files, virtual environments and .env * 903e816 Check that grams are between 100 and 10,000 * 08d3d64 Add line price calculation
Merge conflictsناکۆکییەکانی بەیەککردن
Most merges are automatic. A merge conflict happens only when both branches changed the same lines of a file in different ways: Git cannot know which is right, so it stops and asks a person. The next day Soran phones: fuel is dearer, delivery is now 3,000 IQD. Shilan changes DELIVERY_FEE = 2500 to 3000 on fix/delivery-fee. At the same time Karwan, on feature/free-delivery, adds the rest of R4 — free delivery from 50,000 IQD of goods — and adds a comment on the same line. Shilan's branch is merged first (a fast-forward). Then Karwan's:
زۆربەی خۆکارن. تەنیا کاتێک ڕوو دەدات کە هەردوو هەمان دێڕەکانی بە دوو شێوەی جیاواز گۆڕیبن: Git نازانێت کامیان ڕاستە، بۆیە دەوەستێت و پرسیار لە کەسێک دەکات. ڕۆژی دواتر سۆران تەلەفۆن دەکات: سووتەمەنی گرانتر بووە، گەیاندن ئێستا 3,000 دینارە. شیلان لەسەر fix/delivery-fee، DELIVERY_FEE = 2500 دەگۆڕێت بۆ 3000. لە هەمان کاتدا کاروان، لەسەر feature/free-delivery، بەشەکەی تری R4 زیاد دەکات — گەیاندنی بێبەرانبەر لە 50,000 دینار کاڵا بەرەو سەرەوە — و لەسەر هەمان دێڕ زیاد دەکات. سەرەتا شیلان تێکەڵ دەکرێت (). پاشان هی کاروان:
git merge feature/free-delivery
git status$ git merge feature/free-delivery Auto-merging prices.py CONFLICT (content): Merge conflict in prices.py Automatic merge failed; fix conflicts and then commit the result. $ git status On branch main You have unmerged paths. (fix conflicts and run "git commit") (use "git merge --abort" to abort the merge) Unmerged paths: (use "git add <file>..." to mark resolution) both modified: prices.py no changes added to commit (use "git add" and/or "git commit -a")
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 1
CONFLICT (content): the same lines differ. The merge is paused, not lost.CONFLICT (content): هەمان دێڕەکان جیاوازن. وەستاوە، ون نەبووە.
Git writes both versions into prices.py, between conflict markers. Everything between <<<<<<< HEAD and ======= is your side (the branch you are on, main); everything between ======= and >>>>>>> is the incoming branch:
Git هەردوو وەشانەکە لە ناو prices.pyـدا دەنووسێت، لە نێوان نیشانەکانی ناکۆکیدا. هەموو ئەوەی لە نێوان <<<<<<< HEAD و =======ـدایە لای خۆتە (ئەو لەسەریتی، main)؛ هەموو ئەوەی لە نێوان ======= و >>>>>>>ـدایە هاتووەکەیە:
"honey": 30000,
}
<<<<<<< HEAD
DELIVERY_FEE = 3000
=======
DELIVERY_FEE = 2500 # IQD, inside Sulaimani
FREE_DELIVERY_FROM = 50_000 # goods total in IQD
>>>>>>> feature/free-deliveryChanged your mind? git merge --abort puts everything back as it was before the merge.
پەشیمان بوویتەوە؟ git merge --abort هەموو شتێک دەگەڕێنێتەوە بۆ ئەوەی پێش بوو.
Resolving a conflictچارەسەرکردنی ناکۆکییەکی بەیەککردن
- Decideبڕیار بدە
Read both sides and decide what the result must be. Here both were right: the new fee 3,000 from Shilan, the comment and
FREE_DELIVERY_FROMfrom Karwan. If you are not sure, ask the people who wrote them.هەردوو لاکە بخوێنەرەوە و بڕیار بدە ئەنجامەکە دەبێت چی بێت. لێرەدا هەردووکیان ڕاست بوون: کرێ نوێیەکەی 3,000 لە شیلانەوە، و
FREE_DELIVERY_FROMلە کاروانەوە. ئەگەر دڵنیا نیت، لەو کەسانە بپرسە کە نووسیویانە. - Editدەستکاری بکە
Write the result and delete the three marker lines.
ئەنجامەکە بنووسە و سێ دێڕە نیشانەکە بسڕەوە.
- Addadd بکە
git add prices.pytells Git the conflict is resolved.git add prices.pyبە Git دەڵێت ناکۆکییەکە چارەسەر کراوە. - Commitcommit بکە
git commitfinishes the merge.--no-editkeeps Git's ready message Merge branch '…'.git commitتەواو دەکات.--no-editپەیامە ئامادەکەی Git، Merge branch '…'، دەهێڵێتەوە.
}
DELIVERY_FEE = 3000 # IQD, inside Sulaimani
FREE_DELIVERY_FROM = 50_000 # goods total in IQD
def round_up_250(amount):git diff --check
git add prices.py
git status
git commit --no-edit
python3 cart.py$ git diff --check $ git add prices.py $ git status On branch main All conflicts fixed but you are still merging. (use "git commit" to conclude merge) Changes to be committed: modified: prices.py $ git commit --no-edit [main bf0326b] Merge branch 'feature/free-delivery' $ python3 cart.py walnuts 500 g 9,000 IQD sumac 350 g 3,000 IQD black tea 250 g 3,500 IQD Goods total 15,500 IQD Delivery 3,000 IQD To pay 18,500 IQD
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 1
Prints nothing: no conflict markers are left.
هیچ پیشان نادات: هیچ نیشانەیەکی ناکۆکی نەماوە.
Editors help: VS Code marks each conflict with Accept Current Change, Accept Incoming Change, Accept Both Changes and Compare Changes, and has a three-way merge editor. Here Accept Both would keep two DELIVERY_FEE lines — the buttons save typing, but you still decide.
دەستکاریکەرەکان یارمەتی دەدەن: VS Code هەر ناکۆکییەک بە Accept Current Change، Accept Incoming Change، Accept Both Changes و Compare Changes نیشان دەکات و دەستکاریکەرێکی سێبەشیی هەیە. لێرەدا Accept Both دوو دێڕی DELIVERY_FEE دەهێڵێتەوە — نووسینت لێ کەم دەکەنەوە، بەڵام هێشتا تۆ بڕیار دەدەیت.
Leftover markers break the programنیشانە بەجێماوەکان بەرنامەکە تێک دەدەن
If you run the program while the markers are still in the file — or, worse, commit them — Python stops at once: <<<<<<< is not Python. This is what Karwan saw when he tried cart.py in the middle of the conflict:
ئەگەر جێبەجێ بکەیت لە کاتێکدا نیشانەکان هێشتا لە — یان خراپتر، بکەیت — Python یەکسەر دەوەستێت: <<<<<<< Python نییە. ئەمە ئەوە بوو کە کاروان بینی کاتێک لە ناوەڕاستی ناکۆکییەکەدا cart.pyـی تاقی کردەوە:
python3 cart.pyTraceback (most recent call last):
File "~/se/bazaar-cart/cart.py", line 2, in <module>
from prices import PRICES, line_price, delivery_fee
File "~/se/bazaar-cart/prices.py", line 12
<<<<<<< HEAD
^^
SyntaxError: invalid syntaxThe traceback points to prices.py, line 12: the <<<<<<< HEAD line (reading a traceback, syntax errors). Before git add, let Git look for you: git diff --check lists every leftover marker.
ئاماژە بە prices.py دەکات، دێڕی 12: دێڕی <<<<<<< HEAD (خوێندنەوەی ڕێچکەی هەڵە، هەڵەکانی داڕستن). پێش git add، با Git بۆت بگەڕێت: git diff --check هەموو نیشانەیەکی بەجێماو لیست دەکات.
git diff --checkprices.py:12: leftover conflict marker prices.py:14: leftover conflict marker prices.py:17: leftover conflict marker
Fewer, smaller conflictsناکۆکیی کەمتر و بچووکتر
Conflicts are normal in a team, not a disaster. But each one costs time, and the longer two lines of work stay apart, the more they differ. Habits that keep conflicts small:
ناکۆکی لە تیمێکدا شتێکی ئاساییە، کارەسات نییە. بەڵام هەریەکەیان کاتی دەوێت و هەتا دوو هێڵی کار زیاتر لێک دوور بمێننەوە، زیاتر لێک جیاواز دەبن. خووەکان کە ناکۆکییەکان بچووک دەهێڵنەوە:
- Small, short-lived branches — one task each, merged within a day or two.
- Merge
maininto your branch often (git merge mainwhile you are on your branch), so you meet other people's changes early, when they are small. - Talk to the team: “I am changing the delivery code today.” Two people should not rewrite the same function at the same time.
- Keep style changes separate: re-indenting a whole file in a feature commit causes conflicts everywhere. Agree on one style.
- Run the program and its tests after every merge — a clean merge can still combine two changes that do not work together (automated testing).
- بچووک و کورتخایەن — هەریەکە یەک کار، لە ماوەی ڕۆژێک یان دوو ڕۆژدا تێکەڵ دەکرێن.
- زۆرجار
mainتێکەڵی بکە (git merge mainکاتێک لەسەر خۆتیت)، بۆ ئەوەی گۆڕانکاریی کەسانی تر زوو ببینیت، کاتێک هێشتا بچووکن. - لەگەڵ تیمەکە قسە بکە: «ئەمڕۆ کۆدی گەیاندن دەگۆڕم.» دوو کەس نابێت لە یەک کاتدا هەمان دووپاتە بنووسنەوە.
- گۆڕانکاریی شێوەی نووسین جیا بکەرەوە: گۆڕینی هەموو لە تایبەتمەندییەکدا لە هەموو شوێنێک ناکۆکی دروست دەکات. لەسەر یەک شێوە ڕێک بکەون.
- دوای هەموو و تاقیکردنەوەکانی جێبەجێ بکە — بێ ناکۆکی هێشتا دەتوانێت دوو گۆڕانکاری پێکەوە ببەستێت کە پێکەوە کار ناکەن (تاقیکردنەوەی خۆکار).
Delete merged branches; name them wellلقە تێکەڵکراوەکان بسڕەوە؛ ناوی باشیان لێ بنێ
A merged branch has done its job. git branch --merged lists the branches whose commits are all in the current branch, and git branch -d deletes them. Only the names go; the commits stay in main's history.
تێکەڵکراو کاری خۆی کردووە. git branch --merged ئەو لیست دەکات کە هەموو لە ئێستادان و git branch -d دەیانسڕێتەوە. تەنیا ناوەکان دەڕۆن؛ لە مێژووی mainـدا دەمێننەوە.
git branch --merged
git branch -d fix/honey-price feature/delivery-fee fix/delivery-fee feature/free-delivery$ git branch --merged feature/delivery-fee feature/free-delivery fix/delivery-fee fix/honey-price * main $ git branch -d fix/honey-price feature/delivery-fee fix/delivery-fee feature/free-delivery Deleted branch fix/honey-price (was 2f5c2b5). Deleted branch feature/delivery-fee (was fadb817). Deleted branch fix/delivery-fee (was 709b275). Deleted branch feature/free-delivery (was 312fb22).
Git protects unmerged work. Karwan tried a 5 % discount on experiment/discount, and Soran said no. -d refuses to delete a branch that is not merged; only -D forces it — and then those commits are lost:
Git کاری تێکەڵنەکراو دەپارێزێت. کاروان داشکاندنی 5% لەسەر experiment/discount تاقی کردەوە و سۆران گوتی نا. -d ڕەت دەکاتەوە تێکەڵنەکراو بسڕێتەوە؛ تەنیا -D بە زۆر دەیسڕێتەوە — و ئەوکات ئەو ون دەبن:
git switch -c experiment/discount
git commit -am "Try 5 % off every order"
git switch main
git branch -d experiment/discount
git branch -D experiment/discount$ git switch -c experiment/discount Switched to a new branch 'experiment/discount' $ git commit -am "Try 5 % off every order" [experiment/discount b792b43] Try 5 % off every order 1 file changed, 1 insertion(+) $ git switch main Switched to branch 'main' $ git branch -d experiment/discount error: the branch 'experiment/discount' is not fully merged hint: If you are sure you want to delete it, run 'git branch -D experiment/discount' hint: Disable this message with "git config set advice.forceDeleteBranch false" $ git branch -D experiment/discount Deleted branch experiment/discount (was b792b43).
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 2
-am: stage all changed tracked files and commit in one step. Handy, but it skips your look atgit status.-am: هەموو چاودێریکراوە گۆڕاوەکان ئامادە دەکات و لە یەک هەنگاودا دەکات. بەسوودە، بەڵام سەیرکردنیgit statusلێ دەبڕێت.
Names tell the team what a branch is for: feature/… for new work, fix/… for bug fixes, short, lowercase, words joined with hyphens — feature/free-delivery, fix/honey-price. Some teams add the issue number: fix/12-honey-price.
ناوەکان بە تیمەکە دەڵێن بۆ چییە: feature/… بۆ کاری نوێ، fix/… بۆ چاککردنی ، کورت، بە پیتی بچووک، وشەکان بە هێڵی کورت بەستراون — feature/free-delivery، fix/honey-price. هەندێک تیم ژمارەی ئیشووەکەش زیاد دەکەن: fix/12-honey-price.
A name that stays: tagsناوێک کە دەمێنێتەوە: تاگەکانی Git
Bazaar Cart now has all of rule R4 (3,000 IQD inside Sulaimani, free from 50,000 IQD of goods) and the honey fix — a good moment to mark a version. A tag is a name for one commit that, unlike a branch, never moves:
Bazaar Cart ئێستا هەموو ڕێسای R4ـی تێدایە (3,000 دینار لە ناو سلێمانی، بێبەرانبەر لە 50,000 دینار کاڵا بەرەو سەرەوە) و چاککردنەکەی هەنگوینیش — کاتێکی باشە بۆ نیشانکردنی . ناوێکە بۆ یەک کە بە پێچەوانەی هەرگیز ناجووڵێت:
git tag v0.2.0
git log --oneline -1$ git tag v0.2.0 $ git log --oneline -1 bf0326b (HEAD -> main, tag: v0.2.0) Merge branch 'feature/free-delivery'
What the numbers in 0.2.0 and 1.0.0 promise, annotated tags (git tag -a) and releases are taught in Versions and builds.
ئەوەی ژمارەکانی 0.2.0 و 1.0.0 بەڵێنی دەدەن، جۆری annotatedـی (git tag -a) و لە وەشان و بیلد فێر دەکرێن.
Branching strategies: GitHub flow and trunk-basedستراتیژییەکانی بەکارهێنانی لق: GitHub flow و trunk-based
A branching strategy is the team's agreement on how branches are used: when to make one, how long it lives, how it is named and how it gets back into main. Three you will meet:
ڕێککەوتنی تیمەکەیە لەسەر چۆنیەتیی بەکارهێنانی : کەی دروست دەکرێت، چەند دەژی، چۆن ناو دەنرێت و چۆن دەگەڕێتەوە ناو main. سێ دانەیان دەبینیت:
- GitHub flow:
mainis always ready to use. Every change gets a short branch, then a pull request with a review, then a merge, and the branch is deleted. Pull requests are the topic of GitHub and teamwork. - Trunk-based development: everyone merges into
main(the trunk) at least once a day, with branches that live a day or less. Automatic tests keepmainworking (automated testing). - Long-lived branches, for example Git Flow with separate
developandreleasebranches: they suit software released in planned versions, but the branches drift apart and merges bring more conflicts.
- GitHub flow:
mainهەمیشە ئامادەی بەکارهێنانە. هەر گۆڕانکارییەک کورت وەردەگرێت، پاشان لەگەڵ پێداچوونەوە، پاشان و دەسڕدرێتەوە. بابەتی GitHub و کاری تیمیـن. - Trunk-based development: هەموو کەسێک لانیکەم ڕۆژی جارێک کارەکەی تێکەڵی
main(قەد) دەکات، بە کە ڕۆژێک یان کەمتر دەژین.mainکارکەر دەهێڵنەوە (تاقیکردنەوەی خۆکار). - درێژخایەن، بۆ نموونە Git Flow بە جیای
developوrelease: بۆ ئەو گونجاون کە بە وەشانی پلاندانراو بڵاو دەکرێنەوە، بەڵام لێک دوور دەکەونەوە و ناکۆکیی زیاتر دەهێنن.
Bazaar Cart's team of four uses GitHub flow: short branches, a review before every merge, main always ready for Soran's shop. Its six steps on GitHub are shown in GitHub and Teamwork.
تیمە چوار کەسییەکەی Bazaar Cart GitHub flow بەکار دەهێنێت: کورت، پێداچوونەوە پێش هەموو ، main هەمیشە ئامادە بۆ دوکانەکەی سۆران. شەش هەنگاوەکەی لەسەر GitHub لە GitHub و کاری تیمی پیشان دراون.
Common mistakesهەڵە باوەکان
- Working on
mainby mistake. Make the branch before you start; the first line ofgit status(On branch …) tells you where you are. - Merging the wrong way.
git merge Xbrings X into the branch you are on. To bring a feature intomain, switch tomainfirst. - Resolving by clicking one side without reading. Accept Current may delete a teammate's work. Read both sides; often the answer keeps parts of each.
- Committing conflict markers →
SyntaxError. Rungit diff --checkand the program beforegit add. git branch -Dto tidy up. It deletes unmerged work without asking. Use-dand read its message.- Branches that live for weeks. Merge small pieces often instead.
- Switching with uncommitted work and not noticing that the changes came along to the other branch. Check
git statusaftergit switch.
- کارکردن لەسەر
mainبە هەڵە. پێش دەستپێکردن دروست بکە؛ یەکەم دێڕیgit status(On branch …) پێت دەڵێت لە کوێیت. - بە ئاڕاستەی هەڵە.
git merge XX دەهێنێتە ناو ئەو لەسەریتی. بۆ هێنانی تایبەتمەندییەک بۆ ناوmain، سەرەتا بچۆ سەرmain. - چارەسەرکردن بە کرتەکردن لە یەک لا بێ خوێندنەوە. Accept Current لەوانەیە کاری هاوکارێک بسڕێتەوە. هەردوو لا بخوێنەرەوە؛ زۆرجار وەڵامەکە بەشێک لە هەریەکەیان دەهێڵێتەوە.
- نیشانەکانی ناکۆکی ←
SyntaxError. پێشgit add،git diff --checkو جێبەجێ بکە. git branch -Dبۆ ڕێکخستن. کاری تێکەڵنەکراو بێ پرسیار دەسڕێتەوە.-dبەکار بهێنە و پەیامەکەی بخوێنەرەوە.- ئەو چەند هەفتەیەک دەژین. لە جیاتی ئەوە بەشی بچووک زۆرجار تێکەڵ بکە.
- گواستنەوە بە کاری و هەست پێنەکردن کە گۆڕانکارییەکان لەگەڵت هاتوونەتە سەر ترەکە. دوای
git switchسەیریgit statusبکە.
Exercisesڕاهێنانەکان
(a) Lana makes fix/typo from main, commits once, and nobody else commits; she merges it into main. (b) Rebin makes feature/map from main and commits twice; meanwhile Hana's fix is merged into main; then Rebin's branch is merged. Which kind of merge is each?
(a) لانا fix/typo لە main دروست دەکات، یەک جار دەکات و کەسی تر ناکات؛ تێکەڵی mainـی دەکات. (b) ڕێبین feature/map لە main دروست دەکات و دوو جار دەکات؛ لەو کاتەدا چاککردنەکەی هانا تێکەڵی main دەکرێت؛ پاشان ڕێبین تێکەڵ دەکرێت. هەریەکەیان چ جۆرە ؟
Show answerوەڵامەکە پیشان بدە
- (a) Fast-forward:
mainhad nothing new, so its name just moves to Lana's commit. - (b) Three-way: both sides have new commits, so Git makes a merge commit with two parents.
- (a) :
mainهیچی نوێی نەبوو، بۆیە ناوەکەی تەنیا دەچێت بۆ لانا. - (b) سێلایەنە: هەردوو لا نوێیان هەیە، بۆیە Git بە دوو دایک دروست دەکات.
In Hawler Ride, Hana raised the base fare and Rebin added a night fare on the same line. Git shows this. Write the resolved lines, keeping both ideas.
لە Hawler Ride، هانا کرێی بنەڕەتی بەرز کردەوە و ڕێبین لەسەر هەمان دێڕ کرێی شەوی زیاد کرد. Git ئەمە پیشان دەدات. دێڕە چارەسەرکراوەکان بنووسە و هەردوو بیرۆکەکە بهێڵەرەوە.
<<<<<<< HEAD
BASE_FARE = 2500
=======
BASE_FARE = 2000
NIGHT_FARE = 3000 # from 23:00 to 06:00
>>>>>>> feature/night-fareShow answerوەڵامەکە پیشان بدە
BASE_FARE = 2500
NIGHT_FARE = 3000 # from 23:00 to 06:00Hana's new base fare (2,500) and Rebin's night fare both stay; the three marker lines are gone. Then git add fares.py and git commit. If the night fare was meant to be relative to the old base fare, ask Rebin before you decide.
کرێ بنەڕەتییە نوێیەکەی هانا (2,500) و کرێی شەویی ڕێبین هەردووکیان دەمێننەوە؛ سێ دێڕە نیشانەکە نەماون. پاشان git add fares.py و git commit. ئەگەر کرێی شەوی بەپێی کرێ بنەڕەتییە کۆنەکە دانرابوو، پێش بڕیاردان لە ڕێبین بپرسە.
Starting from one commit A on main, these commands run: git switch -c feature/x, commit B, git switch main, commit C, git merge feature/x. Draw the commits, the branch names and HEAD.
لە یەک A لەسەر mainـەوە، ئەم جێبەجێ دەکرێن: git switch -c feature/x، B، git switch main، C، git merge feature/x. ، ناوی و بکێشە.
Show answerوەڵامەکە پیشان بدە
git log --oneline --graph --all* 0ea4daf (HEAD -> main) Merge branch 'feature/x' |\ | * 8c04d05 (feature/x) B * | 2f639c2 C |/ * 61b6f0d A
C and B both have A as their parent. The merge commit (the top line) has two parents, C and B, so the graph splits below it. main and HEAD are on the merge commit; feature/x stays on B until you delete it.
C و B هەردووکیان A وەک دایک هەیانە. (دێڕی سەرەوە) دوو دایکی هەیە، C و B، بۆیە لە ژێریدا دەبێت بە دوو. main و لەسەر ؛ feature/x لەسەر B دەمێنێتەوە تا دەیسڕیتەوە.
In your practice repository from the last lesson, make two branches from main that change the same line of menu.txt differently. Merge both into main, resolve the conflict, and finish with git log --oneline --graph.
لە practiceـی وانەی پێشوودا، دوو لە main دروست بکە کە هەمان دێڕی menu.txt بە دوو شێوەی جیاواز دەگۆڕن. هەردووکیان تێکەڵی main بکە، ناکۆکییەکە چارەسەر بکە و بە git log --oneline --graph کۆتایی پێ بهێنە.
Hintئاماژە
Both branches must start from the same main commit and edit the same line.
هەردوو دەبێت لە هەمان mainـەوە دەست پێبکەن و هەمان دێڕ دەستکاری بکەن.
Show answerوەڵامەکە پیشان بدە
git switch -c fix/dolma-price
# change the dolma line, then:
git commit -am "Change the dolma price"
git switch main
git switch -c feature/dolma-name
# change the same line in another way, then:
git commit -am "Rename dolma to yaprax"
git switch main
git merge fix/dolma-price # Fast-forward
git merge feature/dolma-name # CONFLICT (content)
# edit menu.txt, remove the markers, then:
git diff --check
git add menu.txt
git commit --no-edit
git log --oneline --graphGive a branch name for each task: (1) show prices in Kurdish digits; (2) the total is wrong for 0 g of tea; (3) try a dark colour theme, which may be thrown away.
بۆ هەر کارێک ناوێکی دابنێ: (1) پیشاندانی نرخەکان بە ژمارەی کوردی؛ (2) کۆی گشتی بۆ 0 گرام چا هەڵەیە؛ (3) تاقیکردنەوەی ڕەنگێکی تاریک کە لەوانەیە فڕێ بدرێت.
Show answerوەڵامەکە پیشان بدە
- (1)
feature/kurdish-digits - (2)
fix/zero-grams-total - (3)
experiment/dark-theme— delete it with-Dif the team says no.
- (1) بۆ نموونە
feature/kurdish-digits - (2) بۆ نموونە
fix/zero-grams-total - (3)
experiment/dark-theme— ئەگەر تیمەکە گوتی نا، بە-Dبیسڕەوە.
Summaryپوختە
- A branch is a movable name for a commit; it costs almost nothing. HEAD marks where you are.
git switch -c <name>creates a branch and moves to it. - New commits move only the branch HEAD is on.
git log --oneline --graph --alldraws every branch. - Unfinished work blocks a switch when it would be overwritten: commit it, or
git stashand latergit stash pop. git merge Xbrings X into the current branch. Fast-forward: the name only moves. Three-way: a merge commit with two parents ('ort' strategy).- A merge conflict means both sides changed the same lines. Decide, edit, delete the markers,
git add,git commit;git merge --abortcancels. - Leftover markers break the code (
SyntaxError);git diff --checkfinds them. - Small, short-lived branches, merging
mainin often and talking to the team keep conflicts small. - Delete merged branches with
git branch -d; name themfeature/…andfix/…. A tag such asv0.2.0never moves. - Strategies: GitHub flow and trunk-based (short branches) vs long-lived branches (Git Flow). Never rebase commits others already have.
- Next: GitHub and teamwork — the same branches, shared through a remote repository and pull requests.
- ناوێکی جووڵاوە بۆ ؛ نزیکەی هیچی تێناچێت. نیشانی دەدات لە کوێیت.
git switch -c <name>دروست دەکات و دەچێتە سەری. - نوێ تەنیا ئەو دەجووڵێنن کە لەسەریەتی.
git log --oneline --graph --allهەموو دەکێشێت. - کاری تەواونەکراو ڕێگە لە گواستنەوە دەگرێت ئەگەر لەناو بچێت: بکە، یان
git stashو دواترgit stash pop. git merge XX دەهێنێتە ناو ئێستا. : تەنیا ناوەکە دەجووڵێت. سێلایەنە: بە دوو دایک ('ort' strategy).- واتە هەردوو لا هەمان دێڕەکانیان گۆڕیوە. بڕیار بدە، دەستکاری بکە، نیشانەکان بسڕەوە،
git add،git commit؛git merge --abortهەڵیدەوەشێنێتەوە. - نیشانە بەجێماوەکان کۆدەکە تێک دەدەن (
SyntaxError)؛git diff --checkدەیاندۆزێتەوە. - بچووک و کورتخایەن، زۆرجار تێکەڵکردنی
mainو قسەکردن لەگەڵ تیم ناکۆکییەکان بچووک دەهێڵنەوە. - تێکەڵکراوەکان بە
git branch -dبسڕەوە؛ ناویان بنێfeature/…وfix/…. وەکv0.2.0هەرگیز ناجووڵێت. - ستراتیژییەکان: GitHub flow و trunk-based ( کورت) بەرامبەر درێژخایەن (Git Flow). هەرگیز ئەو rebase مەکە کە کەسانی تر هەیانە.
- دواتر: GitHub و کاری تیمی — هەمان ، کە لە ڕێی و هاوبەش دەکرێن.
Lesson complete!وانەکە تەواو بوو!
Well done. Review the key terms, then go on to the next lesson.دەستخۆش. سەیرێکی زاراوە سەرەکییەکان بکەرەوە، پاشان بڕۆ بۆ وانەی داهاتوو.
Key termsزاراوە سەرەکییەکان
GitHub and Teamwork: Remotes, Pull Requests and IssuesGitHub و کاری تیمی: کۆگاکانی کۆدی دوور، داواکارییەکانی بەیەککردن و ئیشووەکان
Related lecturesوانە پەیوەندیدارەکان
- GitHub and Teamwork: Remotes, Pull Requests and IssuesGitHub و کاری تیمی: کۆگاکانی کۆدی دوور، داواکارییەکانی بەیەککردن و ئیشووەکان
- Errors and Debuggingهەڵەکان و کرمەکوژی
- Publishing Your Website: Hosting, Domains and HTTPSبڵاوکردنەوەی تۆڕگەکەت: هۆستینگ، ناوەکانی دۆمەین و HTTPS
- Building Softwareدروستکردنی نەرمەواڵە
References and further readingسەرچاوەکان و خوێندنەوەی زیاتر
This lecture is a first edition. The Kurdish text and terminology are waiting for review by Kurdish IT teachers.ئەم وانەیە چاپی یەکەمە. دەقە کوردییەکە و زاراوەکانی چاوەڕێی پێداچوونەوەی مامۆستایانی کوردی بواری IT ن.