15 Вопрос: Переименуйте главную ветку для локальных и удаленных Git-репозиториев.

вопрос создан в Wed, Jun 11, 2014 12:00 AM

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

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

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

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

    
782
  1. Рецепт, данный в принятом ответе, действительно применяется к ветви любого имени, но предостережения (как отмечено) - нет, из-за (по умолчанию) специальной роли master ветви в Git.
    2012-04-18 16: 18: 17Z
  2. @ kynan: мне кажется, я не понимаю. Какие предостережения относятся к мастеру и не применяются к другим веткам? Если бы это была ветка с именем xy, и другие люди отслеживали эту ветку, как бы это было иначе?
    2012-04-19 13: 05: 17Z
  3. Предупреждение о том, что вы не можете обычно удалить удаленный мастер. Это не относится к ответу Аристотеля, так что вы можете пометить его как принятый ответ. Вы правы, любой git push -f влияет на возможность pull из любой удаленной ветви отслеживания.
    2012-04-19 13: 47: 22Z
  4. вы можете создать новую ветвь master-old, которая указывает на тот же коммит, что и предыдущая ветвь master. Затем вы можете перезаписать ветку master новыми изменениями, выполнив merge со стратегией ours. Выполнение слияния работает, когда пульт не допускает внесения изменений без ускоренной передачи. Это также означает, что у других пользователей не будет принудительных обновлений.
    2014-06-20 17: 30: 32Z
  5. @ kynan master является особенным только при условии, что это единственная существующая ветвь. Как только у вас будет более одного, все ветви будут в равных условиях.
    2014-09-14 10: 58: 35Z
15 ответов                              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 не пытается отслеживать переименования веток. Если новый master еще не существует, git pull выдает ошибку. Если новый master был создан. Команда pull попытается объединить master и master-old. Поэтому, как правило, это плохая идея, если вы не сотрудничаете со всеми, кто ранее проверял хранилище.

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

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

    
596
2014-08-12 14: 32: 00Z
  1. ветви - это просто пара (name, hash) - ни больше, ни меньше. В ветвях есть reflog, но он никогда не показывается удаленным клиентам.
    2009-10-06 21: 03: 33Z
  2. Я бы создал master-old на удаленном, прежде чем удалить master на удаленном. Я просто параноик.
    2010-08-11 16: 58: 19Z
  3. Ответ Аристотеля, приведенный ниже, позволяет вам сделать это без удаления мастера, поэтому я думаю, что это предпочтительнее.
    2012-03-24 23: 43: 14Z
  4. было бы ясно и БЕЗОПАСНО, если бы вы могли использовать new-branch-name и old-branch-name вместо master/master-old, поэтому это общая проблема.
    2012-09-18 22: 53: 20Z
  5. Если на удаленную ветку (здесь: master) не ссылаются другие ветви, git может собрать все коммиты на этой ... ну ... "ветке". - Некоторые команды git фарфор вызывают сборку мусора. - Поэтому: сначала создайте новое имя (указывая на тот же коммит), затем удалите старое имя.
    2015-01-14 12: 35: 04Z

Предполагается, что вы находитесь на 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. Ни одно из других решений, опубликованных на момент написания этой статьи, не включало это.) р>     

253
2010-09-24 20: 26: 43Z
  1. Я согласен, что это лучший ответ, чем "ответ", но для людей, которые пришли сюда, чтобы просто переименовать ветку (явно не master), третий шаг не выполняется не имеет большого смысла.
    2012-08-28 23: 22: 07Z
  2. Это не имеет абсолютно никакого значения для ответа, находитесь ли вы на master или другой ветке. Хотя вопрос был плохо назван, он спрашивает о более сложной задаче, чем просто переименование ветви.
    2012-08-29 08: 12: 23Z
  3. Это оказалось решением, которое сработало для меня. Я пытался заменить мастера на другую ветку. Я сделал git log -1 origin /what_i_want_as_new_master, чтобы получить $new_master_commit для шага 3. После нажатия (шаг 4) другие разработчики извлекут и получат сообщения «Ваша ветвь впереди мастера на 295 коммитов». Чтобы это исправить, я разослал электронное письмо, сообщающее им о каждом запуске: git pull; git checkout some_random_branch; git branch -D master; мерзавец; мастер проверки git; По сути, им нужно удалить своего локального мастера и вытащить новую версию, в противном случае они находятся в неправильном месте локально.
    2013-11-14 22: 44: 27Z
  4. Вы могли бы сделать это гораздо проще: если бы они уже были на master, то они могли бы просто сделать git fetch && git reset --hard origin/master, чтобы заставить их локальный master быть таким же, как на origin.Я задокументировал это, а также более сложный случай, когда у вас есть локальные коммиты поверх master, которые вы хотите сохранить, в stackoverflow.com/д /4084868
    2013-11-17 06: 27: 45Z
  5. Убедитесь, что в файле удаленной конфигурации установлено значение "denyNonFastforwards = false", иначе вы получите "remote: error: отказ в отказе от перемотки вперед refs /heads /master (вы должен тянуть первым) "
    2014-05-28 13: 57: 06Z

С 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
    
151
2013-04-25 17: 22: 13Z
  1. Альтернатива --set-upstream заключается в следующем: как только ваша ветка переименована локально и удалена в источнике, просто сделайте: git push -u --all
    2013-07-09 17: 36: 26Z
  2. Это не будет работать с основной веткой, так как git не позволит вам удалить удаленный главный.
    2014-01-06 16: 23: 05Z
  3. @ AlexandreNeto В этом случае вы можете выполнить 3-ю строку перед 2-й, установить для ветви по умолчанию значение new_branch, а затем в конечном итоге удалить удаленный master со 2-й строкой.
    2015-02-03 20: 00: 56Z
  4. Удивительно простые шаги. Это лучший ответ на вопрос
    2015-02-20 10: 09: 21Z
  5. Удаление удаленной ветви git push origin --delete old_branch немного более читабельно.
    2015-10-14 03: 21: 41Z
git checkout -b new-branch-name
git push remote-name new-branch-name :old-branch-name

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

    
35
2014-03-12 11: 43: 27Z
  1. Удаляет ли какая-либо часть этого решения локальное old-branch-name или это отдельное упражнение?
    2013-09-15 12: 03: 26Z
  2. Я думаю, что в конце должен быть запущен git branch -d old-branch-name для удаления локальной старой ветви.
    2013-12-08 21: 47: 05Z
  3. Вы можете отправить изменения только одной командой: git push remote-name new-branch-name :old-branch-name.
    2014-01-15 23: 04: 18Z
  4. Таким образом, вы не усложните историю git? Потому что вместо этого вы открываете новую ветку, просто переименовываете текущую.
    2014-01-23 16: 14: 39Z
  5. @ androider No. Филиалы в git - это простые ссылки .
    2014-03-05 14: 14: 54Z

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

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

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

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

# 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
    
26
2016-10-24 16: 12: 36Z
  1. Спасибо! git merge -s ours master-old - важная часть, которую другие ответы упускают. Кроме того, «легко сделать» не означает «легко понять или выяснить», что, по-видимому, имеет место для большинства мерзавцев, но я отвлекся.
    2016-07-28 14: 50: 46Z
  2. Мне нравится тот факт, что никакие удаления не упоминаются и что переход для тех, кто работает с клонами восходящего потока, является "бесшовным". Спасибо!
    2016-11-16 03: 16: 09Z

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

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

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

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

    
11
2017-05-23 11: 54: 59Z
  1. Да, это та же проблема, просто была одна идея, как ее решить. Но даже если бы я не делал это переименование ветки, мне было бы интересно, если бы это было возможно. Я думал, что такие ссылки как "master" являются только ссылками на конкретные коммиты. Я действительно не хочу менять историю. Я думал, что просто укажу мастер-ссылку на другую голову. Это также означает, что я никогда больше не смогу использовать имя ветви, если я использовал его раньше?
    2009-10-06 17: 35: 21Z
  2. Действительно, ветви являются ссылками - указателями на коммиты. Дело в том, что мы ожидаем, что глава ветви будет развиваться определенным образом (а именно, всегда перемотка вперед). С точки зрения кого-то другого, перемещение ветки в вашем публичном репо - это то же самое, что переписывание истории ветки. Он больше не указывает на коммит, содержащий все, что он использовал.
    2009-10-06 19: 16: 15Z

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

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

    
8
2017-05-23 12: 18: 26Z
  1. На git push remote: master произойдет сбой, если это будет проверено на удаленной стороне - вы увидите "remote: error:" в качестве префикса в строках журнала ошибок.
    2015-04-13 15: 17: 13Z

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

        
    3
    2012-10-26 18: 32: 55Z
    1. Я забыл учетные данные для входа на сервер github. Кто-нибудь с полномочиями там :-P
      2013-07-23 12: 37: 14Z

    Как насчет

    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
    
        
    1
    2010-08-17 08: 21: 10Z
    1. не справляется с отслеживанием веток - пользователям, возможно, придется исправлять свои ветви локально?
      2016-10-24 15: 39: 53Z

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

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

    git branch -m my_old_branch_name my_new_branch_name
    

    Нажмите «перемещенную» ветку на пульт, установите «upstream» с помощью -u

    git push origin -u my_new_branch_name
    

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

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

    git push origin -D <old_name>
    

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

        
    1
    2017-12-08 01: 15: 25Z

    ОК , переименовать ветку как локально , так и на удаленный довольно просто! ...

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

    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> р>

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

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

        
    1
    2018-03-26 10: 51: 32Z

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

    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
    

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

        
    0
    2017-08-16 14: 04: 45Z

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

    Например:

    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
    

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

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

        
    0
    2018-04-08 17: 51: 48Z

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

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

    doublerename master-new master master-old
    

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

    # 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.

        
    - 1
    2016-07-28 15: 35: 05Z
    git update-ref newref oldref
    git update-ref -d oldref newref
    
        
    - 3
    2014-08-12 14: 33: 42Z
    1. Мне кажется, это не работает, я получаю: git update-ref trunk trunk2 fatal: trunk2: недопустимый SHA1
      2010-12-07 21: 20: 27Z
источник размещен Вот