Накладка коммитов

Предположим мы работаем с напарником. Он как и вы работает в ветке master что является недопустимым в большом бизнесе, однако вполне нормально в маленьком.
Итак 9 утра мы пришли за рабочее место и так как вчера могли быть сделанны изменения выполняем команду git pull.
Мы начинаем работать, у нас уже имеются изменения которые ближе к вечеру превратятся в коммит.
Паралельно с нами работает наш напарник(естественно). К вечеру ждать он не собирается и делает промежуточные коммиты которые отправляет в центральный репозиторий в обед.
Вечером когда мы захотим наш коммит отправить в центральный репозиторий, выполнение команды git push может привести к 2-м вариантам последствий:

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

Итак что делать если нам git говорит о том что есть чужие коммиты.
Поговорим о 2-х вариантах решения проблемы:

Собственно merge это то что в 99% случаев будет сделанно разработчиками. А так как мы работаем с консолью то и процесс решения конфликтов будет выполнен в консольном стиле с помощью консольных редакторов.

Проблема

Проверяем состояние файлов, видим что у нас есть изменения
Screenshot

Добавляем все изменения в стейдж
Screenshot
Так как файл редактируется в разных ОС гит пытается унифицировать файлы. В данном случае гит говорит нам о том что он преобразует символ перехода на новую строку из windows формата в linux.

Создаем коммит
Screenshot

И пробуем пушить в центральный репозиторий
Screenshot
Вот и наша проблема.

  1. ! [rejected] - гит говорит нам о том что наш пуш не прошел
  2. (fetch first) - гит просит сперва проверить состояние репозитория и ветки куда мы хотим пушить
  3. error: failed to push ... - гит так же нам говорит что не так
  4. hint: - подсказка что пошло не так и что можно сделать

Решение

Для решения данной задачи правильно нам нужно выполнить сперва git pull для того чтоб наш локальный репозиторий знал какие коммиты лежат в центральном репозитории о которых мы не знаем. Но на этом этапе есть одна интересная особенность. у команды git pull есть атрибут --rebase.
Атрибут --rebase заставит перенести наши коммиты на верх. Другими словами гит сперва откатится к общему одинаковому коммиту(с которого мы начали работать) далее загрузит все коммиты которые уже были запушены в ветку и только потом наложит наши коммиты сверху. НО при этом может понадобится вручную мержить(от анг. merge) файлы. Ведь у нас из-за этих файлов и появился конфликт.

Итак, пишем команду git pull --rebase
Screenshot
Гит тут же нам сообщает о конфликте который мы должны будем исправить вручную.
Так же наша консольная строка изменилась теперь в скобках не только имя ветки в который мы сейчас находимся а ещё и этап ребейса (master | REBASE 1/1). Это значит что ребейс происходит поэтапно. В нашем случае этап всего один - 1/1. И когда нам нужно будет перейти к следующему этапу или же закончить ребейс пишем git rebase --continue но об этом позже.

После команды git pull --rebase лучше проверить какие же файлы следует поправить. Посмотрим текущий статус git status
Screenshot
Файл somefile.txt следует поправить.

Открываем любой нам известный/удобный редактор либо же это та среда разработки где мы и собственно пишем это всё и видим следующее:
Screenshot
Гит самостоятельно выделил строки в файле которые конфликтуют.
<<<<<<< HEAD - В текущем случае с этого места начинаются строки которые лежат в центральном репозитории. Так же эта строка отмечает начало блока кода.
======= - Это промежуточная отметка блока кода. Отметка говорит нам где заканчивается то что лежит в центральном репозитории и где начинаются наши изменения.
>>>>>>> Add ending for som........ - Отметка конца всего конфликта.

Теперь нам предстоит решить какие изменения оставить. Либо оставить голову(HEAD) либо оставить наши изменения.
Предположим мы хотим оставить свои изменения. Для этого мы удалим голову и вспомогительные строки/символы.
Screenshot
Screenshot

Когда все исправления закончили выполняем git add . и переходим к следующему этапу или же завершаем ребейс командой git rebase --continue
Screenshot

Проверяем еще раз статус и отправляем на сервер git push
Screenshot

Собственно проблема конфликта решена, однако это всего лишь первый вариант. Есть вариант без ребейса. Разница между в том что пулл без ребейса заставит создать дополнительный коммит который будет называться Merge ........... И засунет наши коммиты по временной точке. Это значит что наш коммит не будет сверху истории коммитов.

Вариант без ребейса рассматривать на данный момент не буду. Если нужно будет позже опишу.