Ana dalı hem yerel hem de uzak Git depoları için yeniden adlandırın


820

Şubeyi sahip masteruzaktan şube izler origin/master.

Bunları master-oldhem yerel olarak hem de uzaktan kumandada yeniden adlandırmak istiyorum . Mümkün mü?

origin/masterYerel masterşubesini izleyen (ve her zaman yerel şubelerini kimin üzerinden güncelleyen) diğer kullanıcılar için git pull, uzak şubeyi yeniden adlandırdıktan sonra ne olur? Hala çalışıyorlar mıydı yoksa artık bulamadığı bir hata mı
veriyorlar ?git pullorigin/master

Daha sonra, yeni bir masterşube oluşturmak istiyorum (hem yerel hem de uzak). Yine, bunu yaptıktan sonra, diğer kullanıcılar yaparsa ne olur git pull?

Sanırım tüm bunlar çok fazla sorunla sonuçlanacaktır. İstediğimi elde etmenin temiz bir yolu var mı? Yoksa sadece masterolduğu gibi bırakmalı ve yeni bir dal oluşturmalı master-newve orada daha fazla mı çalışmalıyım?


2
Kabul edilen cevapta verilen tarif herhangi bir isimdeki bir dal için geçerlidir, ancak uyarılar Git'te ana dalın (varsayılan olarak) özel rolü nedeniyle (belirtildiği gibi) geçerli değildir .
kynan

3
@kynan: Sanırım anlamıyorum. Usta için hangi uyarılar uygulanır ve diğer dallara uygulanmaz? Eğer xy adlı bir şube olsaydı ve diğer insanlar bu dalı izlese, bu nasıl farklı olurdu?
Albert

4
Uzaktaki master'ı normalde silemediğiniz uyarı. Bu Aristoteles'in cevabı için geçerli değildir, bu yüzden bunu kabul edilen cevap olarak işaretlemek isteyebilirsiniz. Doğru, herhangi bir uzaktan izleme şubesinden git push -fyeteneğini etkiler pull.
kynan

master-oldönceki masterdalla aynı taahhüdün işaretini gösteren yeni bir dal oluşturabilirsiniz . Ardından , stratejiyi kullanarak masterbir yeni dalınızla şubenin üzerine yazabilirsiniz . Birleştirme yapmak, uzaktan kumanda ileriye dönük olmayan değişikliklere izin vermediğinde çalışır. Bu, diğer kullanıcıların zorunlu güncellemeler yapmayacağı anlamına gelir. mergeours
dnozay

1
@kynan mastersadece varolan tek şube olduğu sürece özeldir. Birden fazla alana sahip olduğunuzda, tüm şubeler eşit temeldedir.
jub0bs

Yanıtlar:


614

Yeniden adlandırmaya en yakın şey, uzaktan kumandanın silinmesi ve yeniden oluşturulmasıdır. Örneğin:

git branch -m master master-old
git push remote :master         # delete master
git push remote master-old      # create master-old on remote

git checkout -b master some-ref # create a new local master
git push remote master          # create master on remote

Ancak bunun bir sürü uyarısı vardır. Birincisi, hiçbir varolan checkouts yeniden adlandırma hakkında bilecek - git gelmez değil dal yeniden adlandırmaları izlemek için çalışırlar. Yeni masterhenüz yoksa, git pull hatası verir. Yeni masteroluşturulmuşsa. çekme birleşmeye çalışır masterve master-old. Bu nedenle, daha önce depoyu kontrol eden herkesin işbirliği yapmadığınız sürece genellikle kötü bir fikirdir.

Not: Git'in daha yeni sürümleri, ana dalı varsayılan olarak uzaktan silmenize izin vermez. Sen ayarlayarak bu kılabilirsiniz receive.denyDeleteCurrentyapılandırma değeri warnveya ignoreüzerinde uzaktan depo. Aksi takdirde, hemen yeni bir master oluşturmaya hazırsanız, git push remote :masteradımı atlayın ve adıma --forcegeçin git push remote master. Uzaktan kumandanın yapılandırmasını değiştiremiyorsanız, ana dalı tamamen silemeyeceğinizi unutmayın!

Bu uyarı yalnızca geçerli dal (genellikle masterdal) için geçerlidir ; diğer tüm dallar yukarıdaki gibi silinebilir ve yeniden oluşturulabilir.


2
dalları sadece (isim, hash) çifti - başka bir şey, hiçbir şey daha az. Şubelerde reflog var, ancak bu asla uzak istemcilere maruz kalmaz.
bdonlan

122
Uzaktan kumandadaki master'ı silmeden önce uzaktan kumandada master-old oluştururdum. Ben sadece paranoyakum.
Adam Dymitruk

6
Aristoteles'in aşağıdaki cevabı, ustayı silmeden bunu yapmanıza izin veriyor, bu yüzden bunu tercih ederim.
Kil Köprüler

13
kullanabilirsiniz new-branch-nameve / old-branch-nameyerine açık ve güvenli olurdu , bu nedenle bu genel bir sorundur. mastermaster-old
Jaider

2
Silinen şubeye (burada: master) başka şubeler tarafından referans verilmezse, git bu işlemdeki tüm taahhütleri toplayabilir ... iyi ... “şube”. - Bazı git porselen komutları çöp toplama işlemini tetikler. - Bu nedenle: önce yeni adı oluşturun (aynı taahhüdü işaret ederek), ardından eski adı silin.
Robert Siemer

257

Şu anda bulunduğunuzu varsayarsak master:

git push origin master:master-old        # 1
git branch master-old origin/master-old  # 2
git reset --hard $new_master_commit      # 3
git push -f origin                       # 4
  1. Önce yerel depodaki taahhüdü esas master-oldalarak origindepoda bir şube yapın master.
  2. Bu yeni şube için yeni bir yerel şube oluşturun origin/master-old(otomatik olarak izleme dalı olarak düzgün şekilde ayarlanır).
  3. Şimdi masteryerelinizi işaret etmek istediğiniz taahhüde yönlendirin.
  4. Son olarak, kuvvet-değişim masteriçinde origindepoya yeni yerel yansıtmak için master.

(Başka bir şekilde yaparsanız master-old, doğru şekilde izlemek üzere ayarlandığından emin olmak için en az bir adım daha yapmanız gerekir origin/master-old. Bu yazı sırasında gönderilen diğer çözümlerin hiçbiri buna dahil değildir.)


11
Bu, "cevap" dan daha iyi bir cevap, katılıyorum, ama buraya gelen insanlar için sadece bir dalı (açıkça usta değil) yeniden adlandırmak için, 3. adım pek mantıklı değil.
knocte

İster masterbaşka bir branşta , ister başka bir branşta olsun, cevapta kesinlikle hiçbir fark yaratmaz. Soru kötü bir şekilde başlıklandırılmıştı, sadece bir kolu yeniden adlandırmaktan daha karmaşık bir görev soruyor .
Aristoteles Pagaltzis

3
Bu benim için işe yarayan bir çözüm oldu. Ustayı başka bir dalla değiştirmeye çalışıyordum. Adım 3 için $ new_master_commit almak için bir git log -1 origin / what_i_want_as_new_master yaptım. İtme işleminden sonra (4. adım), diğer geliştiriciler çekip "şubeniz 295 taahhütte ustanın önünde" mesajlarını alırdı. Bunu düzeltmek için her çalışmaya bildiren bir e-posta gönderdim: git pull; git checkout some_random_branch; git branch -D yöneticisi; git çekme; git ödeme yöneticisi; Temel olarak, yerel master'larını kaldırmaları ve yeni sürümü çekmeleri gerekiyor, aksi takdirde yerel olarak yanlış yerdeler.
nairbv

Bunu çok daha kolay bir şekilde yapabilirdiniz: zaten açık olduklarını varsayarak , yerel olanları aynı olanla aynı şekilde zorlamak için masteryapabilirlerdi . Bunu ve saklamak istediğiniz yerel taahhütlerin olduğu daha karmaşık davayı stackoverflow.com/q/4084868git fetch && git reset --hard origin/mastermasteroriginmaster
Aristotle Pagaltzis

Uzak yapılandırma dosyasının "denyNonFastforwards = false" olduğundan emin olun, yoksa "remote: error" iletisini alırsınız: hızlı ilerlemeyen refs / heads / master'ı reddetme (önce çekmeniz gerekir) "
gjcamann

160

Git v1.7 ile, bunun biraz değiştiğini düşünüyorum. Yerel şubenizin izleme referansını yeni uzaktan kumandaya güncellemek artık çok kolay.

git branch -m old_branch new_branch         # Rename branch locally    
git push origin :old_branch                 # Delete the old branch    
git push --set-upstream origin new_branch   # Push the new branch, set local branch to track the new remote

10
Bir alternatif --set-upstreamaşağıdaki gibidir: git push -u --all
Şubenizi

4
Git uzak ana silmenize izin vermeyeceğinden, bu ana dal ile çalışmaz.
Alexandre Neto

4
@AlexandreNeto Bu durumda 3. satırı 2. satırdan önce yürütebilir, varsayılan dalı ayarlayabilir new_branchve daha sonra uzaktan kumandayı master2. satırla silebilirsiniz .
Tristan Jahier

3
İnanılmaz basit adımlar. Bu sorunun en iyi cevabı
siddhusingh

13
Uzak dalı silmek git push origin --delete old_branchbiraz daha okunabilir.
ThomasW

35
git checkout -b new-branch-name
git push remote-name new-branch-name :old-branch-name

new-branch-nameSilmeden önce manuel olarak geçiş yapmanız gerekebilirold-branch-name


Bu çözümün herhangi bir kısmı yerel eski şube adını siliyor mu, yoksa bu özel bir egzersiz mi?
GreenAsJade

4
Sonunda git branch -d old-branch-nameyerel eski şube silmek için çalıştırılması gerektiğini düşünüyor .
Nabi KAZ

Yalnızca bir komutla değişiklikleri itebilir: git push remote-name new-branch-name :old-branch-name.
sigod

Bu şekilde git tarihini zorlaştırmayacak mısınız? Çünkü sadece geçerli olanı yeniden adlandırmak yerine yeni bir şube açıyorsunuz.
androidevil

1
@androider Hayır. Git'teki şubeler basit referanslardır .
sigod

29

Şubeyi yeniden adlandırmanın birçok yolu var, ancak daha büyük soruna odaklanacağım: "istemcilerin hızlı bir şekilde ilerlemelerine ve şubeleriyle yerel olarak uğraşmak zorunda kalmamaya nasıl" .

Önce kısa bir resim: ana dalı yeniden adlandırma ve istemcilerin hızlı ileri almalarına izin verme

Bu gerçekten kolay bir şey; ama kötüye kullanmayın. Tüm fikir birleştirme taahhütlerine bağlıdır; hızlı ileriye izin veriyorlar ve bir dalın geçmişini bir başkasıyla ilişkilendiriyorlar.

şubeyi yeniden adlandırmak:

# rename the branch "master" to "master-old"
# this works even if you are on branch "master"
git branch -m master master-old

yeni "ana" dalın oluşturulması:

# create master from new starting point
git branch master <new-master-start-point>

ebeveyn-çocuk geçmişine sahip bir birleştirme taahhüdü oluşturmak:

# now we've got to fix the new branch...
git checkout master

# ... by doing a merge commit that obsoletes
# "master-old" hence the "ours" strategy.
git merge -s ours master-old

ve voila.

git push origin master

Bu bir mergetaahhüt oluşturduğu için şubenin yeni bir revizyona hızlı bir şekilde yönlendirilmesine izin verdiği için çalışır .

makul bir birleştirme taahhüdü mesajı kullanma:

renamed branch "master" to "master-old" and use commit ba2f9cc as new "master"
-- this is done by doing a merge commit with "ours" strategy which obsoletes
   the branch.

these are the steps I did:

git branch -m master master-old
git branch master ba2f9cc
git checkout master
git merge -s ours master-old

3
Teşekkürler! git merge -s ours master-olddiğer cevapların kaçırdığı çok önemli bir parçadır. Ayrıca, "yapması kolay", "gitmesi kolay" anlamına gelmez, bu da git'in çoğunda durum gibi görünüyor, ama konuya giriyorum.
Martin Vidner

3
Hiçbir silme işleminden bahsedilmemesi ve yukarı akıştaki klonlarla çalışanlar için geçişin "kesintisiz" olduğu gerçeğini seviyorum. Teşekkür ederim!
Piotrek

12

Hala önceki sorunuzdakiyle aynı durumu sorduğunuzu varsayıyorum . Yani, master-new geçmişinde master-old içermeyecektir. * Master-new "master" adını verirseniz, etkili bir şekilde tarihi yeniden yazmış olursunuz. Fark etmez ne sen efendi o durumdayken sadece o, ustanın bir önceki pozisyonun soyundan olmadığı bir duruma girecek.

Master mevcut değilken çekmeye çalışan diğer kullanıcılar sadece çekimlerinin başarısız olmasını sağlar (uzaktan kumandada böyle bir ref yok) ve yeni bir yerde tekrar var olduğunda, çekimlerinin efendisini yeni uzak master ile birleştirmeye çalışması gerekir, tıpkı deponuzda master-old ve master-new'i birleştirmişsiniz gibi. Burada yapmaya çalıştığınız göz önüne alındığında, birleşmenin çatışmaları olacaktır. (Eğer çözülmüşlerse ve sonuç depoya geri gönderildiyse, daha da kötü bir durumda olacaksınız - tarihin her iki sürümü de orada.)

Sorunuzu basitçe cevaplamak için: bazen tarihinizde hatalar olacağını kabul etmelisiniz. Tamamdır. Herkesin başına geliyor. Git.git deposunda geri döndürülmüş taahhütler vardır. Önemli olan tarih yayınladıktan sonra, herkesin güvenebileceği bir şeydir.

* Eğer öyleyse, bu bazı değişiklikleri master'a aktarmaya ve daha sonra olduğu yerde yeni bir dal oluşturmaya eşdeğer olacaktır. Sorun değil.


Evet, aynı sorun, nasıl çözüleceğine dair bir fikir vardı. Ancak bu şube yeniden adlandırmayı yapmasam bile, mümkün olsaydı ilginçtim. Ben "usta" gibi refs sadece belirli taahhütlere referans olduğunu düşündüm. Gerçekten hiçbir tarihi değiştirmek istemiyorum. Usta referansını başka bir kafaya işaret edeceğimi düşündüm. Bu aynı zamanda, daha önce hiç kullandıysam, bir daha asla bir şube adı kullanamayacağım anlamına mı geliyor?
Albert

Gerçekten de, şubeler taahhüt ederler. Mesele şu ki, bir şube başkanının belirli bir şekilde gelişmesini bekliyoruz (yani, her zaman hızlı ilerleyen). Başka birinin bakış açısından, bir şubeyi genel repoda taşımak şubenin tarihini yeniden yazmakla aynıdır. Artık eskiden her şeyi içeren bir taahhüdü işaret etmiyor.
Cascabel

8

Seçilen cevap Denedim zaman başarısız oldu. Bu bir hata atar: refusing to delete the current branch: refs/heads/master. Benim için neyin işe yaradığını söyleyeceğim:

git checkout master             # if not in master already

git branch placeholder          # create placeholder branch
git checkout placeholder        # checkout to placeholder
git push remote placeholder     # push placeholder to remote repository

git branch -d master            # remove master in local repository
git push remote :master         # remove master from remote repository.

İşin püf noktası, uzak depoya göndermeden hemen önce yer tutucuyu kontrol etmektir. Gerisi kendiliğinden açıklayıcıdır, ana dalı silip uzak depoya itmek şimdi çalışmalıdır. Excerpted burada .


Git push remote: master öğesinde bu uzak tarafta işaretlenirse başarısız olur - hata günlüğü satırlarında önek olarak "remote: error:" ifadesini görürsünüz.
rafalmag

2

İyi. Benim 2 sentim. Sunucuda oturum açma, git dizinine gitme ve çıplak depodaki dalı yeniden adlandırma hakkında. Bu, aynı dalı yeniden yükleme ile ilgili tüm sorunlara sahip değildir. Aslında, 'istemciler' değiştirilen adı otomatik olarak tanır ve uzaktan referanslarını değiştirir. Daha sonra (veya daha önce) şubenin yerel adını da değiştirebilirsiniz.


8
Github sunucusunda oturum açmak için kimlik bilgilerini unuttum. Orada kimlik bilgileri olan herkes :-P
Daniel Fisher lennybacon

1

Ne dersin:

git checkout old-branch-name
git push remote-name new-branch-name
git push remote-name :old-branch-name
git branch -m new-branch-name

şube takibi ile uğraşmak - kullanıcılar şubelerini yerel olarak düzeltmek zorunda kalabilir mi?
dnozay

1

Bu bildiğim en basit ve en 'okunabilir' yol:

-M kullanarak yerel dalı 'taşı'

git branch -m my_old_branch_name my_new_branch_name

'Taşınan' dalı uzaktan kumandaya itin, -u tuşunu kullanarak 'yukarı akış' ayarını yapın

git push origin -u my_new_branch_name

('yukarı akış' ayarı, yerel şubenizi uzaktan kumandaya 'bağlar', böylece getirme, çekme ve itme gibi şeyler çalışır)

Eski dalı uzaktan kumandadan silme

git push origin -D <old_name>

(yerel şubeniz zaten gitti, çünkü 1. adımda 'taşıdınız')


1

Tamam , her ikisi de bir şube yeniden adlandırma yerel ve üzerinde uzaktan oldukça kolaydır! ...

Şubede iseniz, kolayca yapabilirsiniz:

git branch -m <branch>

ya da değilse, yapmanız gerekenler:

git branch -m <your_old_branch> <your_new_branch>

Ardından, silme işlemini uzaktan kumandaya şu şekilde itin:

git push origin <your_old_branch>

Şimdi yaptınız, itmeye çalışırken yukarı doğru hata alırsanız, şunları yapın:

git push --set-upstream origin <your_new_branch>

Ayrıca, aşağıdaki adımları gerçek komut satırında göstermek için oluşturuyorum, sadece adımları izleyin ve iyi olacaksınız:

resim açıklamasını buraya girin


0

Aşağıdakileri yapabilirsiniz:

git -m master master-old #rename current master
git checkout -b master   #create a new branch master
git push -f origin master #force push to master

Ancak, diğer insanlar bu depoyu paylaşıyorsa, zorla itme kötü bir fikirdir. Zorla itme, revizyon geçmişlerinin yenisiyle çatışmasına neden olacaktır.


0

İşi yapmak için kabuk komut dosyasına aşağıdakiler kaydedilebilir:

Örneğin:

remote="origin"

if [ "$#" -eq 0 ] # if there are no arguments, just quit
then
    echo "Usage: $0 oldName newName or $0 newName" >&2
    exit 1
elif
    [ "$#" -eq 1 ] # if only one argument is given, rename current branch
then 
    oldBranchName="$(git branch | grep \* | cut -d ' ' -f2)" #save current branch name
    newBranchName=$1
else
    oldBranchName=$1
    newBranchName=$2
fi

git branch -m $oldBranchName $newBranchName

git push $remote :$oldBranchName #delete old branch on remote
git push --set-upstream $remote $newBranchName # add new branch name on remote and track it

Burada varsayılan uzak ad olan "origin" kodunun sabit olduğunu, yapılandırılabilir olması için komut dosyasını genişletebileceğinizi lütfen unutmayın!

Daha sonra bu komut dosyası bash takma adları, git takma adları ile veya örneğin kaynak özel eylemlerinde kullanılabilir.


-1

Ben anahtar bir performans gösterdiğine işaret gerçekleşme olduğuna inanıyoruz çift : yeniden adlandırma masteriçin master-oldve ayrıca master-newüzere master.

Diğer tüm cevaplardan bunu sentezledim:

doublerename master-new master master-old

burada önce doublerenameBash işlevini tanımlamamız gerekir :

# doublerename NEW CURRENT OLD
#   - arguments are branch names
#   - see COMMIT_MESSAGE below
#   - the result is pushed to origin, with upstream tracking info updated
doublerename() {
  local NEW=$1
  local CUR=$2
  local OLD=$3
  local COMMIT_MESSAGE="Double rename: $NEW -> $CUR -> $OLD.

This commit replaces the contents of '$CUR' with the contents of '$NEW'.
The old contents of '$CUR' now lives in '$OLD'.
The name '$NEW' will be deleted.

This way the public history of '$CUR' is not rewritten and clients do not have
to perform a Rebase Recovery.
"

  git branch --move $CUR $OLD
  git branch --move $NEW $CUR

  git checkout $CUR
  git merge -s ours $OLD -m $COMMIT_MESSAGE

  git push --set-upstream --atomic origin $OLD $CUR :$NEW
}

Bu, git rebaseşube içeriğinin oldukça farklı olması nedeniyle geçmişin değişmesine benzer , ancak istemcilerin hala hızlı bir şekilde güvenli bir şekilde ilerlemelerinden farklıdır git pull master.


-5
git update-ref newref oldref
git update-ref -d oldref newref

2
Bu benim için çalışmıyor gibi görünüyor, alıyorum: git update-ref trunk trunk2 ölümcül: trunk2: geçerli bir SHA1
Gregg Lind
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.