Системы контроля версий и клиенты для Windows: GIT и SourceTree
Автор: Кулик Алексей aka kpblc | Дата: 19 Март 2014 · 13 коммент.
GIT и SourceTree
Плюем на все и скачиваем встроенную версию Git (самый верхний вариант). Объем – около 21 МБ.
После установки необходимых компонентов (среди них есть .NET 4.5) появляется следующее окно:
Mercurial– еще одна система, с ней не работал. Выбираю “Я не хочу использовать Mercurial”. Дальше устанавливаем согласие с лиц.соглашением:
Если не заполнить поля Полное имя и Адрес e-mail, нажатие кнопки Вперед приведет к ошибке:
Фактически эти данные нужны только для отслеживания «кто внес изменения». Поэтому заполнять можно любой абракадаброй, хотя я вводил реальные значения.
Далее идет запрос на выбор SSH-клиента.
SSH-клиент: программа, обеспечивающая работу по т.н. «безопасному» протоколу. Фактически требуется только для общения с внешними GIT-репозиториями. Поскольку нам на нее параллельно, выбираем значение по умолчанию – PuTTY.
“Пропускать настройку” не рекомендую – кто его знает, что и как установится…
На вопрос “Есть ли у вас SSH-ключ?” отвечаем “Нет”:
Далее программа запрашивает данные на коннект к сторонним git-репозиториям. Нам оно без надобности, посему жмем Завершить.
Прежде всего сменим текущий рабочий каталог на v:
Переименовываем русские каталоги в английские: «Градостроительство» – в «TownBuild», «Изыскания» – в «TownBuild.Searches» и т.п. После этого инициируем новую рабочую копию.
Добавим созданный нами репозиторий в SourceTree:
В принципе, имя можно задавать любое. Мне было лень переделывать – оставил как есть.
Жмем кнопку [Добавить].
Все, репозиторий создан. Прежде чем его инициализировать и начинать с ним работать, его надо немного настроить.
Выберем в левой части окна SourceTree нужный репозиторий (если их у нас несколько), выполним двойной клик для активации соответствующей закладки и в меню вызовем его настройки:
Нам будет интересна вторая закладка (Дополнительно) и на ней кнопка Редактировать. Нажмем ее.
При установках Windows «по умолчанию» файлы с расширением .gitignore не ассоццированы ни с каким приложением. Первое движение – открыть файл в блокноте Windows – претворять в жизнь не стоит.
Дело в том, что SourceTree читает этот файл, используя кодировку UTF-8, а Блокнот создаст этот файл с кодировкой ANSI-1251. В принципе, некритично, если вдруг Вы не собираетесь в критерии обработки помещать кириллические символы.
Для вящего спокойствия настоятельно рекомендую скачать тот же самый Notepad++, который позволяет как минимум корректно поменять кодировку существующему файлу, и ассоциировать именно его с файлами .ginignore.
Итак, открываем файл .gitignore в Notepad++, и сразу же меняем кодировку на UTF-8:
Теперь в этом файле, используя некоторые несложные правила, запишем – что мы хотим обрабатывать, а что – нет.
Прежде всего:
Если строка начинается с символа #, то строка считается комментарием.
Если строка пустая, она игнорируется (очень удобно разделять некие логические элементы)
Если строка начинается с символа !, то все, что за ней, обязательным образом обрабатывается
Если строка заканчивается символом обратного слеша (/), то считается, что она касается каталога
В строках поддерживаются маски (*, ?, квадратные скобки и т.п.).
Волевым решением считаем ненужными файлы страховых копий. Т.е. исключаем все bak, err, log, _ls, *.bak.* файлы:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | # Убираем страховые копии файлов *.bak *.bak.* *.err *.mn[rc] *._ls *.dwl* *.log # Точно не понадобятся файлы, которые создает Windows: Thum*.db # Так же считаем, что не понадобятся архивы – rar, zip, 7z *.rar *.zip *.7z |
Проведем небольшой эксперимент. Создадим «временный» репозиторий (в любом каталоге), в его .gitignore вставим наши строки, добавим туда пару каталогов и несколько файлов, отвечающих требованиям игнорирования:
Активируем SourceTree (при настройках по умолчанию он сразу выполняет сканирование активного репозитория) и попробуем в нем найти файл _hawk-stamp-dcl-execute._ls :
Как видно, такой файл в репозиторий не попадет: он отвечает настройкам .gitignore. И никаких дополнительных действий по указыванию таких файлов выполнять уже не надо.
Вспомним о том, что изначально у нас использовалась SVN, которая хранит все свои данные в каталогах .svn (возможно, дополнительно проявятся каталоги db, locks,conf…). Такие каталоги тоже надо исключать:
1 2 3 4 5 6 7 | # Исключаем данные SVN: .svn/ db/ locks/ conf/ hooks/ format/ |
Обратите внимание: вложенность таких каталогов тоже не указывается. Они будут искаться везде и автоматически. И все их содержимое будет исключаться из обработки.
Допустим, что мы точно знаем, какие каталоги нам надо сохранять (остальные отправляем в игнор). Это будут каталоги Apps, Settings, ну и, к примеру, DotNet. Нам нужны будут эти каталоги и все их содержимое, независимо от степени вложенности.
Устанавливаем соответствующие настройки:
1 2 3 4 5 6 7 | # Элементы, которые надо сохранить !App*/ !App*/**/ !dotnet/ !dotnet/**/ !settings/ !settings/**/ |
Переименовывая каталоги, я все русские названия начинал со слова TownBuild. Поэтому добавим еще пару строк в .gitignore:
1 2 3 4 | 1С/ TownBuild*/ _Отчуждаемые/ VersionControl/ |
И, наконец, последнее: убираем все файлы из корня сетевого диска:
1 | /*.* |
Но при этом нам надо оставить файл .gitignore:
1 | !.gitignore |
Отредактировав файл, достаточно его просто сохранить и можно не закрывать приложение редактора.
Возвращаемся в SourceTree:
Выполняем коммит:
Обязательно указываем пояснение (сообщение) к коммиту. Это у нас стартовый коммит – так и обзовем. После этого вносим в коммит те файлы, которые нам интересны (а интересны на данный момент нам все файлы):
По окончании процесса у нас есть рабочая копия, хранящаяся на сервере. Пришло время преобразовать ее в нормальный центральный репозиторий.
Сначала создадим центральный репозиторий, внутри которого не хранятся собственно рабочие файлы. Вызываем терминал, меняем в нем текущий каталог на v:\VersionControl и потом выполняем команду
1 | git init --bare |
Теперь собственно клонирование «рабочей копии» в «центральный» репозиторий:
1 | git clone −−bare <путь до локального репозитория> <имя директории с локальным репозиторием> |
Учитывая наши условия, получим нечто типа:
1 | git clone --bare v:/ v:/versioncontrol |
Обратите внимание на двойной минус и на направление слешей.
Создаем теперь локальную рабочую копию, над которой в процессе работы и будем измываться.
Возвращаемся в SourceTree, и клонируем репозиторий:
Указываем, откуда клонируем, куда, задаем имя. Остальные настройки не трогаем. Нажимаем Клонировать.
По окончании работы зайдем в каталог c:\git_tmp:
В свое время в .gitignore мы задавали именно такие настройки. Вот и получили чего хотели
В подкаталоге Settings создадим папку с названием “Новая папка”, внутри – текстовый файл TestTextDoc.txt:
1 2 3 | qwerty asdfgh zcvbn |
Возвращаемся в SourceTree:
Выполняем коммит.
Допустим, в результате долгих действий мы добились нормальной работы. Теперь это дело надо “слить” с основным репозиторием:
После объединения изменений можно выполнить обновление рабочей копии на сервере:
Если бы у нас было несколько внешних репозиториев, нам бы понадобилось указывать, из какого репозитория надо «вытаскивать» данные. Сейчас же у нас всего один репозиторий, поэтому все намного проще:
Крайне желательно нажать кнопку “Обновить”, потом выбрать ветку, с которой надо вытаскивать. Все, жмем ОК.
Выполняется слияние ветки master с веткой test (ветка master была выделена перед вызовом команды слияния):
В результате мы можем получить нечто типа
Видны места разветвления и слияния ревизий, виды все комментарии. По-моему, достаточно удобно.
Плюсы:
- Работа выполняется в своем собственном окне
- Видна вся иерархия разработки, включая ветки и их историю
- Внесение комментариев к коммитам обязательно.
Из минусов:
- Необходимость работы с терминалом при создании центрального репозитория
- Невозможность обработки (без дополнительных настроек) каталогов с неанглийскими первыми символами.
Полезная информация, а как настроить поддержку кирилkицы в терминале mingw32?
А при чём тут mingw? Если я правильно понимаю, это вообще среда разработки, а не git-клиент.
>Плюем на все и скачиваем встроенную версию Git (самый верхний вариант). Объем – около 21 МБ.
Возможно будет интересно: http://git-for-windows.github.io/
Я пробовал использовать этот софт. Но мне он как-то не очень понравился - чисто с эстетической точки зрения. Хотя, насколько я помню, свои задачи выполнял в нормальном режиме )
>Фактически эти данные нужны только для отслеживания «кто внес изменения». Поэтому заполнять можно любой абракадаброй,
Позже это может выйти боком, если вдруг по каким-либо причинам реально потребуется связаться с разработчиком.
>Эти данные хранятся в специальном текстовом файле с очень странным (с точки зрения пользователя Windows) именем .gitignore.
На самом деле файлов с настройками игнорирования может быть несколько и имеют они разные имена: .gitignore (находятся в отслеживаемых каталогах), ./.git/info/exclude, а так же шаблоны из файла, указанного в переменной core.excludesFile любого из конфигурационных файлов git. В зависимости от необходимой области действия шаблон задаётся в том или ином файле игнорирования.
>Если строка начинается с символа !, то все, что за ней, обязательным образом обрабатывается
Неверно. Это символ инвертирования результата.
>Проведем небольшой эксперимент. Создадим «временный» репозиторий (в любом каталоге), в его .gitignore вставим наши строки, добавим туда пару каталогов и несколько файлов, отвечающих требованиям игнорирования:
Можно сделать проще: команды git add и git rm поддерживают опцию -n (либо ключ --dry-run). Опция позволяет посмотреть результат работы команды, фактически не выполняя её. Возможно, что и в GUI SourceTree должна присутствовать возможность выполнять аналогичное действие. Если есть возможность открыть консоль git из контекстного меню в проводнике windows (что-то вроде этого: http://www.git-for-win.red-bee.ru/index.html?cui_or_gui.html ), то запустив команду git rm -n "*" можно посмотреть состав выбранных файлов.
>Как видно, такой файл в репозиторий не попадет: он отвечает настройкам .gitignore. И никаких дополнительных действий по указыванию таких файлов выполнять уже не надо.
Если какой либо файл, отсеиваемый фильтрами, всё же по каким-либо соображениям должен быть отслеживаемым, то применительно к нему команда git add должна запускаться с опцией -f.
>Допустим, что мы точно знаем, какие каталоги нам надо сохранять (остальные отправляем в игнор). Это будут каталоги Apps, Settings, ну и, к примеру, DotNet. Нам нужны будут эти каталоги и все их содержимое, независимо от степени вложенности.
># Элементы, которые надо сохранить
>!App*/
>!App*/**/
>!dotnet/
>!dotnet/**/
>!settings/
>!settings/**/
На мой взгляд, это несколько странный набор фильтров... Почему было не ограничиться таким вариантом(?):
#*********************************************
# Элементы, которые надо сохранить
!Apps/
!dotnet/
!settings/
#*********************************************
Согласно указанным мною фильтрам из игнорирования исключаются обозначенные каталоги и всё их содержимое (рекурсивно). Насколько я тебя понял - тебе нужно именно это. В соответствии с процитированным текстом, а так же с этим скрином: http://autolisp.ru/wp-content/uploads/2014/03/svn_folderstruct.png, у тебя только один каталог, имя которого соответствует App* - это каталог Apps, поэтому и в фильтре можно указывать сразу Apps вместо App*.
>По окончании процесса у нас есть рабочая копия, хранящаяся на сервере. Пришло время преобразовать ее в нормальный центральный репозиторий.
Стоп... На каком "сервере"? Ты же работал с локальным каталогом c:\git_tmp (согласно скрину http://autolisp.ru/wp-content/uploads/2014/03/st_gui03.png )...
> На самом деле это не столько создание, сколько “клонирование”. На диске C: создаем каталог git_tmp:
Ты ведь его уже создал ещё в самом начале (согласно обозначенному выше скрину)...
Вообще, на мой взгляд, плохая идея - мешать мух с котлетами. Не вижу смысла в одном каталоге хранить исходный код проектов наряду с каталогами содержимое которое не имеет никакого отношения к программированию (которые нужно прописывать в настройках игнорирования). Добавив очередной каталог, аля "Вася Пупкин - чемпион", тебе снова придётся вносить правки в настройки игнорирования. В один прекрасный момент ты забудешь это сделать, т.к. тебя кто-то будет отвлекать по телефону или стоять над душёй с глупым вопросом, в результате чего "Вася Пупкин" войдёт в состав очередного коммита (что может быть обнаружено тобой не сразу).
К сожалению, невозможно задать такое правило:
*/
!./(Apps|dotnet|settings)/
Это обусловлено тем, что:
An optional prefix "!" which negates the pattern; any matching file excluded by a previous pattern will become included again. It is not possible to re-include a file if a parent directory of that file is excluded. Git doesn’t list excluded directories for performance reasons, so any patterns on contained files have no effect, no matter where they are defined.
Т.о. лучше заблаговременно отделять мух от котлет, дабы не создавать самому себе в прок лишних проблем в будущем.
В общем, я споткнулся об эту фразу:
>По окончании процесса у нас есть рабочая копия, хранящаяся на сервере. Пришло время преобразовать ее в нормальный центральный репозиторий.
>Сначала создадим центральный репозиторий, внутри которого не хранятся собственно рабочие файлы.
Перестал что либо понимать, в виду чего далее пока не читал. Продолжу после того, как ты внесёшь некоторую ясность в обозначенные мною выше вопросы.
Не понял... А куда пропал мой самый первый, самый большой коммент с кучей замечаний и вопросов?
Никуда не делся. Он упал в премодерирование.
У меня на работе именно через систему контроля версий распространяются как исходные коды, так и готовые к употреблению модули - как .NET, так и lsp. Ты не забывай, что не все и не всегда используют только С# - вполне могут быть и другие варианты.
Я не забываю и про это даже не заикался. Честно говоря, по твоему ответу я так и не понял, каким образом контролирование исходников и откомпилированного кода соотносится к наличию каталогов, не относящихся к ПО и его исходникам: __Градостроительство, Изыскания и т.п. Зачем лепить эти каталоги и потом прописывать фильтры их игнорирования. Кто-то может добавить туда новый каталог, а ты этого не заметишь - в результате существует вероятность, что этот каталог может попасть в состав твоих коммитов. Ну да ладно, об этом я уже писал выше. Дело твоё.
Так и не дождался ответа на вопрос, для чего присутствуют фильтры !App*/**/, !dotnet/**/ и !settings/**/.
>Жмем кнопку [Добавить].
> Все, репозиторий создан. Прежде чем его инициализировать и начинать с ним работать, его надо немного настроить.
Этого момента я не понял. Снова создал, что ли? Ты ведь уже перед этим создал репозиторий при помощи git init. Т.е. ты сейчас средствами SourceTree создаёшь клон на основе этого, только что созданного репозитория (т.е.выполняешь git clone)? Или же ты просто указываешь SourceTree где находится нужный тебе репозиторий (без лишнего клонирования)? На скрине консоли ты пишешь v:, а на скрине SourceTree у тебя указан путь c:\git_tmp. Уточняю на всякий случай, а то вдруг ты действительно клонируешь...
>Все, репозиторий создан. Прежде чем его инициализировать и начинать с ним работать, его надо немного настроить.
Ты его уже инициализировал командой git init.
>Важно! Есть один очень серьезный, и не очень приятный момент: каталоги верхнего уровня не могут иметь первым символом неанглийские буквы. SourceTree, как выяснилось, такие названия не обрабатывает вообще.
Весьма существенный минус, на мой взгляд (ложка дёгтя). Порой переименовывание каталогов может оказаться неприемлемым, т.к. их имена фигурирую в различного рода настройках различных приложений, в т.ч. и в административных утилитах.
> И, наконец, последнее: убираем все файлы из корня сетевого диска:
> /*.*
Не только файлы, но и каталоги, в имени которых присутствует точка.
>Сначала создадим центральный репозиторий, внутри которого не хранятся собственно рабочие файлы. Вызываем терминал, меняем в нем текущий каталог на v:\VersionControl и потом выполняем команду
> git init --bare
Правильней так: "не содержащий рабочего дерева (working tree)".
>По окончании процесса у нас есть рабочая копия, хранящаяся на сервере. Пришло время преобразовать ее в нормальный центральный репозиторий.
На каком ещё "сервере"? Ты ведь работал с виртуальным диском который, по сути - один из каталогов твоего диска D:\. Я не понял, что ты подразумеваешь под "преобразовать"...
> Теперь собственно клонирование «рабочей копии» в «центральный» репозиторий:
> git clone −−bare
>
> Учитывая наши условия, получим нечто типа:
> git clone --bare v:/ v:/versioncontrol
А зачем ты перед этим делал git init --bare для каталога v:\VersionControl? В этом не было необходимости, т.к. git clone --bare v:/ v:/versioncontrol и так сделает всё как надо.
>Возвращаемся в SourceTree, и клонируем репозиторий:
Знакомая картинка... Выше ты её уже скрин с обозначенными путями (хотя там должны были пути начинаться с v:\).
> Возвращаемся в SourceTree, и клонируем репозиторий:
> Указываем, откуда клонируем, куда, задаем имя. Остальные настройки не трогаем. Нажимаем Клонировать.
На скрине указан неверный каталог источника: вместо v:\ должен был быть указан v:\VersionControl, ведь именно его ты назначаешь "центральным" и доступным для выполнения git push.
> Теперь для обоих репозиториев (и того, который на сервере, и локального) устанавливаем в качестве внешнего наш V:\_GIT_VersionControl.
А почему на том же самом локальном диске? В чём соль? Я ещё понимаю, если у тебя:
1) рабочий репозиторий - непосредственно для работы.
2) тот, который ты назвал "центральным" (я бы предпочёл назвать его "расшаренным") так же находится на твоём диске, но доступен по сети др. программерам для выполнения git fetch (т.е. доступен только для чтения).
3) а этот самый _GIT_VersionControl находится в сетевом каталоге, доступный всем программерам только для чтения и лишь их "боссу" для записи - вот это действительно "центральный" репозиторий.
Причём у каждого девелопера свои рабочий и расшаренный репозитории. Каждый девелопер в настройках своих расшаренных и рабочих репозиториев имеет записи для "внешних репозиториев" (remote repositories).
>Возвращаемся в SourceTree:
Что за муть показана на скрине в тексте файла Settings/Users/Users.ini? Сплошные кракозяблы... Смотрю SourceTree серьёзно не дружит с кирилицей, хотя вроде комменты к комитам показывает корректно...
Этот скрин: http://autolisp.ru/wp-content/uploads/2014/03/sourcetreesetup_041.png как-то выподает из общей логики повествования. Неплохо было бы пояснить, что user.name и user.email нужно хранить в конфиг-файлах git (каждый конфиг имеет свою область влияния).
> Крайне желательно нажать кнопку “Обновить”, потом выбрать ветку, с которой надо вытаскивать. Все, жмем ОК.
Неплохо было бы пояснить почему: потому, что если кто-то уже отправил свой коммит в центральный репозиторий, то ты не сможешь сделать этого до тех пор, пока предварительно не синхронизируешься с центральным репом.
>В любой момент, имея несколько ревизий, можно восстановить состояние рабочей копии – достаточно в SourceTree выполнить двойной клик на нужной ревизии. Обновление выполняется практически моментально.
Что подразумевается по "ревизией"? Коммиты, что ли?
> Для объединения желательно выбрать основную (master) ветку и объединять именно с ней.
Чем обусловлено это самое "желательно"? Ветки, при необходимости, можно закидывать и в центральный репозиторий, как альтернативные пути развития ПО.
> http://autolisp.ru/wp-content/uploads/2014/03/sourcetree_branch05.png
Весьма неинформативные имена коммитов.
> 1. Работа выполняется в своем собственном окне
Этой фразы я не понял. Имеется в виду то, что это GUI-приложение, а не консольное?
> Необходимость работы с терминалом при создании центрального репозитория
Странно... Может ты просто плохо искал?
> Необходимость работы с терминалом при создании центрального репозитория
не "центрального", а "голого" репозитория, (bare repository). Такие репозитории не обязательно центральные.