Новые кодеры иногда пишут такой код:
my_calculator.button_0 = tkinter.Button(root, text=0)
my_calculator.button_1 = tkinter.Button(root, text=1)
my_calculator.button_2 = tkinter.Button(root, text=2)
...
Затем кодер остается с кучей именованных переменных с усилием кодирования O ( m * n ), где m - это число именованных переменных, а n - это количество раз, к которому необходимо получить доступ к группе переменных (включая создание) , Более проницательный новичок отмечает, что единственная разница в каждой из этих строк - это число, которое изменяется на основе правила и решает использовать цикл. Тем не менее, они зациклились на том, как динамически создавать эти имена переменных, и могут попробовать что-то вроде этого:
for i in range(10):
my_calculator.('button_%d' % i) = tkinter.Button(root, text=i)
Вскоре они обнаруживают, что это не сработает.
Если программа требует произвольных переменных «имена», лучше всего подходит словарь, как объясняется в других ответах. Однако, если вы просто пытаетесь создать много переменных, и вы не возражаете ссылаться на них с последовательностью целых чисел, вы, вероятно, ищете list
. Это особенно верно, если ваши данные однородны, например, ежедневные показания температуры, еженедельные оценки викторины или сетка графических виджета.
Это можно собрать следующим образом:
my_calculator.buttons = []
for i in range(10):
my_calculator.buttons.append(tkinter.Button(root, text=i))
Этот list
также может быть создан в одной строке с пониманием:
my_calculator.buttons = [tkinter.Button(root, text=i) for i in range(10)]
Результат в любом случае - это заполненный list
, с первым элементом, к которому обращаются с помощью my_calculator.buttons[0]
, следующего с my_calculator.buttons[1]
и т. д. Имя переменной «base» становится именем list
, и для доступа к нему используется различный идентификатор.
Наконец, не забудьте другие структуры данных, такие как set
- это аналогично словарю, за исключением того, что каждое «имя» не имеет привязанного к нему значения. Если вам просто нужна «сумка» объектов, это может быть отличным выбором. Вместо этого:
keyword_1 = 'apple'
keyword_2 = 'banana'
if query == keyword_1 or query == keyword_2:
print('Match.')
У вас будет следующее:
keywords = {'apple', 'banana'}
if query in keywords:
print('Match.')
Используйте последовательность list
для последовательности похожих объектов, a set
для произвольного - помещенный пакет предметов или dict
для мешка с именами со связанными значениями.
Хотя слияние, безусловно, самый простой и наиболее распространенный способ интеграции изменений, это не единственный: Rebase является альтернативным средством интеграции.
Понимание слияния немного лучше
Когда Git выполняет слияние, он ищет три коммиты:
Fast-Forward или Merge Commit
В очень простых случаях одна из двух ветвей не работает [new]
В этом случае выполнение интеграции мертво simple: Git может просто добавить все коммиты другой ветви поверх общей фиксации предка. В Git эта простейшая форма интеграции называется «быстрым» слиянием. Обе ветви тогда имеют одну и ту же историю.
Однако во многих случаях обе ветви перемещались индивидуально.
Чтобы выполнить интеграцию, Git должен будет создать новый коммит, содержащий различия между ними - слияние.
Человеческие комманды & amp; Merge Commits
Обычно коммит тщательно создается человеком. Это значимая единица, которая обертывает только связанные изменения и комментирует их комментарием.
Согласование слияния немного отличается: вместо создания разработчиком он автоматически создается Git. И вместо того, чтобы обернуть набор связанных изменений, его цель - соединить две ветви, точно так же, как узел. Если вы хотите понять операцию слияния позже, вам нужно взглянуть на историю обеих ветвей и соответствующий граф фиксации.
Интеграция с Rebase
Некоторые люди предпочитают идти без таких автоматических слияний. Вместо этого они хотят, чтобы история проекта выглядела так, как если бы она эволюционировала по одной прямой. Пока нет указаний на то, что в какой-то момент она была разбита на несколько ветвей.
Давайте шаг за шагом проведем операцию по перестановке. Сценарий такой же, как в предыдущих примерах: мы хотим интегрировать изменения из ветки-B в ветвь-A, но теперь с помощью rebase.
Мы сделаем это в три этапа
git rebase branch-A // syncs the history with branch-A
git checkout branch-A // change the current branch to branch-A
git merge branch-B // merge/take the changes from branch-B to branch-A
Во-первых, Git «отменит» все фиксации на ветке-A, которая произошла после того, как линии начали разветвляться (после того, как общий предок совершил). Однако, конечно, он не отбросит их: вместо этого вы можете думать о том, что эти фиксации являются «временно сохраненными».
Затем, он применяет фиксации от ветви-B, которую мы хотим интегрировать. На этом этапе обе ветви выглядят одинаково.
На последнем этапе новые фиксации на ветке-A теперь снова применяются, но на новая позиция, поверх интегрированных коммитов из ветки-B (они основаны на повторной основе). Результат выглядит так, как будто развитие произошло по прямой. Вместо компиляции слияния, которая содержит все объединенные изменения, исходная структура фиксации была сохранена.
Наконец, вы получаете чистую ветвь ветки A с никакие нежелательные и автоматически сгенерированные коммиты.
Примечание: взято из удивительной записи на git-tower
. Недостатки of rebase
также хорошо читаются в том же сообщении.
Это просто, с rebase вы говорите, что используете новую ветку в качестве новой базы для вашей работы.
Если у вас есть ветка master
и вы создаете ветку для реализации новой функции, скажем, вы назовете его cool-feature
, конечно, главная ветка является базой для вашей новой функции.
Теперь в определенный момент вы хотите добавить новую функцию, реализованную в ветви master
. Вы можете просто переключиться на master
и объединить ветвь cool-feature
:
$git checkout master
$git merge cool-feature
, но таким образом добавляется новая фиктивная фиксация, если вы хотите избежать спагетти-истории, которую вы можете переустановить:
$git checkout cool-feature
$git rebase master
, а затем объединить его в master
:
$git checkout master
$git merge cool-feature
На этот раз, поскольку ветвь темы имеет те же самые коммиты мастера плюс фиксации с новой функцией, слияние будет просто быстрой перемоткой вперед.
but this way a new dummy commit is added, if you want to avoid spaghetti-history
- Как это плохо?
– アレックス
19 May 2014 в 15:07
Sean Schofield
помещает его в комментарий: «Rebase также хорош, потому что, как только u в конечном итоге объединит ур материал обратно в master (что тривиально, как уже описано), у вас есть сидение в верхней части страницы. истории фиксации ур. В более крупных проектах, где функции могут быть записаны, но объединены через несколько недель, вы не хотите просто объединять их в мастер, потому что они получают "stuffed & quot; в мастер путь назад в истории. Лично мне нравится иметь возможность делать git log и видеть, что недавняя функция прямо на вершине. Обратите внимание, что даты фиксации сохраняются - rebase не изменяет эту информацию. & Quot;
– Adrien Be
1 March 2016 в 05:37
merge
, rebase
, fast-forward
и т. Д.) Относятся к конкретным манипуляциям направленного ациклического графа. Им становится легче рассуждать с учетом этой ментальной модели.
– Roy Tinker
27 January 2017 в 20:24
Многие ответы здесь говорят о том, что слияние превращает все ваши коммиты в одну, и поэтому предлагаю использовать rebase для сохранения ваших коммитов. Это неверно. И плохая идея, если вы уже сделали свои коммиты.
Слияние not уничтожает ваши коммиты. Слияние сохраняет историю! (просто посмотрите на gitk) Rebase перезаписывает историю, которая является Bad Thing после того, как вы нажали .
Использовать слияние - не переустанавливать всякий раз, когда вы уже нажали.
Вот Линус (автор git) берет на себя . Это действительно хорошо читать. Или вы можете прочитать мою собственную версию той же идеи ниже.
Снятие ветви на master:
Напротив, объединение ветви темы в master:
Объединить означает: создать новый новый коммит, который объединяет мои изменения в пункт назначения.
Rebase означает: Создайте целую серию коммитов, используя мой текущий набор коммитов в качестве подсказок. Другими словами, вычислите, как мои изменения выглядели бы, если бы я начал делать их с того момента, когда я перестраиваю. Поэтому после переустановки вам может потребоваться повторная проверка ваших изменений и во время переустановки, возможно, у вас будет несколько конфликтов.
Учитывая это, зачем вам переустанавливать? Просто чтобы история развития была ясна. Предположим, вы работаете над функцией X, и когда вы закончите, вы объедините свои изменения. Теперь у получателя будет одно коммит, который будет говорить что-то в строках «Добавлена функция X». Теперь вместо слияния, если вы переустановили и затем объединили, история развития назначения будет содержать все отдельные коммиты в одной логической прогрессии. Это значительно облегчает анализ изменений. Представьте, как бы вы могли найти его, чтобы просмотреть историю развития, если 50 разработчиков все время объединяли различные функции.
Тем не менее, если вы уже нажали на ветку, над которой вы работаете, она не должна пересобираться, а вместо этого слить. Для ветвей, которые не были выдвинуты вверх по течению, переустановите, протестируйте и слейте.
В другой раз, когда вы захотите переустановить, вы должны избавиться от коммитов из своей ветки, прежде чем нажать вверх. Например: Commits, которые вводят некоторый код отладки на ранней стадии, а другие фиксируют далее, что очищают этот код. Единственный способ сделать это - выполнить интерактивную rebase: git rebase -i <branch/commit/tag>
UPDATE: вы также хотите использовать rebase, когда вы используете Git для взаимодействия с системой управления версиями, которая не поддерживает (например, подрывная история). При использовании моста git-svn очень важно, чтобы изменения, которые вы объединили обратно в subversion, представляют собой последовательный список изменений поверх последних изменений в магистрали. Есть только два способа сделать это: (1) Вручную заново создать изменения и (2) Использовать команду rebase, которая намного быстрее.
UPDATE2: Еще один способ подумать о переустановке заключается в том, что он позволяет сопоставить вид вашего стиля разработки с стилем, принятым в репозитории, в который вы совершаете. Предположим, вы любите совершать в маленьких крошечных кусках. У вас есть одна фиксация, чтобы исправить опечатку, одну фиксацию, чтобы избавиться от неиспользуемого кода и так далее. Когда вы закончите то, что вам нужно сделать, у вас есть длинная серия коммитов. Теперь предположим, что репозиторий, который вы совершаете, поощряет большие коммиты, поэтому для работы, которую вы делаете, можно ожидать одного или двух коммитов. Как вы берете свою строку коммитов и сжимаете их до ожидаемого? Вы бы использовали интерактивную переработку и сквош, чтобы ваши крошечные коммиты превращались в более маленькие куски. То же самое верно, если обратное было необходимо - если ваш стиль был несколькими крупными коммитами, но репо требовало длинные строки мелких коммитов. Для этого вы также будете использовать rebase. Если бы вы слились вместо этого, теперь вы перенесли свой стиль фиксации в основной репозиторий. Если есть много разработчиков, вы можете себе представить, как тяжело было бы следить за историей с несколькими разными стилями фиксации через некоторое время.
UPDATE3: Does one still need to merge after a successful rebase?
Да. Причина в том, что перебаза по существу включает в себя «переключение» коммитов. Как я уже сказал выше, эти коммиты вычисляются, но если у вас было 14 коммитов от точки ветвления, то при условии, что с вашей перестановкой ничего не получится, вы будете на 14 коммитов вперед (с того момента, когда вы переустанавливаете) после rebase делается. У вас была ветка до переустановки. После этого у вас будет ветка одинаковой длины. Вам все равно нужно объединиться, прежде чем публиковать свои изменения. Другими словами, rebase столько раз, сколько вы хотите (опять же, только если вы не подтолкнули свои изменения вверх по течению). Объединить только после переустановки.
git merge
поддерживает параметр --no-ff
, который заставляет его совершать слияние.
– g.rocket
8 June 2017 в 22:31
Git rebase используется для того, чтобы пути ветвления в структуре истории и структуры хранилища были линейными.
Он также используется для того, чтобы ваши ветви были созданы вами частными, так как после перезагрузки и нажатия изменений на сервере, если вы удалите свою ветку, не будет никаких доказательств отрасли, над которой вы работали. Таким образом, ваш филиал теперь является вашим местным концерном.
После выполнения rebase мы также избавляемся от дополнительной фиксации, которую мы использовали, чтобы увидеть, выполняем ли мы обычное слияние.
И да, все еще нужно объединиться после успешной перезагрузки, так как команда rebase просто помещает вашу работу поверх ветки, которую вы упомянули во время rebase say master, и делает первое коммит вашей ветки прямым потоком главная ветвь. Это означает, что теперь мы можем выполнить быстрое слияние, чтобы внести изменения из этой ветви в ведущую ветвь.
Итак, когда вы используете один из них?
init
новый репо, add
файл и commit
. Оформить новую ветвь функции (checkout -b feature
.) Измените текстовый файл, зафиксируйте и повторите, чтобы в ветви функции были две новые фиксации. Затем checkout master
и merge feature
. В log
я вижу свою начальную фиксацию на главном, а затем две, которые были объединены с функцией. Если вы merge --squash feature
, функция объединяется в master, но не фиксируется, поэтому единственным новым фиксатором на master будет тот, который вы сделаете сами.
– spaaarky21
27 May 2013 в 21:55
Книга pro git как действительно хорошее объяснение на странице rebasing .
В принципе, слияние будет принимать 2 коммита и объединить их.
A rebase перейдет к общему предку на 2 и постепенно применит изменения друг к другу. Это создает «более чистую» и более линейную историю.
Но когда вы переустанавливаете, вы отказываетесь от предыдущих коммитов и создаете новые. Поэтому вы никогда не должны переустанавливать репо, которое является публичным. Другие люди, работающие над репо, будут вас ненавидеть.
По этой причине я почти исключительно сливаюсь. В 99% случаев мои ветви не сильно различаются, поэтому, если есть конфликты, это только в одном или двух местах.
перед слиянием / rebase:
A <- B <- C [master]
^
\
D <- E [branch]
после git merge master
:
A <- B <- C
^ ^
\ \
D <- E <- F
после git rebase master
:
A <- B <- C <- D' <- E'
(A , B, C, D, E и F являются коммитами)
этот пример и гораздо более хорошо иллюстрированная информация о git можно найти здесь: http://excess.org/article/2008/ 07 / огр-ГИТ-учебник /
Это предложение получает:
В общем, способ получить лучшее из обоих миров состоит в том, чтобы переустановить локальные изменения, которые вы сделали, но еще не поделились, прежде чем вы нажимаете их по порядку чтобы очистить ваш рассказ, но никогда не перегружайте все, что вы куда-то нажали.
Источник: http://www.git-scm.com/book/en/v2/ Гит-Ветвление-перебазирования # Rebase-против-Merge
Когда я использую git rebase
? Почти никогда, потому что он переписывает историю. git merge
- почти всегда предпочтительный выбор, потому что он уважает то, что на самом деле произошло в вашем проекте.
Некоторые практические примеры, несколько связанные с крупномасштабным развитием, где gerrit используется для проверки и интеграции доставки.
Я сливаю, когда я поднимаю свою ветвь свойств на новый удаленный мастер. Это дает минимальную работу по поднятию, и легко следить за историей разработки функции, например, в gitk.
git fetch
git checkout origin/my_feature
git merge origin/master
git commit
git push origin HEAD:refs/for/my_feature
Я сжимаюсь при подготовке коммита доставки.
git fetch
git checkout origin/master
git merge --squash origin/my_feature
git commit
git push origin HEAD:refs/for/master
Я переустанавливаю, когда моя передача не завершает интеграцию по какой-либо причине, и мне нужно обновить ее до нового удаленного мастера.
git fetch
git fetch <gerrit link>
git checkout FETCH_HEAD
git rebase origin/master
git push origin HEAD:refs/for/master
Этот ответ широко ориентирован вокруг Git Flow . Таблицы были созданы с помощью приятного ASCII Table Generator и деревьев истории с этой замечательной командой ( aliased as git lg
):
git log --graph --abbrev-commit --decorate --date=format:'%Y-%m-%d %H:%M:%S' --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%ad%C(reset) %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n'' %C(white)%s%C(reset) %C(dim white)- %an%C(reset)'
Таблицы находятся в обратном хронологическом порядке, чтобы быть более совместимыми с деревьями истории. См. Также разницу между git merge
и git merge --no-ff
в первую очередь (обычно вы хотите использовать git merge --no-ff
, поскольку это приближает вашу историю к реальности):
git merge
Команды:
Time Branch "develop" Branch "features/foo"
------- ------------------------------ -------------------------------
15:04 git merge features/foo
15:03 git commit -m "Third commit"
15:02 git commit -m "Second commit"
15:01 git checkout -b features/foo
15:00 git commit -m "First commit"
Результат:
* 142a74a - YYYY-MM-DD 15:03:00 (XX minutes ago) (HEAD -> develop, features/foo)
| Third commit - Christophe
* 00d848c - YYYY-MM-DD 15:02:00 (XX minutes ago)
| Second commit - Christophe
* 298e9c5 - YYYY-MM-DD 15:00:00 (XX minutes ago)
First commit - Christophe
git merge --no-ff
Команды:
Time Branch "develop" Branch "features/foo"
------- -------------------------------- -------------------------------
15:04 git merge --no-ff features/foo
15:03 git commit -m "Third commit"
15:02 git commit -m "Second commit"
15:01 git checkout -b features/foo
15:00 git commit -m "First commit"
Результат:
* 1140d8c - YYYY-MM-DD 15:04:00 (XX minutes ago) (HEAD -> develop)
|\ Merge branch 'features/foo' - Christophe
| * 69f4a7a - YYYY-MM-DD 15:03:00 (XX minutes ago) (features/foo)
| | Third commit - Christophe
| * 2973183 - YYYY-MM-DD 15:02:00 (XX minutes ago)
|/ Second commit - Christophe
* c173472 - YYYY-MM-DD 15:00:00 (XX minutes ago)
First commit - Christophe
git merge
vs git rebase
Первая точка: всегда объединяйте функции в разработку, никогда не перестраивайте их из функций. Это является следствием Золотого правила репозиции :
Золотое правило
git rebase
заключается в том, чтобы никогда не использовать его на ветвях public .Никогда не перепутайте все, что вы куда-то нажали.
Я лично добавлю: , если это не ветвь с функциями, и вы и ваша команда не знаете о последствиях .
Таким образом, вопрос о
git merge
vsgit rebase
применяется почти только к ветвям признаков (в следующих примерах--no-ff
всегда использовался при слиянии). Обратите внимание, что, поскольку я не уверен, что есть одно лучшее решение ( существует дебат ), я расскажу только, как ведут себя обе команды. В моем случае я предпочитаю использоватьgit rebase
, поскольку он создает более приятное дерево истории:)Между ветвями функций
git merge
Команды:
Time Branch "develop" Branch "features/foo" Branch "features/bar" ------- -------------------------------- ------------------------------- -------------------------------- 15:10 git merge --no-ff features/bar 15:09 git merge --no-ff features/foo 15:08 git commit -m "Sixth commit" 15:07 git merge --no-ff features/foo 15:06 git commit -m "Fifth commit" 15:05 git commit -m "Fourth commit" 15:04 git commit -m "Third commit" 15:03 git commit -m "Second commit" 15:02 git checkout -b features/bar 15:01 git checkout -b features/foo 15:00 git commit -m "First commit"
Результат:
* c0a3b89 - YYYY-MM-DD 15:10:00 (XX minutes ago) (HEAD -> develop) |\ Merge branch 'features/bar' - Christophe | * 37e933e - YYYY-MM-DD 15:08:00 (XX minutes ago) (features/bar) | | Sixth commit - Christophe | * eb5e657 - YYYY-MM-DD 15:07:00 (XX minutes ago) | |\ Merge branch 'features/foo' into features/bar - Christophe | * | 2e4086f - YYYY-MM-DD 15:06:00 (XX minutes ago) | | | Fifth commit - Christophe | * | 31e3a60 - YYYY-MM-DD 15:05:00 (XX minutes ago) | | | Fourth commit - Christophe * | | 98b439f - YYYY-MM-DD 15:09:00 (XX minutes ago) |\ \ \ Merge branch 'features/foo' - Christophe | |/ / |/| / | |/ | * 6579c9c - YYYY-MM-DD 15:04:00 (XX minutes ago) (features/foo) | | Third commit - Christophe | * 3f41d96 - YYYY-MM-DD 15:03:00 (XX minutes ago) |/ Second commit - Christophe * 14edc68 - YYYY-MM-DD 15:00:00 (XX minutes ago) First commit - Christophe
git rebase
Команды:
Time Branch "develop" Branch "features/foo" Branch "features/bar" ------- -------------------------------- ------------------------------- ------------------------------- 15:10 git merge --no-ff features/bar 15:09 git merge --no-ff features/foo 15:08 git commit -m "Sixth commit" 15:07 git rebase features/foo 15:06 git commit -m "Fifth commit" 15:05 git commit -m "Fourth commit" 15:04 git commit -m "Third commit" 15:03 git commit -m "Second commit" 15:02 git checkout -b features/bar 15:01 git checkout -b features/foo 15:00 git commit -m "First commit"
Результат:
* 7a99663 - YYYY-MM-DD 15:10:00 (XX minutes ago) (HEAD -> develop) |\ Merge branch 'features/bar' - Christophe | * 708347a - YYYY-MM-DD 15:08:00 (XX minutes ago) (features/bar) | | Sixth commit - Christophe | * 949ae73 - YYYY-MM-DD 15:06:00 (XX minutes ago) | | Fifth commit - Christophe | * 108b4c7 - YYYY-MM-DD 15:05:00 (XX minutes ago) | | Fourth commit - Christophe * | 189de99 - YYYY-MM-DD 15:09:00 (XX minutes ago) |\ \ Merge branch 'features/foo' - Christophe | |/ | * 26835a0 - YYYY-MM-DD 15:04:00 (XX minutes ago) (features/foo) | | Third commit - Christophe | * a61dd08 - YYYY-MM-DD 15:03:00 (XX minutes ago) |/ Second commit - Christophe * ae6f5fc - YYYY-MM-DD 15:00:00 (XX minutes ago) First commit - Christophe
От
develop
до ветки функции
git merge
Команды:
Time Branch “develop" Branch "features/foo" Branch "features/bar" ------- -------------------------------- ------------------------------- ------------------------------- 15:10 git merge --no-ff features/bar 15:09 git commit -m “Sixth commit" 15:08 git merge --no-ff development 15:07 git merge --no-ff features/foo 15:06 git commit -m “Fifth commit" 15:05 git commit -m “Fourth commit" 15:04 git commit -m “Third commit" 15:03 git commit -m “Second commit" 15:02 git checkout -b features/bar 15:01 git checkout -b features/foo 15:00 git commit -m “First commit"
Результат:
* 9e6311a - YYYY-MM-DD 15:10:00 (XX minutes ago) (HEAD -> develop) |\ Merge branch 'features/bar' - Christophe | * 3ce9128 - YYYY-MM-DD 15:09:00 (XX minutes ago) (features/bar) | | Sixth commit - Christophe | * d0cd244 - YYYY-MM-DD 15:08:00 (XX minutes ago) | |\ Merge branch 'develop' into features/bar - Christophe | |/ |/| * | 5bd5f70 - YYYY-MM-DD 15:07:00 (XX minutes ago) |\ \ Merge branch 'features/foo' - Christophe | * | 4ef3853 - YYYY-MM-DD 15:04:00 (XX minutes ago) (features/foo) | | | Third commit - Christophe | * | 3227253 - YYYY-MM-DD 15:03:00 (XX minutes ago) |/ / Second commit - Christophe | * b5543a2 - YYYY-MM-DD 15:06:00 (XX minutes ago) | | Fifth commit - Christophe | * 5e84b79 - YYYY-MM-DD 15:05:00 (XX minutes ago) |/ Fourth commit - Christophe * 2da6d8d - YYYY-MM-DD 15:00:00 (XX minutes ago) First commit - Christophe
git rebase
Команды:
Time Branch “develop" Branch "features/foo" Branch "features/bar" ------- -------------------------------- ------------------------------- ------------------------------- 15:10 git merge --no-ff features/bar 15:09 git commit -m “Sixth commit" 15:08 git rebase development 15:07 git merge --no-ff features/foo 15:06 git commit -m “Fifth commit" 15:05 git commit -m “Fourth commit" 15:04 git commit -m “Third commit" 15:03 git commit -m “Second commit" 15:02 git checkout -b features/bar 15:01 git checkout -b features/foo 15:00 git commit -m “First commit"
Результат:
* b0f6752 - YYYY-MM-DD 15:10:00 (XX minutes ago) (HEAD -> develop) |\ Merge branch 'features/bar' - Christophe | * 621ad5b - YYYY-MM-DD 15:09:00 (XX minutes ago) (features/bar) | | Sixth commit - Christophe | * 9cb1a16 - YYYY-MM-DD 15:06:00 (XX minutes ago) | | Fifth commit - Christophe | * b8ddd19 - YYYY-MM-DD 15:05:00 (XX minutes ago) |/ Fourth commit - Christophe * 856433e - YYYY-MM-DD 15:07:00 (XX minutes ago) |\ Merge branch 'features/foo' - Christophe | * 694ac81 - YYYY-MM-DD 15:04:00 (XX minutes ago) (features/foo) | | Third commit - Christophe | * 5fd94d3 - YYYY-MM-DD 15:03:00 (XX minutes ago) |/ Second commit - Christophe * d01d589 - YYYY-MM-DD 15:00:00 (XX minutes ago) First commit - Christophe
Боковые заметки
git cherry-pick
Когда вам просто нужно определенное коммит,
git cherry-pick
является хорошим решением (опция-x
добавляет строку, которая гласит: « (вишня выбрана из фиксации ...) "в исходное тело сообщения фиксации, поэтому обычно рекомендуется использовать его -git log <commit_sha1>
, чтобы увидеть его):Команды:
Time Branch “develop" Branch "features/foo" Branch "features/bar" ------- -------------------------------- ------------------------------- ----------------------------------------- 15:10 git merge --no-ff features/bar 15:09 git merge --no-ff features/foo 15:08 git commit -m “Sixth commit" 15:07 git cherry-pick -x <second_commit_sha1> 15:06 git commit -m “Fifth commit" 15:05 git commit -m “Fourth commit" 15:04 git commit -m “Third commit" 15:03 git commit -m “Second commit" 15:02 git checkout -b features/bar 15:01 git checkout -b features/foo 15:00 git commit -m “First commit"
Результат:
* 50839cd - YYYY-MM-DD 15:10:00 (XX minutes ago) (HEAD -> develop) |\ Merge branch 'features/bar' - Christophe | * 0cda99f - YYYY-MM-DD 15:08:00 (XX minutes ago) (features/bar) | | Sixth commit - Christophe | * f7d6c47 - YYYY-MM-DD 15:03:00 (XX minutes ago) | | Second commit - Christophe | * dd7d05a - YYYY-MM-DD 15:06:00 (XX minutes ago) | | Fifth commit - Christophe | * d0d759b - YYYY-MM-DD 15:05:00 (XX minutes ago) | | Fourth commit - Christophe * | 1a397c5 - YYYY-MM-DD 15:09:00 (XX minutes ago) |\ \ Merge branch 'features/foo' - Christophe | |/ |/| | * 0600a72 - YYYY-MM-DD 15:04:00 (XX minutes ago) (features/foo) | | Third commit - Christophe | * f4c127a - YYYY-MM-DD 15:03:00 (XX minutes ago) |/ Second commit - Christophe * 0cf894c - YYYY-MM-DD 15:00:00 (XX minutes ago) First commit - Christophe
git pull --rebase
Не уверен, что я могу объяснить это лучше, чем Дерек Гурлей ... В основном, используйте
git pull --rebase
вместоgit pull
:) Однако в статье отсутствует то, что вы можете включить по умолчанию :git config --global pull.rebase true
git rerere
Опять же, хорошо объяснено здесь . Но поставите просто, если вы включите его, вам больше не придется разрешать один и тот же конфликт.