ฉันคิดว่าปัญหาพื้นฐานของคุณที่นี่คือคุณกำลังตีความผิดและ / หรือเข้าใจผิดว่า git ทำอะไรและทำไมถึงทำเช่นนั้น
เมื่อคุณโคลนที่เก็บอื่น git จะสร้างสำเนาของสิ่งที่ "อยู่ตรงนั้น" นอกจากนี้ยังใช้ป้ายกำกับสาขา "ของพวกเขา" เช่นmaster
และทำสำเนาของป้ายกำกับนั้นซึ่งมี "ชื่อเต็ม" ในแผนผังคอมไพล์ของคุณ (ปกติ) remotes/origin/master
(แต่ในกรณีของคุณremotes/upstream/master
) ส่วนใหญ่เวลาที่คุณได้รับการละเว้นส่วนเกินไปดังนั้นคุณจึงสามารถอ้างถึงว่าเป็นสำเนาต้นฉบับremotes/
upstream/master
หากตอนนี้คุณทำการเปลี่ยนแปลงบางอย่างกับไฟล์บางไฟล์แสดงว่าคุณเป็นคนเดียวที่มีการเปลี่ยนแปลงเหล่านั้น ในขณะเดียวกันคนอื่น ๆ อาจใช้ที่เก็บดั้งเดิม (ซึ่งคุณสร้างโคลนของคุณ) เพื่อสร้างโคลนอื่น ๆ และเปลี่ยนร่างโคลนเหล่านั้น แน่นอนพวกเขาเป็นคนเดียวที่มีการเปลี่ยนแปลง ในที่สุดบางคนอาจมีการเปลี่ยนแปลงที่ส่งกลับไปยังเจ้าของเดิม (ผ่าน "พุช" หรือแพตช์หรืออะไรก็ตาม)
git pull
คำสั่งส่วนใหญ่จะเป็นเพียงแค่จดชวเลขตามมาด้วยgit fetch
git merge
นี่เป็นสิ่งสำคัญเพราะหมายความว่าคุณต้องเข้าใจว่าการดำเนินการทั้งสองนั้นทำอะไรได้จริง
git fetch
คำสั่งบอกว่าจะกลับไปยังปลายทางที่คุณโคลนจาก (หรืออย่างอื่นได้ตั้งขึ้นเป็นสถานที่ที่จะดึงข้อมูลจาก) ไปหา "คนอื่นสิ่งใหม่ ๆ เพิ่มหรือเปลี่ยนแปลงหรือเอาออก" การเปลี่ยนแปลงเหล่านั้นจะถูกคัดลอกไปและนำไปใช้ในการสำเนาของสิ่งที่คุณได้รับจากพวกเขาก่อนหน้า พวกเขาไม่ได้ใช้กับงานของคุณเองเฉพาะกับงานของพวกเขาเท่านั้น
git merge
คำสั่งมีความซับซ้อนมากขึ้นและเป็นที่ที่คุณจะไปเป๋ สิ่งที่ทำเกินไปย่อเล็กน้อยคือเปรียบเทียบ "สิ่งที่คุณเปลี่ยนแปลงในสำเนาของคุณ" เป็น "การเปลี่ยนแปลงที่คุณดึงมาจากคนอื่นและได้เพิ่มลงในสำเนาของงานของคนอื่น" หากการเปลี่ยนแปลงของคุณและการเปลี่ยนแปลงดูเหมือนจะไม่ขัดแย้งกันการmerge
ดำเนินการจะรวมเข้าด้วยกันและให้ "การรวม" ที่เชื่อมโยงการพัฒนาและการพัฒนาของคุณเข้าด้วยกัน (แม้ว่าจะมีกรณี "ง่าย" ที่พบบ่อยมากซึ่งคุณไม่มี การเปลี่ยนแปลงและคุณจะได้รับ "กรอไปข้างหน้า")
สถานการณ์ที่คุณกำลังเผชิญอยู่ตอนนี้คือสถานการณ์ที่คุณได้ทำการเปลี่ยนแปลงและมุ่งมั่นกับมันเก้าครั้งในความเป็นจริงด้วยเหตุนี้ "ข้างหน้า 9" - และพวกเขาไม่ได้ทำการเปลี่ยนแปลงใดๆ ดังนั้นโดยfetch
ไม่ต้องทำอะไรเลยจากนั้นก็merge
รับการเปลี่ยนแปลงและไม่ทำอะไรเลย
สิ่งที่คุณต้องการคือดูหรืออาจจะ "รีเซ็ต" เป็น "เวอร์ชัน" ของรหัส
หากคุณเพียงต้องการดูคุณสามารถตรวจสอบเวอร์ชันนั้นได้:
git checkout upstream/master
remotes/upstream/master
ที่บอกคอมไพล์ที่คุณต้องการที่จะย้ายไดเรกทอรีปัจจุบันไปยังสาขาที่มีชื่อเต็มเป็นจริง คุณจะเห็นรหัสเป็นครั้งสุดท้ายที่คุณเรียกใช้git fetch
และได้รับรหัสล่าสุด
หากคุณต้องการละทิ้งการเปลี่ยนแปลงทั้งหมดของคุณเองสิ่งที่คุณต้องทำคือเปลี่ยนความคิดของคอมไพล์ว่าmaster
ควรตั้งชื่อการแก้ไขป้ายกำกับของคุณ ปัจจุบันตั้งชื่อคอมมิตล่าสุดของคุณ หากคุณกลับเข้าสู่สาขานั้น:
git checkout master
จากนั้นgit reset
คำสั่งจะช่วยให้คุณ "ย้ายป้ายกำกับ" ได้เหมือนเดิม ปัญหาเดียวที่เหลืออยู่ (สมมติว่าคุณพร้อมที่จะละทิ้งทุกสิ่งที่คุณไม่ได้ทำ) คือการค้นหาว่าป้ายกำกับควรชี้ไปที่ใด
git log
จะช่วยให้คุณหาชื่อเหล่านั้นเป็นตัวเลขสิ่งเช่น7cfcb29
-which ถาวร (ไม่เคยเปลี่ยน) ชื่อและมีจำนวนที่ไร้สาระของวิธีการอื่น ๆ ที่จะตั้งชื่อพวกเขา upstream/master
แต่ในกรณีนี้คุณต้องการเพียงแค่ชื่อ
ในการย้ายป้ายกำกับให้ลบการเปลี่ยนแปลงของคุณเอง (สิ่งที่คุณได้กระทำนั้นสามารถกู้คืนได้ในระยะหนึ่ง แต่จะยากกว่ามากหลังจากนี้ดังนั้นโปรดแน่ใจมาก ๆ ):
git reset --hard upstream/master
--hard
บอกคอมไพล์ที่จะเช็ดออกสิ่งที่คุณได้รับการทำย้ายป้ายสาขาในปัจจุบันและแล้วตรวจสอบให้กระทำ
มันไม่ได้เป็นซุปเปอร์เรื่องธรรมดาที่จะจริงๆต้องการgit reset --hard
และเช็ดออกพวงของการทำงาน วิธีที่ปลอดภัยกว่า (ทำให้การกู้คืนงานนั้นง่ายขึ้นมากหากคุณตัดสินใจว่าบางอย่างคุ้มค่าหลังจากนั้น) คือการเปลี่ยนชื่อสาขาที่มีอยู่:
git branch -m master bunchofhacks
จากนั้นสร้างสาขาท้องถิ่นใหม่ชื่อmaster
"แทร็ก" (ฉันไม่ชอบคำนี้มากนักเพราะฉันคิดว่ามันทำให้คนสับสน แต่นั่นคือคำ git :-)) ต้นกำเนิด (หรือต้นน้ำ) ต้นแบบ:
git branch -t master upstream/master
ซึ่งคุณสามารถดำเนินการได้ด้วยตัวเอง:
git checkout master
คำสั่งสามคำสุดท้ายทำอะไร (มีทางลัดที่จะทำให้เป็นเพียงสองคำสั่ง) คือเปลี่ยนชื่อที่วางบนป้ายที่มีอยู่แล้วสร้างป้ายกำกับใหม่จากนั้นเปลี่ยนไปใช้:
ก่อนทำอะไร:
C0 - "remotes/upstream/master"
\
\- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9 "master"
หลังจากgit branch -m
:
C0 - "remotes/upstream/master"
\
\- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9 "bunchofhacks"
หลังจากgit branch -t master upstream/master
:
C0 - "remotes/upstream/master", "master"
\
\- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9 "bunchofhacks"
นี่C0
คือคอมมิตล่าสุด (แผนผังแหล่งที่มาที่สมบูรณ์) ที่คุณได้รับเมื่อคุณทำgit clone
ไฟล์. C1 ถึง C9 คือความมุ่งมั่นของคุณ
โปรดทราบว่าหากคุณเป็นเช่นgit checkout bunchofhacks
นั้นgit reset --hard HEAD^^
สิ่งนี้จะเปลี่ยนภาพสุดท้ายเป็น:
C0 - "remotes/upstream/master", "master"
\
\- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 - "bunchofhacks"
\
\- C8 --- C9
เหตุผลก็คือHEAD^^
ตั้งชื่อการแก้ไขสองขึ้นจากส่วนหัวของสาขาปัจจุบัน (ซึ่งก่อนการรีเซ็ตจะเป็นbunchofhacks
) reset --hard
จากนั้นจึงย้ายป้ายกำกับ Commits C8 และ C9 ตอนนี้ส่วนใหญ่มองไม่เห็น (คุณสามารถใช้สิ่งต่างๆเช่น reflog และgit fsck
ค้นหาได้ แต่มันไม่สำคัญอีกต่อไป) ป้ายกำกับของคุณเป็นของคุณที่จะย้ายตามที่คุณต้องการ คำสั่งดูแลคนที่เริ่มต้นด้วยfetch
remotes/
เป็นเรื่องธรรมดาที่จะจับคู่ "ของคุณ" กับ "ของพวกเขา" (ดังนั้นหากพวกเขามีremotes/origin/mauve
คุณก็จะตั้งชื่อของคุณmauve
ด้วยเช่นกัน) แต่คุณสามารถพิมพ์ "ของพวกเขา" ได้ทุกเมื่อที่คุณต้องการตั้งชื่อ / ดูว่าคุณได้รับ "จากพวกเขา" (โปรดจำไว้ว่า "หนึ่งคอมมิต" คือแผนผังซอร์สทั้งหมดคุณสามารถเลือกไฟล์เฉพาะหนึ่งไฟล์จากคอมมิตหนึ่งไฟล์git show
ตัวอย่างเช่น