ทำให้สาขา Git ปัจจุบันเป็นสาขาหลัก


1657

ฉันมีที่เก็บใน Git ฉันสร้างสาขาจากนั้นก็ทำการเปลี่ยนแปลงทั้งกับอาจารย์และสาขา

จากนั้นหลายสิบข้อผูกมัดในภายหลังฉันตระหนักว่าสาขาอยู่ในสถานะที่ดีกว่าต้นแบบดังนั้นฉันต้องการให้สาขาเป็น "กลายเป็น" เจ้านายและไม่สนใจการเปลี่ยนแปลงในต้นแบบ

ฉันไม่สามารถรวมมันได้เพราะฉันไม่ต้องการให้การเปลี่ยนแปลงกับต้นแบบ ฉันควรทำอย่างไรดี?

พิเศษ : ในกรณีนี้ต้นแบบ 'เก่า' ได้ถูกนำpushไปใช้กับที่เก็บอื่นแล้วเช่น GitHub สิ่งนี้เปลี่ยนแปลงได้อย่างไร


2
ตรวจสอบคำตอบสำหรับคำถามที่คล้ายกันมากstackoverflow.com/q/2862590/151641
mloskot

4
มีปัญหาเดียวกัน แต่ฉันเพิ่งลบต้นแบบและเปลี่ยนชื่อสาขาอื่นเป็นหลัก: stackoverflow.com/a/14518201/189673
jayarjo

10
@jayarjo คุณควรหลีกเลี่ยงสิ่งนี้หากคุณสามารถทำได้เพราะมันจะเขียนประวัติและทำให้เกิดปัญหากับคนอื่นเมื่อพวกเขาพยายามที่จะดึงต้นแบบต่อไป
joelittlejohn

3
นี่คือเหตุผลที่ฉันชอบคำตอบของ @Jefromi ไม่มีการจัดโครงสร้างประวัติของหน่วยเก็บถาวร
froggythefrog

คำตอบ:


2134

ปัญหาของอีกสองคำตอบก็คือเจ้านายคนใหม่ไม่มีเจ้านายเก่าในฐานะบรรพบุรุษดังนั้นเมื่อคุณผลักมันคนอื่น ๆ ก็จะสับสน นี่คือสิ่งที่คุณต้องการทำ:

git checkout better_branch
git merge --strategy=ours master    # keep the content of this branch, but record a merge
git checkout master
git merge better_branch             # fast-forward master up to the merge

หากคุณต้องการให้ประวัติของคุณชัดเจนขึ้นฉันขอแนะนำให้เพิ่มข้อมูลบางอย่างลงในข้อความยืนยันการรวมเพื่อให้ชัดเจนว่าคุณได้ทำอะไรไปบ้าง เปลี่ยนบรรทัดที่สองเป็น:

git merge --strategy=ours --no-commit master
git commit          # add information to the template merge message

25
หมายเหตุเกี่ยวกับการผสาน "กลยุทธ์" คอมไพล์ของ: จะแตกต่างจาก--strategy=ours --strategy=recursive -Xoursเช่น "ของเรา" อาจเป็นกลยุทธ์ในตัวเอง (ผลลัพธ์จะเป็นสาขาปัจจุบันไม่ว่าจะเกิดอะไรขึ้น) หรือส่งผ่านเป็นตัวเลือกสำหรับกลยุทธ์ "เรียกซ้ำ" (นำมาซึ่งการเปลี่ยนแปลงของสาขาอื่นและนำการเปลี่ยนแปลงของสาขาปัจจุบันโดยอัตโนมัติเมื่อมีความขัดแย้ง )
เคลวิน

5
ฉันต้องสร้างบรรทัดที่สองgit merge --strategy=ours master -m "new master"เพื่อให้มันใช้งานได้
ยอง

5
@Johsm นั่นคือสิ่งที่ประโยคแรกของคำตอบของฉันพูดถึง หากคุณทำเช่นนั้นต้นแบบใหม่จะไม่มีประวัติเหมือนกับต้นแบบเก่าซึ่งแย่มากหากคุณต้องการกด / ดึง คุณต้องแบ่งปันบรรพบุรุษเพื่อที่จะทำงานได้อย่างถูกต้อง ถ้าคุณทำสิ่งที่คุณพูดแทนเมื่อคุณพยายามที่จะผลักมันมันก็จะล้มเหลวเว้นแต่คุณจะบังคับมัน (เพราะมันแย่และมันก็พยายามหยุดคุณ) และถ้าคุณบังคับมันแล้วใครก็ตามที่ดึง จะพยายามรวมเจ้านายเก่ากับเจ้านายใหม่ซึ่งอาจจะเป็นซากรถไฟ
Cascabel

4
หากตัวแก้ไข vi ระหว่างการผสานปรากฏขึ้นให้พิมพ์: w (สำหรับการบันทึก): q (สำหรับการออกจาก vi)
Tomas Kubes

9
คำตอบนี้ใช้งานได้ดี ฉันแค่อยากจะเพิ่ม (สำหรับคนที่อาจจะใหม่หรือไม่แน่ใจ) ว่าคุณจะต้องทำgit pushทันทีหลังจากนี้ถ้าคุณต้องการให้รหัสของคุณถูกผลักไปที่รีโมต คุณอาจเห็นคำเตือนเช่นYour branch is ahead of 'origin/master' by 50 commits.นี้เป็นสิ่งที่คาดหวัง เพียงแค่กดมัน! : D
chapeljuice

387

ตรวจสอบให้แน่ใจว่าทุกอย่างถูกส่งไปยังที่เก็บข้อมูลระยะไกลของคุณ (GitHub):

git checkout master

เขียนทับ "master" ด้วย "better_branch":

git reset --hard better_branch

บังคับให้กดไปที่ที่เก็บรีโมตของคุณ:

git push -f origin master

81
นี่อาจเป็นคำตอบที่คนส่วนใหญ่มองหา คำตอบอื่น ๆ ทั้งหมดที่มีการผสานกลยุทธ์ BS ไม่ได้แทนที่สาขาทั้งหมด สิ่งนี้ทำให้ทุกอย่างเหมือนที่ฉันต้องการเพียงเขียนทับกิ่งไม้และดันมันขึ้นมา
Gubatron

31
ถึงแม้ว่านี่จะเป็นสิ่งที่คนส่วนใหญ่มองหา แต่ก็ควรสังเกตว่าสำเนาอื่น ๆ ในพื้นที่ของ repo จะต้องใช้ในgit reset --hard origin/masterครั้งต่อไปที่พวกเขาต้องการดึงมิฉะนั้น git จะพยายามรวมการเปลี่ยนแปลงในท้องถิ่นที่แตกต่างกันของพวกเขา อันตรายของสิ่งนี้ถูกอธิบายเพิ่มเติมในคำตอบนี้
7yl4r

3
โปรดทราบว่าคุณจำเป็นต้องได้รับอนุญาตให้บังคับให้ส่งไปยังที่เก็บ - เช่นในสภาพแวดล้อมทางธุรกิจสิ่งนี้จะไม่ทำงาน
inetphantom

ส่วนต่าง ๆ ของที่นี่อาจเป็นข้อเสียขึ้นอยู่กับสิ่งที่ผู้คนต้องการ หากคุณต้องการเปลี่ยนประวัติศาสตร์ของอาจารย์ด้วยประวัติของสาขาอื่นนี่คือคำตอบของคุณ
b15

75

แก้ไข:คุณไม่ได้พูดว่าคุณผลักไปที่ repo สาธารณะ! นั่นทำให้โลกแตกต่าง

มีสองวิธีคือ "สกปรก" และ "สะอาด" new-masterสมมติว่าสาขาที่ท่านเป็นชื่อ นี่เป็นวิธีที่สะอาด:

git checkout new-master
git branch -m master old-master
git branch -m new-master master
# And don't do this part.  Just don't.  But if you want to...
# git branch -d --force old-master

สิ่งนี้จะทำให้ไฟล์ปรับเปลี่ยนเปลี่ยนให้ตรงกับกิ่งที่ถูกเปลี่ยนชื่อ

นอกจากนี้คุณยังสามารถทำได้ด้วยวิธีที่สกปรกซึ่งจะไม่อัปเดตไฟล์กำหนดค่า นี่คือสิ่งที่เกิดขึ้นภายใต้ประทุนข้างต้น ...

mv -i .git/refs/new-master .git/refs/master
git checkout master

2
ขอบคุณ. อีกหนึ่งคำถาม ฉันกำลังผลักดันให้ GitHub จะเกิดอะไรขึ้นถ้าฉันทำเช่นนี้?
Karel Bílek

3
@Karel: มันจะสร้างความสับสนให้กับผู้ใช้รายอื่น พวกเขาจะต้องรีเซ็ตนายของพวกเขาเป็นนาย github หากคุณต้องการหลีกเลี่ยงปัญหาใด ๆ ให้ดูคำตอบของฉัน
Cascabel

6
@Dietrick Epp: ฉันไม่แน่ใจว่ามันเป็นความคิดที่ดีที่จะแนะนำวิธีที่สกปรก มันจะเลอะการติดตามระยะไกล reflogs ... ไม่สามารถคิดด้วยเหตุผลใด ๆ ก็ตามที่คุณเคยทำ
Cascabel

2
อานั่นเป็นจุดที่ดี คุณสามารถใช้ทั้งสองวิธีได้: git branch old-master master; git branch -f master new-master. สร้างสาขาสำรองใหม่จากนั้นย้ายต้นแบบไปยังต้นแบบใหม่โดยตรง (และขออภัยในการสะกดชื่อของคุณเพียงสังเกตว่า)
Cascabel

2
@FakeName ผมไม่ได้สรุปมีเหตุผลที่จะทำมันไม่เพียงแค่ว่ามีเหตุผลที่จะทำมันไม่มีวิธีสกปรก คุณสามารถทำได้โดยใช้คำสั่งปกติ (เช่นเดียวกับความคิดเห็นก่อนหน้าของฉัน) และได้รับผลเดียวกันยกเว้น reflogs ไม่บุบสลายและไม่มีโอกาส borking สิ่งต่าง ๆ และรับประกันว่าจะทำงานได้เนื่องจากคุณไม่ได้ล้อเล่นรายละเอียดการใช้งาน
Cascabel

46

เปลี่ยนชื่อสาขาเป็นmasterโดย:

git branch -M branch_name master

11
น่าเสียดายที่คอมไพล์ไม่ได้ติดตามการเปลี่ยนชื่อสาขาดังนั้นหากคุณผลัก repo ของคุณไปที่ระยะไกลและคนอื่น ๆ มีการเปลี่ยนแปลงในท้องถิ่นในสาขาหลักเก่าของท้องถิ่นพวกเขาจะมีปัญหา
thSoft

มีความแตกต่างระหว่างนี้และgit checkout master&&git reset --hard better_branch?
wotanii

26

จากสิ่งที่ฉันเข้าใจคุณสามารถแยกสาขาปัจจุบันเป็นสาขาที่มีอยู่ โดยพื้นฐานแล้วสิ่งนี้จะเขียนทับmasterสิ่งที่คุณมีในสาขาปัจจุบัน:

git branch -f master HEAD

เมื่อคุณทำเช่นนั้นปกติแล้วคุณสามารถผลักmasterสาขาในท้องถิ่นของคุณอาจต้องใช้พารามิเตอร์แรงที่นี่เช่นกัน:

git push -f origin master

ไม่มีการผสานไม่มีคำสั่งยาว เพียงbranchและpush- แต่ใช่แล้วนี่จะเป็นการเขียนประวัติของmasterสาขาดังนั้นถ้าคุณทำงานในทีมคุณต้องรู้ว่าคุณกำลังทำอะไรอยู่




หรือฉันพบว่าคุณสามารถผลักดันสาขาใด ๆ ไปยังสาขาระยะไกลใด ๆ ดังนั้น:

# This will force push the current branch to the remote master
git push -f origin HEAD:master

# Switch current branch to master
git checkout master

# Reset the local master branch to what's on the remote
git reset --hard origin/master

ง่ายมากและทำงานได้อย่างสมบูรณ์แบบ! คำสั่ง git ง่ายและเข้าใจง่ายสองคำ repo คอมไพล์ของฉันได้รับการบันทึกและตอนนี้ดูสะอาดมาก ขอบคุณ!
thehelix

16

ฉันพบคำตอบที่ฉันต้องการในบล็อกโพสต์แทนที่สาขาหลักด้วยสาขาอื่นในคอมไพล์ :

git checkout feature_branch
git merge -s ours --no-commit master
git commit      # Add a message regarding the replacement that you just did
git checkout master
git merge feature_branch

มันเป็นหลักเช่นเดียวกับคำตอบของ Cascabel ยกเว้นว่า "ตัวเลือก" เขาเพิ่มด้านล่างวิธีการของเขาถูกฝังอยู่ในบล็อกรหัสหลักของฉัน

หาทางนี้ง่ายกว่า

ฉันกำลังเพิ่มสิ่งนี้เป็นคำตอบใหม่เพราะถ้าฉันต้องการโซลูชันนี้ในภายหลังฉันต้องการมีรหัสทั้งหมดที่ฉันจะใช้ในบล็อกโค้ดหนึ่ง

มิฉะนั้นฉันอาจคัดลอกวางแล้วอ่านรายละเอียดด้านล่างเพื่อดูบรรทัดที่ฉันควรมีการเปลี่ยนแปลง - หลังจากที่ฉันดำเนินการแล้ว


14

โซลูชันที่ให้ไว้ที่นี่ (เปลี่ยนชื่อสาขาใน 'ต้นแบบ') ไม่ยืนยันผลที่ตามมาสำหรับ repo ระยะไกล (GitHub):

  • หากคุณไม่ได้ผลักดันอะไรเลยตั้งแต่สร้างสาขาคุณสามารถเปลี่ยนชื่อและผลักดันได้โดยไม่มีปัญหา
  • ถ้าคุณมีหลักในการผลักดัน GitHub คุณจะต้อง '-f ผลักดันคอมไพล์' สาขาใหม่: คุณสามารถผลักดันไม่ได้อยู่ในโหมดไปข้างหน้าอย่างรวดเร็ว
    -f
    --บังคับ

โดยปกติแล้วคำสั่งปฏิเสธที่จะอัพเดตการอ้างอิงระยะไกลที่ไม่ใช่บรรพบุรุษของการอ้างอิงในท้องถิ่นที่ใช้ในการเขียนทับมัน การตั้งค่าสถานะนี้ปิดใช้งานการตรวจสอบ สิ่งนี้สามารถทำให้ที่เก็บข้อมูลรีโมตสูญเสียการคอมมิท ใช้ด้วยความระมัดระวัง

หากผู้อื่นดึง repo ของคุณไปแล้วพวกเขาจะไม่สามารถดึงประวัติต้นแบบใหม่โดยไม่ต้องเปลี่ยนต้นแบบของตนเองด้วยสาขาหลัก GitHub ใหม่นั้น (หรือจัดการกับการรวมจำนวนมาก)
มีทางเลือกให้กับ --force คอมไพล์ผลักดันให้ Repos
คำตอบของ Jefromi (การรวมการเปลี่ยนแปลงที่ถูกต้องกลับไปที่ต้นแบบเดิม) เป็นหนึ่งในนั้น


14

ฉันพบวิธีการง่าย ๆ ในการทำงานที่ดีที่สุด มันไม่ได้เขียนประวัติและการเช็คอินก่อนหน้านี้ทั้งหมดของสาขาจะถูกผนวกเข้ากับต้นแบบ ไม่มีอะไรหายไปและคุณสามารถเห็นได้อย่างชัดเจนว่าเกิดอะไรขึ้นในบันทึกการกระทำ

วัตถุประสงค์: ทำให้สถานะปัจจุบันของ "branch" เป็น "master"

ทำงานในสาขายอมรับและผลักดันการเปลี่ยนแปลงของคุณเพื่อให้แน่ใจว่าที่เก็บข้อมูลในพื้นที่และระยะไกลของคุณเป็นรุ่นล่าสุด:

git checkout master      # Set local repository to master
git reset --hard branch  # Force working tree and index to branch
git push origin master    # Update remote repository

หลังจากนี้เจ้านายของคุณจะเป็นสถานะที่แน่นอนของการกระทำครั้งสุดท้ายของสาขาและบันทึกการกระทำหลักของคุณจะแสดงการเช็คอินทั้งหมดของสาขา


10

ท่านสามารถเช็คเอาท์ไฟล์ทั้งหมดจากสาขาอื่น ๆ ไปยังต้นแบบ

git checkout master
git checkout better_branch -- .

จากนั้นส่งการเปลี่ยนแปลงทั้งหมด


5

หากต้องการเพิ่มคำตอบของ Jefromi หากคุณไม่ต้องการผสานความหมายในประวัติศาสตร์ของsourceสาขาคุณสามารถสร้างสาขาชั่วคราวสำหรับการoursรวมแล้วทิ้งมันไป:

git checkout <source>
git checkout -b temp            # temporary branch for merge
git merge -s ours <target>      # create merge commit with contents of <source>
git checkout <target>           # fast forward <target> to merge commit
git merge temp                  # ...
git branch -d temp              # throw temporary branch away

วิธีการผสานจะกระทำได้เฉพาะในประวัติศาสตร์ของtargetสาขา

อีกทางเลือกหนึ่งถ้าคุณไม่ต้องการสร้างการผสานเลยคุณสามารถคว้าเนื้อหาsourceและใช้เพื่อทำการคอมมิตใหม่target:

git checkout <source>                          # fill index with contents of <source>
git symbolic-ref HEAD <target>                 # tell git we're committing on <target>
git commit -m "Setting contents to <source>"   # make an ordinary commit with the contents of <source>

3

สำหรับฉันฉันต้องการให้ devl ของฉันกลับไปหานายหลังจากที่อยู่ข้างหน้า

ในขณะที่การพัฒนา:

git checkout master
git pull

git checkout develop
git pull

git reset --hard origin/master
git push -f

2

วิธีการทำสิ่งต่าง ๆ ของฉันมีดังต่อไปนี้

#Backup branch
git checkout -b master_backup
git push origin master_backup
git checkout master
#Hard Reset master branch to the last common commit
git reset --hard e8c8597
#Merge
git merge develop

2

หากคุณใช้eGitในEclipse :

  • คลิกขวาที่โหนดโครงการ
  • เลือกทีม →จากนั้นขั้นสูง →จากนั้นเปลี่ยนชื่อสาขา
  • จากนั้นขยายโฟลเดอร์การติดตามระยะไกล
  • เลือกสาขาที่มีชื่อผิดจากนั้นคลิกที่ปุ่มเปลี่ยนชื่อเปลี่ยนชื่อเป็นชื่อใหม่
  • เลือกต้นแบบใหม่แล้วเปลี่ยนชื่อเป็นต้นแบบ

ฉันทำอย่างนั้น แต่ไม่แน่ใจว่าทำงานได้หรือไม่ บน GitHub ไม่มีอะไรเปลี่ยนแปลง แต่ในส่วนขยาย git ฉันสามารถเห็นสาขาถูกเปลี่ยนชื่อ
Pramod

0

ขั้นตอนต่อไปนี้จะดำเนินการในเบราว์เซอร์ Git ที่ขับเคลื่อนโดย Atlassian (เซิร์ฟเวอร์ Bitbucket)

ทำให้ {current-branch} เป็น master

  1. สร้างสาขาจากmasterและตั้งชื่อมันว่า
  2. สร้างสาขาจาก {current-branch} และตั้งชื่อว่า“ {current-branch} -copy”
  3. ในการตั้งค่าพื้นที่เก็บข้อมูล (Bitbucket) เปลี่ยน“ Default Branch” ให้ชี้ไปที่“ ต้นแบบที่ซ้ำกัน” (ไม่มีขั้นตอนนี้คุณจะไม่สามารถลบ master -“ ในขั้นตอนถัดไป”)
  4. ลบสาขา“ หลัก” - ฉันทำขั้นตอนนี้จากซอร์สต้นไม้ (คุณสามารถทำได้จากเบราว์เซอร์ CLI หรือ Git)
  5. เปลี่ยนชื่อ“ {current-branch}” เป็น“ master” และ push to repository (สิ่งนี้จะสร้างสาขาใหม่“ master” ยังคง“ {current-branch}” อยู่)
  6. ในการตั้งค่าที่เก็บเปลี่ยน "สาขาเริ่มต้น" เพื่อชี้ไปที่ "หลัก"
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.