После мучительной работы с обычным копированием файлов многие столкнулись с тем, что командная разработка становится тем сложнее, чем больше людей в ней участвует. Больше всего проблем возникает, когда люди работают над одними и теми же файлами.
Иллюстрация из перевода статьи разработчика Warcraft Патрика Вайата:
"...когда я начал активно работать с другими художниками и разработчиками, мы обычно использовали «пешеходную локалку», то есть по сути носили друг другу из офиса в офис флоппи-диски с изменениями, которые необходимо было внедрить в код или в дизайн.
Боб Фитч был вторым разработчиком на проекте и мы с ним постоянно копировали файлы и изменения в коде между собой. Периодически мы ошибались при интеграции и баги, которые мы уже фиксили, открывались заново. Мы вылавливали их снова и обнаруживали, что когда копировали файлы, вносили изменения — мы перезаписывали что-то поверх удачных баг-фиксов, и порой приходилось вспоминать как мы уже закрывали эти баги заново.
И эта ситуация повторялось всё чаще и чаще, ведь мы ускорялись в разработке, а никакого другого процесса для контроля версий, помимо метода «запоминание где и что мы редактировали» у нас не было. Мне в какой-то степени повезло больше, ведь мой компьютер хранил «мастер» ветку нашего кода, куда мы добавляли патчи, поэтому мои изменения в коде терялись реже. Сегодня для этого мы используем системы контроля версий, но тогда мы даже не могли вообразить себе такие радости жизни!"
первая часть статьи вторая часть статьи
Итак, основная проблема - перезаписывание неактуального кода поверх актуального, потеря актуального кода.
Были предприняты попытки контролировать человеческий фактор, распределять файлы между разработчиками, но это все только осложнило.
Уже в 1974 году существовала юниксовая команда diff.
Ниже приведен пример простого текста.
1qweqwe
2erfevef
3efvercer
4vfvrvtr
6dvdfvdfv
В следующем листинге тот же самый текст немного изменен с целью демонстрации программы diff.
1qweqwe
3efvercer
4vfvrvtr
5owiceowcno
6dvdfvdfv
Имея два практически идентичных файла, можно при помощи команды diff с ключами -uN понять, какая между ними разница:
diff -uN test.txt test1.txt:
--- test.txt 2019-03-04 16:34:31.000000000 +0200
+++ test1.txt 2019-03-04 16:34:57.000000000 +0200
@@ -1,5 +1,5 @@
1qweqwe
-2erfevef
3efvercer
4vfvrvtr
+5owiceowcno
6dvdfvdfv
Команда diff работает для двух разных файлов. Система контроля версий отслеживает изменения в одном и том же файле разных версий.
Затем стали задумываться над тем, чтобы ограничить все возникающие сложности и управлять проблемами при помощи кода и автоматизации, стали изобретать различные программы для этих целей.
Программы, которые позволяют сохранять различные файлы и различные версии этих файлов, сравнивать файлы и различные их версии, иметь возможность переходить между различными версиями файлов, называются Системами контроля версий.
Первая, простейшая СКВ - это просто резервное копирование файлов.
Можно сохранять все в файл, или записывать в БД инфу о файлах и их версиях, но суть не меняется - все хранится на локальном компьютере.
Второй, более продвинутый вариант - централизованная СКВ. Суть такого подхода - хранение кода на сервере и использование на локальных машинах.
Писк же моды в данном вопросе - распределенная СКВ.
Изменения делаются на локальных машинах, версии же сохраняются и на них, и на сервере.
Вот этот парень - Линус Торвальдс.
Он когда-то и придумал GIT, о котором мы сегодня и поговорим.
Для того, чтобы установить git под windows, попробуйте [вот эту ссылку] (https://git-for-windows.github.io/). Установка там проста, надо соглашаться на изначальные установки и нажимать кнопку Next.
Предположим, что у нас в системе стоит git.
Для начала работы нам нужна пустая папка в удобном месте и открытая консоль в этой папке. Создаем пустую папку, заходим туда. Если у вас git bash, щелкните правой кнопкой по пустому месту в папке и выберите git bash here
.
Оказавшись в пустой папке, мы создаем там пустой локальный git репозиторий:
git init
Стандартный ответ:
Initialized empty Git repository in /Users/bandy/sites/form/.git/
Команда git init
создает в папке новую подпапку .git
, в которой git хранит все необходимые ему данные. Эту папку лучше не трогать. После этого все изменения в файлах, которые находятся в этой папке или в папках глубже этой находятся под контролем версий. Git будет видеть изменения в файлах, но решать, какие изменения сохранить в какой момент и в каких файлах - решать программисту.
Итак, локальный репозиторий создан.
В локальном репозитории, как и в любой обычной папке, могут находиться файлы и папки. Отличие локального репозитория от обычной папки на вашем жестком диске в том, что за изменениями файлов и папок следит система контроля версий. Файлы могут быть неотслеживаемыми т.е. теми, которые не находятся под контролем версий, отслеживаемыми, измененными и подготовленными к коммиту. Рассмотрим эти состояния поподробнее:
- Неотслеживаемый (untracked) - изначально файлы и папки в локальном репозитории являются неотслеживаемыми. Если файл хоть один раз добавлялся под контроль версий, он уже отслеживаемый.
- Отслеживаемый (tracked) - файл уже под контролем версий git, но со времени последнего сохранения в него не вносились изменения.
- Измененный (modified) - файл под контролем версий и в нем есть несохраненные изменения, которые пока не проиндексированы.
- Проиндексированный или подготовленный к коммиту (staged) - в файле есть изменения, которые проиндексированы и будут сохранены в ближайшем коммите.
Понятие индексирования довольно простое. Есть некий индекс (index, stage), который является набором изменений в файлах. Это те изменения, которые находятся под контролем версий, и которые программист запланировал сохранить в самом ближайшем сохранении - коммите.
Проследим за статусом файла index.html на нашем локальном репозитории, для этого добавим в наш репозиторий файл(просто скопируем или переместим файл в нашу папку) и посмотрим на его статус:
git status
Обнаружен файл index.html
, который пока не добавлен в планы на сохранения.
Добавим этот файл при помощи команды git add index.html
и проверим статус после этого:
При помощи команды git add
можно добавлять файл, группу файлов, папку с файлами или даже файлы по маске к индексу. Добавляются как неотслеживаемые файлы, так и измененные, и все они становятся проиндексированными.Все добавленное при ближайшем коммите будет сохранено.
Если внести изменения в файл index.html после того, как мы добавили его в индекс, файл у нас будет одновременно и измененным и проиндексированным:
Git работает не с целыми файлами, и не со строками этих файлов. Минимальными единицами информации в git являются изменения в файлах, выполненнные с момента прошлого сохранения.
Сохранения каждого файла можно добавлять или не добавлять в планы на будущее сохранение версии. Добавленные будут сохранены при ближайшем сохранении версии, не добавленные остануться несохраненными.
Рекомендуется проверять статус репозитория часто и внимательно.
Продолжим, проиндексируем изменения и попробуем их сохранить при помощи команды git commit -m"comment"
:
У большинства из студентов будет выведено нечто похожее. Git сообщает нам, что для подписи коммитов ему нужно знать email и имя пользователя. Команды
git config --global user.name "username"
git config --global user.email "usermail"
помогут внести нужные изменения. Не забудьте заменить username и usermail на свои никнейм и почту.
Повторим попытку коммита (git commit -m"comment"
):
Мы успешно сохранили версию нашего кода под контролем версий.
Обратите внимание на опцию -m
у команды. Она позволяет задать краткий комментарий к коммиту, если ее не применить, запустится редактор, из которого еще надо уметь выйти (trollface)
Проверим ситуацию с сохранениями командой git log
:
Команда покажет нам журнал наших коммитов. Там можно увидеть уникальный номер коммита, дату и время сохранения, ник и email автора коммита а так же краткий комментарий. Выход из журнала - буква q
Далее, нам необходимо создать удаленный репозиторий на каком-нибудь сервере или подключиться к готовому. Можно пользоваться любым сервером удаленных репозиториев, но самым популярным является github
.
Если вы там уже зарегистрированы, войдите туда, залогиньтесь. Далее, необходимо подружить между собой локально установленный git и выбранный сервер удаленных репозиториев.
Есть два пути для их общения: https
и ssh
. HTTPS
- довольно простой путь, мы попробуем более сложный и интересный путь SSH
. Первая ссылка в приложении поможет вам создать такие ключи.
Для создания репозитория необходимо нажать кнопку new и заполнить форму создания нового репозитория.
В поле Repository name необходимо ввести имя репозитория, которое одновременно будет не слишком большим и в то же время информативным.
После того, как репозиторий создан, его надо подключить к нашему локальному репозиторию.
git remote add origin %%serverpath%%
git remote -v
git pull origin master
$ git push
fatal: The current branch master has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin master
Гит ругается, говорит, ветка не задана, сервер не задан, он не понимает, куда пушить. Поясним:
$ git push origin master
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 789 bytes | 0 bytes/s, done.
Total 5 (delta 0), reused 0 (delta 0)
To https://github.com/Bandydan/custom
003085e..775d992 master -> master
И сделаем так, чтобы он больше не ругался:
git push --set-upstream origin master
Branch master set up to track remote branch master from origin.
Everything up-to-date
git add filename # Добавление файла filename в индекс
git add * # Добавление всех файлов в индекс
git add . # Добавление всех файлов в индекс
git rm filename # Удаление файла из индекса
git status # Просмотр статуса локального репозитория
git commit # Добавление из индекса в слепок/ Требует ввода комментария
git commit -m "comment" # Добавление из индекса в слепок c быстрым вводом комментария
git diff # Сравнение веток, рабочей директории и индекса и прочие сравнения
git diff --cached # сравнение проиндексированных изменений с непроиндексировной версией кода
git reset # Отмена изменений
git push # Залить закоммиченные изменения на сервер
git fetch # Скачать новые изменения с сервера (без слияния)
git pull # Скачать новые изменения с сервера (со слиянием)
git checkout # Переключиться на ветку
git checkout -b # Переключиться на новую ветку и создать ее
git checkout filename # отменить все изменения в файле
git branch # удаляет, создает и перечисляет ветки
Правила размещения проекта в A-level Gitlab