Измените удаленную HEAD Git, чтобы указать на что-то помимо мастера


124

Как мне установить ссылку HEAD на удаленном Git, чтобы она указывала на что-то помимо "master"?

В моем проекте есть политика не использовать «главную» ветку (все ветки должны иметь значимые имена). Кроме того, канонический главный репозиторий доступен только через ssh: // без доступа к оболочке (например, GitHub или Unfuddle).

Моя проблема в том, что в удаленном репозитории все еще есть ссылка HEAD на refs / Heads / master, но мне нужно, чтобы она указывала на другую ветку. Это вызывает две проблемы:

  1. При клонировании репо есть это,

    предупреждение: удаленная ГОЛОВА относится к несуществующей ссылке, невозможно оформить заказ.

    Это сбивает с толку и неудобно.

  2. Веб-обозреватель кода зависит от HEAD как основы для просмотра дерева. Тогда мне нужно, чтобы HEAD указывал на действительную ветку.


Просто добавлена ​​одна возможность для записи, но не подходит для вашего случая.
VonC

Уловка "без общего предка": интересно. Вы можете опубликовать его как подробный ответ и выбрать его как официальный, если вы обнаружите, что он работает.
VonC

12
FWIW, поскольку вы упомянули GitHub в вопросе - если вы хотите изменить ссылку HEAD на GitHub, просто перейдите на экран «Администратор» репозитория и измените раскрывающийся список «Ветвь по умолчанию» на любую ветку, на которую должен указывать HEAD.
Joe


Ответы:


63

Год назад на GitHub был почти такой же вопрос .

Идея заключалась в том, чтобы переименовать главную ветку:

git branch -m master development
git branch -m published master
git push -f origin master 

Заставить мастера иметь то, что вы хотите, чтобы люди использовали, а всю остальную работу выполняли в ветвях.

(" git-symbolic-ref HEAD refs/head/published" не будет передано в удаленное репо)

Это похоже на « Как удалить origin / master в Git ».


Как сказано в этой теме : (выделено мной)

" git clone" создает только одну локальную ветвь.
Для этого он смотрит на HEAD refудаленное репо и создает локальную ветвь с тем же именем, что и удаленная ветка, на которую он ссылается.

Итак, чтобы завершить это, у вас есть репо A и клонируйте его:

  • HEADссылки refs/heads/masterи что существует
    -> вы получаете локальную ветку с именем master, начиная с origin / master

  • Ссылки HEAD refs/heads/anotherBranchи которые существуют
    -> вы получаете локальную ветвь с именем anotherBranch, начиная сorigin/anotherBranch

  • Ссылки HEAD refs/heads/master, которых не существует
    -> "git clone" жалуется

Не уверен, есть ли способ напрямую изменить HEADссылку в репо .

(в этом весь смысл вашего вопроса, я знаю;))


Может быть, единственным выходом будет «издание для бедных» , где вы:

 $ git-symbolic-ref HEAD refs/head/published
 $ git-update-server-info
 $ rsync -az .git/* server:/local_path_to/git/myRepo.git/

Но для этого потребуется доступ для записи на сервер, что не всегда возможно.


Как я объясняю в « Git: правильный способ изменить активную ветку в пустом репозитории? », git remote set-headНичего не изменится в удаленном репозитории .

Это изменит только ветку удаленного отслеживания, хранящуюся локально в вашем локальном репо, в remotes/<name>/HEAD.


Спасибо, VonC. Я прочитал это, прежде чем размещать здесь. Но, как вы можете видеть, ветвь под названием «master» нежелательна в этом проекте по техническим и политическим причинам.
JasonSmith

Затем вы можете применить эту политику, запретив любое обновление в главной ветке с помощью ловушки предварительной фиксации.
VonC

Да, если окажется, что нет возможности сделать то, что я хочу, я сделаю именно это и приму ваш ответ. Спасибо за продолжение!
JasonSmith

Спасибо за обновление. На данный момент я использовал уловку «без общего предка», чтобы создать главную ветку только с одной фиксацией. (То есть: git branch -D master; echo ref: refs / heads / master> .git / HEAD; rm *). Затем я просто коснулся файла GO_AWAY, и сообщение фиксации объясняет ситуацию. Пока это будет работать. Я могу проверить источник и отследить, где принимающая сторона устанавливает HEAD для окончательного ответа.
JasonSmith

1
@ctn Это просто потому, что я забыл опцию -f( --force). Я соответствующим образом отредактировал ответ. Тогда ответ, который вы ссылаетесь, использует тот же вариант.
VonC

42

Обновление: это работает только для локальной копии репозитория («клиент»). Пожалуйста, смотрите комментарии других ниже.

В последней версии git (февраль 2014 г.) правильная процедура будет следующей:

git remote set-head $REMOTE_NAME $BRANCH

Так, например, переключение головы с пульта originна ветку developбудет:

git remote set-head origin develop


Требуется ли для этой функции последняя версия git на сервере или этого достаточно, если на клиентском компьютере установлена ​​последняя версия git?
Mikko Rantalainen 06

3
@Totor краток, но прав; этот ответ должен быть отклонен. В Git есть несколько сбивающая с толку концепция «локальной ветки по умолчанию для удаленного». Он позволяет вводить «origin» вместо «origin / defaultbranch» и является чисто клиентской вещью. Длинная история на git-scm.com/docs/git-remote # set-head
MarcH

1
чтобы подтвердить, о чем говорит @MarchH: беги git checkout -b default; git push origin HEAD; git remote set-head origin default. Затем вы можете проверить локальные изменения с помощью cat .git/refs/remotes/origin/HEAD(это должно быть ref: refs/remotes/origin/default) и отсутствие удаленных изменений с помощью git remote show origin(это все равно будет тем, что было до добавления ветки по умолчанию).
De Novo

37

Поскольку вы упомянули GitHub, чтобы сделать это на их сайте, просто войдите в свой проект, затем ...

admin > Default Branch > (choose something)

Готово.


1
Превосходно! Это был последний недостающий бит.
Berkus

Мой origin / HEAD уже указывает на ветку функции вместо master. Я пробовал менять "основную ветку" туда-сюда, но это не повлияло на HEAD ... Есть предложения?
Даниил Шевелев

3
Настройки> Ветви> Ветвь по умолчанию
Чун Ян

12

См .: http://www.kernel.org/pub/software/scm/git/docs/git-symbolic-ref.html

Это устанавливает ветку по умолчанию в репозитории git. Вы можете запустить это в голых или зеркальных репозиториях.

Использование:

$ git symbolic-ref HEAD refs/heads/<branch name>

6
$ git symbolic-ref HEAD refs / Heads / name-of-branch
Лами

Я сделал это в своем удаленном репо, и он устранил мои проблемы с клонированием, когда по какой-то причине голова была другим именем ветки, и поэтому попытка клонирования мастера приведет к ошибке при попытке закрыть мастер в композиторе, это может быть очень специфичным для этого сценария , но другие могут оказаться в таком положении и задаются вопросом, что делать
Кристофер Томас

10

(Уже был практически такой же вопрос « создать символическую ссылку git в удаленном репозитории », на который не было универсального ответа.)

Но есть конкретные ответы для различных "ферм" git (где несколько пользователей могут управлять репозиториями git через ограниченный интерфейс: через http и ssh): http://Github.com , http://Gitorious.org , http: / /repo.or.cz , Girar ( http://git.altlinux.org ).

Эти конкретные ответы могут быть полезны для тех, кто читает эту страницу и думает об этих конкретных услугах.


4
Теперь у них есть раскрывающееся меню для выбора ветки HEAD на repo.or.cz (пример: repo.or.cz/editproj.cgi?name=for-me-and-for-all_imz.git ) и gitorious.org , слишком. Большой!
imz - Иван Захарящев 04

7

Если у вас есть доступ к удаленному репо из оболочки, просто зайдите в .git (или в основной каталог, если это голое репо) и измените файл HEAD, чтобы он указывал на правильную голову. Например, по умолчанию он всегда содержит «refs: refs / Heads / master», но если вам нужно, чтобы foo был вместо HEAD, просто отредактируйте файл HEAD и измените его содержимое на «refs: refs / heads / foo».


У меня есть права администратора на сервере Git, и я сделал то же самое. Мы используем Gitolite, и я зашел в созданный мной репозиторий. Имя каталога myrepo.git. Содержимое файла HEAD в данном каталоге было изменено с ref: refs/heads/masterна ref: refs/heads/mainline. Теперь, когда я пытаюсь клонировать репозиторий в моем локальном ящике, он все еще указывает на master. Я запустил git clone ssh://gitolite@git.server/myrepoкоманду. Есть идеи для такого поведения?
Technext

Версия сервера Git: git version 1.7.1& Версия клиента Git:git version 1.9.4.msysgit.2
Technext,

5

Вы можете создать отдельную главную ветку, используя только фарфоровые команды Git:

git init
touch GO_AWAY
git add GO_AWAY
git commit -m "GO AWAY - this branch is detached from reality"

Это дает нам основную ветку с грубым сообщением (вы можете быть более вежливым). Теперь создаем нашу «настоящую» ветку (назовем ее в честь SVN стволом ) и отделяем ее от мастера :

git checkout -b trunk
git rm GO_AWAY
git commit --amend --allow-empty -m "initial commit on detached trunk"

Вуаля! gitk --all покажет мастер и ствол без связи между ними.

«Магия» здесь в том, что --amend заставляет git commit создать новый коммит с тем же родителем, что и текущий HEAD, а затем сделать так, чтобы HEAD указывал на него. Но текущий HEAD не имеет родителя, поскольку это начальная фиксация в репозитории, поэтому новый HEAD также не получает его, что делает их отделенными друг от друга.

Старый коммит HEAD не удаляется git-gc, потому что refs / Heads / master все еще указывает на него.

--Allow пустого флаг нужен только потому , что мы совершаем пустое дерево. Если бы после git rm было несколько git add , в этом не было бы необходимости.

По правде говоря, вы можете создать отдельную ветку в любое время, разветвив исходную фиксацию в репозитории, удалив ее дерево, добавив свое отдельное дерево, а затем выполнив git commit --amend .

Я знаю, что это не отвечает на вопрос о том, как изменить ветку по умолчанию в удаленном репозитории, но дает четкий ответ о том, как создать отдельную ветку.


1
Вы можете проще создать отдельную ветвь, получив несвязанную ветку из другого репо и дав ей имя. Например, git fetch git:user@example.com:foo remote-branch-name && git checkout -b detached-branch FETCH_HEADдобавит новую ветку detached-branch, соответствующую ветке remote-branch-nameв удаленном git:user@example.com:foo. Конечно, «удаленным» может быть репозиторий в локальной файловой системе, который вы заранее подготовили.
Mikko Rantalainen

2

Сначала создайте новую ветку, которую вы хотите установить по умолчанию, например:

$>git branch main

Затем переместите эту ветку в начало координат :

$>git push origin main

Теперь, когда вы входите в свою учетную запись GitHub, вы можете перейти в свой репозиторий, выбрать «Настройки»> «Ветвь по умолчанию» и выбрать « основной ».

Затем, если вы захотите, вы можете удалить главную ветку:

$>git push origin :master


Ключевым моментом для понимания является то, что если ваш хостинг-провайдер (GitHub в этом примере) не предоставляет метод для изменения ветки по умолчанию, вам не повезло. Протокол Git не предоставляет возможности изменять удаленную ветку по умолчанию; вам нужно будет иметь возможность запускаться git symbolic-refв удаленной оболочке или иным образом изменять текстовый файл, вызываемый HEADв корневом каталоге удаленного репозитория.
Mikko Rantalainen

2

Что касается вопроса, я оказался здесь, когда искал:

Как сделать так, чтобы локальное репо узнало об измененной ветке по умолчанию на GitHub

Для полноты картины добавляем ответ:

git remote set-head origin -a

0

Для гитолитов гитолит поддерживает команду - подождите - symbolic-ref. Это позволяет вам запускать эту команду удаленно, если у вас есть разрешение W (запись) в репо.


-1

Просто войдите в свою учетную запись GitHub и в дальнем правом углу в меню навигации выберите « Настройки» , на вкладке «Настройки» выберите « Ветвь по умолчанию» и вернитесь на главную страницу своего репозитория, которая сработала для меня.


1
Хотя он показывает новую ветку по умолчанию в интерфейсе GitHub, при выполнении git clone [repo] я не получаю эту ветку. т.е. .git / HEAD содержит неправильную ссылку.
Джозеф Шиди,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.