Git'te, bir havuza ilgisiz bir dal eklemenin basit bir yolu var mı?


328

Bugün git problemi olan bir arkadaşa yardım ederken, daldan tamamen ayrı olması gereken bir dal tanıtmak zorunda kaldım master. Bu dalın içeriği, dalda geliştirilenden gerçekten farklı bir kökene sahipti master, ancak masterdaha sonra dalda birleştirileceklerdi .

John Wiegley'nin Git'i aşağıdan yukarıya doğru, dalların aslında belirli bir konvansiyonu takip eden bir taahhüde nasıl bir etiket olduğunu ve bir taahhüdün bir dosya ağacına ve isteğe bağlı olarak üst taahhütlere nasıl bağlandığını hatırladım . Git'in tesisatını kullanarak mevcut depoya ebeveynsiz bir taahhüt oluşturmaya gittik:

Dizin içindeki tüm dosyalardan kurtulduk ...

$ git rm -rf .

... bir tarball'dan çıkartılan dizinler ve dosyalar, bunları dizine ekledi ...

$ git add .

... ve bir ağaç nesnesi yarattı ...

$ git write-tree

( git-write-treebize oluşturulan ağaç nesnesinin sha1sum'unu anlattı.)

Daha sonra, ebeveyn taahhütlerini belirtmeden ağacı taahhüt ettik ...

$ echo "Imported project foo" | git commit-tree $TREE

( git-commit-treeoluşturulan taahhüt nesnesinin sha1sum'unu anlattı.)

... ve yeni oluşturulan taahhüdümüzü gösteren yeni bir şube oluşturdu.

$ git update-ref refs/heads/other-branch $COMMIT

Sonunda masterorada çalışmaya devam etmek için şubeye döndük .

$ git checkout -f master

Bu planlandığı gibi çalıştı. Ancak bu, git'i kullanmaya yeni başlayan birine hafifçe koymak için tavsiye edeceğim bir prosedür değil. Depoda şu ana kadar olan her şeyle tamamen ilgisiz yeni bir dal yaratmanın daha kolay bir yolu var mı?

Yanıtlar:


510

Yeni bir özellik var (V1.7.2'den beri), bu görevi diğer cevapların hepsinden biraz daha yüksek bir seviyeye getiriyor.

git checkoutartık --orphanseçeneği destekliyor . Gönderen adam sayfası :

git checkout [-q] [-f] [-m] --orphan <new_branch> [<start_point>]

<start_point> 'ten başlayarak <new_branch> adlı yeni bir yetim dalı oluşturun ve bu şubeye geçin. Bu yeni dalda yapılan ilk taahhüdün ebeveynleri olmayacak ve diğer tüm dal ve taahhütlerden tamamen ayrılan yeni bir tarihin kökü olacak.

Bu, tam olarak askerin istediği şeyi yapmaz , çünkü dizini ve çalışma ağacını doldurur <start_point>(çünkü sonuçta bir ödeme komutu). Gerekli olan diğer tek işlem, istenmeyen öğeleri çalışma ağacından ve dizinden kaldırmaktır. Ne yazık ki, git reset --hardişe yaramaz, ancak git rm -rf .bunun yerine kullanılabilir (bunun rm .git/index; git clean -fdxdiğer cevaplarda verilene eşdeğer olduğuna inanıyorum ).


Özetle:

git checkout --orphan newbranch
git rm -rf .
<do work>
git add your files
git commit -m 'Initial commit'

<start_point>Belirtilmemiş bıraktım çünkü varsayılan olarak HEAD'e ayarlandı ve biz gerçekten umursamıyoruz. Bu sıra, korkutucu sıhhi tesisat komutlarına başvurmadan, Artem'in cevabındaki komut sırası ile aynı şeyi yapar .


Diğer "ağaçtan" ​​herhangi bir dalı ödünç aldığınızda görünür kalan bir yetim dalı oluşturmanın mümkün olup olmadığını biliyor musunuz?
JJD

1
@JJD: Bence istediğin git birleştirme. ( git checkout master && git merge --no-commit "orphan-branch" ) Bazı benzer hileler git-reset kullanarak veya dizinle oynatılır. Ancak istediğiniz iş akışına bağlıdır.
phord

@Matthew İşte git 1.7.2 için değişiklik günlüğü .
JJD

@phord Yetimin, projenin kaynak kodundan ayrılmış birim testleri veya belgeler gibi şeyleri içermesini az çok düşündüm.
JJD

2
@JJD: Verdiğim senaryo seni yanlış anlamadıysan sana istediğini vermeli. "Görünür olarak kalır" dediğinde, farklı bir şubeyi işaretlemiş olsanız bile dosyaların çalışma dizininde kalacağı anlamına mı geliyor? Kullanılması --no-commitüzerine git mergebunu başarmak olacaktır. Bir git reset origin/mastersonraki taahhüdünüzün istediğiniz yere gitmesi için bunu izlemeniz gerekebilir, ancak yetim dalınızdaki dosyalar .gitignore dosyanıza da dahil edilmedikçe "izlenmemiş dosyalar" olarak görünecektir.
phord

32

Gönderen Git Topluluk Kitabı :

git symbolic-ref HEAD refs/heads/newbranch 
rm .git/index 
git clean -fdx 
<do work> 
git add your files 
git commit -m 'Initial commit'

1
Bir sonraki cevap git'in modern versiyonları için daha iyidir.
kikito

14
@kikito: Re: "Bir sonraki cevap daha iyi" ... Burada SO'daki sipariş istikrarlı değil. Daha iyi bir yanıt olduğunu düşündüğünüze işaret eden bir bağlantı ekler misiniz?
David J.

2
Stackoverflow.com/a/4288660/312586 adresine başvuruyordum . Haklısın, "sonraki" dememeliydim. Ben yorum yaparken bu cevap daha az puanı vardı.
kikito


Bu "daha önce yoksa şube oluşturmak istiyorum" davası için daha iyi çalışır
max630 13:15

22

Her ne kadar çözümle birlikte git symbolic-refve dizin kaldırma işlemi çalışıyor olsa da, yeni depo oluşturmak kavramsal olarak daha temiz olabilir

$ cd /path/to/unrelated
$ git init
[edit and add files]
$ git add .
$ git commit -m "Initial commit of unrelated"
[master (root-commit) 2a665f6] Initial commit of unrelated
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 foo

sonra getir

$ cd /path/to/repo
$ git fetch /path/to/unrelated master:unrelated-branch
warning: no common commits
remote: Counting objects: 3, done.
Unpacking objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
From /path/to/unrelated
 * [new branch]      master     -> unrelated-branch

Artık / path / to / ilgisiz silebilirsiniz


Benim düşünceme göre, temiz bir kavram git branchveya için bir seçenek içerecektir git checkout. Git'in bu tür şeyleri mümkün kıldığına sevindim, ama neden daha kolay olmasın?
hillu

3
Çünkü bu nadir bir şeydir ve olmalıdır. İlgisiz şeyler şubeniz varsa, mevcut istisnada doldurmak yerine genellikle ilgisiz depoya aittir (istisnalar olmasına rağmen).
Jakub Narębski

1
+1. Git yeni başlayanlar için, görünüşe göre dalları üzerinden listeleyebilir git branchve aralarında geçiş yapabilirsiniz git checkout BRANCH_NAME.
akavel

Bunun için teşekkürler, bunu kendi başıma düşünmezdim. Bu, diğer repo için (varsa) geçmişini koruduğu için çok faydalıdır.
BM5k

13

Github , Github tarafından sunulacak dosyaları sağlamak için projenizde belirli bir adlandırılmış dal oluşturabileceğiniz Proje Sayfaları adlı bir özelliğe sahiptir . Talimatları aşağıdaki gibidir:

$ cd /path/to/fancypants
$ git symbolic-ref HEAD refs/heads/gh-pages
$ rm .git/index
$ git clean -fdx

Buradan sonra yeni içeriğinizi ekleyebileceğiniz boş bir havuzunuz var.


10

Şu anda seçili cevap doğru, ben sadece tesadüfen eklemek istiyorum ...

Aslında github.com, kullanıcıların depoları için Github Sayfaları oluşturmalarına izin verilen bir şube aracılığıyla tam olarak böyle yapmalarını sağlar gh-pages. Güzel adımlar burada verilmiştir ve açıklanmıştır:

https://help.github.com/articles/creating-project-pages-manually

Temel olarak bunu ayarlamak için git komutları aşağıdaki gibidir:

  1. git checkout --orphan gh-pages (repolarınızda gh-sayfaları adı verilen ebeveynsiz bir şube oluşturun)
  2. git rm -rf . (tüm dosyaları şube çalışma ağacından kaldırır)
  3. rm '.gitignore' (gitignore bile)
  4. Şimdi web sitesi içeriği ekleyin (index.html vb. Ekleyin) ve taahhüt edin ve itin.
  5. Kar.

Ayrıca, depodaki bir / docs klasörünü Github'un web sitesini oluşturmak için kullandığı "Proje Sitesi" nin kaynağı olarak atayabilirsiniz .

Bu yardımcı olur umarım!


3

Bazen sadece projede boş şube oluşturmak istiyorum sonra çalışmaya başlıyorum, sadece aşağıdaki komutu kullanacağım:

git checkout --orphan unrelated.branch.name
git rm --cached -r .
echo "init unrelated branch" > README.md
git add README.md
git commit -m "init unrelated branch"

1

Mevcut içeriğiniz zaten işlenmişse, artık (Git 2.18 Q2 2018), yeni uygulamaların "git rebase -i --root " sıralayıcı makinelerini daha fazla kullanmak üzere güncellendi.

Bu sıralayıcı, artık başka yerde taahhüt grafiğinin tüm topolojisinin nakledilmesine izin veren odur .

Bkz. Taahhüt 8fa6eea , taahhüt 9c85a1c , taahhüt ebddf39 , taahhüt 21d0764 , taahhüt d87d48b , taahhüt ba97aea (03 Mayıs 2018), Johannes Schindelin ( dscho) .
(Göre Birleştirilmiş Junio Cı Hamano - gitster- içinde c5aa4bc tamamlama 2018 30 May)

sequencer: yeni root taahhütlerinin kullanılmasına izin ver

--rebase-mergesMevcut şube topolojisini serbestçe değiştirmeye izin vermek için özel olarak tasarlanan yeni mod bağlamında, kullanıcı taahhütleri yeni oluşturulan bir kök taahhüdü ile başlayan tamamen yeni bir şubeye çıkarmak isteyebilir .

Bu artık kök kök haline gelmek isteyen taahhüdü reset [new root]girmeden önce komutun eklenmesi ile mümkün pick. Misal:

reset [new root]
pick 012345 a commit that is about to become a root commit
pick 234567 this commit will have the previous one as parent

Bu, resetkomutun diğer kullanımlarıyla çakışmaz, çünkü [new root]geçerli bir ref adı (parçası değildir): hem açılış parantezleri hem de boşluk ref adlarında geçersizdir.


0

Bu komut dosyasını http://wingolog.org/archives/2008/10/14/merging-in-unrelated-git-branches adresinde buldum ve çok iyi çalışıyor!

#!/bin/bash

set -e

if test -z "$2" -o -n "$3"; then
    echo "usage: $0 REPO BRANCHNAME" >&2
    exit 1
fi

repo=$1
branch=$2

git fetch "$repo" "$branch"

head=$(git rev-parse HEAD)
fetched=$(git rev-parse FETCH_HEAD)
headref=$(git rev-parse --symbolic-full-name HEAD)

git checkout $fetched .

tree=$(git write-tree)

newhead=$(echo "merged in branch '$branch' from $repo" | git commit-tree $tree -p $head -p $fetched)
git update-ref $headref $newhead $head
git reset --hard $headref

1
Aynı etkinin kullanılarak elde edilebileceğine inanıyorum git fetch $REMOTE $REMOTE_BRANCH:$LOCAL_BRANCH. Bir şey mi kaçırıyorum?
hillu
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.