Git deposunu belirli bir revizyon / changeet ile nasıl klonlayabilirim?


393

Git deposunu belirli bir revizyonla nasıl kopyalayabilirim, genellikle Mercurial'ta yaptığım gibi:

hg clone -r 3 /path/to/repository

3
Değişiklik kümeleri veya revizyonlara özgü değil, ancak belirli bir dalda en son klonlamak etkili olabilir yani git clone -b 10.1 https://github.com/MariaDB/server.git --depth=1 mariadb-server-src
MrMesees


Tarihin sığ olmasını mı istiyorsunuz, yani örneğin yalnızca revizyon 3'ü mi yoksa ebeveynlerini mi?
sschuberth

Söz konusu havuz başka bir havuzun içinden klonlanıyorsa ve bu dahili repoyu belirli bir sha'da klonlamak istiyorsanız, git alt modülleri bunu tam olarak otomajik bir şekilde yapar.
J0hnG4lt

Yanıtlar:


202

GÜNCELLEME 2 Git 2.5.0'dan beri aşağıda açıklanan özellik konfigürasyon değişkeni ile sunucu tarafında etkinleştirilebilir uploadpack.allowReachableSHA1InWant, burada GitHub özellik isteği ve GitHub bu özelliği etkinleştirmeyi taahhüt eder . Bazı Git sunucularının varsayılan olarak bu seçeneği etkinleştirdiğini unutmayın, örneğin Bitbucket Sunucusu 5.5+ sürümünden beri etkinleştirmiştir . Yapılandırma seçeneğinin nasıl etkinleştirileceğine dair bir örnek için Stackexchange'teki bu cevaba bakınız .

GÜNCELLEME 1 Git sürümleri 1.7 < v < 2.5için Vaibhav Bajpai'nin cevabında açıklandığı gibi git clone ve git reset komutunu kullanın

Deponun tamamını almak istemiyorsanız, muhtemelen kullanmamalısınız clone. Getirmek istediğiniz dalı seçmek için her zaman getir komutunu kullanabilirsiniz. Ben bir hg uzmanı değilim bu yüzden detaylarını bilmiyorum -rama git gibi böyle bir şey yapabilirsiniz.

# make a new blank repository in the current directory
git init

# add a remote
git remote add origin url://to/source/repository

# fetch a commit (or branch or tag) of interest
# Note: the full history up to this commit will be retrieved unless 
#       you limit it with '--depth=...' or '--shallow-since=...'
git fetch origin <sha1-of-commit-of-interest>

# reset this repository's master branch to the commit of interest
git reset --hard FETCH_HEAD

32
Bence işe yaramaz git fetch origin <sha1>; etiket veya şube adı gibi adlandırılmış bir referans iletmeniz gerekiyor gibi görünüyor. Bkz. Kerneltrap.org/mailarchive/git/2009/1/13/4707444
artur

48
@artur: İşe yaradığını düşünmüyorsunuz, ya da denediniz ve çalışmıyor mu?
CB Bailey

37
Git 1.4 ile, git fetch origin <SHA1>uzaktan kumandadan ustayı getirdikten reset --hardve şubeyi yerel olarak gerçekleştirmek için yaptıktan sonra istediğim herhangi bir revizyona geçmek için kullanabildiğimi buldum . Bireysel düzeltmeleri doğrudan getiremedim. Git 1.7 ile, git fetch origin <SHA1>@artur tarafından bildirildiği gibi çalışmadı; kullanmanız ve git checkout <SHA1>ardından a reset --hard.
Joe McMahon

6
SHA-1 tarafından getirilmesi yalnızca http ve rsync protokolleriyle çalışır. Bkz. Kerneltrap.org/mailarchive/git/2009/1/14/4716044/…
CharlesB

23
Bu cevap eski. Bu ne git 1.7 ne de git 1.8, ne https: // ne de ssh protokolü ile çalışmaz. ("Uzaktan ref df44398762393c67af487edeb0831ad9579df4aa bulunamadı" - bu bir ref değil, bu bir taahhüttür.)
Paŭlo Ebermann

839
$ git clone $URL
$ cd $PROJECT_NAME
$ git reset --hard $SHA1

Tekrar en son işleme geri dönmek için

$ git pull

13
Bu yalnızca taahhüt ana daldaysa çalışır, eğer değilse yerel referansı bozar. Neden git reset ve ilk başta git checkout değil?
Şaka

72
Bu, her şeyi çektiği için büyük depolar için iyi bir seçenek değildir.
Gizli

1
Bu çözüm en üstte olmalıdır. Kimse bunun "optimal değil" umurunda değil, OP'nin istediği bu. Özellikle: "Git deposunu belirli bir düzeltme ile nasıl klonlayabilirim"?
Florian Segginger

20
@FlorianSegginger Belirli bir revizyonu klonlamak istiyorsam, muhtemelen her şeyi klonlamak istemiyorum, ama sadece bu revizyon. Bana sorulan soru buydu. Bu çözüm farklı bir soruyu yanıtlıyor: "Repo'mdaki belirli bir düzeltmeyi nasıl görüntülerim?". Tüm repoyu getirmek, burada birçok insanın kaçınmak istediği şey.
Renato

1
Gerçek soru IMHO'ya cevap vermez, çünkü klon sırasında bir revizyon belirleyebilmem de --depthbüyük depolar için çok önemli olan kullanmamı sağlar . Bu çözüm, tüm nesnelerin çekilmesini ve ardından daha önceki bir revizyona sıfırlanmasını gerektirir. Bu çok zaman alıcı ve ağ bant genişliğini boşa harcıyor.
void.pointer

54

Bir git deposunu klonlamak, uygun bir şekilde tüm deposu klonlar: klonlamak için yalnızca bir düzeltme seçmenin bir yolu yoktur. Ancak, bir kez gerçekleştirdiğinizde git clone, belirli bir düzeltmeyi yaparak yapabilirsiniz checkout <rev>.


4
Sadece bir revizyonu klonlamak istemiyorum. Sadece klonlama sınırını belirtmek istiyorum. Başka bir deyişle, belirtilen revizyona kadar her şeyi klonlamak istiyorum.
John

6
Bunu yapamazsın. git clonetüm depoyu kapar. Elinize geçtikten sonra, belirli bir düzeltmeyi kontrol edebilirsiniz.

4
Dikkat edilmesi gereken bir şey; Git genellikle geçmişi saklama konusunda oldukça verimlidir, bu yüzden revizyonların sadece yarısını klonlayarak büyük miktarda alandan tasarruf edersiniz.
Amber

Bu, "yerden tasarruf etmek" ile ilgili değil - sadece belirli bir revizyona geçmekle ilgili - yeni bir değişiklik bir hata getirdiğinde olduğu gibi, ve bu yeni değişikliği istemiyorum - Git'in yapamayacağını söylüyorsunuz bu? Bu doğru olamaz - eski bir sürüme geri dönemezseniz neden kaynak kontrolünüz olsun?
BrainSlugs83

1
"klonlamak için sadece bir revizyon seçmek için bir yol yok" - evet, var:git clone --single-branch ...
morxa

33

Belirli bir dalda veya etikette yalnızca tek bir belirli taahhüdü klonlamak için :

git clone --depth=1 --branch NAME https://github.com/your/repo.git

Ne yazık ki, NAMEyalnızca şube adı veya etiket adı olabilir (SHA taahhüt edilemez).

--depthGeçmişin tamamını indirmek için bayrağı atlayın ve ardından o dal veya etiketi kontrol edin:

git clone --branch NAME https://github.com/your/repo.git

Bu git son sürümü ile çalışır (Ben sürüm ile yaptım 2.18.0).


ama eski versiyonda değil 2.17.1
RzR

4
Bunun için daha fazla oy gerekiyor. Bu, diğer eski cevaplardan çok daha iyi.
Étienne

32

Başından belirli bir noktaya kadar her şeyi almak istediğinizi söylüyorsanız, Charles Bailey'in cevabı mükemmeldir. Tersi yapmak ve geçerli tarihten itibaren geçmişin bir alt kümesini almak istiyorsanız, git clone --depth [N] N'yi istediğiniz tarihin devir sayısı olarak kullanabilirsiniz . Ancak:

--depth

Belirtilen revizyon sayısına kesilmiş bir geçmişe sahip sığ bir klon oluşturun. Sığ bir havuzun birtakım sınırlamaları vardır (ondan klonlayamaz veya getiremez, ne de ne de içine itemezsiniz), ancak yalnızca uzun bir geçmişi olan büyük bir projenin yakın geçmişiyle ilgileniyorsanız ve düzeltmeleri yama olarak gönder.


4
Git'in yeni sürümünde geliştirilmiş sığ klonlar var ve ondan çekip itebilirsiniz.
orion78fr

26

Sadece bir şeyleri özetlemek için (git - 1.7.2.1):

  1. git cloneRepoyu istediğiniz yerde düzenli yapın (her şeyi bugüne kadar alır - biliyorum, ne istersen değil, oraya gidiyoruz)
  2. git checkout <sha1 rev> istediğin devrin
  3. git reset --hard
  4. git checkout -b master

6
3. ve 4. adımlar ne işe yarar?
BrainSlugs83

Adım 4 benim için çalışmadı, ancak adım 3'e kadar hile yaptı - Teşekkürler
Gene Bo

@ BrainSlugs83: Adım 4 adlı yerel bir dal oluşturur masterve buna geçiş yapar.
LarsH

3
@phill: Neden git reset --hard? Bunun için dokümanlar "Dizini ve çalışma ağacını sıfırlar. <commit> [şu anda varsayılan olarak HEAD olan varsayılan] olan çalışma ağacında izlenen dosyalarda yapılan değişiklikler <sha1 rev>atılır." Ancak bu noktada klonlamadan bu yana herhangi bir değişiklik yapmadık, amacı nedir? Şu andaki dalı kesiyor mu <sha1 rev>?
LarsH

19

TL; DR - Kaynak deposunda klonlamak istediğiniz işleme karşı bir etiket oluşturun ve etiketi getir komutunda kullanın. Temizlemek için etiketi daha sonra orijinal depodan silebilirsiniz.

Peki, 2014 ve Charles Bailey'nin 2010'dan kabul edilen cevabı şimdiye kadar iyi ve gerçekten modası geçmiş gibi görünüyor ve diğer cevapların çoğu (hepsi?) Birçok insanın kaçınmayı umduğu klonlamayı içeriyor.

Aşağıdaki çözüm, OP ve diğerlerinin aradıklarını başarır, bu da tarih de dahil olmak üzere bir havuzun kopyasını oluşturmanın bir yoludur, ancak yalnızca belirli bir taahhüde kadar.

Git sürüm 2.1.2 ile belirli bir noktaya kadar yerel bir repoyu (başka bir dizindeki bir havuzu) klonlamak için kullandığım komutlar şunlardır:

# in the source repository, create a tag against the commit you want to check out
git tag -m "Temporary tag" tmptag <sha1>

# create a new directory and change into that directory
cd somewhere_else;mkdir newdir;cd newdir

# ...and create a new repository
git init

# add the source repository as a remote (this can be a URL or a directory)
git remote add origin /path/to/original/repo

# fetch the tag, which will include the entire repo and history up to that point
git fetch origin refs/tags/tmptag

# reset the head of the repository
git reset --hard FETCH_HEAD

# you can now change back to the original repository and remove the temporary tag
cd original_repo
git tag -d tmptag

Umarım bu çözüm birkaç yıl daha çalışmaya devam eder! :-)


2
Bu, repo sahibisiniz, bakmadığınız genel depolarla çalışıp çalışmadığından emin değilsiniz
Suhaib

18

Basitçe kullanabilirsiniz git checkout <commit hash>

bu sırayla

bash git clone [URLTORepository] git checkout [commithash]

kesin karma şöyle "45ef55ac20ce2389c9180658fdba35f4a663d204"


önceki gibi - neden klonladıktan sonra ödeme. Klonladıktan sonra, yerel repodaki tüm geçmişe sahip olursunuz. Neden bu cevabın çok fazla oyu var?
Dmitry Perfilyev

2

Yukarıdaki cevaplardan 2 tanesini kullanmak ( Git deposunu belirli bir revizyon / changeet ile klonlama ?) Ve Git deposunu belirli bir revizyon / changeet ile klonlama? ) Bir noktaya kadar klonlamak istiyorsanız, o nokta sadece bir SHA değil, bir etiket / dal olmak zorundadır veya FETCH_HEAD'ın kafası karışır. Git getirme kümesinin ardından, bir dal veya etiket adı kullanırsanız yanıt alırsınız, yalnızca bir SHA-1 kullanırsanız yanıt alamazsınız.
İşte yaptığım şey: - asıl kökeninden tam repo'nun tam çalışan bir klonunu oluşturmak

cd <path to create repo>
git clone git@<our gitlab server>:ui-developers/ui.git 

Sonra ilginç bir noktada yerel bir şube oluşturun

git checkout 2050c8829c67f04b0db81e6247bb589c950afb14
git checkout -b origin_point

Daha sonra yerel kopyamın kaynağı olarak yeni bir boş repo oluştur

cd <path to create repo>
mkdir reduced-repo
cd reduced-repo
git init
git remote add local_copy <path to create repo>/ui
git fetch local_copy origin_point

O noktada bu yanıtı aldım. Bunu not ediyorum, çünkü yukarıdaki dal yerine bir SHA-1 kullanırsanız, hiçbir şey olmuyor, bu nedenle yanıt

/ var / www / html / ui-hacking $ git fetch local_copy origin_point
uzak: Nesneleri saymak: 45493, bitti.
uzak: Nesneleri sıkıştırma:% 100 (15928/15928), bitti.
uzak: Toplam 45493 (delta 27508), yeniden kullanılan 45387 (delta 27463)
Nesneleri alma:% 100 (45493/45493), 53,64 MiB | 50.59 MiB / s, bitti.
Çözülen deltalar:% 100 (27508/27508), yapıldı.
/ Var / www / html / ui dizininden
 * şube orijin noktası -> FETCH_HEAD
 * [yeni şube] origin_point -> origin / origin_point

Şimdi benim durumumda, daha sonra yeni bir repo olarak gitlab üzerine koymam gerekiyordu.

git remote add origin git@<our gitlab server>:ui-developers/new-ui.git

Bu git --git-dir=../ui/.git format-patch -k -1 --stdout <sha1> | git am -3 -kda kiraz seçimini uzaktan kullanarak sonra repo benim origin_point yeniden inşa anlamına geliyordugit push origin yeni evine geri yüklemek için .

Birisine yardımcı olan umarım


"FETCH_HEAD karıştı" ile ne demek istediğinizi açıklayabilir misiniz? Peki sizin git fetch local_copy origin_pointJamesG'lerinizden farkı nedir git fetch origin refs/tags/tmptag?
not2qubit

git fetch local_copy origin_pointBoş bir halde bırakmak reduced-reposadece içeren dizine .git. Bu talimatlarda eksik başka bir şey var ...
not2qubit

2

Benim versiyonum kabul edilen ve en çok oylanan cevapların bir kombinasyonuydu. Ama bu biraz farklı, çünkü herkes SHA1 kullanıyor ama kimse size nasıl alacağınızı söylemiyor

$ git init
$ git remote add <remote_url>
$ git fetch --all

şimdi tüm şubeleri ve taahhütleri görebilirsiniz

$ git branch -a
$ git log remotes/origin/master <-- or any other branch

Sonunda istenen taahhüdün SHA1'ini biliyorsunuz

git reset --hard <sha1>

1

Bu snippet'i herhangi bir revizyon etiketini, dalı veya karmayı kapatmak için GNU make ile kullanıyorum

git sürüm 2.17.1'de test edildi

${dir}:
    mkdir -p ${@D}
    git clone --recursive --depth 1 --branch ${revison} ${url} ${@} \
 || git clone --recursive --branch ${revison} ${url} ${@} \
 || git clone ${url} ${@}
    cd ${@} && git reset --hard ${revison}
    ls $@





0

git clone https://github.com/ORGANIZATION/repository.git (depoyu klonlayın)

cd repository (navigate to the repository)

git fetch origin 2600f4f928773d79164964137d514b85400b09b2

git checkout FETCH_HEAD


2
klonladıktan sonra neden getireyim. Klonladıktan sonra, yerel repodaki tüm geçmişe sahip olursunuz. Bu cevapta neden iki oy var?
madhairsilence

0
# clone special tag/branch without history
git clone  --branch=<tag/branch> --depth=1 <repository>


# clone special revision with minimal histories
git clone --branch <branch> <repository> --shallow-since=yyyy-MM-ddTHH:mm:ss  # get the commit time
cd <dir>
git reset --hard <revision> 

uploadpack.allowReachableSHA1InWant=truesunucu tarafında ayarlanmadıysa geçmiş olmadan revizyon alamazsınız, bunun için bir etiket oluşturabilir ve bunun yerine özel etiketi kopyalayabilirsiniz.


-3

Basit. Geçerli dal için yukarı akış ayarlamanız yeterlidir

$ git clone repo
$ git checkout -b newbranch
$ git branch --set-upstream-to=origin/branch newbranch
$ git pull

Bu kadar


-4
git clone -o <sha1-of-the-commit> <repository-url> <local-dir-name>

gitkelimeyi originpopüler olarak bilinenlerin yerine kullanırrevision

Aşağıdaki kılavuzdan bir pasaj $ git help clone

--origin <name>, -o <name>
    Instead of using the remote name origin to keep track of the upstream repository, use <name>.

4
Burada neden indirildiğine dair bir fikrim yok; benim kullanım durumum için tam olarak görmeyi umduğum şey buydu: Linux çekirdeğinin belirli bir sürümünü bir sürümden almak, bir sürüm olarak etiketlemek için iyi bir anlama sahip değildi (RPi insanlarıyla ilgili bir sorun gibi görünüyor), Linux'un tüm çok gigabaytlık geçmişini indirme. Bu arada, bir tedavi çalıştı.
Fordi

1
--depth=1yanıtta bahsedilmiyorsa, neden burada belirtilmeyen başka şeyler eklediyseniz neden bu cevabın işe yaradığını söylüyorsunuz? Sizin için çalıştığı için mutluyum, ancak bu cevap yanıltıcı ve kısmen de olsa soruyu cevaplamıyor. Bu yüzden aşağı oylar.
Emil Styrke

5
@Fordi: Bu yanıtı kullanma sayılı kelimesi kelimesine size alır tam bir vanilya alacağındançok aynı ağaç git clone <url> <local_dir_name>sadece kendiniz deneyin. Tek fark, uzaktan kumandanın (kullanılarak gösteriliyor git remote) alışılmış "orijin" adı yerine bazı şifreli sha1 sekansı olarak adlandırılacağıdır. Başka bir deyişle, <sha1-of-the-commit>bu yanıtta belirtilen , hangi revizyonların sunucudan getirildiği veya hangi şubenin teslim alınacağı konusunda hiçbir etkisi yoktur.
Emil Styrke

6
@Fordi: Az önce yaptım git clone -o 896066ee1cf4d653057dac4e952f49c96ad16fa7 https://github.com/torvalds/linux.git linux --depth=1. Bu bana revizyon verir 8a28d674ve değil 896066ee siz ve bu cevap iddiaları gibi.
Emil Styrke

4
"köken" in "revizyon" ile ilgisi olmadığını ve bu cevabın tamamen yanlış olduğunu vurgulamak.
Eevee
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.