การเปลี่ยนชื่อสาขาจากระยะไกลใน Git


407

หากมีพื้นที่เก็บข้อมูลที่ฉันgit://สามารถเข้าถึง (และมักจะเพียงแค่กด + pull) มีวิธีเปลี่ยนชื่อสาขาในพื้นที่เก็บข้อมูลนั้นในลักษณะเดียวกับที่ฉันจะทำในพื้นที่ด้วยgit branch -m?


48
คำถาม "ที่ซ้ำกัน" ที่เชื่อมโยงจะขอให้เปลี่ยนชื่อสาขา "ทั้งภายในและระยะไกล" อย่างไรก็ตามคำถามนี้เพียงถามถึงวิธีการเปลี่ยนชื่อสาขาจากระยะไกลซึ่งช่วยให้การทำให้เข้าใจง่ายขึ้น นี่คือสิ่งที่ฉันทำเพื่อเปลี่ยนชื่อสาขาบนเซิร์ฟเวอร์โดยไม่จำเป็นต้องชำระเงินและ / git push origin origin/old_name:refs/heads/new_name && git push origin :old_nameหรือสร้างสาขาในประเทศ:
sschuberth

1
@sschuberth: คุณสามารถให้ทั้งสองคำสั่งได้ในครั้งเดียว และนี่ควรเป็นคำตอบสำหรับคำถามนี้
Joachim Breitner

2
@JoachimBreitner คุณพูดถูกฉันได้เพิ่มประสิทธิภาพนั้นในสคริปต์ของฉันแล้ว
sschuberth

1
@sschuberth คุณควรโพสต์ความคิดเห็นของคุณเป็นคำตอบเนื่องจากฉันชอบดีกว่าคนอื่นด้านล่าง
phatmann

เสร็จสิ้น
sschuberth

คำตอบ:


480

คุณเพียงแค่ต้องสร้างสาขาท้องถิ่นใหม่ที่มีชื่อที่ต้องการผลักไปที่รีโมตแล้วลบสาขารีโมตเก่า:

$ git branch new-branch-name origin/old-branch-name
$ git push origin --set-upstream new-branch-name
$ git push origin :old-branch-name

จากนั้นหากต้องการดูชื่อสาขาเก่าลูกค้าแต่ละรายของที่เก็บจะต้องทำ:

$ git fetch origin
$ git remote prune origin

หมายเหตุ: หากสาขาเก่าของคุณเป็นสาขาหลักของคุณคุณควรเปลี่ยนการตั้งค่าสาขาหลักของคุณ มิฉะนั้นเมื่อคุณเรียก $ git push origin :old-branch-nameคุณจะได้รับข้อผิดพลาด"ลบสาขาปัจจุบันต้องห้าม"


8
ดีถ้าชื่อเก่าและใหม่เหมือนกันนั่นหมายความว่าคุณไม่จำเป็นต้องเปลี่ยนชื่อสาขาดังนั้นจึงไม่มีจุดใดที่จะรันคำสั่งในตอนแรก ;-)
Sylvain Defresne

9
แน่ใจ ฉันแค่หมายความว่าหากคุณกำลังเรียกสิ่งนี้ด้วยวิธีอัตโนมัติ (เป็นส่วนหนึ่งของสคริปต์อื่น ๆ ) คุณอาจไม่ได้ทำสิ่งผิดถ้าคุณสามารถหลีกเลี่ยงได้
แดนลึกลับ

9
วิธีของแดน: จัดลำดับคำสั่งใหม่เพื่อให้ทำงานได้ตลอดเวลา วิธีของ Earth Engine: อย่าลืมตรวจสอบอยู่เสมอหรือข้อมูลสูญหาย ฉันรู้ว่าฉันจะเลือกอันไหน
Doradus

2
ผู้ใช้สามารถเรียกใช้: git fetch origin --prune(เพื่อดึงสาขาใหม่อย่างมีประสิทธิภาพและกำจัดการอ้างอิงไม่ได้อยู่ในระยะไกลอีกต่อไป)
DolphinDream

2
สามารถใช้-dหรือ--deleteแทนที่จะ:เป็นคอมไพล์รุ่นที่ใหม่กว่า
Zitrax

285

หากคุณต้องการเปลี่ยนชื่อสาขาจากระยะไกลจริงๆโดยไม่ต้องเปลี่ยนสาขาท้องถิ่นในเวลาเดียวกันคุณสามารถทำได้ด้วยคำสั่งเดียว:

git push <remote> <remote>/<old_name>:refs/heads/<new_name> :<old_name>

ฉันเขียนสคริปต์นี้ ( git-rename-remote-branch ) ซึ่งให้ทางลัดที่สะดวกในการทำสิ่งต่าง ๆ ได้อย่างง่ายดาย

ในฐานะที่เป็นฟังก์ชั่นทุบตี:

git-rename-remote-branch(){
  if [ $# -ne 3 ]; then
    echo "Rationale : Rename a branch on the server without checking it out."
    echo "Usage     : $(basename $0) <remote> <old name> <new name>"
    echo "Example   : $(basename $0) origin master release"
    exit 1 
  fi

  git push $1 $1/$2:refs/heads/$3 :$2
}

หากต้องการรวมความคิดเห็นของ @ ksrb : สิ่งนี้จะเป็นการผลักสองคำสั่งเดียวก่อนอื่นgit push <remote> <remote>/<old_name>:refs/heads/<new_name>ให้กดสาขาระยะไกลใหม่ตามสาขาการติดตามระยะไกลเก่าก่อนแล้วจึงgit push <remote> :<old_name>ลบสาขาระยะไกลเก่า


10
สำหรับผู้ที่ต้องการนามแฝงของคำสั่งนั้น: rename = "! f () {git push Origin origin / $ 1: refs / heads / $ 2: $ 1;}; f" สามารถใช้เป็น> git rename <old_name> < new_name>
Jonathan Schmidt

33
สำหรับผู้ที่อยากรู้ว่าคำสั่งนี้หมายถึงอะไรจริง ๆ แล้วการgit push <remote>/<old_name>:refs/heads/<new_name>กด2 หมายถึงการผลักดันรีโมตใหม่ที่ใช้รีโมตเก่าเป็น src จากนั้น git push [space]:<old_name>หมายถึงลบรีโมตเก่า
ksrb

3
ทำไมคุณต้องใช้refs/heads/name? คุณไม่สามารถใช้nameโดยตรงสร้างคำสั่งแรกได้git push <remote> <remote>/<old_name>:<new_name>หรือไม่
Drew Noakes

6
ไม่เพราะสาขาระยะไกล<new_name>ยังไม่มีอยู่ หากสาขานั้นไม่มีอยู่ Git ต้องการให้คุณใช้ชื่อเต็มมิฉะนั้น<new_name>อาจอ้างถึงชื่อแท็ก
sschuberth

3
เราใช้วิธีนี้ในระบบการสร้างของเรา ข้อแม้เดียวที่เราพบคือถ้าrefs/heads/<new_name> มีอยู่แล้ว การลบยังคงสำเร็จส่งผลให้<remote>/<old_name>ถูกลบเท่านั้น การตรวจสอบบางอย่างก่อนที่มือจะสามารถหลีกเลี่ยงได้
Apeiron

172

ชำระเงินครั้งแรกไปยังสาขาที่คุณต้องการเปลี่ยนชื่อ:

git branch -m old_branch new_branch
git push -u origin new_branch

วิธีลบสาขาเก่าออกจากremote:

git push origin :old_branch

12
เมื่อคุณผลักสาขาที่ถูกเปลี่ยนชื่อ (new_branch) ไปที่รีโมต (แหล่งกำเนิด) คุณควรตั้งค่าอัปสตรีมของมันเพื่อติดตามสาขาด้วยชื่อใหม่ (เช่นgit push -u origin new_branch) มิฉะนั้นสาขาที่ถูกเปลี่ยนชื่อ (new_branch) จะยังคงติดตามต้นทาง / old_branch และเมื่อคุณลบ old_branch ระยะไกล new_branch จะยังคงติดตาม Origin / old_branch ถึงแม้ว่าตอนนี้สาขาจะหายไป
DolphinDream

@DolphinDream ฉันแก้ไขคำตอบเพื่อรวมการเปลี่ยนแปลงต้นน้ำที่มีประโยชน์ของคุณ
mVChr

10

แน่ใจ เพียงเปลี่ยนชื่อสาขาในพื้นที่ผลักสาขาใหม่และผลักการลบเก่า

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


1
ดังนั้นเมื่อพยายามที่จะลบต้นแบบฉันได้ลอง $ git clone ../src $ cd src $ git branch notmaster $ git checkout notmaster $ git branch -d master $ git push ../src: master แต่มันบ่น: ปลายทาง refspec ไม่ตรงกับ ref ที่มีอยู่บนรีโมตหรือเริ่มต้นด้วย refs / และเราไม่สามารถเดาคำนำหน้าตามการอ้างอิงของแหล่งที่มา ข้อผิดพลาด: ไม่สามารถผลักดันผู้อ้างอิงบางคนไปที่ '../alpha/' รีโมตจริงๆมีสาขาชื่อ master
kdt

2

TL; DR

"การเปลี่ยนชื่อ" สาขาระยะไกลเป็นกระบวนการ 2 ขั้นตอนจริง ๆ (ไม่จำเป็นต้องสั่งซื้อ):

  • การลบสาขารีโมตเก่า ( git push [space]:<old_name>ดังที่อธิบายไว้ใน ksrb );
  • ผลักดันไปยังสาขาระยะไกลใหม่ (ความแตกต่างระหว่างคำสั่งสองคำตอบด้านล่าง)

ลบ

ฉันใช้TortoiseGitและเมื่อฉันพยายามลบสาขาผ่านบรรทัดคำสั่งฉันได้รับ:

$ git push origin :in
  • ร้ายแรง: 'ที่มา' ไม่ปรากฏว่าเป็นที่เก็บคอมไพล์

  • ร้ายแรง: ไม่สามารถอ่านจากที่เก็บระยะไกล

โปรดตรวจสอบว่าคุณมีสิทธิ์การเข้าถึงที่ถูกต้องและมีที่เก็บข้อมูลอยู่

นี่อาจเป็นเพราะผู้เข้าร่วมไม่ได้โหลดคีย์ส่วนตัว (ซึ่งTortoiseGit จะโหลดเข้าสู่การประกวดโดยอัตโนมัติ) นอกจากนี้ฉันสังเกตเห็นว่าคำสั่งTortoiseGitไม่มีการoriginอ้างอิงในนั้น (เช่นgit.exe push --progress "my_project" interesting_local:interesting)

ฉันยังใช้Bitbucketและในฐานะที่เป็นผู้จัดการ git ออนไลน์บนเว็บคนอื่น ๆ ในการจัดเรียง (GitHub, GitLab) ฉันสามารถลบสาขาระยะไกลได้โดยตรงผ่านส่วนต่อประสานของพวกเขา (หน้าสาขา):

ลบ Bitbucket สาขา

อย่างไรก็ตามในTortoiseGitคุณอาจลบสาขาระยะไกลผ่านการสืบค้นแบบเรียกดู :

เรียกดูเมนูอ้างอิง

โดยการคลิกขวาที่สาขาระยะไกล (รายการรีโมท) ตัวเลือกลบสาขาระยะไกลจะปรากฏขึ้น:

TortoiseGit ลบสาขาระยะไกล

ใจเร่งเร้า

หลังจากลบสาขาระยะไกลเก่าฉันผลักโดยตรงในสาขาที่ห่างไกลใหม่ผ่านTortoiseGitเพียงแค่พิมพ์ชื่อใหม่ในระยะไกล:ด้านการผลักดันหน้าต่างและสาขานี้ถูกสร้างขึ้นโดยอัตโนมัติและมองเห็นได้ในBitbucket

แต่ถ้าคุณยังคงต้องการที่จะทำมันด้วยตนเองจุดที่ยังไม่ได้รับการกล่าวถึงยังอยู่ในหัวข้อนี้คือ=-u--set-upstream

จากgit pushเอกสาร , -uเป็นเพียงนามแฝงของ--set-upstreamดังนั้นคำสั่งในคำตอบของซิลแว็ง ( -set-upstream new-branch)และShashank ( -u origin new_branch)เทียบเท่าตั้งแต่ได้รับเตะระยะไกลเริ่มต้นที่originหากไม่มีการเตะโทษอื่น ๆ ที่ถูกกำหนดไว้ก่อนหน้านี้:

  • git push origin -u new_branch= git push -u new_branch จากคำอธิบายเอกสาร :

    originหากการตั้งค่าจะหายไปเป็นค่าเริ่มต้น

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


originปัญหาคือว่าระยะไกลของคุณไม่ได้เรียกว่า git remoteคุณจะต้องตั้งชื่อระยะไกลของคุณในขณะที่คุณได้รับจากการทำงานคำสั่ง Git ทำงานร่วมกับsshสิ่งที่แสดงถึงว่าคุณใช้กุญแจสาธารณะ + ส่วนตัว ฉันคิดว่าAutoload Putty keysTortoiseGit เป็นเพียงการกดปุ่มที่จำเป็นเพื่อให้คุณทำทุกอย่างด้วยการอ้างอิงจากระยะไกลของคุณ สิ่งสุดท้ายgit push -uคือไม่ได้เป็นนามแฝงสำหรับผลักเข้าไปในสาขาระยะไกลมันเป็นนามแฝงสำหรับผลักเข้าไปในสาขาระยะไกลที่ถูกสร้างขึ้นในประเทศและการอ้างอิงระยะไกลยังไม่ได้สาขานี้
juanecabellob

1
@juancab -uเป็นชื่อแทน--set-upstreamและ "หากการกำหนดค่าหายไปค่าเริ่มต้นคือorigin " ซิลแว็งและShashankใช้นี้สำหรับการผลักดันให้เป็นที่สร้างขึ้นใหม่สาขาที่ห่างไกล สำคัญปัญหาอาจจะเป็นเพราะการประกวดไม่ได้มีมันโหลดเมื่อฉันพยายามgit push origin :inในเปลือก ดังนั้นฉันไม่เข้าใจ downvote ของคุณฉันเพิ่งชี้รายละเอียดของฉันและที่ไม่ได้พูดถึงในคำตอบอื่น ๆ อธิบายและแก้ไขพวกเขา
CPHPython

คุณกำลังระบุสิ่งที่ผิดและคำตอบส่วนใหญ่ไม่เกี่ยวข้องกับคำถามนั้น หากคุณกำลังชี้ให้เห็นว่าอะไรได้ผลสำหรับคุณฉันขอแนะนำให้คุณ จำกัด คำตอบสำหรับสิ่งที่ได้ผลและถ้าคุณต้องการให้คำอธิบายจริง ๆ โปรดแจ้งตัวเองให้ดีขึ้น Btw: -uเป็นนามแฝงสำหรับ--set-upstreamแต่นั่นไม่ใช่นามแฝงสำหรับผลักเข้าไปในสาขาระยะไกลตามที่คุณพูด หากต้องการผลักดันไปยังสาขาระยะไกลที่คุณต้องการโดยเฉพาะgit push <remote>และหากยังไม่ได้อยู่ในระยะไกลคุณต้องเพิ่มgit push -u <remote>คุณเพิ่ม ดังนั้น-uจะใช้ในการสร้างการอ้างอิงของสาขาในระยะไกล
juanecabellob

1
@juancab บางทีสิ่งที่คุณถือว่าผิดเป็นส่วนใหญ่นามแฝงถ้อยคำหรือเลือกคำ ฉันปรับโครงสร้างคำตอบของฉันและปรับโครงสร้างใหม่เพื่อให้คำอธิบายที่ครบถ้วนของโซลูชันที่พบเพื่อเปลี่ยนชื่อสาขาระยะไกล
CPHPython

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

1

ฉันไม่รู้ว่าทำไม แต่คำตอบของ @Sylvain Defresne ไม่เหมาะกับฉัน

git branch new-branch-name origin/old-branch-name
git push origin --set-upstream new-branch-name
git push origin :old-branch-name

ฉันต้องยกเลิกการอัปสตรีมและจากนั้นฉันสามารถตั้งค่าสตรีมอีกครั้ง ต่อไปนี้เป็นวิธีที่ฉันทำ

git checkout -b new-branch-name
git branch --unset-upstream
git push origin new-branch-name -u
git branch origin :old-branch-name

0

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

git push origin old_branch:new_branch
git push origin :old_branch

เท่าที่ฉันสามารถบอกได้นี่คือสิ่งที่ทุกคำตอบอื่น ๆ ทำ คำตอบของคุณสั้นกระชับกว่านี้
Clear

-1

คุณสามารถสร้างสาขาใหม่ตามสาขาเก่า เช่นนี้แล้วลบสาขาเก่ามากกว่า !!!ป้อนคำอธิบายรูปภาพที่นี่


นั่นคือ GitHub ไม่ใช่ Git ;)
Bouncner

-4

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

if git ls-remote --heads "$remote" \
    | cut -f2 \
    | sed 's:refs/heads/::' \
    | grep -q ^"$newname"$; then
    echo "Error: $newname already exists"
    exit 1
fi
git push "$oldname" "$remote/$oldname:refs/heads/$newname" ":$oldname"

(เช็คมาจากคำตอบนี้ )


ผมจะได้นำมาใช้แทนgit show-ref --quiet --verify -- refs/heads/$new_name ls-remote | cut | sed | grep
Andy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.