Отримайте конкретну комісію з віддаленого сховища Git


189

Чи є спосіб отримати лише один конкретний фільтр із віддаленого репортажу Git, не клонувавши його на моєму ПК? Структура віддаленого репо є абсолютно такою ж, як у моєї, і тому конфліктів не буде, але я не маю уявлення, як це зробити, і я не хочу клонувати це величезне сховище.

Я новачок в git, чи є спосіб?


1
Ваш існуючий репо вже є клоном віддаленого чи він зовсім інший?
CharlesB

Ну, репо - це джерело ядра Linux, і його майже все
Varun Chitre

так це клон чи ні?
CharlesB

1
Не зовсім. Вважайте це: Нехай віддалений репо буде на чолі D, а мій - на голові A і відстає від B, C, D. Я хочу об'єднати команду B з одного репо, а C з іншого і D з іншого - так само, як B, C, D зобов’язані в цих репостах відрізняються своїми спеціальностями
Varun Chitre

1
@VarunChitre Ви можете прийняти іншу відповідь від VonC?
CharlesB

Відповіді:


109

Починаючи з версії Git 2.5+ (ІІ квартал 2015 р.), Отримання єдиного комітету (без клонування повного репо-репортажу) є фактично можливим.

Див. Комісію 68ee628 від Фредріка Медлі ( moroten) , 21 травня 2015 р.
(Об’єднав Хуніо С Хамано - gitster- у комісії a9d3493 , 01 червня 2015 р.)

Тепер у вас є нова конфігурація (на стороні сервера)

uploadpack.allowReachableSHA1InWant

Дозволити upload-packприймати запит на отримання, який запитує об'єкт, який можна отримати з будь-якого відгуку. Однак зауважте, що обчислення доступності об'єкта обчислювально дорого.
За замовчуванням до false.

Якщо ви поєднаєте цю конфігурацію на сервері з дрібним клоном ( git fetch --depth=1), ви можете попросити провести один комікс (див t/t5516-fetch-push.sh.:

git fetch --depth=1 ../testrepo/.git $SHA1

Ви можете скористатися git cat-fileкомандою, щоб побачити, що комісія була отримана:

git cat-file commit $SHA1

" git upload-pack" що обслуговує " git fetch" може бути запропоновано обслуговувати комітети, які не знаходяться на кінчику жодної посилання, доки вони доступні із списку із uploadpack.allowReachableSHA1InWant змінною конфігурації.


Повна документація:

upload-pack: необов'язково дозволити отримання доступного sha1

Якщо uploadpack.allowReachableSHA1InWantпараметр конфігурації встановлений на стороні сервера, " git fetch" може зробити запит у рядку "хочу", який називає об'єкт, який не був рекламований (ймовірно, був отриманий поза діапазону або з підмодуля вказівника).
Обробляються лише об'єкти, доступні за підказками гілок, тобто об'єднання рекламованих гілок та гілок, прихованих від transfer.hideRefsних.
Зауважте, що пов’язана ціна з необхідністю повернутися назад по історії, щоб перевірити доступність.

Ця функція може бути використана при отриманні вмісту певної комісії, для якої відомий sha1, без необхідності клонування всього сховища, особливо якщо використовується неглибокий збір .

Корисні випадки, наприклад

  • сховища, що містять великі файли в історії,
  • отримання лише необхідних даних для замовлення підмодуля,
  • коли ви ділитесь sha1, не повідомляючи, якій саме гілці він належить та в Gerrit, якщо ви думаєте з точки зору комітів замість зміни чисел.
    (Випадок Геррі вже вирішений, allowTipSHA1InWantоскільки кожна зміна Герріта має посилання)

Git 2.6 (Q3 2015) покращить цю модель.
Див. Команду 2bc31d1 , фіксувати cc118a6 (28 липня 2015 р.) Джеффа Кінга ( peff) .
(Об’єднав Хуніо С Хамано - gitster- у комітеті 824a0be , 19 серпня 2015 р.)

refs: підтримка негативна transfer.hideRefs

Якщо ви приховали ієрархію refs за допомогою transfer.hideRefsconfig, не існує можливості згодом змінити цей конфігурацію, щоб "приховати" його.
Цей патч реалізує "негативне" приховування, яке спричиняє негайне позначення матчів як невідомі, навіть якщо інша відповідність ховала б його.
Ми дбаємо про те, щоб застосувати сірники в зворотному порядку, від того, як вони подаються нам на конфігураційній техніці, оскільки це дозволяє нашому звичайному роботі пріоритету конфігурації "останній виграш" (а записи .git/config, наприклад, переважатимуть /etc/gitconfig).

Тепер ви можете робити:

git config --system transfer.hideRefs refs/secret
git config transfer.hideRefs '!refs/secret/not-so-secret'

щоб приховати refs/secretвсі репости, за винятком одного публічного біта в одному конкретному репо.


Git 2.7 (листопад / грудень 2015 року) знову покращиться:

Див. Виконувати 948bfa2 , фіксувати 00b293e (05 листопада 2015 р.), Здійснювати 78a766a , вчиняти 92cab49 , вчиняти 92cab49 , вчиняти 92cab49 (03 листопада 2015 р.), Здійснювати 00b293e , вчиняти 00b293e (05 листопада 2015 р.) Та виконувати 92cab49 , вчиняти 92cab49 , вчиняти 92cab49 , виконувати 92cab49 (03 листопада 2015 р.) Лукас Флейшер ( lfos) .
Допоможи: Ерік Саншайн ( sunshineco) .
(Об'єднав Джефф Кінг - peff- у комітеті dbba85e , 20 листопада 2015 р.)

config.txt: документуйте семантику hideRefsпросторів імен

Наразі немає чіткого визначення того, як transfer.hideRefsслід вести себе при встановленні простору імен.
Поясніть, що hideRefsпрефікси збігаються з викресленими іменами в цьому випадку. Ось так hideRefsобробляються шаблони в отриманому пакеті.

hidRefs: додайте підтримку для відповідності повних посилань

Окрім відповідності позбавленим рефлексу, тепер можна додати hideRefsшаблони, проти яких повна (нерозгалужена) відповідність.
Для того, щоб розрізняти стриптовані та повні збіги, ці нові візерунки повинні бути встановлені за допомогою контуру ( ^).

Звідси нова документація :

transfer.hideRefs:

Якщо використовується простір імен, префікс простору імен знімається з кожного посилання перед тим, як він буде узгоджений з transfer.hiderefsшаблонами.
Наприклад, якщо refs/heads/masterвказано в transfer.hideRefsі поточний простір імен foo, а потім refs/namespaces/foo/refs/heads/master опускається від реклами , але refs/heads/masterі refs/namespaces/bar/refs/heads/masterпо - , як і раніше рекламували в якості так званих «мати» лінії.
Щоб відповідати рефлексу перед знімком, додайте ^перед назвою посилання. Якщо ви комбінуєте !і ^, !потрібно вказати спочатку.


R .. в коментарях згадує конфігурацію uploadpack.allowAnySHA1InWant, яка дозволяє upload-packприйняти fetchзапит, який взагалі запитує будь-який об’єкт. (За замовчуванням false).

Див. Комісію f8edeaa (листопад 2016, Git v2.11.1) від Девіда "novalis" Тернера ( novalis) :

upload-pack: необов'язково дозволити отримання будь-якого ша1

Здається, трохи нерозумно перевірити реабілітаційність у випадку, коли ми довіряємо користувачеві отримати доступ до абсолютно всього репозиторію.

Крім того, це сильно поширюється в розподіленій системі - можливо, один сервер рекламує відмову, але з тих пір інший силовий поштовх до цього списку, і, можливо, два запити HTTP спрямовуються на ці різні сервери.


4
Чи можете ви навести більш повний приклад того, як створити клон repo за допомогою цього єдиного комітету? Я спробував, але не вдалося .. Дякую!
Ларс Більке

1
Я хочу натиснути на GitHub. Можливо, вони цього не дозволяють.
Ларс Більке,

2
@LarsBilke ми говоримо про клонування або тягнення сюди, а не натискання. І я впевнений, що GitHub ще не має Git 2.5 на стороні сервера.
VonC

2
Тепер ще краще, що uploadpack.allowAnySHA1InWantбез штрафу за доступність-обчислення (і вектора DoS) немає.
R .. GitHub СТОП ДОПОМОГАЙТЕ

1
Дякую! Мені здається смішним, що вони описують це як «довіряти користувачеві доступ», а не «довіряють авторам репо не наштовхуватися на випадкові лайно, які вони не збираються оприлюднювати».
R .. GitHub ЗАСТАНОВИТИ ДІЯ

98

Ви клонуєте лише один раз, тому якщо у вас вже є клон віддаленого сховища, витягнення з нього не завантажуватиме все знову. Просто вкажіть, яку галузь ви хочете витягнути, або отримайте зміни та оформить бажане зобов’язання.

Витяг з нового сховища є дуже дешевим у пропускній здатності, оскільки він завантажує лише ті зміни, яких у вас немає. Подумайте з точки зору того, як Git робить правильну справу, з мінімальним навантаженням.

Git зберігає все в .gitпапці. Здійснення комітету неможливо отримати та зберігати ізольовано, воно потребує всіх своїх предків. Вони взаємопов'язані .


Однак, щоб зменшити розмір завантаження, ви можете попросити git отримати лише об'єкти, пов’язані з певною гілкою або виконувати:

git fetch origin refs/heads/branch:refs/remotes/origin/branch

При цьому завантажуватимуться лише комісії, що містяться у віддаленій гілці branch (і лише ті, які вам не вистачає) , і зберігатимуться в них origin/branch. Потім ви можете злитися або замовити.

Ви також можете вказати лише комісію SHA1:

git fetch origin 96de5297df870:refs/remotes/origin/foo-commit

Це завантажить лише команду зазначеної SHA-1 96de5297df870 (та її предків, які ви сумуєте), і збережіть її як (неіснуючу) віддалену гілку origin/foo-commit.


3
Схоже, ти робиш плутанину щодо того, що означає клон. Коли ви отримуєте зміни з віддаленого репо, ви не клонуєте їх, ви просто отримуєте комітети у своїй історії. Тоді ви вибираєте, яку
комісію

1
Він все ще завантажує багато даних (430mb) за допомогою git fetch. Необхідна комісія - всього кілька кілограмів. Немає спеціальної команди, щоб це зробити насправді? А що робити, якщо я хочу видалити репо "git fetched"? де він зберігається?
Varun Chitre

9
Зараз це досить застаріло. У нас є здатність виконувати дрібний клон , а також отримати єдиний коміт . Неглибоким клонам тепер дозволено нормально підштовхувати та отримувати, не знаючи всієї історії проекту, тому не можна коректно говорити, що комісія не може існувати одна без своїх предків. Те, що ви говорите про отримання після початкового клонування, дуже вірно, але у нас є ще дешевші варіанти.
Теодор Мердок

6
Остання команда (використовуючи команду SHA1) не працює для мене. Команда мовчки робить "щось" деякий час, а потім виходить без жодних повідомлень чи явних побічних ефектів.
HRJ

1
@HRJ Так, я зіткнувся і з цим на Ubuntu 16.04 з Git 2.7.4-0ubuntu1.3. Однак при використанні 2.16.2-0ppa1~ubuntu16.04.1з git-core PPA це працює як слід. Звучить помилка, яку виправили. Не вдалося знайти посилання на це при швидкому пошуку. Якщо хтось може отримати мені вказівник на це, я б хотів отримати підтримку цього виправлення.
gertvdijk

62

Я потягнув за собою git repo:

git pull --rebase <repo> <branch>

Дозвіл git втягнути весь код для гілки, і тоді я пішов зробити скидання на комітет, який мене зацікавив.

git reset --hard <commit-hash>

Сподіваюся, це допомагає.


1
Жодна з відповідей не спрацювала, однак ця врятувала мені життя! Дякую купу!
michaeltintiuc

Скидання - твердий працював на мене після клонування! Дякую.
Нік-АСНБ

3
-1: "деструктивні" команди, такі як git reset --hard, коли вони діляться в узагальнених рішеннях, можуть привести людей у ​​пастки, де вони втрачають дані (або, у цьому випадку: у стан, коли повернення їх даних нетривіально).
yaauie

54

Ви можете просто отримати одне фіксування віддаленого репо

git fetch <repo> <commit>

де,

  • <repo>може бути віддалене ім’я репо (наприклад origin) або навіть віддалене URL репо (наприклад https://git.foo.com/myrepo.git)
  • <commit> може бути комітом SHA1

наприклад

git fetch https://git.foo.com/myrepo.git 0a071603d87e0b89738599c160583a19a6d95545

після того, як ви взяли коміт (і зниклих предків), ви можете їх просто оформити

git checkout FETCH_HEAD

Зауважте, що це приведе вас у стан "відстороненої голови".


10
Коли я намагаюся на fetchпевному обороті, як у вас там, git не спрацьовує з кодом помилки 1 і відсутністю виводу. Це було щось, що раніше працювало в попередніх версіях? (Я v2.0.2.)
Джек О'Коннор

2
Редагувати: Це спрацьовує, якщо у мене вже є те, що здійснюють локально, як, якщо я вже зробив повне fetch, хоча в такому випадку я не впевнений, в чому користь.
Джек О'Коннор

2
Дійсно, це теж не працює для мене з git 2.0.2. :(
Потік

2
git checkout FETCH_HEADдопомагає.
lzl124631x

1
Цей метод не працюватиме з дрібним вилученням (наприклад --depth=1)!
королівство

16

Ви можете просто отримати віддалене репо за допомогою:

git fetch <repo>

де,

  • <repo>може бути віддалене ім’я репо (наприклад origin) або навіть віддалене URL репо (наприклад https://git.foo.com/myrepo.git)

наприклад:

git fetch https://git.foo.com/myrepo.git 

після того, як ви отримали репост, ви можете об'єднати потрібні вами зобов’язання (оскільки питання стосується отримання однієї комісії, замість злиття ви можете використати вишневий вибір, щоб вибрати лише одну комісію):

git merge <commit>
  • <commit> може бути комітом SHA1

наприклад:

git cherry-pick 0a071603d87e0b89738599c160583a19a6d95545

або

git merge 0a071603d87e0b89738599c160583a19a6d95545

якщо це остання комісія, яку потрібно об'єднати, ви також можете використовувати змінну FETCH_HEAD:

git cherry-pick (or merge) FETCH_HEAD

Для цього потрібна настройка облікового запису Git на машині. Він не працює під тестовим рахунком. У вас є щось, що працює під тестовим рахунком?
jww

що ти маєш на увазі ? ви не можете зробити git fetch?
Серхіо

Еммм , тому команда буде git config set uploadpack.allowReachableSHA1InWant ?
Олександр Міллз

2

Це найкраще працює:

git fetch origin specific_commit
git checkout -b temp FETCH_HEAD

назвіть "темп" що завгодно ... хоча ця гілка може бути сиротою


Ясно НЕ зі старими версіями git, такими як 1.8.x
sorin

1

Нарешті я знайшов спосіб клонувати конкретні фішки за допомогою git cherry-pick . Якщо припустити, що у вас немає локального сховища, і ви віддаляєте певну комісію з віддаленого місця,

1) створити порожнє сховище в локальному і git init

2) git remote add origin " url-of-repository "

3) походження git fetch [це не перемістить ваші файли до локальної робочої області, якщо ви не злиєтесь]

4) git cherry-pick " Enter-long-commit-hash-that-you need "

Готово. Таким чином, у вас будуть лише файли з цього конкретного комітету у вашому локальному регіоні.

Введіть-хеш-хеш:

Ви можете отримати це за допомогою -> git log --pretty = oneline



0

Якщо запитується фіксація знаходиться в запитах на вилучення віддаленого репо, ви можете отримати його за його ідентифікатором:

# Add the remote repo path, let's call it 'upstream':
git remote add upstream https://github.com/repo/project.git

# checkout the pull ID, for example ID '60':
git fetch upstream pull/60/head && git checkout FETCH_HEAD
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.