هل هناك فرق بين "إعادة تعيين GIT -Hard Hard" و "Git Checkout Hash"؟

StackOverflow https://stackoverflow.com/questions/2541545

  •  23-09-2019
  •  | 
  •  

سؤال

بينما reset و checkout لديك استخدامات مختلفة معظم الوقت ، لا أستطيع أن أرى الفرق بين هذين.

من المحتمل أن يكون هناك واحد أو لا أحد كان سيزعج إضافة أ --hard خيار للقيام بشيء أساسي checkout يمكن القيام به.

ربما هناك فرق هو الطريقة التي سترى بها التاريخ؟

هل كانت مفيدة؟

المحلول

يتم نقل هذه الإجابة في الغالب من إجابتي إلى سؤال سابق: إعادة تعيين git باللغة الإنجليزية العادية.

الإثنان مختلفان جدا. إنها تؤدي إلى نفس الحالة لمؤشرك وشجرة العمل ، لكن التاريخ الناتج والفرع الحالي ليسا متماثلين.

لنفترض أن تاريخك يبدو هكذا ، حيث تم فحص الفرع الرئيسي حاليًا:

- A - B - C (HEAD, master)

وأنت تركض git reset --hard B. ستحصل على هذا:

- A - B (HEAD, master)      # - C is still here, but there's no
                            # branch pointing to it anymore

ستحصل بالفعل على هذا التأثير إذا كنت تستخدم --mixed أو --soft أيضًا - الفرق الوحيد هو ما يحدث لشجرة عملك والفهرس. في ال --hard الحالة ، تطابق شجرة العمل والفهرس B.

الآن ، افترض أنك ستشغل git checkout B في حين أن. ستحصل على هذا:

- A - B (HEAD) - C (master)

لقد انتهى بك الأمر في حالة رأس منفصلة. HEAD, ، شجرة العمل ، فهرس كل مطابقة B, ، كما هو الحال مع إعادة التعيين الصلب ، ولكن تم ترك الفرع الرئيسي وراءه C. إذا قمت بالتزام جديد D في هذه المرحلة ، ستحصل على هذا ، وهو ربما ليس ما تريده:

- A - B - C (master)
       \
        D (HEAD)

لذلك ، يمكنك استخدام الخروج ، حسنًا ، تحقق من هذا الالتزام. يمكنك أن تملأ معها ، تفعل ما تريد ، لكنك تركت فرعك وراءك. إذا كنت تريد نقل الفرع أيضًا ، فأنت تستخدم إعادة التعيين.

نصائح أخرى

إذا لم تساعدك الوثائق المقدمة بـ GIT ، فقم بإلقاء نظرة على مرجع GIT المرئي بقلم مارك لوداتو.

على وجه الخصوص إذا كنت تقارن git checkout <non-branch> مع git reset --hard <non-branch> (Hotlinked):

git checkout master~3
(مصدر: github.com)

git reset --hard master~3

لاحظ أنه في حالة git reset --hard master~3 أنت تترك وراءها جزءًا من DAG of Revisions - بعض الالتزامات لا يتم الرجوع إليها من قبل أي فرع. تلك محمية (بشكل افتراضي) 30 يومًا ريتش; ؛ سيتم تقليمهم في النهاية (إزالته).

git-reset hash يحدد مرجع الفرع إلى التجزئة المحددة ، ويتحقق منه اختياريًا ،--hard.

git-checkout hash يضع شجرة العمل على التجزئة المعطاة ؛ وما لم يكن التجزئة اسم فرع ، فسوف ينتهي به الأمر برأس منفصل.

في النهاية ، يتعامل Git مع 3 أشياء:

                   working tree (your code)
-------------------------------------------------------------------------
                     index/staging-area
-------------------------------------------------------------------------
      repository (bunch of commits, trees, branch names, etc)

git-checkout بشكل افتراضي ، فقط يقوم بتحديث الفهرس والشجرة العاملة ، ويمكنه تحديث شيء ما في المستودع اختياريًا (مع -b اختيار)

git-reset بشكل افتراضي ، فقط يقوم بتحديث المستودع والفهرس ، واختياري شجرة العمل (مع --hard اختيار)

يمكنك التفكير في المستودع مثل هذا:

 HEAD -> master

 refs:
    master -> sha_of_commit_X
    dev -> sha_of_commit_Y

 objects: (addressed by sha1)

    sha_of_commit_X, sha_of_commit_Y, sha_of_commit_Z, sha_of_commit_A ....

git-reset يعالج ما يشير إليه المراجع الفرع.

لنفترض أن تاريخك يبدو هكذا:

           T--S--R--Q [master][dev]
          / 
   A--B--C--D--E--F--G [topic1]
                   \
                    Z--Y--X--W [topic2][topic3]

ضع في اعتبارك أن الفروع هي مجرد أسماء تتقدم تلقائيًا عند الالتزام.

لذلك لديك الفروع التالية:

 master -> Q
 dev -> Q
 topic1 -> G
 topic2 -> W
 topic3 -> W

وفرعك الحالي topic2, ، أي ، يشير الرأس إلى Topic2.

HEAD -> topic2

ثم، git reset X سوف يعيد تعيين الاسم topic2 للإشارة إلى x ؛ بمعنى أنه إذا قمت بالتزام P on Branch Topic2 ، فستبدو الأمور هكذا:

           T--S--R--Q [master][dev]
          / 
   A--B--C--D--E--F--G [topic1]
                   \
                    Z--Y--X--W [topic3]
                           \
                            P [topic2]
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top