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

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

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

15 ответов


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

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 does не попытка отслеживать переименования ветвей. Если новый master еще не существует, git pull будет ошибка. Если новый master была создана. тяга будет пытаться объединить master и master-old. Так это вообще плохая идея, если у вас есть сотрудничество всех, кто ранее проверял хранилище.

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

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


предполагая, что вы в настоящее время на 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 commit в локальном репозитории.
  2. создайте новую локальную ветвь для этого нового origin/master-old ветвь (которая будет автоматически настроена правильно как ветвь отслеживания).
  3. теперь укажите ваш местный master к какой бы фиксации вы ни указали.
  4. наконец, force-change master в origin репозиторий, чтобы отразить ваш новый локальный master.

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


с 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

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

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


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

сначала быстрое изображение: renaming master branch and allowing clients to fast-forward

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

переименование бранч:

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

создание новой ветви" master":

# 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 commit позволяет быстрая перемотка вперед ветвь к новой редакции.

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

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

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

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

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

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


на выбранный ответ не удалось, когда я попробовал его. Он выдает ошибку: 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        # checkout 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.

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


хорошо. Мои 2 цента. Как насчет входа на сервер, перехода в каталог git и переименования ветки в голом репозитории. Это не имеет всех проблем, связанных с повторной загрузкой той же ветви. Фактически, "клиенты" автоматически распознают измененное имя и изменяют свою удаленную ссылку. После этого (или до) вы также можете изменить локальное имя ветви.


о:

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

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

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

git branch -m my_old_branch_name my_new_branch_name

нажимаем "переехал" филиал в пульте, набор 'вверх' через -у

git push origin -u my_new_branch_name

(установка "вверх по течению" по существу "соединяет" вашу локальную ветвь с удаленным, так что такие вещи, как fetch, pull и push, будут работать)

удалить старую ветку с пульта

git push origin -D <old_name>

(ваша местная ветвь уже ушла, потому что вы "переместили" ее на 1-м шаге)


OK, переименовании филиала и локально и пульт довольно легко!...

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

git branch -m <branch>

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

git branch -m <your_old_branch> <your_new_branch>

затем нажимаем удаление к удаленному такой:

git push origin <your_old_branch>

теперь вы сделали, если вы получаете ошибку вверх по течению при попытке нажать, просто do:

git push --set-upstream origin <your_new_branch>

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

enter image description here


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

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

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


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

например:

remote="origin"

if [ "$#" -eq 0 ] # if there are no arguments, just quit
then
    echo "Usage:  oldName newName or  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=
else
    oldBranchName=
    newBranchName=
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

обратите внимание, что здесь по умолчанию удаленное имя "origin" жестко закодировано, вы можете расширить скрипт, чтобы сделать его настраиваемым!

затем этот скрипт можно использовать с псевдонимами bash, Git или, например, в пользовательских действиях sourcetree.


Я считаю, что ключом является осознание того, что вы выполняете двойной переименовать: master to 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=
  local CUR=
  local OLD=
  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.


git update-ref newref oldref
git update-ref -d oldref newref