Який найкращий (і найбезпечніший) спосіб об’єднати гіт Git у master?


2102

Створено нову гілку master, яку ми називаємо test.

Є кілька розробників, які або зобов’язуються masterстворювати інші гілки, і пізніше об'єднуються в master.

Скажімо, робота над цим testзаймає кілька днів, і ви хочете постійно testоновлюватись із зобов’язаннями всередині master.

Я б зробив git pull origin masterз test.

Питання 1: Це правильний підхід? Інші розробники могли легко працювати над тими ж файлами, що і я працював у btw.


Моя робота над testвиконана, і я готовий повернути її назад master. Ось два способи я можу придумати:

A:

git checkout test
git pull origin master
git push origin test
git checkout master
git pull origin test 

B:

git checkout test
git pull origin master
git checkout master
git merge test

Я не використовую, --rebaseтому що, наскільки я розумію, Rebase отримає зміни masterта встановить мою поверх, отже, це може замінити зміни, внесені іншими людьми.

Запитання 2: Який із цих двох методів правильний? Яка там різниця?

Ціль у всьому цьому полягає в тому, щоб моє testвідділення оновлювалося тим, що відбувається, masterі пізніше я міг би їх об'єднати назад, masterсподіваючись зберегти часову шкалу якомога лінійніше.


18
ні .. база даних ніколи не перезаписується, вона просто намагається досягти більш чистої історії.
повторним підключенням

7
Rebase не замінює ваші зобов’язання. Він скасовує ваші зобов’язання, застосовує коміти в головній гілці до вашої тестової гілки, а потім застосовує ваші зобов’язання назад для тестування.
зунді

Відповіді:


2992

Як я це зробив би

git checkout master
git pull origin master
git merge test
git push origin master

Якщо у мене є локальне відділення з віддаленого, я не відчуваю себе комфортно при злитті інших гілок, крім цієї, з віддаленою. Крім того, я б не наполягав на своїх змінах, поки я не задоволений тим, що хочу натиснути, і я взагалі не підштовхую речі, які є лише для мене та мого місцевого сховища. З вашого опису, здається, testце тільки для вас? Тож немає підстав публікувати його.

git завжди намагається поважати ваші та інші зміни, і так буде --rebase. Я не думаю, що я можу це пояснити належним чином, тому погляньте на книгу Git - Rebasing або git-ready: Введіть рибалінг для невеликого опису. Це досить класна функція


2
git merge testдає мені fatal: 'test' does not point to a commit. Мені потрібно шукати git logточку фіксації на тестовій гілці, повертатися назад у головну гілку, тоді робити git merge 0f37d3154abbf52a4cbbbb5109f08af6a7567234.
Данканму

17
@Duncanmoo Ну, звичайно, філія testповинна існувати. Звичайно, ви можете використовувати хеш фіксації замість цього, але зазвичай простіше використовувати назву гілки. Всередині він просто витягує хеш HEADгілки.
KingCrunch

44
@shanyangqu Щоб отримати останні зміни з пульта. Якщо ви працюєте поодинці і тільки з однією системою, то жодних проблем не буде. Але коли є зміни, висунуті з іншої системи (можливо, від іншого розробника), ви побачите конфлікт, як тільки спробуєте відсунути об'єднання назад (четвертий крок). Єдине рішення тепер - це об'єднати місцевого майстра з віддаленим майстром, який закінчується досить потворним "об'єднаним майстром у походження / майстер" об'єднання. Тому завжди корисно здійснити тягу перед злиттям
KingCrunch

7
"Згідно з вашим описом, здається, що тест лише для вас? Тож немає підстав публікувати його". Можливо, ви захочете підключити свою локальну гілку до сервера, якщо, наприклад, цей сервер надає резервну копію, якщо ваш локальний диск не працює, або якщо у вас немає іншого способу зробити резервну копію.
Ерік

5
"... Крім того, я б не наполягав на своїх змінах, поки я не задоволений тим, що хочу натиснути ..." чому б не наполягати на тому, щоб створити резервну копію вашого коду, якщо ваші місцеві машини вмирають і дні зусиль пішли?
Багатий камінь

400

Це дуже практичне запитання, але всі відповіді вище не практичні.

Подібно до

git checkout master
git pull origin master
git merge test
git push origin master

Цей підхід має два питання :

  1. Це небезпечно, тому що ми не знаємо, чи є конфлікти між тестовою гілкою та основною гілкою.

  2. Це "видавить" усі тестові завдання в один об'єкт злиття для головного; тобто на головній гілці, ми не можемо побачити всі журнали змін тестової гілки.

Отже, коли ми підозрюємо, що виникнуть якісь конфлікти, ми можемо мати наступні операції git:

git checkout test
git pull 
git checkout master
git pull
git merge --no-ff --no-commit test

Випробуйте mergeраніше commit, уникайте швидкого переходу вперед --no-ff,

Якщо виник конфлікт, ми можемо побігти git statusперевірити деталі конфліктів і спробувати вирішити

git status

Після того, як ми вирішимо конфлікти, або , якщо немає конфлікту, ми commitі pushїх

git commit -m 'merge test branch'
git push

Але цей спосіб втратить історію змін, зафіксованих у тестовій гілці, і іншим розробникам було б важко зрозуміти історію проекту.

Тож найкращим методом є те, що ми повинні використовувати rebaseзамість цього merge(припустимо, коли за цей час ми вирішили галузеві конфлікти).

Нижче наводиться один простий зразок. Для розширених операцій зверніться до http://git-scm.com/book/en/v2/Git-Branching-Rebasing

git checkout master
git pull
git checkout test
git pull
git rebase -i master
git checkout master
git merge test

Так, коли ви завершите роботу, усі доручення тестування будуть перенесені на голову відділення Master. Основна перевага звільнення полягає в тому, що ви отримуєте лінійну та набагато чіткішу історію проекту.

Єдине, чого потрібно уникати: ніколи не використовуйте rebaseна публічній гілці, як головна гілка.

Ніколи не робіть таких операцій :

git checkout master
git rebase -i test

Деталі для https://www.atlassian.com/git/tutorials/merging-vs-rebasing/the-golden-rule-of-rebasing

додаток:


4
Я погоджуюся звільнення тестової гілки для подальшого об'єднання в майстер - це шлях. Навіть інші відповіді правильні, це збереже історію змін тесту філії в голові майстра, оскільки автор згадує "Ви отримуєте проект для вкладишів та набагато чистіших", що є метою системи управління версіями.
le0diaz

16
Заява "це не один безпечний спосіб, тому що ми не знаємо, чи є конфлікти між тестовою гілкою та основною гілкою" не відповідає дійсності: завжди можна скасувати злиття. І навіть якщо немає конфліктів, ви завжди можете скасувати останнє місцеве зобов'язання до тих пір, поки воно не буде висунуте. Без правильного розуміння git деякі речі можуть здатися трохи страшними або незрозумілими, але "небезпечно" просто неправильно. Будьте обережні, щоб не плутати інших з невірною інформацією.
Пол ван Левен

4
погоджуйтесь з @PaulvanLeeuwen, коли ви збираєте об'єднати тестову гілку в головну, вам буде повідомлено про конфлікти, і там ви вступатимете та об'єднуєте зміни. Як тільки ви закінчите, ви зробите злиття і відштовхнетесь. Якщо ви пошкодуєте чи не можете здатися, що це правильно злилося, ви завжди можете відмовитися від роботи та знову відійти від майстра. Так що це точно не небезпечно ..
Хуан

3
чому rebase -i?
MushyPeas

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

90

Ні ребаза, ні злиття не повинні перезаписувати будь-які зміни (якщо ви не вирішите це зробити при вирішенні конфлікту).

Звичайний підхід при розробці - це

git checkout master
git pull
git checkout test
git log master.. # if you're curious
git merge origin/test # to update your local test from the fetch in the pull earlier

Коли ви будете готові знову об'єднатися в майстер,

git checkout master
git log ..test # if you're curious
git merge test
git push

Якщо ви переживаєте про те, щоб щось зламати на злитті, git merge --abortє для вас.

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


1
Цей процес збільшуватиме кількість комісій, кожного разу, коли ви переходите між гілками, вам доведеться ввести філію.
iBug

2
Що? Ви хочете сказати, що це збільшуватиме кількість комісій щоразу, коли ви перемикаєте гілки? Або ти кажеш, що кожного разу, коли ти перемикаєш гілки, ти маєш "фіксувати свою гілку"? Перше - неправда, і я не впевнений, що означає другий.
raylu

перед оформленням замовлення вам доведеться скористатись відділенням. це те, що я говорю
iBug

11
Ви цього не робите: це (одна з речей) git stash- для.
msanford

1
Або ви можете змінити свій останній вчинок (у місцевому відділенні) і зробити його ідеальним, перш ніж натискати.
whihathac

42

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

Крім відповіді KingCrunches , я пропоную використовувати

git checkout master
git pull origin master
git merge --squash test
git commit
git push origin master

Можливо, ви зробили багато комісій в іншій гілці, яка повинна бути лише однією фіксацією в головній гілці. Щоб зберегти історію фіксації якомога більш чистою, ви, можливо, захочете скосати всі свої зобов’язання з тестової гілки на одну команду в головній гілці (див. Також: Git: Сквош або не сквош? ). Тоді ви також можете переписати повідомлення про фіксацію на щось дуже виразне. Щось, що легко читати та розуміти, не занурюючись у код.

редагувати: Вас може зацікавити

Отже, на GitHub я в кінці кінців роблю наступне для функції функції mybranch:

Отримайте останню інформацію про походження

$ git checkout master
$ git pull origin master

Знайдіть хеш бази злиття:

$ git merge-base mybranch master
c193ea5e11f5699ae1f58b5b7029d1097395196f

$ git checkout mybranch
$ git rebase -i c193ea5e11f5699ae1f58b5b7029d1097395196f

Тепер переконайтесь, що тільки перший pick, решта s:

pick 00f1e76 Add first draft of the Pflichtenheft
s d1c84b6 Update to two class problem
s 7486cd8 Explain steps better

Далі виберіть дуже гарне повідомлення про фіксацію та натисніть на GitHub. Зробіть запит на витяг.

Після об'єднання запиту на виклик ви можете видалити його локально:

$ git branch -d mybranch

і на GitHub

$ git push origin :mybranch

" який повинен бути лише одним комітом у головній галузі ", ну не обов'язково; ви, можливо, захочете зберегти історію
Cocowalla

Звичайно. Але тоді просто не розбивайте коміти
Мартін Тома,

Я думаю - перший батько здається найкращим рішенням. davidchudzicki.com/posts/first-parent
bkribbs

7

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

Оновіть майстер та відділення:

git checkout master
git pull --rebase origin master
git checkout <branch_name>
git pull --rebase origin <branch_name>

Об’єднати відділення поверх головного майстра:

git checkout <branch_name>
git rebase master

Необов’язково: Якщо ви зіткнулися з конфліктами під час Rebase:

Спочатку вирішіть конфлікт у файлі. Тоді:

git add .
git rebase --continue

Натисніть свою відновлювану гілку:

git push origin <branch_name>

Тепер у вас є два варіанти:

  • A) Створіть PR (наприклад, на GitHub) і об'єднайте його там через інтерфейс користувача
  • В) Поверніться в командному рядку і об'єднайте гілку в головний
git checkout master
git merge --no-ff <branch_name>
git push origin master

Зроблено.


6

Це робочий процес, який я використовую у своїй роботі з колективом. Сценарій такий, як ви описали. По-перше, коли я закінчую роботу, testя переспівуюсь з майстром, щоб втягнути все, що було додано до майстра за час, коли я працював у testгалузі.

git pull -r upstream master

Це призведе до зміни змін до головного моменту, оскільки ви роздрібнили testгілку та застосуєте їх, а потім застосуйте внесені вами зміни, щоб перевірити "поверх" поточний стан головного. Тут можуть виникнути конфлікти, якщо інші люди внесли зміни до тих самих файлів, які ви редагували в тесті. Якщо вони є, вам доведеться виправити їх вручну та зробити фіксацію. Як тільки ви це зробите, вам буде зручно перейти на головну гілку і злитися testбез проблем.


3
git checkout master
git pull origin master
# Merge branch test into master
git merge test

Після об'єднання, якщо файл буде змінено, то при злитті він стане через помилку "Вирішити конфлікт"

Тоді вам потрібно спочатку вирішити всі свої конфлікти, потім вам доведеться знову здійснити всі зміни, а потім натиснути

git push origin master

Це краще зробити тому, хто змінив тест-галузь, тому що він знав, які зміни він зробив.


3

Я б використав метод rebase. Переважно тому, що це прекрасно відображає вашу справу семантично, тобто. що ви хочете зробити - це оновити стан вашої поточної філії та "зробити вигляд" так, ніби воно було засноване на останніх.

Отже, навіть не перевіряючи master, я б:

git fetch origin
git rebase -i origin/master
# ...solve possible conflicts here

Звичайно, лише отримання даних від походження не оновлює локальний стан вашого master(оскільки він не здійснює злиття), але це цілком нормально для нашої мети - ми хочемо уникати перемикань, заради економії часу.


2

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

git checkout test
git pull
git checkout master
git pull origin master
git merge test
git push origin master

0

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

git checkout master
git pull

Не потрібно спочатку перевіряти; rebase робить правильну справу з двома аргументами

git rebase master test  

git checkout master
git merge test

git push за замовчуванням відсуває всі гілки, які існують тут і на пульті

git push
git checkout test

0

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

З: https://git-scm.com/docs/merge-strategies

З цією опцією "злиття-рекурсивний" витрачає трохи додаткового часу, щоб уникнути занурень, які іноді трапляються через неважливі відповідні лінії (наприклад, дужки з різних функцій). Використовуйте це, коли гілки, які потрібно об'єднати, дико розходяться. Див. Також git-diff [1] - хвороба.

Використання:

git fetch
git merge -s recursive -X patience origin/master

Git Alias

Для цього я завжди використовую псевдонім, наприклад, запустіть один раз:

 git config --global alias.pmerge 'merge -s recursive -X patience'

Тепер ви можете зробити:

git fetch
git pmerge origin/master


0

Я відповім відповідно до галузей розробки та функції,

якщо ви перебуваєте у відділенні функції та вам потрібно оновити його за допомогою команд розробки нижче: команда git checkout розробити функцію git pull git checkout / xyz git merge

Тепер ваша функція оновлюється з розвитком, ви можете натиснути свої зміни.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.