Git: حذف الفروع، الدمج، والتراجع عن push سيئ

August 2, 2026 · زوار

تتكرر هذه الأمور الثلاثة طوال الوقت، ومع ذلك فإن الأوامر لا تعلق في الذهن تمامًا من مرة إلى أخرى بطريقة أو بأخرى. لذا إليكم إياها، مكتوبة بشكل صحيح هذه المرة.

حذف فرع (Branch)

git branch -d feature-x

هذا هو الخيار الآمن — يتحقق Git أولًا، ويرفض التنفيذ إذا كان لدى feature-x التزامات (commits) لم تصل بعد إلى فرعك الحالي. إذا كنت متأكدًا، يمكنك تجاوز ذلك: (1)

git branch -D feature-x

لكن هذا يحذفه محليًا فقط. إذا كان الفرع موجودًا أيضًا على المستودع البعيد (remote) — على GitHub مثلًا — فعليك حذفه هناك بشكل منفصل:

git push origin --delete feature-x

شيء يستحق المعرفة: حذف فرع لا يحذف التزاماته فعليًا. هي فقط تصبح بلا مرجع وتبقى في المستودع إلى أن يأتي عليها جامع القمامة (garbage collector) في Git ويكنسها في النهاية، وقد يستغرق ذلك وقتًا. لذا فإن git branch -D أكثر تسامحًا مما يبدو — إذا حذفت الفرع الخطأ، عادة ما يبقى هناك طريق للعودة (المزيد عن ذلك في قسم reflog أدناه). لن أعتمد على هذا كخطة، لكن من الجيد معرفة أنه موجود.

دمج الفروع (Merge)

الشكل المعتاد هو: انتقل (checkout) إلى الفرع الذي تريد الدمج فيه، ثم ادمج الفرع الآخر إليه.

git checkout main
git merge feature-x

ما يحدث بعد ذلك يعتمد على ما إذا كان main قد تحرك منذ أن تفرّعت عنه. إذا لم يتحرك، فإن Git يزحف بمؤشر main إلى الأمام ليطابق feature-x ببساطة — وهذا ما يسمى تقديم سريع (fast-forward)، دون أي التزام دمج (merge commit). أما إذا تحرك main في تلك الأثناء، فإن Git ينشئ التزام دمج فعليًا يربط بين التاريخين (2).

أحيانًا تريد ذلك الالتزام حتى عندما يكون التقديم السريع ممكنًا — فهو يترك علامة واضحة في التاريخ على أن فرع ميزة كان موجودًا وتم دمجه، بدلًا من أن يندمج التغيير بهدوء دون أثر. لهذا الغرض:

git merge --no-ff feature-x

إذا لُمست الأسطر نفسها من الجانبين، يتوقف Git ويترك التعارض (conflict) لك لتسويته:

git status

سيسرد ذلك الملفات المتعارضة. افتح كل واحد منها، وسترى علامات <<<<<<< و======= و>>>>>>> حول التغييرات المتنافسة — اختر ما ينبغي أن يبقى فعليًا، احذف العلامات، ثم:

git add resolved-file.txt
git commit

وإذا تحول الأمر إلى فوضى أكبر مما يستحق، يمكنك ببساطة الانسحاب من العملية برمتها:

git merge --abort

هذا يعيد كل شيء تمامًا كما كان قبل أن تبدأ الدمج.

التراجع عن push سيئ

هذا هو الموقف الذي يصاب فيه الناس بالذعر، وبصراحة فإن هذا الذعر غالبًا لا مبرر له — لكن الحل الذي تلجأ إليه هنا مهم فعلًا.

إذا كان هناك أي احتمال أن شخصًا آخر قد سحب (pull) الفرع بالفعل، فلا تلمس التاريخ. أضف بدلًا من ذلك التزامًا جديدًا يلغي القديم:

git revert <bad-commit-sha>
git push

هذا هو الخيار المُمل، الآمن دائمًا. لا يعيد كتابة أي شيء — بل يضيف فقط التزامًا فوق السابق يُلغي الخطأ، بحيث يبقى تاريخ الجميع متزامنًا دون أن يحتاج أي أحد للقيام بشيء خاص من جانبه (3).

إذا كان الفرع ملكك حقًا ولم يسحبه أحد بعد، يمكنك إرجاعه وإعادة كتابته: (4)

git reset --hard <last-good-commit-sha>
git push --force-with-lease

استخدم --force-with-lease بدلًا من --force وحدها، ولو من باب العادة إن لم يكن لسبب آخر. الفرق أهم مما يبدو: يتحقق --force-with-lease من أن أحدًا لم يدفع إلى الفرع منذ آخر مرة جلبت (fetch) فيها، ويرفض التنفيذ إن كان قد فعل. أما --force وحدها فلا تتحقق من شيء — ستقوم بسعادة بالكتابة فوق عمل شخص آخر دون حتى تحذير (5).

وإذا كنت تحدق في طرفيتك محاولًا تذكر ما كان عليه آخر التزام سليم — فإن git log لن يساعدك هنا، لأنه يعرض فقط الالتزامات التي يمكن الوصول إليها من موضعك الحالي، وهذا لا يشمل ما أعدت ضبطه (reset) بعيدًا عنه بالفعل. ما تحتاجه هو:

git reflog

يعرض هذا كل موضع أشار إليه فرعك مؤخرًا، بما في ذلك تلك التي سقطت خارج التاريخ العادي. مرّر للخلف إلى ما قبل أن تسوء الأمور، ثم: (6)

git reset --hard HEAD@{2}

(استبدل ذلك بأي موضع أو SHA يطابق حالتك فعليًا). سجل المراجع (reflog) محلي على جهازك، ويحتفظ عادة بالإدخالات لحوالي 90 يومًا، لذا فهو أقرب إلى شبكة أمان عامة لـ"أظن أنني كسرت شيئًا للتو" منه إلى "تراجع طارئ عن دفعات سيئة" تحديدًا — يستحق أن تتذكر وجوده حتى خارج هذا الموقف بالذات.

فكرة ختامية

تعتمد هذه الأمور الثلاثة كلها على الحقيقة نفسها الكامنة: لا يتخلص Git من أي شيء فورًا تقريبًا أبدًا. الفروع المحذوفة، والالتزامات المُعاد ضبطها، والمواضع القديمة على فرع ما — كلها تبقى لفترة أطول مما تبدو عليه. هذا في الحقيقة ما يجعل -D وreset --hard والدفع القسري (force push) آمنة بما يكفي لاستخدامها يوميًا، طالما تعرف أين تبحث إذا تبين أن أحدها كان خطأ.

قراءات ذات صلة

قراءات إضافية

  1. git-branch — إنشاء الفروع، سردها، وحذفها.
  2. git-merge — استراتيجيات الدمج وحل التعارضات.
  3. git-revert — التراجع عن الالتزامات عبر إنشاء التزامات جديدة.
  4. git-reset — تحريك مؤشر الفرع، مع الفرق بين --soft و--mixed و--hard.
  5. git-push: --force-with-lease — لماذا هي أكثر أمانًا من --force.
  6. git-reflog — استعادة الالتزامات التي لم تعد تظهر في التاريخ العادي.

التعليقات