Git'te şubeleri uzaktan yeniden adlandırma


407

Yalnızca git://erişebileceğim bir havuz varsa (ve genellikle yalnızca + çekin), bu havuzdaki dalları yerel olarak yaptığım şekilde yeniden adlandırmanın bir yolu var git branch -mmı?


48
Bağlantılı "yinelenen" soru, bir dalın "hem yerel hem de uzak" olarak yeniden adlandırılmasını ister. Bununla birlikte, bu soru sadece şubelerin nasıl yeniden adlandırılacağını sorar, bu da basitleştirmeye izin verir. Bu, bir şubeyi kullanıma alma ve / veya yerel bir şube oluşturmaya gerek kalmadan sunucudaki bir dalı yeniden adlandırmak için yaptığım şeydir git push origin origin/old_name:refs/heads/new_name && git push origin :old_name.
sschuberth

1
@sschuberth: Her iki komutu bir seferde verebilirsiniz. Ve bu gerçekten bu sorunun cevabı olmalı.
Joachim Breitner

2
@JoachimBreitner Haklısın, bu optimizasyonu zaten bu senaryomda yaptım .
sschuberth

1
@sschuberth, yorumunuzu cevap olarak göndermelisiniz, çünkü aşağıdaki diğerlerinden daha iyi seviyorum.
phatmann

Yanıtlar:


480

İstediğiniz ada sahip yeni bir yerel şube oluşturmanız, uzaktan kumandanıza itmeniz ve ardından eski uzak dalı silmeniz yeterlidir:

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

Ardından, eski şube adını görmek için, deponun her istemcisinin şunları yapması gerekir:

$ git fetch origin
$ git remote prune origin

NOT: Eski dalınız ana dalınızsa, ana dal ayarlarınızı değiştirmeniz gerekir. Aksi takdirde, çalıştırdığınızda "geçerli dalın silinmesi yasak"$ git push origin :old-branch-name hatasını alırsınız .


8
Eski ve yeni isimler aynı ise, şubeyi yeniden adlandırmanız gerekmediği anlamına gelir, bu yüzden ilk etapta komutu çalıştırmanın bir anlamı yoktur ;-)
Sylvain Defresne

9
Elbette. Sadece bunu otomatik bir şekilde (başka bir komut dosyasının fonksiyon parçası olarak) çağırıyorsanız, bunu önleyebiliyorsanız yanlış şeyi yapamayacağınız anlamına gelir.
Gizemli Dan

9
Dan'ın yolu: komutları yeniden sıralayın, böylece her zaman çalışırlar. Earth Engine'in yolu: her zaman kontrol etmeyi unutmayın veya verileri kaybedersiniz. Hangisini seçeceğimi biliyorum.
Doradus

2
Kullanıcılar sadece şunları çalıştırabilir: git fetch origin --prune(yeni dalları etkili bir şekilde getirmek ve artık uzaktan kumandadaki referanslardan kurtulmak için).
DolphinDream

2
Git'in daha yeni sürümlerinde -dveya --deleteyerine kullanılabilir :.
Zitrax

285

Yerel şubeleri aynı anda yeniden adlandırmadan şubeleri uzaktan yeniden adlandırmak istiyorsanız, bunu tek bir komutla yapabilirsiniz:

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

Yukarıdakileri kolayca yapmak için kullanışlı bir kısayol sağlayan bu komut dosyasını ( git-rename-remote-branch ) yazdım .

Bir bash işlevi olarak:

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'nin yorumunu entegre etmek için : Bunun temel olarak yaptığı şey, tek bir komutta iki kez itmektir , önce git push <remote> <remote>/<old_name>:refs/heads/<new_name>eski uzaktan izleme kolunu temel alan yeni bir uzak dalı itmek ve sonra git push <remote> :<old_name>eski uzak dalı silmek için.


10
Bu komutun bir takma adını isteyenler için: rename = "! F () {git push origin origin / $ 1: refs / heads / $ 2: $ 1;}; f" bu> git rename <old_name> < new_name>
Jonathan Schmidt

33
Bu komutun aslında ne anlama geldiğini merak edenler için 2 git push <remote>/<old_name>:refs/heads/<new_name>itme, eski uzaktan kumandayı src olarak kullanan yeni bir uzaktan kumandayı itmek anlamına gelir, daha sonra git push [space]:<old_name> eski uzaktan kumandayı silmek anlamına gelir
ksrb

3
Neden kullanmanız gerekiyor refs/heads/name? Sadece namedoğrudan komut kullanamaz git push <remote> <remote>/<old_name>:<new_name>mısın?
Drew Noakes

6
Hayır, çünkü uzak dal <new_name>henüz mevcut değil. Şube mevcut değilse Git, tam adı kullanmanızı gerektirir; aksi takdirde <new_name>etiket adına da başvurabilir.
sschuberth

3
Bu yaklaşımı yapı sistemimizde kullanıyoruz. Karşılaştığımız tek uyarı refs/heads/<new_name> zaten varsa. Silme işlemi hala başarılı olur ve <remote>/<old_name>yalnızca silinir. El öncesi bazı kontroller bunu kolayca önleyebilir.
Apeiron

172

Yeniden adlandırmak istediğiniz şubeye ilk ödeme:

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

Eski bir dalı kaldırmak için remote:

git push origin :old_branch

12
Yeniden adlandırılan dalı (new_branch) uzak (orijin) konumuna ittiğinizde, dalını yeni adla izlemek için yukarı akışını da ayarlamanız gerekir (örn. git push -u origin new_branch) Aksi takdirde yeniden adlandırılan şube (new_branch) orijin / old_branch'ı izlemeye devam eder. Ve old_branch uzaklığını sildiğinizde, new_branch yine de bu şube gitti olsa da, orijin / old_branch'ı takip edecektir.
DolphinDream

@DolphinDream Cevabı, yararlı yukarı akış değişikliğinizi içerecek şekilde düzenledim.
mVChr

10

Elbette. Sadece şubeyi yerel olarak yeniden adlandırın, yeni dalı itin ve eskisini silin.

Tek gerçek sorun, deponun diğer kullanıcılarının yerel izleme dallarının adını değiştirmemeleri.


1
bu yüzden master silmeye çalışırken $ git clone denedim ../src $ cd src $ git branch notmaster $ git checkout notmaster $ git branch -d master $ git push ../src: master Ama şikayet ediyor: Hedef refspec ne uzaktan kumandadaki mevcut bir ref ile eşleşmiyor ne de refs / ile başlıyor ve kaynak ref'ye dayalı bir önek tahmin edemiyoruz. hata: bazı referansları '../alpha/' adresine gönderemedi Uzaktan kumandanın gerçekten master adlı bir şubesi var
kdt

2

TL; DR

Uzak bir dalın "yeniden adlandırılması" aslında 2 adımlı bir işlemdir (zorunlu olarak sipariş edilmez):

  • Eski uzak şube (silinmesi git push [space]:<old_name>olarak ksrb açıklanmıştır );
  • yeni bir uzak dal içine itin (aşağıdaki birkaç cevap komutu arasındaki fark).

Silme

Kullandığım TortoiseGit İlk komut satırı dalı silmeye çalışırken, ben hallederim ve:

$ git push origin :in
  • fatal: 'origin' bir git deposu gibi görünmüyor

  • ölümcül: Uzak depodan okunamadı.

Lütfen doğru erişim haklarına sahip olduğunuzdan ve havuzun var olduğundan emin olun.

Bunun nedeni, pageant'ın özel anahtarı ( TortoiseGit otomatik olarak pageant'a yükleyememesi ) yüklememesiydi . Dahası, TortoiseGit komutlarının originiçinde ref olmadığını (örneğin git.exe push --progress "my_project" interesting_local:interesting) fark ettim .

Ayrıca Bitbucket kullanıyorum ve diğerleri web tabanlı çevrimiçi git yöneticileri gibi (GitHub, GitLab), uzak dalı doğrudan arabirimleri (şubeler sayfası) aracılığıyla silebilirdim:

Şube Bitbucket'i Sil

Bununla birlikte, TortoiseGit'te Uzak Dalları Referanslara Gözat ile de silebilirsiniz :

Referanslara Göz At menüsü

Uzak bir dalı (uzaktan kumandalar listesi) sağ tıklatarak Uzak dalı sil seçeneği görünür :

TortoiseGit uzaktan şube silme

itme

Eski uzak dalı sildikten sonra, yalnızca Push penceresinin Remote: alanına yeni adı yazarak TortoiseGit aracılığıyla doğrudan yeni bir uzak şubeye ittim ve bu dal otomatik olarak oluşturuldu ve Bitbucket'te görünür .

Bununla birlikte, yine de el ile yapmayı tercih ediyorsanız, bu iş parçacığında henüz belirtilmemiş bir nokta -u= --set-upstream.

Gönderen git pushdokümanlar , -usadece bir diğer adıdır --set-upstream, cevaplarından kadar komutlar Sylvain ( -set-upstream new-branch) ve shashank ( -u origin new_branch) , eşdeğerdir uzak ref beri varsayılanorigin başka hiçbir ref Eğer daha önce:

  • git push origin -u new_branch= git push -u new_branch Den dokümanlar açıklama :

    Yapılandırma eksikse, varsayılan olarak origin.

Sonunda, buradaki diğer cevaplar tarafından önerilen komutları manuel olarak yazmadım veya kullanmadım, bu yüzden belki de bu benzer bir durumda başkaları için yararlı olabilir.


sorun uzaktan kumandanızın çağrılmamasıdır origin. Komutu çalıştırırken uzaktan kumandanızı adlandırmanız gerekir git remote. Git ssh, genel + özel anahtarları kullandığınız anlamına gelen şeylerle çalışır . Autoload Putty keysTortoiseGit'in uzaktan referansınızla herhangi bir şey yapmanız için gerekli anahtarları otomatik olarak yüklediğini varsayıyorum . Son şey, git push -uuzak bir dalı itmek için bir takma ad değil, yerel olarak oluşturulan uzak bir dalda itmek için bir takma addır ve uzaktan başvurusunda henüz bu dal yoktur .
juanecabellob

1
@juancab -u, --set-upstream"yapılandırma eksikse varsayılan olarakorigin " bir takma addır . Sylvain ve Shashank bunu yeni oluşturulan uzak bir şubeye itmek için kullanıyor . Anahtar konu nedeniyle olabilir yarışmasında Denedim zaman yüklü olmamasından git push origin :inkabuk üzerinde. Bu yüzden downvote'unuzu anlamadım, diğer cevaplarda benimkini ve ele alınmamış ayrıntıları işaret ettim, açıkladım ve çözdüm.
CPHPython

Yanlış şeyler söylüyorsunuz ve bu cevabın çoğu sorunun kendisiyle alakasız. Sizin için neyin işe yaradığını işaret ediyorsanız, cevabı işe yarayanlarla sınırlandırmanızı öneririm ve gerçekten bir açıklama yapmak istiyorsanız, lütfen kendinizi daha iyi bilgilendirin. Btw: -uiçin bir takma addır, --set-upstreamancak dediğin gibi uzak bir şubeye itmek için takma ad değildir. Bir uzak dalı içine itmek için benzersiz bir şekilde ihtiyacınız var git push <remote>ve henüz uzaktan kumandada değilse, eklersiniz git push -u <remote>. Bu nedenle, -uuzaktan kumandadaki dalın bir referansını oluşturmak için kullanılır.
juanecabellob

1
@juancab belki de yanlış gördüğünüz şey çoğunlukla takma ad ifade veya kelimelerin seçimiydi. Cevabımı yeniden yapılandırdım ve uzak bir şubeyi yeniden adlandırdığımı bulduğum çözümlerin tam bir açıklamasını sağlamak için yeniden ifade ettim .
CPHPython

Daha da ileri ifade ederim. Şimdi daha mantıklı, ama yine de çok uzun. Soruna daha açık olacağım, yani TortoiseGit kullanıcıları için önerilen çözümlerin çalışmadığını belirtin. Bir hikaye anlatıyorsunuz ve bu kafa karıştırıcı ve kullanıcıların okumaktan kaçınmasına neden oluyor. Cevabınızı bir teklifle düzenleyeceğim.
juanecabellob

1

Nedenini bilmiyorum ama @Sylvain Defresne'nin cevabı benim için çalışmıyor.

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

Yukarı akışın ayarını kaldırmalıyım ve sonra akışı tekrar ayarlayabilirim. İşte bunu nasıl yaptım.

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

0

Bunun doğru ya da yanlış olup olmadığını bilmiyorum, ancak dalın "eski adını" dalın "yeni adına" ittim, sonra eski dalı tamamen aşağıdaki iki satırla sildim:

git push origin old_branch:new_branch
git push origin :old_branch

Anlayabildiğim kadarıyla, diğer tüm cevaplar tam olarak budur. Cevabınız sadece daha kısa ve öz.
Daha net

-1

Eski adlı dalı temel alan yeni bir dal oluşturabilirsiniz. Aynen böyle, sonra eski şubeyi silin !!!resim açıklamasını buraya girin


Bu GitHub, Git değil. ;)
Bouncner

-4

Daha önce verilen yanıtlara ek olarak, önce yeni dalın zaten var olup olmadığını kontrol eden bir sürüm (böylece bir komut dosyasında güvenle kullanabilirsiniz)

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"

(çek bu cevaptan alınmıştır )


Bunun git show-ref --quiet --verify -- refs/heads/$new_nameyerine kullanırdım ls-remote | cut | sed | grep.
Andy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.