Git merge — будут ли старые проблемы объединены в master, если я объединим старую ветку?

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

Вскоре после начала работы над этим проектом я создал ветку под названием updateCards для работы над устранением конкретной ошибки в проекте.

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

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

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

Однако в чем я не уверен, так это в том, что, учитывая, что я внес несколько других изменений в master на сервере с момента создания updateCards, если я сейчас объединим updateCards в master, буду ли я объединять какие-либо старые ошибки, которые существовали в updateCards, но теперь разрешено в master вернуться к master, поскольку файлы, в которых эти ошибки были исправлены на мастере, будут отличаться от тех же файлов на updateCards? Или Git увидит, что изменения в master для этих файлов более свежие, чем изменения в updateCards, и не объединит эти изменения?

Я запустил git diff master..updateCards, и это отобразило вывод о различиях между двумя ветвями:

diff --git a/buying/templates/buying/update_card_numbers.html b/buying/templates/buying/update_card_numbers.html
index 6cc5938..5f6a8f3 100644
--- a/buying/templates/buying/update_card_numbers.html
+++ b/buying/templates/buying/update_card_numbers.html
@@ -25,8 +25,8 @@
            <table class="left">
                    <thead>
                            <tr>
-                                       <th>Cardholder</th>
                                    <th>card no</th>
+                                       <th>Cardholder</th>
                            </tr>
                    </thead>

diff --git a/buying/views.py b/buying/views.py
index 08d2fd6..c777020 100644
--- a/buying/views.py
+++ b/buying/views.py
@@ -1555,6 +1555,8 @@ def update_card_numbers(request):
                                            cardholder = data['id']
                                            cardholder.card_no = data['card_no']
                                            cardholder.save()
+                                               #cardholder.card_no.save()
+                                               #data['travis_card_no'].save()
                                            print cardholder, cardholder.card_no

                            HttpResponseRedirect(reverse('buying:update_card_numbers'))
diff --git a/costing/templates/pdf2_base.html b/costing/templates/pdf2_base.html
index 3826a98..c139068 100644
--- a/costing/templates/pdf2_base.html
+++ b/costing/templates/pdf2_base.html
@@ -83,8 +83,6 @@
                                            <td>
                                                    <span class="project-name">{{project.project_name|upper}}</span>
                                            </td>
-                                               <!--ERF(07/12/2016 @ 1615) Display today's date in the header -->
-                                               <td> {% date_to_display %}</td>
                                    </tr>
                            </table>
                    </div>  
diff --git a/costing/views.py b/costing/views.py
index 902f9ff..f8a3f77 100644
--- a/costing/views.py
+++ b/costing/views.py
@@ -2438,9 +2438,6 @@ def pdf2_master(request, project_id):
            """ Save to the current budget (no version number), as versions not used once deposit is received """
            budget = get_current_budget(project_id)

-               #ERF(07/12/2016 @ 1615) Create a date variable to displays today's date on the PDF when it's generated
-               date_to_display = datetime.now()
-
            if not budget:
                    Budget.objects.create(project=project, current_marker=1)

Но я не уверен, как интерпретировать этот вывод... Строки, начинающиеся с -, существуют в updateCards, но не в master, а строки, начинающиеся с +, существуют в master, но не в updateCards, или наоборот наоборот?

Какие изменения будут скопированы и в каком направлении, если я запущу merge?


person Noble-Surfer    schedule 20.12.2016    source источник


Ответы (2)


Вы никогда не можете ожидать слияния от одного diff

Чтобы увидеть результат слияния, вам нужны два сравнения1.

Вам также нужно найти базу слияния (или попросить Git сделать это за вас). Это связано с тем, что слияние — это объединение изменений, а чтобы объединить изменения двух людей, мы должны найти общее место, с которого они оба начали. Эта отправная точка позволяет нам (или Git) выяснить, «что сделали мы» и «что сделали они».

Затем вы можете запустить два дифференциала: git diff merge-base tip1 и git diff merge-base tip2. Выполнение слияния — это «слияние» как глагол — затем объединит эти два различия в одно большое изменение, которое применяется к базе слияния.

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

Например, если вы находитесь в ветке main и выполняете слияние в ветке fix, tip1 — это идентификатор фиксации main, а tip2 — идентификатор фиксации fix. решает. Как только слияние (как глагол) завершится, вы сделаете новую фиксацию слияния — это «слияние» как прилагательное — на main, так что main теперь будет называть новую фиксацию слияния, которую вы только что сделали. Содержимое нового слияния («слияние» как существительное, означающее «слияние фиксации») создается с помощью процесса слияния как глагола, который объединяет два различия.


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


Если это сбивало с толку, я не уверен, что остальное поможет. Но в конце вас ждет награда: быстрый способ запустить git diff, чтобы получить два нужных вам различия. :-)

Определения

Поскольку вы новичок в Git, давайте определим несколько элементов. Они, вероятно, достаточно знакомы, но хорошо иметь конкретные определения.

дерево — это набор файлов. Дерево, над которым вы работаете, является вашим рабочим деревом (также пишется как рабочее дерево, рабочее дерево и т. д.). В вашем рабочем дереве могут быть файлы, которые не фиксируются: это неотслеживаемые файлы. Вы можете заставить Git «игнорировать» (перестать жаловаться) некоторые из этих неотслеживаемых файлов, а также не добавлять их автоматически для отслеживания и фиксации, когда вы используете git add . или git add -A или тому подобное. (Неотслеживаемые файлы не имеют значения для сравнения и слияния, я просто упомянул их для полноты картины.)

Коммит — это постоянный, неизменный снимок дерева, который поставляется вместе с некоторыми столь же постоянными, столь же неизменяемыми метаданными: чье-то имя и адрес электронной почты, отметка времени, сообщение журнала и понятие "родительского" коммита или, для коммитов слияния, двух родителей.2

Чтобы сделать новую фиксацию, вы используете индекс Git, который также называется "областью подготовки" и "кэшем". По сути, это место, где вы создаете следующий коммит. Он начинается с текущей фиксации, и вы обновляете в нем файлы или добавляете новые с помощью git add; затем git commit превращает индекс в новое дерево моментальных снимков, добавляет метаданные коммита, добавляя ваше имя и адрес электронной почты, «сейчас» в качестве метки времени и ваше сообщение журнала.

Каждый коммит имеет уникальный хэш-идентификатор, например d5c49eb32e898663a8e2c396739d831733e945c2. Они слишком большие и уродливые для людей, поэтому мы либо сокращаем их, либо даем им имена. Существует множество форм для имен, но самое главное, что они всегда разрешаются в хэш-идентификатор. Это «настоящие имена».

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

родительский любой новый коммит — это коммит, который был текущим на момент запуска git commit. То есть родителем нового коммита является то, что HEAD было, а затем HEAD принимает новый идентификатор нового коммита. Это верно даже для новых коммитов слияния, даже если у них должно быть как минимум два родителя. Первый и «главный» родитель от HEAD; остальные — из того, что вы объединили.

Вот как Git формирует настоящие ветки. Имена веток эфемерны и существуют только до тех пор, пока вам не все равно. держать их рядом. коммиты постоянны и неизменны, и каждый коммит записывает своего родителя (или родителей)... поэтому мы можем объединить коммиты, работая в обратном порядке, начиная с последнего коммита. .


2Технически два или больше. Фиксация слияния с тремя или более родительскими элементами называется слиянием осьминога. Однако они не делают ничего такого, чего нельзя было бы сделать при обычном слиянии.

Кроме того, к коммитам прикреплены две тройки имя-адрес-почта-временная метка: автор и коммиттер. Для коммитов, которые вы делаете сами, нет такой большой разницы, но для коммитов, которые перебазируются, объединяются или отправляются по электронной почте в виде патчей или чего-то еще, эти отдельные «кто и когда написал этот коммит» от «кто фактически поместил его в репозиторий, и когда".

3Из этого правила есть одно исключение. Очевидно, что в новом, пустом репозитории вообще нет коммитов, поэтому не может быть "текущим коммитом". Git обобщает это до чего-то, что непоследовательно называется либо ветвью-сиротой, либо нерожденной ветвью, в которой HEAD содержит имя ветки, но само имя ветки больше нигде не существует. . Создание новой фиксации в этом состоянии фактически создает имя ветки. Новая фиксация является корневой фиксацией без родителей. После этого это странное неопределенное состояние разрешается, и новые коммиты получают родительские коммиты, как обычно.


Git рисует графики задом наперед; найти базу слияния

Все это означает, что Git (и мы) должны рисовать наши графики с именами веток в конце «новейшей фиксации», указывая на конечную фиксацию каждой ветки. Когда я рисую их горизонтально, я делаю это так:

o <- o   <-- master

Здесь имя master указывает на второй и последний ("tip") коммит в ветке master. Этот коммит указывает на первый коммит. Первая фиксация, разумеется, не имеет предыдущей фиксации, поэтому это корневая фиксация, и на этом мы можем остановиться.

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

o--o--*--o--o     <-- master
       \
        o--o--o   <-- fix

Более новые коммиты, как и прежде, находятся справа, поэтому master и fix, которые являются именами ветвей, указывают на верхние фиксации соответствующих фрагментов графа ветки.

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

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

Найти базу (или базы) слияния легко, если у вас есть хороший чистый рисунок графика. Сложные или беспорядочные графики усложняют задачу. Однако у Git есть команда для поиска базы (баз) слияния конкретных коммитов:

git merge-base master fix

Что это делает, так это разрешает master его фиксацию (конец master) и fix его фиксацию (конец fix), а затем проходит граф по мере необходимости, чтобы найти базу слияния.

(Если есть несколько баз слияния, он выбирает одну и печатает ее. Чтобы увидеть все, добавьте --all. Обычно в любом случае есть только одна.)

Быстрый способ просмотра различий на базе слияния

Предположим, вы хотите посмотреть, какие изменения git merge будут объединены при объединении master и side. Вы можете сделать это:

$ git merge-base --all master fix
face0ff1234567...                   # some big ugly hash
$ git diff face0ff master           # see what we changed
$ git diff face0ff fix              # see what they changed

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

$ git diff fix...master             # see what we did
$ git diff master...fix             # see what they did

Это зависит от того, что процесс поиска базы слияния симметричен: база слияния master и fix является такой же фиксацией, что и база слияния fix и master. Таким образом, независимо от того, как мы перевернем две стороны, мы получим одно и то же основание. Затем Git сравнивает эту базу с фиксацией, указанной справа от этого выражения fix...master или master...fix.

Стоит отметить, что этот синтаксис A...B применим и к git log. Однако в данном случае это означает нечто иное, чем git diff. Обычно A...B означает: Найти каждую фиксацию, достижимую из A, и каждую фиксацию, достижимую из B, а затем отбрасывать каждую фиксацию, достижимую из как A, и B. em> То есть получается симметричная разность (в терминах теории множеств). Но git diff может просматривать только два коммита, а не весь набор; поэтому он крадет этот синтаксис, чтобы означать что-то другое, что полезно для git diff.

person torek    schedule 20.12.2016

Основываясь на вашем выводе git diff, можно объединить карты updateCards в основной ветке. Файлы, сравниваемые двумя ветвями (+ for updateCards and – for master), как показано ниже:

обновленные файлы ветки updateCards,

update_card_numbers.html

views.py добавить функцию update_card_numbers(запрос)

обновленные файлы основной ветки,

pdf2_base.html
views.py добавить новую строку

Так что на самом деле они изменили разные места. Вы можете объединить две ветки, не влияя на исправленные ошибки в ветке updatedCards и новой ветке, которую вы объединили в master.

Вы можете выполнить git merge updateCards --no-commit перед тем, как действительно слиться. Он покажет, какие файлы имеют конфликт, затем вы можете использовать git merge --abort для остановки. Когда вы запустите git merge updateCards, будут конфликтные файлы, просто сохраните то, что вы хотите сохранить, а затем используйте git add filename для каждого конфликтующего файла и git commit.

person Marina Liu    schedule 21.12.2016