Mengganti nama cabang dari jauh di Git

407

Jika ada repositori yang hanya dapat saya git://akses (dan biasanya hanya dengan push + pull), apakah ada cara untuk mengubah nama cabang dalam repositori dengan cara yang sama dengan yang akan saya lakukan secara lokal git branch -m?

kdt
sumber
48
Pertanyaan "duplikat" yang tertaut meminta untuk mengubah nama cabang "baik secara lokal maupun jarak jauh". Namun, pertanyaan ini hanya menanyakan cara mengganti nama cabang dari jarak jauh, yang memungkinkan penyederhanaan. Ini adalah apa yang saya lakukan untuk mengubah nama cabang pada server tanpa perlu untuk checkout dan / atau membuat cabang lokal: git push origin origin/old_name:refs/heads/new_name && git push origin :old_name.
sschuberth
1
@sschuberth: Anda dapat memberikan kedua perintah sekaligus. Dan ini benar-benar harus menjadi jawaban untuk pertanyaan ini.
Joachim Breitner
2
@ JoachimBreitner Anda benar, saya sudah melakukan optimasi itu di skrip saya ini.
sschuberth
1
@sschuberth, Anda harus memposting komentar Anda sebagai jawaban, karena saya lebih menyukainya daripada yang lain di bawah ini.
phatmann
Selesai .
sschuberth

Jawaban:

480

Anda hanya perlu membuat cabang lokal baru dengan nama yang diinginkan, dorong ke remote Anda, dan kemudian hapus cabang remote lama:

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

Kemudian, untuk melihat nama cabang yang lama, setiap klien dari repositori harus melakukan:

$ git fetch origin
$ git remote prune origin

CATATAN: Jika cabang lama Anda adalah cabang utama Anda, Anda harus mengubah pengaturan cabang utama Anda. Jika tidak, saat Anda menjalankan $ git push origin :old-branch-name, Anda akan mendapatkan kesalahan "penghapusan cabang saat ini dilarang" .

Sylvain Defresne
sumber
8
Nah, jika nama lama dan baru sama, maka itu berarti Anda tidak perlu mengubah nama cabang, jadi tidak ada gunanya menjalankan perintah ;-)
Sylvain Defresne
9
Tentu. Maksud saya, jika Anda memanggil ini dengan cara otomatis (sebagai bagian fungsi dari beberapa skrip lain), Anda mungkin tidak akan melakukan hal yang salah jika Anda dapat menghindarinya.
Misterius Dan
9
Cara Dan: menyusun ulang perintah sehingga selalu berfungsi. Cara Earth Engine: selalu ingat untuk memeriksa, atau Anda kehilangan data. Saya tahu yang mana yang akan saya pilih.
Doradus
2
Pengguna hanya dapat menjalankan: git fetch origin --prune(untuk mengambil cabang baru secara efektif dan juga menyingkirkan referensi tidak lagi pada remote).
DolphinDream
2
Dapat digunakan -datau --deletesebagai gantinya :di versi git yang lebih baru.
Zitrax
285

Jika Anda benar-benar hanya ingin mengubah nama cabang dari jarak jauh, tanpa mengubah nama cabang lokal secara bersamaan , Anda dapat melakukan ini dengan satu perintah:

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

Saya menulis skrip ini ( git-rename-remote-branch ) yang menyediakan pintasan praktis untuk melakukan hal di atas dengan mudah.

Sebagai fungsi bash:

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
}

Untuk mengintegrasikan komentar @ ksrb : Yang dilakukan pada dasarnya adalah dua dorongan dalam satu perintah, pertama yang git push <remote> <remote>/<old_name>:refs/heads/<new_name>mendorong cabang jarak jauh baru berdasarkan cabang pelacakan jarak jauh yang lama dan kemudian git push <remote> :<old_name>menghapus cabang jarak jauh yang lama.

sschuberth
sumber
10
Bagi mereka yang menginginkan alias dari perintah itu: rename = "! F () {git push origin origin / $ 1: refs / head / $ 2: $ 1;}; f" ini dapat digunakan sebagai> git rename <old_name> < new_name>
Jonathan Schmidt
33
Bagi mereka yang penasaran dengan arti sebenarnya dari perintah ini, pada dasarnya 2 git push <remote>/<old_name>:refs/heads/<new_name>push berarti mendorong remote baru yang menggunakan remote lama sebagai src kemudian git push [space]:<old_name> berarti menghapus remote lama
ksrb
3
Mengapa Anda perlu menggunakannya refs/heads/name? Tidak bisakah Anda namelangsung menggunakan , membuat perintah pertama git push <remote> <remote>/<old_name>:<new_name>?
Drew Noakes
6
Tidak, karena cabang jarak jauh <new_name>belum ada. Jika cabang tidak ada, Git mengharuskan Anda untuk menggunakan nama lengkap karena selain <new_name>itu juga bisa merujuk ke nama tag.
sschuberth
3
Kami menggunakan pendekatan ini dalam sistem pembangunan kami. Satu-satunya peringatan yang kita temui adalah jika refs/heads/<new_name> sudah ada. Penghapusan masih berhasil, sehingga <remote>/<old_name>hanya dihapus. Beberapa pemeriksaan sebelum tangan dapat dengan mudah menghindari ini.
Apeiron
172

Pertama checkout ke cabang yang ingin Anda rename:

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

Untuk menghapus cabang lama dari remote:

git push origin :old_branch
Shashank Hegde
sumber
12
Saat Anda mendorong cabang yang diganti nama (new_branch) ke jarak jauh (asal), Anda juga harus mengatur upstreamnya untuk melacak cabang dengan nama baru (mis. git push -u origin new_branchJika tidak, cabang yang diganti nama (new_branch) akan terus melacak asal / old_branch. Dan setelah Anda menghapus old_branch jarak jauh, new_branch masih akan melacak asal / old_branch, meskipun sekarang cabang itu hilang.
DolphinDream
@OlphinDream Saya mengedit jawaban untuk menyertakan perubahan hulu yang bermanfaat.
mVChr
10

Tentu. Cukup ganti nama cabang secara lokal, dorong cabang baru, dan dorong penghapusan yang lama.

Satu-satunya masalah sebenarnya adalah pengguna repositori lain tidak akan mengganti nama cabang pelacakan lokal.

Lily Ballard
sumber
1
jadi ketika mencoba untuk menghapus master, saya sudah mencoba $ git clone ../src $ cd src $ git branch notmaster $ git checkout notmaster $ git branch -d master $ git push ../src: master Tetapi komplain: Tujuan refspec tidak cocok dengan ref yang ada pada remote atau dimulai dengan ref /, dan kami tidak dapat menebak awalan berdasarkan sumber ref. galat: gagal mendorong beberapa referensi ke '../alpha/' Remote benar-benar memiliki cabang yang disebut master
kdt
2

TL; DR

"Mengganti nama" cabang jarak jauh sebenarnya adalah proses 2 langkah (tidak harus dipesan):

  • penghapusan cabang lama yang jauh ( git push [space]:<old_name>seperti yang dijelaskan ksrb );
  • dorong ke cabang jauh baru (perbedaan antara beberapa perintah jawaban di bawah).

Menghapus

Saya menggunakan TortoiseGit dan ketika saya pertama kali mencoba menghapus cabang melalui baris perintah, saya mendapatkan ini:

$ git push origin :in
  • fatal: 'origin' sepertinya bukan repositori git

  • fatal: Tidak bisa membaca dari repositori jarak jauh.

Pastikan Anda memiliki hak akses yang benar dan repositori ada.

Ini kemungkinan karena kontes tidak memiliki kunci pribadi dimuat (yang memuat TortoiseGit secara otomatis ke dalam kontes ). Selain itu, saya perhatikan bahwa perintah TortoiseGit tidak memiliki originreferensi di dalamnya (misalnya git.exe push --progress "my_project" interesting_local:interesting).

Saya juga menggunakan Bitbucket dan, seperti yang lain seperti manajer git online berbasis web (GitHub, GitLab), saya dapat menghapus cabang jarak jauh secara langsung melalui antarmuka mereka (halaman cabang):

Hapus cabang Bitbucket

Namun, di TortoiseGit Anda juga dapat menghapus cabang jarak jauh melalui Browse Referensi :

Jelajahi menu Referensi

Dengan mengklik kanan pada cabang jarak jauh (daftar remote), opsi Hapus cabang jauh muncul:

Hapus cabang jarak jauh TortoiseGit

Mendorong

Setelah menghapus cabang jarak jauh lama saya mendorong langsung ke cabang jarak jauh baru melalui TortoiseGit hanya dengan mengetikkan nama baru di bidang Remote: pada jendela Push dan cabang ini secara otomatis dibuat dan terlihat di Bitbucket .

Namun, jika Anda masih lebih suka melakukannya secara manual, titik yang belum disebutkan di utas ini adalah itu -u= --set-upstream.

Dari git pushdocs , -uhanya alias --set-upstream, jadi perintah dalam jawaban Sylvain ( -set-upstream new-branch) dan Shashank ( -u origin new_branch) adalah setara, karena remote ref default keorigin jika tidak ada ref lain yang sebelumnya didefinisikan:

  • git push origin -u new_branch= git push -u new_branch dari deskripsi dokumen :

    Jika konfigurasi tidak ada, defaultnya adalah origin.

Pada akhirnya, saya tidak mengetik secara manual atau menggunakan salah satu perintah yang disarankan oleh jawaban lain di sini, jadi mungkin ini mungkin berguna bagi orang lain dalam situasi yang sama.

CPHPython
sumber
masalahnya adalah bahwa remote Anda tidak dipanggil origin. Anda harus memberi nama remote Anda saat mendapatkannya dari menjalankan perintah git remote. Git bekerja dengan sshapa yang menyiratkan bahwa Anda menggunakan kunci publik + pribadi. Saya berasumsi bahwa Autoload Putty keysTortoiseGit hanya mengunci secara otomatis kunci yang diperlukan agar Anda dapat melakukan apa saja dengan referensi jarak jauh Anda. Hal terakhir adalah itu git push -ubukan alias untuk mendorong ke cabang jauh, itu adalah alias untuk mendorong ke cabang jauh yang dibuat secara lokal dan referensi jarak jauh belum cabang ini .
juanecabellob
1
@ juancab -uadalah alias --set-upstreamdan "jika konfigurasi tidak ada, defaultnya adalahorigin ". Sylvain dan Shashank menggunakan ini untuk mendorong ke cabang terpencil yang baru dibuat . Masalah utama mungkin karena kontes tidak memuatnya ketika saya mencoba git push origin :indi shell. Jadi saya tidak mengerti downvote Anda, saya hanya menunjukkan detail saya dan tidak ditanggapi dalam jawaban lain, menjelaskannya dan menyelesaikannya.
CPHPython
Anda menyatakan hal-hal yang salah dan banyak dari jawaban ini tidak ada hubungannya dengan pertanyaan itu sendiri. Jika Anda menunjukkan apa yang berhasil untuk Anda, saya mendorong Anda untuk membatasi jawaban untuk apa yang berhasil dan jika Anda benar-benar ingin memberikan penjelasan, harap informasikan diri Anda lebih baik. Btw: -uadalah alias untuk --set-upstreamtetapi itu bukan alias untuk mendorong ke cabang jauh seperti yang Anda katakan. Untuk mendorong ke cabang jarak jauh yang Anda butuhkan secara unik git push <remote>, dan jika belum ada di remote, Anda menambahkan git push -u <remote>. Karena itu, -udigunakan untuk membuat referensi cabang di remote.
juanecabellob
1
@ juancab mungkin apa yang Anda anggap salah sebagian besar adalah alias alias pilihan kata. Saya merestrukturisasi jawaban saya dan mengulanginya untuk memberikan penjelasan lengkap tentang solusi yang saya temukan untuk mengubah nama cabang yang jauh.
CPHPython
Saya akan mengulanginya lebih lanjut. Lebih masuk akal sekarang, tetapi masih terlalu lama. Saya akan lebih spesifik untuk masalah ini, yaitu menyatakan bahwa untuk pengguna TortoiseGit solusi yang diusulkan tidak akan berfungsi. Anda menceritakan sebuah kisah dan itu membingungkan dan membuat pengguna menghindari membaca. Saya akan mengedit jawaban Anda dengan proposisi.
juanecabellob
1

Saya tidak tahu mengapa tetapi jawaban @Sylvain Defresne tidak bekerja untuk saya.

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

Saya harus mengatur hulu dan kemudian saya dapat mengatur aliran lagi. Berikut ini adalah bagaimana saya melakukannya.

git checkout -b new-branch-name
git branch --unset-upstream
git push origin new-branch-name -u
git branch origin :old-branch-name
arthur bryant
sumber
0

Saya tidak tahu apakah ini benar atau salah, tetapi saya mendorong "nama lama" cabang ke "nama baru" cabang, lalu menghapus cabang lama seluruhnya dengan dua baris berikut:

git push origin old_branch:new_branch
git push origin :old_branch
EpicPandaForce
sumber
Sejauh yang saya tahu, inilah yang dilakukan oleh semua jawaban lainnya. Jawaban Anda lebih ringkas.
Clearer
-1

Anda dapat membuat cabang baru berdasarkan cabang nama lama. Sama seperti ini, lalu hapus cabang lama, lebih dari !!!masukkan deskripsi gambar di sini

Pober Wong
sumber
Itu GitHub, bukan Git. ;)
Bouncner
-4

Menambah jawaban yang sudah diberikan, berikut adalah versi yang pertama memeriksa apakah cabang baru sudah ada (sehingga Anda dapat menggunakannya dengan aman dalam skrip)

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"

(cek berasal dari jawaban ini )

myzzzl
sumber
Saya akan menggunakan git show-ref --quiet --verify -- refs/heads/$new_namesebagai gantinya ls-remote | cut | sed | grep.
Andy