Для чего нужен гит
Гит - это программа для отслеживания изменений в файлах. В папке проекта файлы добавляются, изменяются, удаляются - гит это видит и позволяет записывать изменения в историю.
Я хочу найти в гит правки контента. Почему нету?
Как работает сайт? Логика проекта, то есть сама программа хранится на сервере в файлах, администратор управляет контентом через панель администратора, контент хранится в базе данных.
Почему нельзя хранить все в базе или всё в файлах.
Код хранится в файлах, потому что важно быстродействие. При заходе пользователя на сайт задействуются сотни файлов с кодом. При том, всего файлов относительно не много - порядка 1000 отдельных файлов расположенных в папках соответствующих логической структуре. Важно, что сайт при работе не изменяет программу.
Контент хранится в базе данных, потому что его бывает много. База данных способна обрабатывать миллионы записей. При том, при использовании сайта, часто нам требуется либо одна конкретная запись (информация об одном товаре), либо какой-то промежуток (первые 20 новостей из раздела Политика). База должна быстро выдавать записи из огромного массива данных по всевозможным фильтрам. Представьте библиотеку, где много книг, но всё структурировано. Спросите у библиотекаря любую книгу, она сразу подойдет к нужной полке и почти сразу найдет нужную книгу.
Так же контент постоянно правится и важна целостность базы. Если несколько человек будут одновременно править новость - база не сломается, чего не скажешь о ситуации, когда несколько человек одновременно правят файл программы.
Контента много, его долго переносить и он не влияет на логику программы. Поэтому он не отслеживается в гит.
Разобрались что где хранится. Теперь перейдем к проблемам работы с кодом.
Ситуация:
На проекте нет гит. Большая задача, модифицировано множество файлов. Доработки ведутся на тестовом сервере уже 2 месяца.
На тесте всё работает, надо деплоить. Как?
- Вспоминать все файлы, в которых были правки - можно что-то забыть. 99 файлов перенесли, 1 забыли - на проекте баг.
- Записывать все правки в файл? - Долго, тоже можно забыть.
Так же сложности:
- При переносе вручную доработки переносятся постепенно. нельзя перенести 100 файлов отновременной. В процессе деплоя сайт может упасть
- Требуется проверять правки в каждом файле, иначе если во время разработки на тестовом на проде были другие доработки - их можно перезаписать.
Требуется автоматизированный инструмент переноса правок на боевой сервер.
O Git
Git — система управления версиями с распределенной архитектурой. Aбсолютный лидер по популярности среди современных систем управления версиями. В отличие от некогда популярных систем вроде CVS и Subversion (SVN), где полная история версий проекта доступна лишь в одном месте, в Git каждая рабочая копия кода сама по себе является репозиторием. Это позволяет всем разработчикам хранить историю изменений в полном объеме и работать без доступа к удаленному репозиторию (например, без интернета).
Гит позволяет работать над одним проектом нескольким разработчикам одновременно, отслеживать историю, не терять правки, переносить изменения от сервера к серверу.
Pull и push
git push - отправить правки из нашего репозитория в удаленный. Если в удаленном репозитории будут коммиты, которых нет у нас, получим ошибку. В этом случае выполните git pull.
git pull - скачать все правки из удаленного репозитория и смержить их с нашим репозиторием.
Удалённый репозиторий — это модификация проекта, которая хранятся в интернете или ещё где-то в сети. Например на GitHub, Gitlab и так далее.
Когда мы выполняем git pull, на самом деле выполняется:
- git fetch - получить правки из удаленного репозитория
- git merge - провести слияние правок
Если мы не хотим проводить слияние, а надо только узнать чем отличается ли наша версия от удаленной - можно выполнить git fetch и далее git diff origin/master (имя удаленного репозитория origin, ветка master).
Ветки
Ветки в гит - способ хранения истории правок. Позволяет параллельно хранить несколько версий кода.
Когда вы начинаете работу над какой-то задачей, создавайте отдельную ветку.
Нельзя коммитить в ветку мастер, когда не требуется переносить правки на продакшн сервер.
Конфликты
При слиянии веток могут появиться конфликты. Если один файл параллельно правили в разных ветках - гит это увидит и выдаст конфликт.
Мне проще всего решать конфликты открывая файлы в IDE и ища сочетания <<<<, ==== или >>>>. Для этого, когда git говорит что появился конфликт, смотрим в каких файлах - открываем эти файлы и решаем конфликты. С помощью git add добавляем правки в гит и коммитим всё.
<<<<<<< HEAD - начало конфликта. Далее контент из текущей ветки.
======= - разделение контента. Далее контент из ветки с которой сливаемся.
>>>>>>> branch1 - конец конфликта.
Оставим, например, только правку из текущей ветки:
Если мы передумали слияние, когда произошел конфликт, можно воспользоваться командой git merge --abort. Она отменит процесс слияния.
Начало работы над задачей с Битрикс, когда есть тестовый сервер
- Перед большой задачей: Подключиться к проду и с помощью команды git status узнать - нет ли там незакоммиченных правок.
- На тестовом проверить состояние гит командой git status.
Если есть не закоммиченные правки - надо разбираться кто что правил и почему не закоммитил.
Введя команду git diff, можно посмотреть конкретно что правилось. Если видно что правки только по контенту - закоммитить самому, имя коммита - "Правки по контенту". Если видно правки логики сайта или верстки - надо искать исполнителя - пусть сам коммитит что надо в нужную ему ветку. - Когда всё закоммичено - смотрим на какой ветке тестовый. Если не мастер - переключаемся на мастер командой git checkout master.
- Актуализируем мастер - git pull.
- Можно начинать работу
- Создаем свою ветку по шаблону:
N.branch_name
Где N - номер задачи в Б24
branch_name - осмысленное имя ветки. Имя pravki - не подходит, оно не отражает суть ветки
Команда: git checkout -b N.branch_name
- Указываем себя в конфигах командой
git config user.name "Your Name" && git config user.email "your@email.com"
Где Your Name - ваше имя, your@email.com - ваша почта. Желательно та, на которую зарегистрирован аккаунт в удаленном репозитории.
Можно открывать ваш IDE/текстовый редактор.
Правим файлы прямо на сервере, в PhpStorm есть вкладка Remote Host, через который надо открывать файлы с сервера и сочетанием Alt+Shift+Q файлы сохраняются сразу обратно на сервер.
Коммитим тоже сразу на сервере через ssh.
Деплой
Порядок работы:
- Вносите правки на сайте.
- В ветке задачи всё коммитите.
- Постановщик задачи проверяет работу. Говорит деплоить.
- На проде проверяем состояние гит. Нет ли там не закоммиченных файлов. Никто ли не залил туда файлы без гит.
- Вы на тестовом переключатесь на мастер git checkout master.
- Актуализируете мастер git pull.
- Проводите слияние с веткой задачи git merge 123.calendar_picker.
- Отправляете правки в удаленный репозиторий git push.
- На проде скачиваете правки git pull.
Я деплою через PhpStorm. Что такого?
Чем плох деплой не через гит, а через FTP вручную/PhpStorm и другое?
Предположим:
У вас была большая задача, вы даже закоммитили на тестовом всё. Но задеплоили на прод через PhpStorm.
- Во время вашей работы в файлы на проде уже могли внести правки и их можно затереть. Но это ладно, PhpStorm скажет что файл был изменен на сервере.
- После деплоя всё работает, вы рапортуете об успешном переносе правок. Через какое-то время другой разработчик приступает к своей задаче и видит на проде 100 измененных файлов не закоммиченных. Что делать? Есть ли эти правки в гит? Есть ли эти правки на тестовом сервере? Не понятно.
Программист не закоммитит файлы на проде и попытается задеплоить через гит свою задачу. Вполне вероятно он получит ошибку, потому что гит не может провести слияние, так как файлы не закоммичены.
Допустим разработчик решил всё закоммитить и через гит прокинуть на тестовый сервер. Так как назначение правок не понятно, имя коммиту дает "Правки". На проде запушили, на тесте запулили. Вроде всё ок, проблему разрешили. Но создали другую проблему, о ней расскажу чуть позже.
Вы можете возразить, давайте просто не пользоваться гитом на проде, а деплоить через PhpStorm. Тут есть тоже проблемы:
- Не все пользуются PhpStorm. Деплоить каждый файл вручную тогда?
- Перед выполнением задачи, надо быть уверенным, что тестовый сервер актуальный, все файлы как на проде. Иначе может случиться такое, что правки на тестовом работают, а на проде после деплоя всё ломают. Без актуального гит убедиться в актуальности проблематично.
Поэтому
Деплоить надо только через гит! Только в этом случае прод всегда будет актуальный и это легко проверить.
Другие варианты работы
Как искать ошибки с помощью Git
Такая ситуация: на сайте найден баг, надо понять кто допустил ошибку и когда. Вы проверяете последние коммиты, откатываете их - баг на месте. Откатываетесь на коммит, который был год назад - бага нет. Получается в ошибка появилась в течении года.
Что делать далее? За год было множество правок, десятки, а то и сотни коммитов. Вручную переключаться между коммитами в поисках ошибки?
Есть такая команда: git bisect. Она позволяет искать коммит, в котором появился баг.
Порядок работы:
- Переключитесь в актуальное состояние ветки.
- Введите команду git bisect start.
- Далее git bisect bad
- git bisect good sha-коммита. Где sha-коммита - id коммита, в котором бага нет.
- Далее гит начнет сам переключать коммиты, которые были между "плохим" и "хорошим" коммитами.
- Вы проверяете сайт и смотрите баг. Есть есть - выполняете git bisect bad, если нету - git bisect good.
- Так после нескольких итераций, гит находит один коммит, в котором баг появляется.
Нашли мы коммит, в котором всё поломалось. Называется он "Правки" и в нем сотни измененных файлов. Помните откуда коммит? Разработчик не мог задеплоить свои правки, потому что кто-то другой не закоммитил свою задачу. Для фикса проблемы появился коммит "Правки". И вот разберись теперь, кто что и для чего правил. Автор коммита не причастен к самим правкам. Поэтому коммитить должен сам автор правок и давать осмысленное название коммиту.
Если закоммитили не то
Чтобы откатывать коммиты, есть команда git revert sha-коммита. Не используйте git reset --soft HEAD~1 или git reset --hard. git revert откатывает коммит, оставляя информацию в истории.
Когда для задачи есть специальный инструмент - надо использовать его, а не сбрасывать гит.
Если закоммитили не в ту ветку.
В не верной ветке откатываем коммит командой git revert. Копируем sha коммита исходного.
Переключаемся на нужную ветку, там пишем git cherry-pick sha-коммита
Результат: коммит в нужной ветке.
git cherry-pick - применяет коммит к текущей ветке.
Как временно откатить правки, которые еще не закоммичены
Бывает такое, что ты начал работу над задачей и на после нашел на сайте какой-то баг. Не понимаешь, то ли это ты уже сломал, то ли сразу так было. Коммитить на половине пути и откатывать коммит не хочется.
Есть решение - git stash. Команда прячет всё, что не было закоммичено в свое укромное место. Правки откатываются, но не теряются.
После проверки пишем git stash apply - из тайника всё возвращается обратно.
Я тут файлы правил и мне мои правки больше не нужны
Что делать?
Чтобы откатить правки к последнему коммиту, можно воспользоваться git checkout -- имя_файла вместо имя_файла можно указать папку.
Удалить новые файлы можно командой git clean.
Узнать что будет удалено: git clean -nd, удалить: git clean -fd.
Удалить файлы из отслеживания гит
Бывает такое, что некоторые файлы не трубуется отслеживать через гит, а они уже есть в истории. Если файл просто добавить в .gitignore - то отслеживание не прекратится.
.gitignore - файл, в котором указываются исключения для отслеживания гит.
Скажем, мы хотим удалить из гит файл robots.txt:
- Добавляем запись в .gitignore
- Удаляем файл из отслеживания: git rm --cached robots.txt. Данная команда удаляет файл из гит, но оставляет физический файл проекта не тронутым.
- Коммитим состояние
Вопрос: мы на тестовом сервере удалили файл из гит, сам файл остался на сервере. Изменения запушили, на тестовом запулили изменения. Что произойдет с файлом robots.txt на проде?
Ответ: он удалится как из гит так и физически с сервера.
Почему так происходит? Потому что гит не помечает файл как "удаленный только из гит", файл просто удаляется из репозитория. Когда мы на проде скачиваем изменения, гит смотрит - раньше файл был в гит, теперь его нет. Значит надо его удалить.
Чтобы не удалился файл, надо выполнить команду git rm --cached robots.txt во всех репозиториях, после выполнить слияния.