Сделайте текущую ветку Git главной веткой

1658

У меня есть хранилище в Git. Я сделал ветку, затем сделал некоторые изменения как в мастере, так и в ветке.

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

Я не могу объединить это, потому что я не хочу сохранять изменения на мастере. Что мне делать?

Дополнительно : в этом случае «старый» мастер уже был pushподключен к другому хранилищу, такому как GitHub. Как это меняет вещи?

Карел Билек
источник
2
Проверьте ответы на очень похожий вопрос stackoverflow.com/q/2862590/151641
mloskot
4
У меня была та же проблема, однако я просто удалил мастер и переименовал другую ветку в мастер: stackoverflow.com/a/14518201/189673
jayarjo
10
@jayarjo вы должны избегать этого, если возможно, потому что это переписает историю и вызовет проблемы для всех остальных, когда они в следующий раз попытаются вытащить мастера.
Joelittlejohn
3
Вот почему я люблю ответ @Jefromi. Никакой деконструкции истории архива не происходит.
froggythefrog

Ответы:

2136

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

git checkout better_branch
git merge --strategy=ours master    # keep the content of this branch, but record a merge
git checkout master
git merge better_branch             # fast-forward master up to the merge

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

git merge --strategy=ours --no-commit master
git commit          # add information to the template merge message
Cascabel
источник
25
Заметка о слиянии git "стратегии": --strategy=oursотличается от --strategy=recursive -Xours. Т.е. «наша» может быть стратегией сама по себе (результатом будет текущая ветка, не смотря ни на что) или передаваться в качестве опции «рекурсивной» стратегии (вносить изменения в другую ветку и автоматически отдавать предпочтение изменениям текущей ветви в случае конфликта ).
Кельвин
5
Я должен был сделать вторую строку, git merge --strategy=ours master -m "new master"чтобы это работало.
Лампа накаливания
5
@Johsm Это именно то, о чем говорится в первом предложении моего ответа. Если вы сделаете это, новый мастер не будет иметь ту же историю, что и старый мастер, что очень плохо, если вы хотите нажать / вытащить. Вы должны иметь общее происхождение, чтобы это работало правильно; если вместо этого вы делаете то, что говорите, то, когда вы пытаетесь подтолкнуть его, он просто потерпит неудачу, если вы не заставите его (потому что это плохо, и он пытается остановить вас), и если вы действительно заставите его, то любой, кто впоследствии тянет будет пытаться объединить старого мастера и нового мастера, что, вероятно, будет крушение поезда.
Каскабель
4
Если во время слияния появляется редактор vi, введите: w (для сохранения): q (для выхода из vi)
Томас Кубес
9
Этот ответ прекрасно работает. Я просто хотел добавить (для людей, которые могут быть новичками или неуверенными), что после этого вам придется делать git pushправильные действия, если вы хотите, чтобы ваш код был удален. Вы можете увидеть предупреждение, как Your branch is ahead of 'origin/master' by 50 commits.это ожидается. Просто нажми! : D
chapeljuice
388

Убедитесь, что все загружено в ваш удаленный репозиторий (GitHub):

git checkout master

Переписать «master» с «better_branch»:

git reset --hard better_branch

Принудительно нажмите на ваш удаленный репозиторий:

git push -f origin master
Брэндон Ховард
источник
81
Это, вероятно, ответ, который ищут большинство людей. Все остальные ответы со слиянием стратегии BS не заменяют полностью ветку. Это сделало все так, как я хотел, просто переписать ветку и подтолкнуть ее вверх.
Губатрон
31
хотя это действительно то, что многие ищут, следует отметить, что любые другие локальные копии репо понадобятся в git reset --hard origin/masterследующий раз, когда они захотят извлечь, иначе git попытается объединить изменения с их (теперь) расходящимися локальными. Опасности этого объясняются больше в этом ответе
7yl4r
3
Также обратите внимание, что вам нужно разрешить принудительное добавление в хранилище - например, в бизнес-среде это не сработает
inetphantom
Плюс здесь также может быть минусом в зависимости от того, чего хотят люди. Если вы хотите пойти дальше, заменив историю мастера на историю другой ветки, это ваш ответ.
b15
75

Редактировать: Вы не сказали, что подтолкнули к публичному репо! Это делает мир различий.

Есть два пути: «грязный» и «чистый». Предположим, что ваша ветка названа new-master. Это чистый способ:

git checkout new-master
git branch -m master old-master
git branch -m new-master master
# And don't do this part.  Just don't.  But if you want to...
# git branch -d --force old-master

Это изменит конфигурационные файлы в соответствии с переименованными ветками.

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

mv -i .git/refs/new-master .git/refs/master
git checkout master
Дитрих Эпп
источник
2
Спасибо. Еще один вопрос. Я подталкиваю это к github. Что там будет, если я это сделаю?
Карел Билек
3
@Karel: это создаст беспорядок для других пользователей; им придется сбросить своего хозяина на мастера github. Если вы хотите избежать неприятностей, взгляните на мой ответ.
Каскабель
6
@ Дитрик Эпп: Я не уверен, что это хорошая идея, даже предложить грязный путь. Это может испортить удаленное отслеживание, повторные журналы ... не могу придумать причину, по которой вы когда-либо это сделаете.
Каскабель
2
Ах, это хороший момент. Вы можете иметь его в обоих направлениях, но: git branch old-master master; git branch -f master new-master. Создайте резервную копию новой ветки, а затем непосредственно переместите мастер на новый мастер. (И извините за неправильное написание вашего имени, только что заметил)
Каскабель
2
@FakeName Я не пришел к выводу, что не было никаких причин делать это, просто нет причин делать это грязным путем . Вы можете сделать это, используя обычные команды (как в моем предыдущем комментарии), и получить тот же результат, за исключением случаев, когда у вас нет неповрежденных повторных флагов, и нет никаких шансов потерять все. И это гарантированно работает, так как вы не копаетесь в деталях реализации.
Каскабель
46

Переименуйте ветку в master:

git branch -M branch_name master
Алан Хаггай Алави
источник
11
К сожалению, git не отслеживает переименования веток, поэтому, если вы уже перенесли репо на удаленный компьютер, а другие имеют локальные изменения в своей старой локальной ветке master, у них будут проблемы.
thSoft
есть ли разница между этим и git checkout master&&git reset --hard better_branch?
wotanii
26

Из того, что я понимаю, вы можете ветвить текущую ветку в существующую ветку. По сути, это перезапишет masterвсе, что у вас есть в текущей ветке:

git branch -f master HEAD

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

git push -f origin master

Нет слияний, нет длинных команд. Просто branchи push- но, да, это будет переписать историю в masterотрасли, так что если вы работаете в команде , вы получили , чтобы знать , что вы делаете.




В качестве альтернативы я обнаружил, что вы можете перенести любую ветку в любую удаленную ветку, поэтому:

# This will force push the current branch to the remote master
git push -f origin HEAD:master

# Switch current branch to master
git checkout master

# Reset the local master branch to what's on the remote
git reset --hard origin/master
fregante
источник
Очень просто и отлично работает! Две простые и понятные команды git. Мой репозиторий git сохранен и теперь выглядит очень чисто. Спасибо!
thehelix
16

Я нашел ответ, который хотел найти в записи блога. Замените основную ветку другой веткой в ​​git :

git checkout feature_branch
git merge -s ours --no-commit master
git commit      # Add a message regarding the replacement that you just did
git checkout master
git merge feature_branch

По сути, это то же самое, что и ответ Каскабель . За исключением того, что «вариант» он добавил ниже своего решения, уже встроена в мой основной блок кода.

Так проще найти.

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

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

SherylHohman
источник
14

Приведенные здесь решения (переименование ветки в «master») не настаивают на последствиях для удаленного (GitHub) репо:

    -f
    --force

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

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

VonC
источник
14

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

Цель: сделать текущее состояние "филиала" "мастером"

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

git checkout master      # Set local repository to master
git reset --hard branch  # Force working tree and index to branch
git push origin master    # Update remote repository

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

Марк Дител
источник
10

Также можно извлечь все файлы из другой ветки в master:

git checkout master
git checkout better_branch -- .

и затем передайте все изменения.

user2064284
источник
5

Чтобы добавить к ответу Джефроми, если вы не хотите помещать бессмысленное слияние в историю sourceветви, вы можете создать временную ветку для oursслияния, а затем выбросить ее:

git checkout <source>
git checkout -b temp            # temporary branch for merge
git merge -s ours <target>      # create merge commit with contents of <source>
git checkout <target>           # fast forward <target> to merge commit
git merge temp                  # ...
git branch -d temp              # throw temporary branch away

Таким образом, коммит слияния будет существовать только в истории targetветки.

В качестве альтернативы, если вы вообще не хотите создавать слияние, вы можете просто взять содержимое sourceи использовать его для нового коммита target:

git checkout <source>                          # fill index with contents of <source>
git symbolic-ref HEAD <target>                 # tell git we're committing on <target>
git commit -m "Setting contents to <source>"   # make an ordinary commit with the contents of <source>
staafl
источник
3

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

Пока на разработке:

git checkout master
git pull

git checkout develop
git pull

git reset --hard origin/master
git push -f
Браден Борман
источник
2

Мой способ ведения дел заключается в следующем

#Backup branch
git checkout -b master_backup
git push origin master_backup
git checkout master
#Hard Reset master branch to the last common commit
git reset --hard e8c8597
#Merge
git merge develop
ар-г
источник
2

Если вы используете eGit в Eclipse :

  • Щелкните правой кнопкой мыши на узле проекта.
  • Выберите Team → затем Advanced → затем переименовать ветку
  • Затем разверните папку удаленного отслеживания .
  • Выберите ветку с неправильным именем, затем нажмите кнопку переименования, переименуйте ее в любое новое имя.
  • Выберите нового мастера, затем переименуйте его в мастера.
Юнчен Лю
источник
Я сделал это, но не уверен, сработало ли это. На github ничего не изменилось, но на расширениях git я вижу, что ветка была переименована.
Прамод
0

Следующие шаги выполняются в браузере Git на платформе Atlassian (сервер Bitbucket)

Делая {current-branch} как master

  1. Сделайте из него ветку masterи назовите ее «master-duplicate».
  2. Сделайте ветку из {current-branch} и назовите ее «{current-branch} -copy».
  3. В настройках репозитория (Bitbucket) измените «Ветвь по умолчанию», указав на «master-duplicate» (без этого шага вы не сможете удалить master - «На следующем шаге»).
  4. Удалить «главную» ветку - я сделал этот шаг из дерева исходных текстов (вы можете сделать это из CLI или браузера Git)
  5. Переименуйте «{current-branch}» в «master» и нажмите в хранилище (это создаст новую «master» ветку, но «{current-branch}» будет существовать).
  6. В настройках репозитория измените «Ветвь по умолчанию», чтобы указать на «мастер».
Purushothaman
источник