2014-09-12 4 views
5

Я хотел бы получить отдельную фиксацию (с историей, конечно) удаленного репозитория в локальную. Некоторые ответы Переполнение стека свидетельствуют о том, что должно работать, но это не делает:Git fetch a single commit

md foo 
cd foo 
git init 
git fetch https://github.com/ld4apps/lda-serverlib.git f1e32e18a90e10c150221af55c69aeafaa42c57a 

Это производит следующее сообщение об ошибке:

error: no such remote ref f1e32e18a90e10c150221af55c69aeafaa42c57a

Удивительно (для меня) следующих же (вид) работы:

git fetch https://github.com/ld4apps/lda-serverlib.git :f1e32e18a90e10c150221af55c69aeafaa42c57a 

Это создает новую локальную ветку под названием f1e32e18a90e10c150221af55c69aeafaa42c57a (который я не хотел), но, по крайней мере, новый филиал имеет содержание я пытался принести. Я мог бы ожидать, что следующая команда будет делать то же самое, но он получает такую ​​же ошибку, как и в первом примере:

git fetch https://github.com/ld4apps/lda-serverlib.git f1e32e18a90e10c150221af55c69aeafaa42c57a:f1e32e18a90e10c150221af55c69aeafaa42c57a 

Я попробовал это на Windows, и Linux с несколькими различными версиями Git и увидел то же самое поведение.

Может ли кто-нибудь объяснить, что здесь происходит? Что я не понимаю о Git, fetch и refspecs? То, что я действительно хочу, это одна команда git fetch, к которой я могу предоставить либо идентификатор удаленной ветви или тега, либо идентификатор фиксации, и он получит соответствующую фиксацию.

+0

Что означает «единая фиксация с историей»? Другие коммиты - это история ... – Ryan

+0

Я имею в виду обычное поведение git, ничего особенного. Я хочу получить конкретную фиксацию, и я понимаю, что git также будет получать коммиты, которые составляют историю для комманда, который я указываю. –

+0

Ну, это не так, если вы используете 'git fetch -depth = 1' (и это действительно срабатывает, так как f1e32e18a90e10c150221af55c69aeafaa42c57a - это текущий совет для вашего примера, но это не вопрос, не так ли?). – Ryan

ответ

5

Обновление: с Git 2.5 (в середине 2015 года или около того), теперь серверы могут выставлять сырые хеши. Это элемент конфигурации на стороне сервера. У вас должен быть достаточный контроль над сервером, чтобы установить его, и вы должны рассмотреть потенциальные проблемы безопасности, прежде чем устанавливать его. См. this answer - Retrieve specific commit from a remote Git repository. (Оригинальный ответ, который относится к предварительно 2.5, или если ручка настройки не установлен, ниже.)


Команда git fetch обеспечивает ссылки (имена, не сырые фиксации идентификаторов) на пульте дистанционного управления, более или менее. (Более конкретно, используйте git ls-remote remotename, чтобы узнать, что удаленный пользователь хочет дать вам с точки зрения имен. Это приводит к отображению SHA-1 слева с именами справа, и единственное, что может сделать ваш fetchask for is имена по-правому. В этот момент вы получите ID-на-левом , если имя на удаленном компьютере все еще указывает на этот идентификатор, поэтому это зависит от того, насколько активно этот удаленный файл обновляется.)

Возможно, по-разному доставлять сырые идентификаторы фиксации на удаленный компьютер и запрашивать удаленное то, что видно, начиная с этой точки, а иногда и работать в обратном направлении через историю, но не через git fetch. (Вы можете использовать git archive, но удаленный компьютер может решить, разрешать ли вам доступ через сырые идентификаторы фиксации или с помощью пульта дистанционного управления, имеющего доступ к веб-серверу, в том числе для конкретных коммитов, вы можете просто просто просмотреть содержимое верхнего уровня commit, и использовать это, чтобы «развернуть», как говорится, на разные части. Но это очень медленный способ сделать это.)

Если вы хотите использовать git fetch, чтобы получить определенную фиксацию, вероятно, самый простой способ сделать это - заставить кого-то с доступом к удаленному подключить имя, скорее всего, тег-идентификатор фиксации. Затем вы можете вернуть git fetch этот refspec и поместить его под любой другой refspec, который вам нравится.Например, предположим, что вы можете SSH непосредственно к тому, что хосты origin:

$ ssh our.origin.host 'cd /repos/repo.git; git tag temporary f1e32e1' 
[enter password, etc; observe tag created] 
$ git fetch origin refs/tags/temporary:refs/heads/newbranch 
[observe fetch happen; now you have local branch 'newbranch'] 
$ ssh our.origin.host 'cd /repos/repo.git; git tag -d temporary' 

Обратите внимание, что имя не должно быть филиалом, она должна быть только ссылка вы можете съехать с git fetch и увидеть git ls-remote. Затем вы используете имя, которое будет соответствовать тому, которое находится в левой части вашего refspec при извлечении. Имя, созданное в , ваше repo контролируется правой стороной refspec (refs/heads/newbranch в приведенном выше примере).

Это также ответ на ваш последний вопрос в параграфе: вы можете только называть вещи, которые имеют имена на пульте дистанционного управления (это частично предназначено для того, чтобы избежать «утечки» неназванных коммитов, которые остаются в репозитории до сбора мусора, поэтому это считается особенностью, а не ошибкой). Эти имена входят в LHS refspec. Ваши собственные имена идут справа.

Ваше имя по праву считается филиалом или именем тега (на основании того, что имя на левых спички, хотя вы можете явно сформулировать refs/heads/ или refs/tags/ переопределить его), так что даже если f1e32e1... является действительным SHA-1, он рассматривается как имя ветки здесь - недостающее имя слева переводит на HEAD, так как отсутствующие имена почти всегда выполняются, а git fetch создает ветку, имя которой вызывает тревогу SHA-1-ish. (Кстати, однажды я создал название ветки, которое выглядело как SHA-1, а позже смутило себя. Я забыл, что именно это имя, что-то вроде de-bead без дефиса. Я переименовал его в переносимую версию, чтобы яснее я понял 't означает необработанный идентификатор фиксации! :-))

+0

Спасибо, Торек, это полезно и, кажется, объясняет большую часть того, что я видел. Я не вижу, чтобы это объясняло, почему/как git fetch https://github.com/ld4apps/lda-serverlib.git :f1e32e18a90e10c150221af55c69aeafaa42c57a работал. То, что там происходит? –

+0

Добавлен последний абзац с «намерением». Посмотрим, смогу ли я пояснить создание ветки ... – torek

+0

Возможно, я здесь скучный. Я понимаю, что RHS контролирует мои собственные имена, поэтому я не удивлен, что «git fetch repo: f1e32e18a90e10c150221af55c69aeafaa42c57a» создал локальную ветвь с именем f1e32e18a90e10c150221af55c69aeafaa42c57a. Меня удивляет то, что он также получил фиксацию того же идентификатора на пульте дистанционного управления, хотя это сообщение не было адресуемым, когда я положил его на LHS. –