Измените удаленную 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.