Переименовать основную ветку как для локальных, так и для удаленных репозиториев Git

У меня есть ветка master, которая отслеживает удаленную ветку origin/master.

Я хочу переименовать их в master-old как локально, так и удаленно. Это возможно?

Для других пользователей, которые отслеживали origin/master (и которые всегда обновляли свою локальную ветку master через git pull), что произойдет после того, как я переименовал удаленную ветку?
Будет ли их git pull по-прежнему работать или будет выдана ошибка, из-за которой не удалось найти origin/master больше?

Затем я хочу создать новую ветку master (как локальную, так и удаленную). Опять же, после того, как я это сделал, что будет теперь, если другие пользователи сделают git pull?

Думаю, все это доставит массу неприятностей. Есть ли чистый способ получить то, что я хочу? Или мне просто оставить master как есть, создать новую ветку master-new и продолжать работать там дальше?


person Albert    schedule 06.10.2009    source источник
comment
Рецепт, приведенный в принятом ответе, действительно применим к ветке с любым именем, но оговорки (как указано) не применимы из-за (по умолчанию) особой роли ветки master в Git.   -  person kynan    schedule 18.04.2012
comment
@kynan: Думаю, я не понимаю. Какие предостережения применимы к мастеру и не применимы к другим ветвям? Если бы это была ветка с именем xy, и другие люди отслеживали бы эту ветку, как бы это было по-другому?   -  person Albert    schedule 19.04.2012
comment
Предостережение, что обычно удаленный мастер удалить нельзя. Это не относится к ответу Аристотеля, поэтому вы можете отметить это как принятый ответ. Вы правы, любое git push -f влияет на возможность pull из любой ветки удаленного отслеживания.   -  person kynan    schedule 19.04.2012
comment
вы можете создать новую ветку master-old, которая указывает на ту же фиксацию, что и предыдущая master ветка. Затем вы можете перезаписать ветку master новыми изменениями, выполнив merge со стратегией ours. Выполнение слияния работает, когда удаленный пульт не разрешает изменения, не связанные с быстрой перемоткой. Это также означает, что у других пользователей не будет принудительных обновлений.   -  person dnozay    schedule 20.06.2014
comment
@kynan master является особенным только в том случае, если это единственная существующая ветка. Как только у вас будет больше одной, все ветви будут в равных условиях.   -  person jub0bs    schedule 14.09.2014
comment
Возможный дубликат Как переименовать локальную ветку Git?   -  person Vineet Jain    schedule 26.08.2017
comment
Решение только для удаленного доступа без локальных манипуляций доступно в комментариях в https://stackoverflow.com/questions/4753888/renaming-branches-remotely-in-git   -  person Vadzim    schedule 01.10.2019


Ответы (16)


Самое близкое к переименованию - это удаление, а затем воссоздание на пульте дистанционного управления. Например:

git branch -m master master-old
git push remote :master         # Delete master
git push remote master-old      # Create master-old on remote

git checkout -b master some-ref # Create a new local master
git push remote master          # Create master on remote

Однако здесь есть много недостатков. Во-первых, ни одна из существующих проверок не будет знать о переименовании - Git не пытается отслеживать переименования веток. Если новый master еще не существует, git pull выдаст ошибку. Если новый master был создан. тяга попытается объединить master и master-old. Так что, как правило, это плохая идея, если у вас нет сотрудничества со всеми, кто ранее проверял репозиторий.

Примечание. Новые версии Git по умолчанию не позволяют удалять главную ветку удаленно. Вы можете изменить это, установив для параметра конфигурации receive.denyDeleteCurrent значение warn или ignore в удаленном репозитории. В противном случае, если вы готовы сразу же создать новый мастер, пропустите шаг git push remote :master и перейдите --force к шагу git push remote master. Обратите внимание: если вы не можете изменить конфигурацию пульта дистанционного управления, вы не сможете полностью удалить главную ветвь!

Это предостережение применимо только к текущей ветке (обычно ветке master); любую другую ветку можно удалить и воссоздать, как указано выше.

person bdonlan    schedule 06.10.2009
comment
ветви - это просто пара (имя, хеш) - ни больше ни меньше. В ветках есть журнал ссылок, но он никогда не отображается для удаленных клиентов. - person bdonlan; 07.10.2009
comment
Я бы создал master-old на удаленном компьютере перед удалением master на удаленном компьютере. Я просто параноик. - person Adam Dymitruk; 11.08.2010
comment
Нет кубика при второй команде: remote: error: по умолчанию удаление текущей ветки запрещено, потому что следующая удаленная: error: 'git clone' не приведет к извлечению какого-либо файла, что вызовет путаницу. remote: error: remote: error: вы можете установить переменную конфигурации 'receive.denyDeleteCurrent' t remote: error: 'warn' или 'ignore' в удаленном репозитории, чтобы разрешить удаление th remote: error: current branch, с предупреждением или без него сообщение. удаленный: ошибка: удаленный: ошибка: Чтобы подавить это сообщение, вы можете установить его на «отказаться». удаленный: ошибка: отказ от удаления текущей ветки: refs / Heads / master - person kdt; 21.01.2011
comment
@kdt, ответ, который вы ищете, находится в сообщении, которое вы только что вставили ... Но да, более новые версии git недовольны удалением основной ветки. Я обновлю пример. - person bdonlan; 21.01.2011
comment
@AdamDymitruk не нужно быть параноиком, если вы не уверены, что сервер, получающий push-удаление ссылки ветки, делает что-то дополнительное (что может быть в случае GitHub). Git по умолчанию не будет выполнять очистку, если вы этого не скажете. - person kynan; 10.12.2011
comment
Ответ Аристотеля ниже позволяет вам сделать это, не удаляя мастер, поэтому я думаю, что это предпочтительнее. - person Clay Bridges; 25.03.2012
comment
было бы ясно и БЕЗОПАСНО, если бы вы могли использовать new-branch-name и old-branch-name вместо _3 _ / _ 4_, поэтому это общая проблема. - person Jaider; 19.09.2012
comment
Если на удаленную ветку (здесь: master) не ссылаются другие ветки, git может собрать все коммиты в этой ... ну ... «ветке». - Некоторые команды git porcelain запускают сборку мусора. - Следовательно: сначала создайте новое имя (указывающее на ту же фиксацию), затем удалите старое имя. - person Robert Siemer; 14.01.2015
comment
git push remote :master ›фатальный:« удаленный »не является репозиторием git. Фатальный: не удалось прочитать из удаленного репозитория. Убедитесь, что у вас есть правильные права доступа и репозиторий существует. - person vee; 27.04.2016
comment
@vee, у меня такая же ошибка - попробуйте git push origin. - person Shurik; 08.02.2017
comment
@vee git имеет отличное автозаполнение, просто введите git push [TABULATOR] - person phil294; 12.02.2017
comment
с этим рецептом я получаю ! [remote rejected] master (refusing to delete the current branch: refs/heads/master) error: failed to push some refs to 'https://github.com/me/repo' на git push -f remote :master - person Dima Lituiev; 06.01.2018
comment
Шаг 2 завершается неудачно: 'remote' не похоже на репозиторий git - person Jesse Barnum; 02.09.2020
comment
@JesseBarnum Вы должны заменить «удаленный» на имя вашего удаленного репозитория. Условно называется происхождение. Вы можете перечислить свои фактические пульты с помощью git remote - person Jonathan Hartley; 22.02.2021

Предполагая, что вы сейчас на master:

git push origin master:master-old        # 1
git branch master-old origin/master-old  # 2
git reset --hard $new_master_commit      # 3
git push -f origin                       # 4
  1. Сначала создайте ветку master-old в репозитории origin на основе фиксации master в локальном репозитории.
  2. Создайте новую локальную ветвь для этой новой ветки origin/master-old (которая будет автоматически настроена правильно как ветвь отслеживания).
  3. Теперь укажите свой локальный master на тот коммит, на который вы хотите, чтобы он указывал.
  4. Наконец, принудительно измените master в репозитории origin, чтобы он отражал ваш новый локальный master.

(Если вы сделаете это каким-либо другим способом, вам понадобится как минимум еще один шаг, чтобы убедиться, что master-old правильно настроен для отслеживания origin/master-old. Ни одно из других решений, опубликованных на момент написания этой статьи, не включает это.)

person Aristotle Pagaltzis    schedule 24.09.2010
comment
Я согласен, это лучший ответ, чем ответ, но для людей, которые пришли сюда, чтобы просто переименовать ветку (не явно ведущую), третий шаг не имеет особого смысла. - person knocte; 29.08.2012
comment
Для ответа абсолютно безразлично, находитесь ли вы в master или в другой ветке. Вопрос был плохо озаглавлен, он касается более сложной задачи, чем простое переименование ветки. - person Aristotle Pagaltzis; 29.08.2012
comment
Это оказалось решением, которое сработало для меня. Я пытался заменить master на другую ветку. Я сделал git log -1 origin / what_i_want_as_new_master, чтобы получить $ new_master_commit для шага 3. После push (шаг 4) другие разработчики будут извлекать и получать сообщения, что ваша ветка опережает master на 295 коммитов. Чтобы исправить это, я разослал им письмо по электронной почте при каждом запуске: git pull; git checkout some_random_branch; git branch -D master; git pull; git checkout master; По сути, им нужно удалить свой локальный мастер и вытащить новую версию, иначе они окажутся не в том месте локально. - person nairbv; 15.11.2013
comment
Вы могли бы сделать это гораздо проще: если они уже подключены master, тогда они могут просто git fetch && git reset --hard origin/master сделать так, чтобы их локальный master был таким же, как и на origin. Я задокументировал это, а также более сложный случай, когда у вас есть локальные коммиты поверх master, которые вы хотите сохранить, в stackoverflow.com/ q / 4084868 - person Aristotle Pagaltzis; 17.11.2013
comment
Убедитесь, что в удаленном конфигурационном файле есть denyNonFastforwards = false, иначе вы получите remote: error: denying non-fast-forward refs / heads / master (вы должны сначала потянуть) - person gjcamann; 28.05.2014

Я думаю, что с Git v1.7 это немного изменилось. Обновить ссылку отслеживания вашего локального филиала на новый пульт теперь очень просто.

git branch -m old_branch new_branch         # Rename branch locally    
git push origin :old_branch                 # Delete the old branch    
git push --set-upstream origin new_branch   # Push the new branch, set local branch to track the new remote
person Excalibur    schedule 25.04.2013
comment
Альтернативой --set-upstream является следующее: после того, как ваша ветка переименована локально и удалена в источнике, просто выполните: git push -u --all - person lucifurious; 09.07.2013
comment
Что происходит с остальной командой после того, как это будет сделано? Что должны сделать другие члены команды, чтобы перейти на новую ветку? - person Michael Teper; 02.01.2014
comment
Это не будет работать с основной веткой, поскольку git не позволит вам удалить удаленный мастер. - person Alexandre Neto; 06.01.2014
comment
@AlexandreNeto В этом случае вы можете выполнить третью строку перед второй, установить ветку по умолчанию на new_branch, а затем в конечном итоге удалить удаленный master со второй строкой. - person Tristan Jahier; 03.02.2015
comment
Удивительно простые шаги. Это лучший ответ на вопрос - person siddhusingh; 20.02.2015
comment
Это наиболее простое и рабочее решение для переименования ветки, отличной от главной. Протестировано на git 2.4, работает !! - person haudoing; 11.05.2015
comment
Это также будет работать в основной ветке, если вы используете github. Вам просто нужно сначала нажать новую ветку, а затем в настройках репозитория по умолчанию. Затем вы можете удалить главную ветку. - person Alma Do; 22.05.2015
comment
Будет ли вся история old_branch в new_branch (в случае, если это делается с помощью master для ясности) - person Steve K; 02.09.2015
comment
Чтобы удалить удаленную ветку, git push origin --delete old_branch немного удобнее. - person ThomasW; 14.10.2015
comment
Да, безусловно, лучший ответ здесь. Всегда стоит проверять и GitHub, поскольку у них обычно тоже есть ответ: gist.github.com/lttlrck/9628955 < / а> - person Belfield; 21.07.2017

git checkout -b new-branch-name
git push remote-name new-branch-name :old-branch-name

Возможно, вам придется вручную переключиться на new-branch-name перед удалением old-branch-name

person Treken    schedule 10.02.2012
comment
Удаляет ли какая-либо часть этого решения локальное старое имя ветки или это отдельное упражнение? - person GreenAsJade; 15.09.2013
comment
Думаю, в конце нужно запустить git branch -d old-branch-name для удаления локальной старой ветки. - person Nabi K.A.Z.; 09.12.2013
comment
Вы можете отправить изменения только одной командой: git push remote-name new-branch-name :old-branch-name. - person sigod; 16.01.2014
comment
Не усложните ли вы таким образом историю git? Потому что вы открываете новую ветку вместо того, чтобы просто переименовывать текущую. - person androidevil; 23.01.2014
comment
@androider Нет. Ветви в git - это простые ссылки. - person sigod; 05.03.2014
comment
git push origin EPIC_localname: EPIC_remotename: oldname - person maxweber; 29.04.2015
comment
По моему опыту, это неправильно обновляет ветвь отслеживания локальной ветки. - person ThomasW; 15.05.2015

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

Сначала быстрое изображение:  переименование основной ветви и разрешение клиентам перемотки вперед

Это действительно легко сделать; но не злоупотребляйте этим. Вся идея зависит от коммитов слияния; поскольку они позволяют выполнять перемотку вперед и связывать истории одной ветки с другой.

переименование ветки:

# rename the branch "master" to "master-old"
# this works even if you are on branch "master"
git branch -m master master-old

создание новой главной ветки:

# create master from new starting point
git branch master <new-master-start-point>

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

# now we've got to fix the new branch...
git checkout master

# ... by doing a merge commit that obsoletes
# "master-old" hence the "ours" strategy.
git merge -s ours master-old

и вуаля.

git push origin master

Это работает, потому что создание merge фиксации позволяет перемотать ветку к новой ревизии.

используя разумное сообщение фиксации слияния:

renamed branch "master" to "master-old" and use commit ba2f9cc as new "master"
-- this is done by doing a merge commit with "ours" strategy which obsoletes
   the branch.

these are the steps I did:

git branch -m master master-old
git branch master ba2f9cc
git checkout master
git merge -s ours master-old
person dnozay    schedule 18.03.2014
comment
Спасибо! git merge -s ours master-old - это ключевой момент, который упускают из виду другие ответы. Кроме того, «легко сделать» не означает «легко понять» или выяснить, что, кажется, имеет место с большей частью git, но я отвлекся. - person Martin Vidner; 28.07.2016
comment
Мне нравится, что никаких удалений не упоминается и что переход для тех, кто работает с клонами апстрима, проходит без проблем. Спасибо! - person Piotrek; 16.11.2016
comment
Работает ли это, если у мастера есть изменения, которые вам не нужны? - person Ethan Fischer; 15.06.2020

Я предполагаю, что вы все еще спрашиваете о той же ситуации, что и в вашем предыдущий вопрос. То есть master-new не будет содержать master-old в своей истории. * Если вы назовете master-new «master», вы фактически переписываете историю. Не имеет значения, как вы попадаете в состояние, в котором мастер не является потомком предыдущей позиции мастера, просто то, что он находится в этом состоянии.

Другие пользователи, пытающиеся извлечь, пока мастер не существует, просто потерпят неудачу (нет такой ссылки на удаленном компьютере), и как только он снова появится в новом месте, их извлечения должны будут попытаться объединить своего мастера с новым удаленным мастером, так же, как если бы вы объединили главный-старый и главный-новый в своем репозитории. Учитывая то, что вы здесь пытаетесь сделать, слияние может привести к конфликтам. (Если бы они были разрешены, а результат был помещен обратно в репозиторий, вы были бы в еще худшем состоянии - обе версии истории присутствовали.)

Чтобы ответить на ваш вопрос просто: вы должны признать, что иногда в вашей истории будут ошибки. Это хорошо. С кем не бывает. В репозитории git.git есть отмененные коммиты. Важно то, что как только мы публикуем историю, каждый может доверять ей.

* Если бы это было так, это было бы эквивалентно отправке некоторых изменений в мастер, а затем созданию новой ветки там, где она была раньше. Без проблем.

person Cascabel    schedule 06.10.2009
comment
Да, это та же проблема, просто была одна идея, как ее решить. Но даже если бы я не стал делать это переименование ветки, мне было интересно, возможно ли это. Я думал, что такие ссылки как master - это только ссылки на определенные коммиты. Я действительно не хочу ничего менять в истории. Я думал, что просто укажу мастер-ссылку на другую голову. Это также означает, что я никогда больше не смогу использовать имя ветки, если я когда-либо использовал его раньше? - person Albert; 06.10.2009
comment
Действительно, ветки - это ссылки - указатели на коммиты. Дело в том, что мы ожидаем, что глава ветки будет развиваться определенным образом (а именно, всегда с быстрой перемоткой вперед). С точки зрения кого-то еще, перемещение ветки в вашем публичном репо - это то же самое, что переписывание истории ветки. Он больше не указывает на коммит, содержащий все, к чему он привык. - person Cascabel; 06.10.2009

выбранный ответ не удалось, когда я попробовал. Выдает ошибку: refusing to delete the current branch: refs/heads/master. Думаю, я опубликую то, что у меня работает:

git checkout master             # If not in master already

git branch placeholder          # Create placeholder branch
git checkout placeholder        # Check out to placeholder
git push remote placeholder     # Push placeholder to remote repository

git branch -d master            # Remove master in local repository
git push remote :master         # Remove master from remote repository.

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

person O.O    schedule 25.12.2011
comment
Это не сработает на git push remote: master, если это проверено на удаленной стороне - вы увидите remote: error: как префикс в строках журнала ошибок. - person rafalmag; 13.04.2015

Войдите на сервер, перейдите в каталог Git и переименуйте ветку в голом репозитории.

У этого нет всех проблем, связанных с повторной загрузкой той же ветки. Фактически, «клиенты» автоматически распознают измененное имя и изменят свою удаленную ссылку.

Впоследствии (или раньше) вы также можете изменить локальное имя ветки.

person Community    schedule 24.12.2010
comment
Я забыл учетные данные для входа на сервер github. Кто-нибудь, у кого есть учетные данные :-P - person Daniel Fisher lennybacon; 23.07.2013

Что о:

git checkout old-branch-name
git push remote-name new-branch-name
git push remote-name :old-branch-name
git branch -m new-branch-name
person Hannes Tydén    schedule 17.08.2010
comment
портит отслеживание веток - пользователям, возможно, придется исправить свою ветку локально? - person dnozay; 24.10.2016
comment
Объяснение было бы в порядке. - person Peter Mortensen; 09.04.2021

Хорошо, переименовать ветку как локально, так и на удаленном очень просто! ...

Если вы в ветке, то легко сможете сделать:

git branch -m <branch>

а если нет, нужно сделать:

git branch -m <your_old_branch> <your_new_branch>

Затем отправьте удаление на пульт следующим образом:

git push origin <your_old_branch>

Теперь все готово.

Если вы получаете ошибку восходящего потока при попытке нажать, просто выполните:

git push --set-upstream origin <your_new_branch>

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

Введите здесь описание изображения

person Alireza    schedule 03.07.2017
comment
ваше предложение о принудительном удалении не сработало, мне нужно было запустить это: git push origin --delete ‹your_old_branch› - person super IT guy; 15.06.2021

Это самый простой и самый "читаемый" способ, который я знаю:

'Переместить' локальную ветку с помощью -m

git branch -m my_old_branch_name my_new_branch_name

Переместите 'перемещенную' ветку на удаленный, установите 'upstream' с помощью -u

git push origin -u my_new_branch_name

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

Удаляем старую ветку с пульта

git push origin -D <old_name>

Ваш локальный филиал уже отсутствует, потому что вы «переместили» его на первом этапе.

person Chris Halcrow    schedule 08.12.2017

Вы можете сделать следующее:

git -m master master-old #rename current master
git checkout -b master   #create a new branch master
git push -f origin master #force push to master

Но принудительное продвижение - плохая идея, если другие люди используют этот репозиторий. Принудительное нажатие приведет к конфликту их истории изменений с новой.

person Riyafa Abdul Hameed    schedule 16.08.2017

Следующее может быть сохранено в сценарии оболочки для выполнения работы:

Например:

remote="origin"

if [ "$#" -eq 0 ] # if there are no arguments, just quit
then
    echo "Usage: $0 oldName newName or $0 newName" >&2
    exit 1
elif
    [ "$#" -eq 1 ] # if only one argument is given, rename current branch
then
    oldBranchName="$(git branch | grep \* | cut -d ' ' -f2)" #save current branch name
    newBranchName=$1
else
    oldBranchName=$1
    newBranchName=$2
fi

git branch -m $oldBranchName $newBranchName

git push $remote :$oldBranchName # Delete old branch on remote
git push --set-upstream $remote $newBranchName # Add new branch name on remote and track it

Обратите внимание, что здесь источник удаленного имени по умолчанию жестко задан. Вы можете расширить сценарий, чтобы сделать его настраиваемым!

Затем этот сценарий можно использовать с псевдонимами Bash, псевдонимами Git или, например, в Sourcetree настраиваемые действия.

person Do-do-new    schedule 08.04.2018

Перейдите на github.com или где-нибудь еще, щелкните ветку и переименуйте ее. Затем запустите их локально:

git branch -m <old-branch-name> <new-branch-name>
git fetch origin
git branch -u origin/<new-branch-name> <new-branch-name>
person Epirocks    schedule 09.04.2021

Я считаю, что ключевым моментом является осознание того, что вы выполняете двойное переименование: master в master-old, а также master-new в master.

Из всех других ответов я синтезировал это:

doublerename master-new master master-old

где мы сначала должны определить doublerename функцию Bash:

# doublerename NEW CURRENT OLD
#   - arguments are branch names
#   - see COMMIT_MESSAGE below
#   - the result is pushed to origin, with upstream tracking info updated
doublerename() {
  local NEW=$1
  local CUR=$2
  local OLD=$3
  local COMMIT_MESSAGE="Double rename: $NEW -> $CUR -> $OLD.

This commit replaces the contents of '$CUR' with the contents of '$NEW'.
The old contents of '$CUR' now lives in '$OLD'.
The name '$NEW' will be deleted.

This way the public history of '$CUR' is not rewritten and clients do not have
to perform a Rebase Recovery.
"

  git branch --move $CUR $OLD
  git branch --move $NEW $CUR

  git checkout $CUR
  git merge -s ours $OLD -m $COMMIT_MESSAGE

  git push --set-upstream --atomic origin $OLD $CUR :$NEW
}

Это похоже на изменение истории git rebase тем, что содержимое ветки сильно отличается, но отличается тем, что клиенты по-прежнему могут безопасно перемещаться вперед с помощью git pull master.

person Martin Vidner    schedule 28.07.2016

person    schedule
comment
У меня это не работает, я получаю: git update-ref trunk trunk2 fatal: trunk2: not a valid SHA1 - person Gregg Lind; 08.12.2010
comment
Объяснение было бы в порядке. - person Peter Mortensen; 09.04.2021