Подтвердить что ты не робот

Почему после слияния GIT говорят "Уже обновлено", но различия между ветвями все еще существуют?

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

Когда я переключился на "newfeature" и слился в "develop", были конфликты в 3 файлах.

Я попал в путаницу, разрешающую конфликты, и в конце концов решил использовать команду "Revert" в меню "Team" Aptana Studio 3 (это моя IDE). Я ожидал, что это вернет меня назад до слияния, которое, похоже, произошло.

В любом случае, когда я снова сливаюсь в "разработке", он говорит: Already-up-to-date, но при сравнении файлов между двумя ветвями они очень разные, а изменения, которые я добавил в другой ветке, не объединяются.

Как я могу объединить две ветки теперь, пожалуйста?

4b9b3361

Ответ 1

Возвращение слияния и слияния слияния

Я предполагаю, что вы на самом деле Already-up-to-date.

Проблема заключается в том, что git revert не отменяет слияние, она отменяет изменения, сгенерированные слиянием. Когда вы создаете фиксацию слияния, вы комбинируете истории фиксации этих двух ветвей.

Слияние

     develop
        |
A---B---C
 \       \
  E---F---M
          |
      newfeature

В приведенном выше случае develop объединяется в newfeature, создавая фиксацию M. Если бы вы выполнили git log newfeature, вы увидели бы все коммиты из обеих ветвей, однако с точки зрения ветки newfeature все эти изменения были выполнены с помощью M commit.

Откат

Команда git revert не удаляет какие-либо коммиты, вместо этого создает новую фиксацию, которая отменяет изменения, содержащиеся в фиксации. Например, если у вас есть фиксация, содержащая этот diff...

-This is the old sentence.
+This is ne new sentence.

Затем вернет это, команда revert создаст новый коммит, который только что сформировал противоположный diff, он просто переворачивает знаки.

-This is ne new sentence.
+This is the old sentence.

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

Возвращение слияния

Однако, в контексте небыстрого слияния он может иметь нежелательный эффект.

     develop
        |
A---B---C
 \       \
  E---F---M---W
              |
         newfeature

Предполагая, что W является фиксацией реверсии, вы можете увидеть, как работает git log newfeature все равно будет включать все коммиты из ветки разработки. В результате дополнительные слияния из develop не будут работать, потому что в вашей ветке ничего не видно.

Используя git reset вместо возврата.

В будущем вам может потребоваться использовать git reset --hard <ref> (где <ref> - хеш фиксации слияния), чтобы отменить слияние, если это слияние не было передано другим разработчикам. В приведенном выше примере после создания слияния M выполнение команды git reset --hard F приведет к следующему.

     develop
        |
A---B---C
 \       \
  E---F---M
      |
  newfeature

Как вы можете видеть, этот метод не уничтожает фиксацию, как некоторые люди склонны думать, она просто переводит вашу ветку обратно в выбранную вами фиксацию. Теперь, если вы запустили git log newfeature, вы получите только commit F, E и A. Теперь слияние фактически исчезло из истории ваших веток, поэтому более поздние попытки повторного объединения в develop не вызовут никаких проблем.

Этот метод не лишен своих осложнений. Поймите, что теперь вы изменяете историю, поэтому, если ветвь newfeature была нажата на удаленную ветвь после слияния M, тогда git будет думать, что вы просто устарели и говорите, что вам нужно для запуска git pull. Если вы просто работаете над этой удаленной ветвью, тогда не стесняйтесь force-push - git push -f <remote> <branch>. Это будет иметь тот же эффект от reset, но на удаленной ветке.

Если эта ветка используется несколькими разработчиками, которые уже сейчас вытащили из нее, то это плохая идея. Именно по этой причине полезно использовать git revert, поскольку оно отменяет изменения, не изменяя фактическую историю.

Использование reset в истории действительно только на опции для коммитов, которые не были разделены.

Решение - возврат реверсии.

Если фиксация слияния уже была разделена, лучшим вариантом является использование git revert в этом объединении. Однако, как мы говорили ранее, вы не можете просто просто объединить ветку и ожидать, что все изменения из этой ветки снова появятся. Ответ заключается в том, чтобы вернуть реверт commit.

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

         develop
            |
A---B---C---D
 \       \
  E---F---M---W
              |
         newfeature

Если теперь вы объедините develop в newfeature, вы получите только D, потому что это единственная команда, которая еще не является частью истории ветки newfeature. Вам также нужно вернуться, чтобы W commit - git revert W выполнить трюк, за которым следует git merge develop.

                 develop
                    |
A---B---C-----------D
 \       \           \
  E---F---M---W---M---G
                      |
                 newfeature

Это восстанавливает все изменения, сделанные первоначальной фиксацией слияния, которые были фактически сделаны с помощью C и B, но были возвращены в W, затем он вносит D через новое объединение слиянием G Я бы рекомендовал возвратить возврат до слияния в недавних изменениях с develop, я подозреваю, что выполнение этого в этом порядке будет иметь более низкий шанс вызвать конфликты.

TL; DR

Возвращение создает "revert commit". При отмене возврата вам необходимо запустить команду revert на revert commit, которая была создана, когда вы вернулись в первый раз. Достаточно легко найти, git стремится автоматически комментировать реверты, чтобы они начинались со слова "Отклонено".

git revert <commit>

Ответ 2

Нашел взломанное решение. Но это работает.

Что бы ни ответил Эддиемоя, это абсолютно полезно. Большое спасибо за объяснение. Я столкнулся с подобной ситуацией. Где я смог увидеть много контента в git diff <branch> но git merge уже говорил, что он в курсе.

И я не смог найти точный возврат из-за большого количества возвратов в журнале. (Да, плохо. Во-первых, не должно было случиться)

Решение

git checkout branchX -- .

Это внесет все изменения из BranchX в мою текущую ветку. Используйте на своем любимом git-клиенте, отключите и отмените все, что не предназначено.

Сделай новый коммит и будь счастлив :)