Зробіть поточну гілку Git головною гілкою


1657

У мене є сховище в Git. Я зробив гілку, потім змінив і майстра, і гілку.

Потім, десятки комітетів пізніше, я зрозумів, що гілка знаходиться в набагато кращому стані, ніж головний, тому я хочу, щоб гілка "стала" господарем і ігнорувала зміни в програмі master.

Я не можу його об'єднати, тому що я не хочу тримати зміни на майстрі. Що я повинен зробити?

Додатково : У цьому випадку "старий" майстер вже pushперейшов до іншого сховища, наприклад, GitHub. Як це змінює речі?


2
Перевірте відповіді на дуже схоже запитання stackoverflow.com/q/2862590/151641
mloskot

4
Якщо б така ж проблема, але я просто видалив майстра і перейменований ще один філія в майстер: stackoverflow.com/a/14518201/189673
jayarjo

10
@jayarjo вам слід уникати цього, якщо можливо, тому що це перепише історію і спричинить проблеми для всіх інших, коли вони наступного разу спробують підтягнути майстра.
joelittlejohn

3
Ось чому я люблю відповідь @Jefromi. Жодної деконструкції історії архіву не триває.
froggythefrog

Відповіді:


2134

Проблема з двома іншими відповідями полягає в тому, що новий господар не має старого господаря предком, тож коли ви натиснете на нього, всі інші зіпсуються. Це те, що ви хочете зробити:

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

25
Зауважте про "стратегії" злиття git: --strategy=oursвідрізняється від --strategy=recursive -Xours. Тобто "наша" може бути стратегією сама по собі (результатом буде поточна галузь незалежно від того), або передаватися як варіант до "рекурсивної" стратегії (внесіть зміни в іншій галузі та автоматично віддайте перевагу поточним змінам гілки, коли виникає конфлікт ).
Келвін

5
Мені довелося зробити другий рядок, git merge --strategy=ours master -m "new master"щоб він працював.
лампа розжарювання

5
@Johsm Саме про це йдеться в першому реченні моєї відповіді. Якщо ви це зробите, новий майстер не матиме тієї самої історії, що і старий, що дуже погано, якщо ви хочете натиснути / потягнути. Вам потрібно мати спільний рід, щоб правильно працювати; якщо замість цього ви робите те, що говорите, тоді, коли ви намагаєтесь натиснути, це просто не вдасться, якщо ви не змусите його (бо це погано, і він намагається зупинити вас), і якщо ви змусите це, то кожен, хто згодом тягне спробує об'єднати старого і нового майстра, що, ймовірно, стане аварією поїзда.
Каскабель

4
Якщо під час злиття з'явиться редактор vi, введіть: w (для збереження): q (для виходу з vi)
Tomas Kubes

9
Ця відповідь чудово працює. Я просто хотів додати (для людей, які можуть бути новими або не впевненими), що git pushпісля цього вам потрібно буде виконати право, якщо ви хочете, щоб ваш код був висунутий на віддалений. Можливо, ви побачите попередження, як Your branch is ahead of 'origin/master' by 50 commits.це очікується. Просто натисніть! : D
chapeljuice

387

Переконайтеся, що все підсунуто до вашого віддаленого сховища (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
@Dietrick Epp: Я не впевнений, чи гарна ідея навіть запропонувати брудний шлях. Це зіпсує віддалене відстеження, відмови ... не можу придумати жодної причини, коли б ви це робили.
Каскабель

2
Ах, це хороший момент. Ви можете мати його в обох напрямках, але: git branch old-master master; git branch -f master new-master. Створіть гілку резервного копіювання свіжою, а потім безпосередньо перемістіть master до new-master. (І вибачте за неправильне написання свого імені, щойно помітив це)
Каскабель

2
@FakeName Я не зробив висновок, що не було ніяких причин це робити, просто що немає причин робити це брудно . Ви можете зробити це за допомогою звичайних команд (як у моєму попередньому коментарі) і отримати той же результат, за винятком непошкоджених непорушних і без шансів нудьгувати речей. І це гарантовано працювати, оскільки ви не зачіпаєте деталі щодо впровадження.
Каскабель

46

Перейменуйте відділення на master:

git branch -M branch_name master

11
На жаль, git не відслідковує перейменування філій, тому якщо ви вже натиснули репо на віддалений шлях, а інші мають місцеві зміни на своїй локальній старій головній гілці, вони опиняться у біді.
thSoft

чи є різниця між цим і git checkout master&&git reset --hard better_branch?
wotanii

26

З того, що я розумію, ви можете відкласти поточну гілку на існуючу гілку. По суті, це буде замінено masterтим, що ви маєте в поточній галузі:

git branch -f master HEAD

Щойно ви зробите це, ви можете зазвичай натиснути свою локальну masterгілку, можливо, і тут потрібен параметр сили :

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

Дуже просто і відмінно працював! Дві прості та зрозумілі команди git. Моє gpo repo збережено і тепер виглядає дуже чисто. Дякую!
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

Це по суті те саме , що відповідь Каскабеля . За винятком того, що "опція", яку він додав під своє рішення, вже вбудована в мій основний блок коду.

Простіше знайти такий спосіб.

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

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


14

Наведені тут рішення (перейменування гілки на "master") не наполягають на наслідках для віддаленого (GitHub) репо:

    -f
    - сила

Зазвичай команда відмовляється від оновлення віддаленого ref, який не є предком локального ref, який використовується для його перезапису. Цей прапор відключає чек. Це може призвести до втрати віддаленого сховища комісій; використовувати його обережно.

Якщо інші вже потягнули вашу репо, вони не зможуть витягнути цю нову історію майстра, не замінивши власного майстра на цю нову головну гілку GitHub (або мати справу з безліччю злиття).
Існують альтернативи git push - сила для публічних репостів .
Відповідь Джефромі (злиття правої зміни повертається до початкового майстра) - одна з них.


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

а потім здійснити всі зміни.


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>

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 :

  • Клацніть правою кнопкою миші на вузлі проекту.
  • Виберіть команду → потім розширений → потім перейменувати гілку
  • Потім розгорніть віддалене відстеження папку .
  • Виберіть гілку з неправильною назвою, потім натисніть кнопку перейменування, перейменуйте її на будь-яку нову назву.
  • Виберіть нового майстра, а потім перейменуйте його на головний.

Я це зробив, але не впевнений, чи спрацювало це. На github нічого не змінилося, але на розширеннях git, я бачу, гілка була перейменована.
Pramod

0

Наступні кроки виконуються в браузері Git, що працює від Atlassian (сервер Bitbucket)

Зробити {current-branch} як master

  1. Створіть гілку masterі назвіть її «головний-дублікат».
  2. Створіть гілку з {current-branch} та назвіть її "{current-branch} -copy".
  3. У налаштуваннях сховища (Bitbucket) змініть параметр "Відділення за замовчуванням" на "головний-дублікат" (без цього кроку ви не зможете видалити майстер - "На наступному кроці").
  4. Видалити гілку "master" - я зробив цей крок із вихідного дерева (ви можете зробити це з браузера CLI або Git)
  5. Перейменуйте "{current-branch}" на "master" і натисніть на сховище (це створить нову гілку "master" все ще "{current-branch}" буде існувати).
  6. У налаштуваннях сховища змініть "Відділення за замовчуванням" на "Головне"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.