Страницы

Поиск по вопросам

Показаны сообщения с ярлыком контроль-версий. Показать все сообщения
Показаны сообщения с ярлыком контроль-версий. Показать все сообщения

четверг, 19 марта 2020 г.

Хостинги для публикации кода

#хостинг #контроль_версий


Есть два понятия:


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


Вопрос в следующем. Я пробовал пользоваться Github, но это несколько затратно ввиду
моих нужд. Нужно, чтобы на некоем сайте можно было начать проект, была примитивная
возможность создавать папки, сливать туда файлы с кодом, и этот же код, просматривать
онлайн. Сливать именно через браузер, а не через систему контроля версий (часто работаю
на разных компьютерах, а устанавливать и настраивать git, желания нет).

Сниппеты не катят, потому что это не файлы. А искать, если проект состоит более чем
из одного файлы радости не доставляет. Плюс бывают файлы с моделями, а их таким образом
уже не зальешь.

Заранее спасибо за дельные советы и ссылки.
    


Ответы

Ответ 1



Обычно в таких ситуациях (когда система контроля версий - слишком тяжеловесно) используют Dropbox. UPD Несколько извращенный вариант, но просмотр кода он-лайн есть, да еще и с примочками: CodeRemarks

Ответ 2



Может быть вам просто подойдет онлайн-хранилище файлов как dropbox,или нужно что-то более специфичное?

Ответ 3



Мне нравится система контроля версий Bazaar. Код сливаю на launchpad, где можно посмотреть код онлайн. Система является распределенной, что является удобной, когда пишу код на разных компьютерах, в разных операционных системах. http://ru.wikipedia.org/wiki/Bazaar

Ответ 4



OwnCloud похоже то, что требуется. Можно поставить свой сервер, можно купить хостинг с этим сервисом. Добавлено. Если все-таки выбирать из всех возможных вариантов, в том числе и с контролем версий, то можно начать отсюда: сравнение хостингов

пятница, 6 марта 2020 г.

В чём состоит отличие между различными workflow? [дубликат]

#git #контроль_версий #dvcs


        
             
                
                    
                        
                            На этот вопрос уже даны ответы здесь:
                            
                        
                    
                
                        
                            Правильное именование веток
                                
                                    (3 ответа)
                                
                        
                                Закрыт 2 года назад.
            
                    
Слышал о существовании большого количества workflow (процессов разработки) — git
flow, github flow, gitlab flow. 

В чём их сущность и чем они отличаются? Ведь ветвление происходит во всех трёх случаях.
    


Ответы

Ответ 1



Да, все workflow имеют много общего, поскольку предназначены для работы с одними и теми же инструментами (в данном случае с git-ом, распределённой системой контроля версий, обладающей возможностью лёгкого ветвления). Однако у них имеются весьма существенные различия в том, как с этими ветками обращаться. Git Flow Есть две фиксированные ветви, «стабильный» master и «развивающийся» develop. При появлении необходимости внесения изменений в код происходит одно из двух: от develop отпочковывается тематическая ветка, если это внесение функционала или подготовка к выпуску новой версии, либо ветка отпочковывается прямо от master, если это исправление ошибки. После окончания работ тематическая ветвь вливается в её родителя, а в ряде случаев — и в master. GitHub Flow То же, что и Git Flow, но фиксированная ветка всего одна — master; всё остальное принадлежит тематическим ветвям. Тематические ветви, в свою очередь, создаются в форках — клонированных копиях репозитория. То есть центральный репозиторий тематических веток не содержит. В том числе и после слияния, так как метки веток при этом снимаются и их головы становятся анонимными. GitLab Flow Как и в GitHub Flow, фиксированная ветка всего одна — master; всё остальное принадлежит тематическим ветвям. Однако, если в том случае релизы размещались в коммитах master-a, то здесь для каждого релиза создаётся своя, отдельная ветка. Причём никакого слияния этих веток с родителем не производится. Если ветка отпочковалась, значит она будет жить своей жизнью, получая исправления ошибок в виде отдельных коммитов (возможно, портированных из головы мастера с учётом накопившейся разницы в функционале между ветками). Иллюстрации были взяты из статьи «잘 밤에 쓸데없는 생각하기...». В корейском я не смыслю, но картинки красивые.

вторник, 18 февраля 2020 г.

Как часто надо делать комит? [дубликат]

#контроль_версий


        
             
                
                    
                        
                            На этот вопрос уже даны ответы здесь:
                            
                        
                    
                
                        
                            Следует ли коммитить в git промежуточные копии когда
библиотека вообще не готова
                                
                                    (3 ответа)
                                
                        
                                Закрыт 2 года назад.
            
                    
когда заканчивается проект? на каждой задаче, либо раз в месяц?)
    


Ответы

Ответ 1



Коммиты не должны быть привязаны ко времени. К задачам тоже не верно. Желательно привязывать к фичам/работающему функционалу. Если речь про git, то рекомендую: На каждую задачу создавать новую ветку. Коммитить функционал по готовности. Как можно детерминированней. Не надо, безусловно, коммитить отдельно каждую функцию. Но, если выбирать между этим и заливкой всех изменений одним коммитом, то лучше первое.

Ответ 2



Зависит от требований тим лидера или заказчика. Если ты себе сеньёр, сам тим лидер и заказчик то сам и решай как часто делать. Можно использовать гит как репозиторий для хранения, тогда коммиты будут делаться редко. При коммите каждой задачи это будет выглядеть: git commit -am"пофиксил задание №777". Лично я люблю коммитить после успешного завершения задачи, то есть полность рабочая кнопка на сайте. Или полность рабочий интерфейс. Бывает что нужно сделать просто страховочный коммит и отправить на репу чтобы код не пропал в случае если жесткий диск накроется например (или твой ноутбук случайно выбросят в окно). Также если нашлись баги то можно писать коммит на каждый баг и писать в описание что мы там пофиксили. А еще можно писать коммиты после написания класса или функции а также написания скрипта. Рекомендую работать с гит через командную строку (терминал на линукс). А если нужно просмотреть код, то использовать прогу визуальный редактор для гит типа ГитКракен или любую другую. Также рекомендую битбакет.

Ответ 3



На каждой задаче. Иногда на каждой подзадаче, я каждый час иногда делаю.

воскресенье, 16 февраля 2020 г.

Как часто надо делать комит? [дубликат]

#контроль_версий


        
             
                
                    
                        
                            На этот вопрос уже даны ответы здесь:
                            
                        
                    
                
                        
                            Следует ли коммитить в git промежуточные копии когда
библиотека вообще не готова
                                
                                    (3 ответа)
                                
                        
                                Закрыт 2 года назад.
            
                    
когда заканчивается проект? на каждой задаче, либо раз в месяц?)
    


Ответы

Ответ 1



Коммиты не должны быть привязаны ко времени. К задачам тоже не верно. Желательно привязывать к фичам/работающему функционалу. Если речь про git, то рекомендую: На каждую задачу создавать новую ветку. Коммитить функционал по готовности. Как можно детерминированней. Не надо, безусловно, коммитить отдельно каждую функцию. Но, если выбирать между этим и заливкой всех изменений одним коммитом, то лучше первое.

Ответ 2



Зависит от требований тим лидера или заказчика. Если ты себе сеньёр, сам тим лидер и заказчик то сам и решай как часто делать. Можно использовать гит как репозиторий для хранения, тогда коммиты будут делаться редко. При коммите каждой задачи это будет выглядеть: git commit -am"пофиксил задание №777". Лично я люблю коммитить после успешного завершения задачи, то есть полность рабочая кнопка на сайте. Или полность рабочий интерфейс. Бывает что нужно сделать просто страховочный коммит и отправить на репу чтобы код не пропал в случае если жесткий диск накроется например (или твой ноутбук случайно выбросят в окно). Также если нашлись баги то можно писать коммит на каждый баг и писать в описание что мы там пофиксили. А еще можно писать коммиты после написания класса или функции а также написания скрипта. Рекомендую работать с гит через командную строку (терминал на линукс). А если нужно просмотреть код, то использовать прогу визуальный редактор для гит типа ГитКракен или любую другую. Также рекомендую битбакет.

Ответ 3



На каждой задаче. Иногда на каждой подзадаче, я каждый час иногда делаю.

пятница, 14 февраля 2020 г.

Как разделить коммит на несколько?

#git #контроль_версий #git_rebase


Закоммитил всё, с помощью git commit -a -m Save, но потом забыл про это и сделал
несколько коммитов поверх него.  

Существует ли возможность разделить коммит в истории git на несколько более специфичных?  
    


Ответы

Ответ 1



В документации Git есть замечательная инструкция, как раз на этот случай: Разделение коммитов В интерактивном режиме, Вы можете пометить коммит действием "edit"(редактировать). Однако, это не означает, что git rebase ожидает результат редактирования в виде ровно одного коммита. На самом деле, Вы можете отменить этот коммит, и/или добавить другие наборы изменений. Это можно использовать, чтобы разделить коммит на несколько: git rebase -i <коммит>^ - Начните интерактивное изменение истории с помощью git rebase -i <коммит>^, где <коммит> - это то, что Вы хотите разделить. На самом деле, тут может быть любой диапазон изменений, если он включает нужный коммит edit - Пометьте тот коммит, который необходимо разделить действием "edit". git reset HEAD^ - Когда дело дойдёт до редактирования этого коммита, выполните git reset HEAD^. Это удалит зафиксированный набор изменений, оставив все изменения в рабочем каталоге. git add; git commit - Теперь фиксируйте изменения таким образом, которым Вы хотели. В процессе, Вы можете делать что угодно, редактировать файлы, убирать изменения в stash, и т.п. git rebase --continue - Когда все изменения зафиксированы в желаемом количестве коммитов(git status пуст), выполните git rebase --continue, чтобы применить все вышележащие изменения поверх новых. Любое изменение в истории контроля версий git, порождает новую историю, несовместимую со старой (все хеши будут обновлены). Поэтому, Вы должны ясно понимать, что Вы делаете. Лучше воздержаться от изменения истории, которая покинула локальный репозиторий и может (даже потенциально) быть у другого разработчика.

среда, 5 февраля 2020 г.

Правильная нумерация ПО?

#php #веб_программирование #cms #контроль_версий #движок


Есть версия ПО 2.9.9 

Нужно выпустить новую версию, при этом не хотелось бы переходить на 3.0 Так и не
смог разобраться, под какой версией выпустить ПО? 

2.9.10? 2.10.1? 2.9.91? 

Да так, чтобы было понятно людям, что эта версия новее предыдущей.
    


Ответы

Ответ 1



Проблема: вы руководствуетесь принципами визуальной упорядоченности при установке версии. Версионирование не имеет никаких связей с визуальной упорядоченностью. Конфликт: вы не можете выбрать между виузальной упорядоченностью, которая говорит вам сделать 3.0.0, и принципом мажорного релиза, который осознаете скорее всего по-своему, но понимаете, что мажорный релиз это не "когда все цифры после первой становятся девятками". Решение: выбрать только одно из двух, потому что принцип мажорной версии запрещает вам скакать, как получится, а визуальная упорядоченность не дает вам использовать двузначное число в качестве одного из компонентов версии. Как все-таки хоть немного программист я могу лишь призвать сделать выбор в пользу разумного назначения версии. Насколько понял, вы уже читали про семантическое версионирование, но, судя по комментарию, думаю, что попытаться адаптировать конвенцию для вас стоит. Семантическая версия состоит из трех номеров: major, minor, patch. Они различаются следующими вещами: patch-версия инкрементируется при выпуске релиза, закрывающего баги minor-версия инкрементируется при выпуске релиза с новым функционалом, не затрагивающем старый major версия инкрементируется при выпуске релиза, которым невозможно пользоваться так, как прежде Поэтому определение "какую версию мне использовать" превращается в довольно простой условный блок: Релиз содержит только багфиксы? Инкрементируется patch-компонент, 2.9.10 Релиз содержит нововведения, но старый функционал остался прежним? 2.10.0 Релиз содержит нововведения, которые меняют способ использования старого функционала? 3.0.0 Отвечая на вопрос, который тут же появляется - "мне что, инкремнтировать major-версию каждый раз, когда я ломаю обратную совместимость?". Ответ на этот вопрос - да, major-версия должна выпускаться каждый раз, когда какие-то вещи ломаются; это не игра в поддавки и визуальную упорядоченность. Если вас заботит скорость выпуска major-версий - это значит, что вы ломаете слишком много вещей, и какие-то обновления стоит придерживать в ветке до того, как появится моральная готовность выпустить новый major-релиз; на адаптацию к этой модели уйдет некоторое время, но на деле это всего лишь цифры, между которыми нет никакой разницы, версия 2.х.х или 17.х.х - для конечного потребителя это не так важно как то, сможет ли он пользоваться новой версией так же, как старой. Не пытайтесь воспринимать 2.9.9. как 299. Это не число и не поддается правилам инкрементирования чисел.

Ответ 2



2.9.91 - самое понятное решение. Если бы вы использовали настроенную систему контроля версий, то она сама бы дала нужные цифры (скорее всего, другие). Вот один из наиболее распространенных подходов: Формат номера версии A.B.C.D[r], где:• A – главный номер версии (major version number). • B – вспомогательный номер версии (minor version number). • C – номер сборки, номер логической итерации по работе над функционалом версии A.B (build number). • D – Номер ревизии, сквозной номер назначаемый автоматически программным обеспечением хранения версий (SVN). Номер ревизии SVN должен синхронизироваться с номером ревизии в AssemblyInfo при каждой сборке релиза (revision number). • [r] – условное обозначение релиза. Подробнее - https://habrahabr.ru/post/119400/

Коммиты для Unity3d-проектов

#git #unity3d #контроль_версий


Когда просто писал на VS C++, например, то коммитил только исходники и этого было
достаточно.

Что нужно коммитить для Unity-проектов? 

Одних исходников явно не достаточно, так как на сцене тоже есть разные объекты. Всю
папку с проектом тоже не вариант, так как, во-первых, много весит, во-вторых, например,
папка Temp не хочет коммитится пока редактор запущен, да и логика подсказывает что
есть куча файлов, которые заново создадутся если их удалить!

И как в Git выбирать какие файлы коммитить? (По одному каждый раз вносить долго!)
    


Ответы

Ответ 1



Если используешь .gitignore то нужно добавить его к коммиту, сделать коммит (в .gitignore уже должны быть записи об игногрируемых файлах), затем удалить из проекта ненужные файлы, сделать "git add ." и сделать коммит подтвердив удаление файлов, после этого должно всё работать и должны игнорироваться файлы по маскам из ".gitignore". Если я правильно помню то .gitignore поддерживает регулярки, но 100% гарантировать не могу. Далее если хочешь добавить новые файлы в игнор то изменяешь .gitignore и делаешь коммит как будто сорцы поправил.

Ответ 2



Лучше всего начинать с документации) Здесь как настроить внешнюю систему контроля версий http://docs.unity3d.com/Manual/ExternalVersionControlSystemSupport.html Здесь как использовать Smartmerge для того чтобы мержить сцены и префабы http://docs.unity3d.com/Manual/SmartMerge.html Ну а вот так выглядит файл .gitignore. Его надо обновить для своей папки с проектом. # =============== # # Unity generated # # =============== # Temp/ Library/ # ===================================== # # Visual Studio / MonoDevelop generated # # ===================================== # ExportedObj/ obj/ *.svd *.userprefs /*.csproj *.pidb *.suo /*.sln *.user *.unityproj *.booproj # ============ # # OS generated # # ============ # .DS_Store .DS_Store? ._* .Spotlight-V100 .Trashes ehthumbs.db Thumbs.db При использовании отдельных плагинов не трудно его расширить. Я когда использую Microsoft Visual Studio Tools for Unity добавляю еще в список файлы из каталога с UnityVS.

Ответ 3



Не знаю на сколько это поможет но меня спас .gitignore когда нужно было игнорить исполняемые файлы и временный файлы IDE при git add . А вот с самим Unity я не знаком к сожалению. gitignore(5) Manual Page

Ответ 4



Для того чтобы уменьшить размер проекта заливаемого на сервер и исключить загрузку временных файлов, настроек AssetStore и прочего я использую файл .gitignore следующего вида: Library/ Temp/ Obj/ Build/ Builds/ Assets/AssetStore* # Autogenerated VS/MD/Consulo solution and project files ExportedOBj/ .consulo/ *.csproj *.unityprof *.sin *.suo *.tmp *.user *.userprefs *.pidb *.booproj *.svd *.pdb # Unity3D generated meta files *.pidb.meta *.meta # Unity3D Generated File On Crash Reports sysinfo.txt # Builds *.apk *.unitypackage Источник

Ответ 5



Добавьте файл .gitignore при помощи GitExtensions или Visual Studio. Добавьте в него строчку Temp/.

понедельник, 6 января 2020 г.

Слияние веток в Git-е: непонятный конфликт строк

#git #контроль_версий


Всем доброго времени суток.

Изучаю Git. Использую гуй SourceTree. Репозиторий лежит на BitBucket. Создал два
аккаунта, чтоб воспроизвести совместную разработку. 
Когда делаю слияние изменений в одной ветке - в блок HEAD помещается только конфликтные
строки. Когда делаю слияние изменений из разных веток - в этот блок попадают все строки.

Например, два автора меняют одну и ту же строку в файле index.php в ветке master.
Мой воображаемый "напарник" успешно пушит свои изменения. А вот я уже должен выполнить
слияние, перед тем как отправить свои изменения. Делаю пул. Файл принимает следующее
состояние:

>>>>>> 18baca2cbbf6685dbe946554f436312e93bd4ff3
exit();

// I don't have new ideas... (((


Тут всё понятно. Строка echo... является конфликтной и я самостоятельно решаю что
мне с ней сделать. А теперь представим тот же файл index.php, но из разных веток. Отличия
между ними лишь в том, что в ветке test появляется две строки: одна из них пустая,
а вторая содержит комментарий. Как мне подумалось, слияние должно вообще пройти без
проблем в автоматическом режиме, ведь нет никаких разных изменений в одной и той же
строке. Однако, здравствуйте. Содержимое файла index.php при попытке слияния:

>>>>>> test


И в конце файла ещё одна пустая строка (после строки >>>>>>> test).

На этом моменте я завис. Не могу понять откуда вообще появились конфликтные строки.
Их быть не должно. Ведь в тесте всего лишь 2 новые строки, не более. Кто может мне
объяснить, где я чего не понял? Это так и должно быть, или я, криворукий, где-то допустил
ошибку, которая приводит к такому результату?

Заранее благодарю за помощь.
С уважением, Юрий.
    


Ответы

Ответ 1



Если у двух строк разные окончания - то они считаются гитом различными. Поэтому важно правильно договариваться об окончаниях строк внутри команды. Также есть вариант принудительно настроить окончания строк для репозитория, это делается в файле .gitattributes Пример настройки в этом файле: *.cs text eol=crlf Здесь написано, что все файлы с расширением .cs надо считать текстовыми, хранить в репозитории с LF окончаниями строк - а в рабочей копии загружать с окончанием строк CRLF. Или вот другой пример: *.xml text eol=lf Здесь во всех xml-файлах окончания строк всегда будут LF. Немного о том, что вообще такое "окончания строк". Окончание строки - это набор невидимых символов, которые отделяют в файле одну строку от другой. Исторически, имеется два разных символа, которые пришли к нам еще с пишущих машинок и телетайпов: CR - возврат каретки, этот символ возвращал каретку в начало текущей строки LF - перевод строки, этот символ переводил каретку к следующей строке, не смещая ее Для электрических печатных машинок или матричных принтеров это были две разные команды (а у машинок - еще и две разные кнопки). Но когда встала задача обработки текстов на компьютере, два разных символа оказалось избыточно, поэтому некоторые системы пошли по пути упрощения. В современном UNIX-мире сейчас принято разделение строк при помощи одного символа LF, на старых маках использовался символ CR - ну а DOS и потом винда остались на CRLF. Тем не менее, все нормальные текстовые редакторы сейчас уже умеют автоматически определять окончания строк или даже работать со смешанными окончаниями строк в одном файле - поэтому вы про них ничего и не знали. Но git работает не с текстом, а с байтами - поэтому в гите важно приводить окончания строк для файла к одному виду.

четверг, 2 января 2020 г.

Как совместить код?

#контроль_версий #dvcs


Я и мой товарищ пишем 1 программу, и приходится ее после совмещать вручную, можно
ли как то это сделать автоматически? Как внести изменения ?
    


Ответы

Ответ 1



Вам нужна система контроля версий. В комментариях совершенно справедливо предлагают две наиболее современных и популярных: Git и Mercurial. Лично я предпочитаю и люблю Git, но это субъективно. В общем и целом процесс будет организован так: Локальный репозиторий у каждого из вас на рабочей машине Удаленный репозиторий - новичку проще всего использовать хостинг GitHub или Bitbucket. У каждого разработчика своя ветка, куда вы вносите изменения. Есть центральная ветка, в которую эти изменения периодически добавляются. При добавлении изменений неизбежно будут конфликты, которые вам придётся разрешать. Вне зависимости от вашего выбора: Прочитайте документацию, хотя бы новичковый курс. Продолжайте читать документацию впоследствии до постижения Дао выбранной системы. Для старта пройдите какой-нибудь онлайн-курс, их много и все вполне хороши. (Платный брать нет смысла) При появлении вопросов приходите на Ru.SO. Сливайте изменения в центральную ветку как можно чаще, чтобы избежать адских страданий, неразрешимых конфликтов и поножовщины (см. ниже про непрерывную интеграцию). Связанные вопросы, рекомендуемые к прочтению: Организация GIT для небольшой команды разработчиков. Git для программиста-одиночки Количество, частота и содержание коммитов Как организовать работу с системами контроля версий для разработки нескольких проектов с общей основой? Что такое непрерывная интеграция? Про Hg не нашёл подходящих, добавляйте.

вторник, 31 декабря 2019 г.

Создание ветки только измененных файлов в GIT или SVN

#git #svn #контроль_версий #git_branch


Есть проект, в котором N - файлов. Периодически создается версия обновления, но в
обновление входят только измененные файлы. Хотим проект завести под систему контроля
версий, типа git или svn. 

Ищем решение, при котором можно было бы выделить все измененные файлы (например из
истории коммитов) автоматически вынесить их в отдельную ветку/branch. 

Подскажите, возможно ли такое?
    


Ответы

Ответ 1



о создании ветки — см. ниже простое решение если создавать ветку не требуется, а надо лишь получить список файлов, изменившихся между коммитом1 и коммитом2, то можно сделать примерно так: $ git log --name-only --pretty="format:" коммит1..коммит2 | grep -v '^$' | sort -u пояснения: --name-only — выводить ещё и имена изменённых файлов --pretty="format:" — вся служебная информация будет выведена как пустые строки grep -v '^$' — удалит эти пустые строки sort -u — удалит дубликаты из списка из получившегося списка можно сразу и архив получить. примерно так (сжатый архив запишется в файл /tmp/archive.tgz): $ tar -czf /tmp/archive.tgz $(git log --name-only \ --pretty="format:" коммит1..коммит2 | grep -v '^$' | sort -u) ещё про «красоту»: файлы в архиве будут иметь тот же путь, что и в репозитории: dir1/file1 file2 чтобы файлы в архиве «лежали» в каталоге, например, proga-1.0: proga-1.0/dir1/file1 proga-1.0/file2 можно команде tar добавить опцию --transform (поддерживается, насколько мне известно, только версией tar из операционной системы gnu): $ tar -czf /tmp/archive.tgz --transform "s,^,proga-1.0/," $(git log --name-only --pretty="format:" коммит1..коммит2 | grep -v '^$' | sort -u) репозиторий со скриптами предложенные выше «однострочники» я поместил в репозиторий под лицензией gplv3. getfiles [ revision..range ] — выдаёт список всех файлов, изменявшихся в промежутке revision..range. если аргумент пропущен, то скрипт выдаст список всех файлов. createarchive revision..range /path/to/archive.tgz [ prefix ] — создаёт указанный архив (см. выше). если указан prefix, он добавляется к именам файлов (слэш в конце префикса автоматически добавляется при необходимости). truncatehistory [ revision..range ] — удаляет из репозитория историю всех файлов, кроме тех, что изменялись в указанный revision..range. используйте с осторожностью! код этого скрипта базируется на вот этом ответе. о создании ветки обрезать историю только для одной ветки, не затрагивая остальные, несколько более сложное решение, чем предложенное ниже. а предлагаю я «обреза́ть» историю не в основном репозитории, а в отдельном его клоне. если возникнет необходимость видеть «обрезанную» историю в своём же репозитории — можно подключить «обрезанный» клон как второй remote. учтите, что история у всех файлов из этого клона полностью отлична от истории файлов в основном репозитории — начиная с самого первого коммита. поэтому вливать такой отдельно-стоящий набор коммитов в рабочий репозиторий я бы не рекомендовал: теоретически могут возникнуть проблемы с последующей жизнедеятельностью репозитория. скачайте файлы или склонируйте мой репозиторий со скриптами. путь к скриптам обозначим как /путь1 сделайте клон вашего репозитория в пустом каталоге: $ git clone адрес-вашего репозитория . запустите: /путь1/truncatehistory revision..range всё, история репозитория полностью переписана и включает только те файлы, которые изменялись в промежутке revision..range

Ответ 2



Вариант действий для любой SCM неверен методологически - предлагается дублировать информацию, и так имеющуюся в системе (коллекция измененных объектов между двумя метками в истории) Опять же любая SCM посредственно/плохо подходит для цели "хранилище коллекций артефактов", для этого есть более другие системы Чисто технически ничто не мешает для любого диапазона истории (в любой на выбор VCS) получать динамически список затронутых файлов для включения в патч-лист (команды будут различаться, но не методология), но правильнее - не адаптрировать возможности новой VCS под старый процесс, а переосмыслить процесс и возможно его изменить (хранение патчей в репо выглядит бессмысленной тратой времени и трудозатрат - натуральнее выглядит тегирование полного дерева и получение патча для деплоя обновления между тэгами, и это - не зависит от того, какая VCS используется) Ну и чисто рекомендация - не надо гнаться за модным и бежать на Git, хотя со ST уходить все же разумное решение

воскресенье, 29 декабря 2019 г.

Система контроля версий. Offline-альтернатива

#visual_studio #контроль_версий


Есть ли offline локальная система контроля версий, подобная Git? Пишу в VS-2017.

Я сейчас просто работаю в такой компании, где стоит CheckPoint, запрещающий доступ
к определенным Web-ресурсам, включая Git (сам сайт github работает, но коммиты, гитклоны
и все остальное не работает).

P.S. это не АйТи контора. Конечно, можно попробовать запросить доступ к Git, но здесь
это очень геморно, потрачу много сил, нервов и времени
    


Ответы

Ответ 1



Git прекрасно работает офлайн. Вместо удаленного репозитория можно использовать обычную папку - по сути просто еще одну копию репозитория: How to add a local repo and treat it as a remote repo git remote add origin /бла/бла/репозиторий/.git Либо можно вообще не хранить удаленные копии репозитория (отказаться от push, pull, fetch и подобных команд), хотя это более рискованно.

Ответ 2



Есть. Эта система называется Git :) ставьте гит, фиксируйте изменения в локальном репозитории, просто не пушите изменения на сервер. Ну и более чем реально поднять собственный git или svn сервер. Если есть оборудование, способное закрывать определенные сайты, думается в компании найдется хоть один компьютер, который можно никогда не выключать и использовать как сервер

среда, 18 декабря 2019 г.

Контроль версий на локальном компьютере windows

#windows #git #контроль_версий


Достаточно давно пишу одну программу. Для сохранения всех данных использую бэкапы.
Но вот решил использовать систему контроля версий. И так что я хочу от системы контроля
версий:


Она должна работать на локальном компьютере и под Windows
Иметь как консольный так и GUI интерфейс
Интегрирована с Visual Studio


И тут возникают трудности: любая статья для чайников предлагает либо использовать
гитхаб, либо ставить и настраивать прорву программного обеспечения (база данных, веб
сервер...). А может кто подсказать (или кинуть в меня ссылкой) как просто и быстро
настроить систему контроля версий (git предпочтительней) с сервером на локальном компьютере?
    


Ответы

Ответ 1



1. Установка Git не нуждается в сервере. Под Windows ставьте это: gitforwindows.org. Там есть 32- и 64-битная версия. Вместе с git будет установлена unix-подобная консоль git-bash и GUI-инструмент. В качестве ещё одного GUI вы сможете использовать Visual Studio. Есть множество других GUI, но при умении работать через консоль и наличии полноценной IDE они вам не пригодятся. 1.1. Интеграция с Visual Studio Если нужна интеграция с Visual Studio, вы можете установить http://gitextensions.github.io/. В комплекте есть плагин для VS. (Ссылка из комментария KoVadim) 2. Запуск и первоначальная конфигурация: Откройте командную оболочку git-bash: кликните правой кнопкой мыши на свободном месте в любой папке и выберите пункт git bash here. Выполните базовую конфигурацию, это нужно сделать один раз. Используйте ваше имя и принадлежащий вам почтовый ящик. Если вы настраиваете Git на рабочем месте, скорее всего вам нужно использовать рабочую почту. git config --global user.name "John Doe" git config --global user.email johndoe@example.com И чтобы использовать окончания строк CRLF, как принято в Windows: git config --global core.autocrlf true Вместо консольных команд можно редактировать файл конфига в любом текстовом редакторе (локальный расположен в %папка_проекта%\.git\config, глобальный в C:\Users\%имя_юзера%\.gitconfig). 3. Начало использования Если git bash уже открыта, перейдите в папку проекта: cd С:/путь/к/проекту Или сразу кликните правой кнопкой мыши на свободном месте в папке проекта и выберите пункт git bash here. Теперь, чтобы создать локальный репозиторий и таким образом начать контроль версий проекта: git init Документация Ещё по этой теме: Git и GitHub на windows от новичка Git и GitHub на windows от новичка (часть 2) Как настроить autocrlf в git для различных систем? Входная точка документации: https://git-scm.com/book/en/v2

Ответ 2



Не самый каноничный вариант, но для любителей GUI очень даже неплохо - https://tortoisegit.org/ (есть на русском). Все, что нужно для работы будет установлено локально, включая сам git. Есть gui, которым первое время можно будет пользоваться, а потом (по желанию) перейти на командную строку. Быстрый старт: скачиваем/устанавливаем tortoisegit кликаем правой кнопкой по вашей папке, затем "Создать репозитарий здесь" и, когда нужно сохранить работу, правой кнопкой по папке и "Commit" Пример просмотра лога коммитов:

вторник, 10 декабря 2019 г.

Количество, частота и содержание коммитов

#контроль_версий


Заметил, что количество моих коммитов сильно превышает количество коммитов других
людей в схожих проектах (на один не самый сложный проект на свете ушло больше 300).
Это, конечно, не является моей основной проблемой в жизни, но у меня сложилось впечатление,
что я делаю что-то не так, и это может затруднить копание в истории проекта.
Я делаю коммит каждый раз, когда в проект добавляется новая фича, и он после этого
приходит в работоспособное состояние, причем неважно, какого размера фича - простое
выправление грамматики, багфикс, внедрение какого-то нового функционала (последнее
может быть разбито и на несколько коммитов, но после каждого из них проект должен быть
работоспособным), причем если я поправил css, сменил отвратительно кривой текст на
просто кривой и пересобрал в контроллере экшен - это, по моей философии, должны быть
три коммита, потому что они затрагивают разные невзаимосвязанные части проекта. В результате,
с одной стороны, я могу получить чуть ли не любой слепок проекта и он в любой момент
будет работоспособен, с другой - я получаю ворох коммитов типа 'Typo fix', 'CSS fix',
'Microfix', которые, наверное, могли бы и не существовать.
Короче, как правильно делать?
p.s. Одна из вероятных причин ситуации - то, что бранчингом почти не пользуюсь. Сам
дурак, знаю.
upd. Если точнее сформулировать вопрос - должны ли вводимые фичи быть атомарными
(один коммит - одна фича или багфикс), или на это можно наплевать?    


Ответы

Ответ 1



По коммитам у меня такие правила: Коммит должен компилироваться без ошибок. Коммит должен обозначать как минимум новую фичу/класс/метод/багфикс. Или хотя бы коммит должен обозначать конец рабочего дня. Коммит не должен задерживать остальных членов команды, ибо merge - это зло (иногда необходимое). Из чего следует, что если я занимаюсь прожектом, то как минимум 1 коммит в день я должен делать. Терпеть не могу коммиты, когда изменения копятся-копятся, потом бабах - глобальный коммит с тучей конфликтов merge. С другой стороны, больше 2-3 коммитов в день - это излишне, ну разве что по просьбе сотоварищей. Update для фанатов git: в данном контексте коммит имеется ввиду не коммит в локальную репу, а гитовский push в глобальную репу.

Ответ 2



Вы все делаете правильно :) И переходите уже, наконец, на git :] Хотите новую фичу - делаете ветку, в которой реализовываете фичу, потом мержите ее в дев, тестите, и далее по списку... Не нужно себя ограничивать в количестве коммитов. Просто у вас будет более детальная история в случае чего :)

четверг, 5 декабря 2019 г.

Как обновлять проект с репозитория?

#git #android_studio #контроль_версий


Кто-то может расстолковать какая разница:




Merge
Rebase
Branch Default


И


Using Stash
Using Shelve


Что в каких случаях используется?
    


Ответы

Ответ 1



Для начала git stash или git shelve. Когда Вы подтягиваете новые изменения, в Вашем рабочем каталоге могут быть измененные (незакоммиченные) файлы. Естественно, что эти файлы при слиянии изменений могут потерятся. Поэтому гит предлагает их "спрятать в карман". Это называется git stash. После того, как новый код будет получен с удаленного репозитория, изменения с stash можно накатить назад (естественн, при этом возможно нужно будет решить конфликты). В "кармане" можно хранить сколько угодно изменений (логично - ограничены своим диском) и карман не передается на сервер. Детальнее о git stash на русском. git shelve - это древний проект (2008 года), который не поддерживается на данный момент. Как и git shash, умеет прятатть изменения, только в отдельные ветки. Зачем оно в студии - не ведомо. Теперь о первой колонке. При накатывании чужих коммитов может произойти две ситуации - в ветке есть Ваши коммиты и чужие и когда есть только с одной стороны. Понятно, что когда есть только коммиты одной стороны, то принять изменения очень просто - их нужно просто "скопировать себе" и поправить указатели на ветки. В том случае, если есть и свои коммиты и чужие, нужно их "сложить вместе". Для этого есть две технологии - merge и rebase. При merge происходит слияние файлов. Там, где файлы одинаковые, проблем нет, там где файлы разные, гит пытается сложить вместе. Иногда у него это не выходит и он просит пользователя "разрешить конфликт" - так как только программист знает, что он хочет. Но есть второй способ - это rebase. Некоторые люди любят этот способ, а некоторые под страхом разрушить репозиторий боятся его использовать. Работает он очень просто. Сравниваются две ветки и ищется общий предок-коммит. Дальше, с локальной ветки откатываются все коммиты до общего коммита. Естественно, что теперь добавить коммиты с удаленного репозитория просто. После этого локальные коммиты "накатываются поверху". Если в процессе накатки возникают конфликты, их нужно решать. А вот что такое Branch default - я не знаю, возможно, студия запоминает последний выбор и применяет его.

Ответ 2



Я бы добавил что Shelve это чисто фича IDEA https://www.jetbrains.com/idea/help/shelving-and-unshelving-changes.html, кое в чём погибче, но git тоже на месте не стоит. Тут похожий вопрос был https://stackoverflow.com/questions/28008139/git-shelve-vs-stash

суббота, 30 ноября 2019 г.

Работа с памятью при использовании Git

#git #контроль_версий


Постараюсь быть максимально кратким.
На сайте русской документации по Git дается такое объяснение принципу его работы:


  Git считает хранимые данные набором слепков небольшой файловой
  системы. Каждый раз, когда вы фиксируете текущую версию проекта, Git,
  по сути, сохраняет слепок того, как выглядят все файлы проекта на
  текущий момент. Ради эффективности, если файл не менялся, Git не
  сохраняет файл снова, а делает ссылку на ранее сохранённый файл.




Так вот, если очень грубо допустить, что размер текстового файла стремится к 1Мб,
то следуя логике работы Git при даже самом малом изменении в этом файле(исправили ошибку
в слове), будет создаваться "слепок"(=копия) файла, размером ~1Мб. 

Вопрос: насколько это выгодно с точки зрения используемой памяти, или же текстовой
файл как-то делится на более мелкие файлы, и созданию "слепков" подлежат уже они?
    


Ответы

Ответ 1



Кратко: приведенная схема - это объяснение наблюдаемого поведения GIT. Если вы будете работать с GIT стандартными командами и не будете лезть руками в бинарные файлы - всё будет выглядеть как будто все так и работает. Но это вовсе не означает что на каждую версию файла будет и правда тратиться по мегабайту... Потому что на более низком уровне, гит все-таки использует дельты между файлами. Прочитать про них можно вот тут: Git изнутри - Pack-файлы Однако, упаковка файлов происходит не всегда, а только при достижении некоторого порога числа распакованных объектов или при пушу коммитов в удаленный репозиторий. При наличии больших файлов в некоторых случаях приходится явно выполнять команду git gc для переупаковки всех блобов (нам, к примеру, однажды пришлось добавлять эту команду в билд-скрипт, потому что на билд-сервере отправка в удаленные репозитории никогда не происходит и локальный репозиторий бесконтрольно рос).

Ответ 2



Как раз об этом повествует "Git изнутри - Pack-файлы". Собственно, там и ответ на вопрос: Однако, время от времени Git упаковывает несколько таких объектов в один pack-файл (pack в пер. с англ. — упаковывать, уплотнять) для сохранения места на диске и повышения эффективности. Это происходит, когда "рыхлых" объектов становится слишком много, а также при вызове git gc вручную, и при отправке изменений на удалённый сервер. То есть, через какое-то время в процессе эксплуатации репозитория различающиеся версии файла попадут в один Pack-файл, который представляет разные версии гораздо более эффективным образом: через основу и дельты (разности, изменения).

Ответ 3



или же текстовой файл как-то делится на более мелкие файлы, и созданию "слепков" подлежат уже они? Нет, файлы (как и любой другой объект, например, папка — список пар «имя дочернего объекта — его хэш») сохраняются именно целиком. Это, кстати, повышает «выживаемость» репозитория — если часть объектов по каким-то причинам будет повреждена или стёрта, остаётся крайне высокая вероятность восстановления если и не последнего commit-а, то хотя бы одного из последних. Однако параллельно с объектным хранилищем (./git/objects) есть и сжатое, где все объекты хранятся в одном упакованном файле (.git/objects/pack/) в виде diff-ов. Туда можно поместить любой объект, при этом оригинальный файл объекта удаляется. Так как операция упаковки является достаточно трудоёмкой, она выполняется только при вызове команды git gc --force. При этом любые дальнейшие изменения в репозитории (добавление commit-ов и переписывание истории) продолжат добавление объектов в основное хранилище; во втором же случае в pack-файле также останутся «хвосты», которые будут удалены только при следующем вызове git gc.

Ответ 4



TL;DR Файлы в гит хранятся целиком и не делятся. Это достаточно выгодно. Есть хорошие статьи по git (пример, пример), где раскрывается внутреннее устройство гит. Пользователь запускает git add на data/letter.txt. Происходят две вещи. Во-первых, создаётся новый блоб-файл в директории .git/objects/. Он содержит сжатое содержимое data/letter.txt. Его имя – сгенерированный хэш на основе содержимого. К примеру, Git делает хэш от а и получает 2e65efe2a145dda7ee51d1741299f848e5bf752e. Первые два символа хэша используются для имени директории в базе объектов: .git/objects/2e/. Остаток хэша – это имя блоб-файла, содержащего внутренности добавленного файла: .git/objects/2e/65efe2a145dda7ee51d1741299f848e5bf752e. Заметьте, что простое добавление файла в Git приводит к сохранению его содержимого в директории objects. Оно будет храниться там, если пользователь удалит data/letter.txt из рабочей копии. Далее показывается механика того, что происходит когда файл меняется. Когда пользователь создал data/number.txt, он хотел написать 1, а не 1234. Он вносит изменение и снова добавляет файл к индексу. Эта команда создаёт новый блоб с новым содержимым. Можете посмотреть файлы в папке object и через команду git cat-file -p увидеть разжатое представление ваших файлов. Это механика на уровне отдельных файлов. Казалось бы - неоптимальный расход. Тем не менее, есть дополнительный механизм - когда происходит упаковка объектов в более крупные файлы. Проблема с хранением больших файлов также привела к появлению LFS. Дело в том, что большие файлы, которые вы даже ни разу не правили (бинарники типа картинок) сохранять в git реально достаточно тяжело, поэтому их сохраняют на отдельные файловые хранилища.

В чем различия между Git и SVN?

#git #svn #контроль_версий


Вопрос, собственно выбора. Чем Git лучше или хуже SVN? Почему чаще от разработчиков
я слышу именно про Git и его удобства, чем про SVN, хотя как по мне, все что слышал
можно делать и в SVN.

Причём для обоих вариантов есть удобный Tortoise, что сводит общение с репозиториями
практически на один уровень.

Может просто что-то плохо рекламируют, а разницы вообще нет?
    


Ответы

Ответ 1



GIT распределяется, а SVN - нет. Другими словами, если есть несколько разработчиков работающих с репозиторием у каждого на локальной машине будет ПОЛНАЯ копия этого репозитория. Разумеется есть и где-то и центральная машина, с которой можно клонировать репозиторий. Это напоминает SVN. Основной плюс в том, что если вдруг у вас нет доступа к интернету, сохраняется возможность работать с репозиторием. Потом только один раз сделать синхронизацию и все остальные разработчики получат поолную историю. GIT сохраняет метаданные изменений, а SVN целые файлы. Это экономит место и время. Система создания branches, versions и прочее в GIT и SVN отличаются значительно. В GIT проще переключатся с ветки на ветку, делать merge между ними. В общем GIT я нахожу немного проще и удобнее, но бывают конечно иногда сложности. Но где их не бывает? Разумеется есть гораздо больше отличий, но я перечислил те, которые чаще всего встречаются при работе с репозиториями и на МОЙ взгляд наиболее важные.

Ответ 2



Git сложнее для освоения. Лично мне git предпочтительнее, позволяет мне проще сделать больше разного. Например реорганизовать порядок и содержание коммитов. Работа с ветками имхо удобнее и быстрее, через git stash удобно проверять перед коммитом что не забыл добавить вновь созданный файл. Удобнее переносить свои наработки в разные ветки - создать локально ветку, в ней вести разработку, потом просто сделать merge ветки, в svn же нужно просматривать лог на предмет нужных коммитов и переносить их ручками.

Ответ 3



Так же распределённость git может быть полезна при восстановлении данных. Был случай когда накрылся жесткий диск на сервере, и все удалось восстановить благодаря локальным копиям. (P.S конечно лучше иметь зеркальные RAID, но дно другого не исключает).

Ответ 4



Сначала у нас контора работала на svn без веток, потом начали активно использовать гит с ветками, сейчас я устроился в другую контору которая работает на svn с ветками, и если честно каждый раз когда приходится сливать ветки - я с такой грустью и тоской вспоминаю гит, как там всё было просто и удобно, интуитивно понятно, и как кропотливо приходится трястись над каждым конфликтом, над каждым изменённым файлом в обеих ветках, когда гит большую часть умел разруливать сам. А заливание каталогов в svn вообще убивает если честно.

Ответ 5



Я бы в качестве одного из краеугольных отличий назвал бы еще lock http://svnbook.red-bean.com/en/1.7/svn.advanced.locking.html git удобнее тем, что не надо бегать с криком "уберите замок пожалуйста". С другой стороны, встает ряд дополнительных вопросов с merge кода, который впрочем при должном навыке с помощью инструментов git нормально решается.

пятница, 29 ноября 2019 г.

Как правильно удалить Git tracking (контроль версий)?

#git #контроль_версий


Если нужно удалить Git tracking (версионирование), правильно ли просто удалить папку
.git/ ?
    


Ответы

Ответ 1



В этом ответе: Какие файлы и директории относятся к Git Как удалить версионирование Git Unix, Windows + git bash Windows, cmd.exe Windows, проводник Как получить новую копию проекта без версионирования 1. Какие файлы и директории относятся к Git Git хранит историю и настройки в папках .git и файлах .git.... Обязательно существует только папка .git, находящаяся в корне вашего проекта. Если в нём есть субмодули, то в наличии есть также файл .gitmodules в корне и файлы .git где-то во вложенных папках. project/ - .git/ - .gitmodules - .gitignore - .gitattributes - пустая-папка/ - .gitkeep - ещё-папка/и-ещё/внутри/ - .git - .gitignore - тут-файлы-и-папки-субмодуля 2. Как удалить версионирование Git Unix-совместимые системы, Windows c git bash или cygwin: Убедитесь, что вы находитесь в корне проекта! cd path/to/project find . -name ".git*" | xargs rm -ri С ключом -i эта команда будет работать в интерактивном режиме и запросит подтверждение на удаление каждого файла. Спасибо KoVadim за улучшенный вариант первоначальной команды. Windows, cmd.exe (взято c en.SO ) cd path\to\project del /F /S /Q /A .git rmdir .git Windows, через проводник Включите отображение скрытых файлов и папок Откройте папку своего проекта, найдите поле поиска: Введите там filename:.git, дождитесь окончания поиска: Заметьте, что другие виды поиска работают хуже: name:.git включает файлы наподобие source.git.cs, ext:.git не включает каталог .git, просто .git включает медленный и ненужный поиск по содержимому файлов Теперь вы можете выбрать файлы, относящиеся к git, и удалить (скорее всего, это будут все найденные файлы). Перепроверить, однако, не помешает никогда. 3. Как получить новую копию проекта без версионирования Возможно, вам нужно просто получить копию проекта, в которой нет версионирования. Для этого отлично подходит git-archive: git archive master --format zip --output path/to/archive.zip Полученный archive.zip можно передать и где-то распаковать, получив новый проект без версионирования. Субмодули таким образом не упакуются.

Ответ 2



Git хранит всю историю и настройки отслеживания проекта в папке с именем .git, находящейся в корне проекта. Поэтому для прекращения отслеживания достаточно удалить эту папку. Но, возможно, в корне проекта присутствуют и другие файлы, относящиеся к Git. Например, это может быть файл .gitignore, в котором хранятся имена неотслеживаемых объектов.

Ответ 3



Если в файловом менеджере не видна папка /.git, то в консоль можно установить Midnight Commander. И находясь в папке, куда инициализировался проект, выполнить команду mc, в консоли откроется файловый менеджер, в котором будет доступна папка /.git. Ctrl+F8 удалит папку. И все. Просто у меня не сработала интерактивность в команде из решения (find . -name ".git*" | xargs rm -ri). Хотя я работаю в юникс-подобной операционке (Finder зло).

среда, 27 ноября 2019 г.

Перенести коммит из одной ветки в другую

#git #контроль_версий


Каким образом в Git перенести отдельный коммит из одной ветки А в ветку Б? При этом
коммит содержит файлы, которые были изменены в ветке Б.    


Ответы

Ответ 1



В Git есть специальная команда cherry-pick, которая позволяет вставлять в текущую ветку изменения из любого коммита. Работает она так: git cherry-pick test Пример выше применяет последний коммит из ветки test в текущую ветку. При желании, можно перенести более одного коммита за один раз. Например: git cherry-pick 8fe1498 mega_fix~3 v1.0.1 Из примера выше видно, что на коммит можно сослаться сразу несколькими способами: Используя SHA хэш коммита (или его сокращенный вариант). Используя имя ветки (можно использовать синтаксис ^ и ~). Используя тэг, которым помечен коммит. Более подробная информация о том, как сослаться на коммит есть в документации к Git. Стоит отметить, что в отличии от слияния (merge) при cherry-pick переносятся только изменения, а не сам коммит полностью. При этом, в целевой ветке создается новый коммит (коммиты) содержащий необходимые изменения.

Ответ 2



Посмотрите на git cherry-pick, например тут. Эта команда позволяет выдернуть определенный коммит с одной ветки и применить его к текущей ветке. При этом он станет новым коммитом. Ну и возможно потом нужно будет разрулить конфликты слияния.

Ответ 3



git cherry-pick найдёт коммит по его хэшу sha1 и вольёт его в текущую ветку Подробнее тут.

понедельник, 25 ноября 2019 г.

git и конфигурационные файлы


Расскажите, кто и как решает проблему хранения конфигурационных файлов в git?

Полностью исключать их нельзя, так как проект может не собраться и/или не запуститься
В тоже время в таких файлах, как правило, хранится частная информация (данные для авторизации на внешних сервисах и т.д.).

Сейчас я размещаю в git файлы с расширением .sample (например Web.config.sample ил
config.yml.sample) и пишу в документации, что перед тем как запустить проект, необходимо переименовать sample-файл и заполнить его правильными значениями. Сами конфигурационные файлы я добавляю в  .gitignore.

Недостатки такого подхода:


необходимо постоянно синхронизировать sample-файл c оригинальным конфигурационным файлом (добавились/изменились/удалились опции),
другим пользователям нужно сделать дополнительное действие (переименовать файл)
что они могут забывать делать (кто же читает документацию?)


Возможно существуют и более удачные решения. Можно ли c git придумать что-то более удобное?
    


Ответы

Ответ 1



К сожалению, все так. В систему контроля версий не должны попадать конфигурационны файлы, которые не запустятся на других хостах, поэтому, как правило, ПО распространяется без реальных конфигов, и в консольные команды добавляется команда начальной конфигурации, которые могут сформировать этот файл. Добавление обязательных конфигурационных опций на ходу - плохая идея, по крайне мере между major-версиями. Они должны иметь свое значение по умолчанию, при которо приложение продолжает вести себя так же, как и раньше. Все эти -webkit-something-tralal в CSS появились ровно оттуда же - давайте добавим эту штуку, но не будем ее пихать как готовую опцию, когда будем готовы к внедрению - внедрим, чтобы она точно не переименовывалась и не менялась потом (конкретно в CSS имена задаются стандартом, но общая идея должна быть ясна). Впрочем, один хак я для себя нашел - весь dev-env засовывается в вагрант, где можн свободно писать любые конфиги и менять их на ходу, в результате в команде разработчиков можно свободно играться с тестовой конфигурацией. Еще одна штука, которая помогает - это "параллельные" файлы, в которых переопределяютс значения: configuration.yml содержит в себе некоторую конфигурацию, а configuration.local.yml - всего пару опций, который "берут верх" над аналогичными опциями из configuration.yml.

Ответ 2



На эту тему высказались авторы манифеста 12 factors. Вот что они пишут о конфигурации: Лакмусовой бумажкой того, правильно ли разделены конфигурация и код приложения является факт того, что кодовая база приложения может быть в любой момент открыта в свободный доступ без компрометации каких-либо приватных данных. Далее: Другим подходом к конфигурации является использование конфигурационных файлов которые не сохраняются в систему контроля версий, например, config/database.yml в Rails Это огромное улучшение перед использованием констант, которые сохраняются в коде, н по-прежнему и у этого метода есть недостатки: легко по ошибке сохранить конфигурационный файл в репозиторий; существует тенденция, когда конфигурационные файлы разбросаны в разных местах и в разных форматах, из за этого становится трудно просматривать и управлять всеми настройками в одном месте. Это как раз способ, который описан в вопросе. Авторы манифеста предлагают такое решение: Приложение двенадцати факторов хранит конфигурацию в переменных окружения (част сокращается до env vars или env). Переменные окружения легко изменить между развёртываниями не изменяя код; в отличие от файлов конфигурации, менее вероятно случайно сохранить их в репозиторий кода; и в отличие от пользовательских конфигурационных файлов или других механизмов конфигурации, таких как Java System Properties, они являются независимым от языка и операционной системы стандартом. Естественно, всё это применимо в основном к веб-приложениям. Для десктопных и мобильных приложений эти правила уже не подходят. От себя добавлю, что Azure-приложения ASP.NET и ASP.NET WebAPI сейчас настраиваютс именно так: в панели приложения на вкладке Application settings можно указать переменные окружения. Тоже самое в Heroku. Пример В нашем проекте требуется рассылать электронные письма и СМС. Естественно, на локальны контурах разработчиков и на общем контуре разработки ничего рассылать не надо, но пр этом нужен доступ к содержимому уведомлений. То есть разработчики должны видеть, что служба уведомлений сработала, и видеть, что именно будет отправлено клиенту на боевом контуре. Поскольку мы используем внедрение зависимостей, мы сделали несколько реализаций классов рассылающих уведомления. Продуктовая реализация осуществляет отправку писем, а реализаци разработчиков пишет уведомления в файл. В качестве библиотеки IoC мы используем Autofac, который позволяет регистрировать зависимости в конфигурационном файле, так что в нашем Web.config была зарегистрирована служба уведомлений для разработчиков. MSBuild умеет трансформировать конфигурационные файлы ASP.NET проектов во время развёртывания Если в вашей папке находятся файлы Web.config и Web.Release.config, при развёртывани проекта в конфигурации Release MSBuild применит трансформации из Web.Release.config к Web.config. Можно менять атрибуты разделов, добавлять и удалять подразделы. Мы у себя меняли регистрируемый класс, так что на контуре Release запускалась реальная служба уведомлений вместо отладочной. Тогда нас такое решение устроило. Некоторое время всё работало хорошо, но потом вышла 4-я версия Autofac, которая стал совместима с новой системой конфигурирования .NET. При этом разработчики Autofac выпилили поддержку старого способа, то есть старых добрых Web.config и App.config. При этом MSBuild не умеет автоматически трансформировать новые файлы конфигурации. Пришлось переделать схему. Теперь для каждого контура мы стали хранить свою верси конфигурации IoC в файлах IoC.Dev.json, IoC.Stage.json, IoC.Release.json. Загрузка нужного файла конфигурации стала осуществляться так: Startup.cs var configName = Environment.GetEnvironmentVariable("APPSETTING_CONFIG_NAME") ?? "Dev"; var config = new ConfigurationBuilder().AddJsonFile($"IoC.{configName}.json", optional: true, reloadOnChange: true); var module = new ConfigurationModule(config.Build()); builder.RegisterModule(module); Это было стихийное решение, которое мы обнаружили в Google и смогли применить к нашем Azure-проекту. Однако это ещё не идеал с точки зрения 12-тифактороного приложения. Часть настройки действительно вынесена в переменную окружения, но часть находится в файлах IoC.*.json. Что не так? Администратор системы может решить, что файлы IoC.Dev.json, IoC.Stage.json IoC.Release.json можно спокойно менять, хотя на самом деле мы довольно суровы относительно них. Нам не нужна здесь универсальность и гибкость, мы бы хотели ограничить настройку двумя вариантами: а) шлём уведомления; б) складываем уведомления в секретное место. Так что мы можем захардкодить эти две стратегии и при старте приложения выбират ту из них, которая указана в переменной окружения: var notifyStrategy = Environment.GetEnvironmentVariable("APPSETTING_NOTIFY_STRATEGY"); switch (notifyStrategy) { case "send": builder.RegisterType().As(); break; case "save": builder.RegisterType().As(); break; default: throw new ArgumentException("Ну всё теперь.", nameof(notifyStrategy)); } Теперь администратор приложения может конфигурировать его на своём уровне погружения. Он не сломает ничего важного в дебрях XML/JSON IoC. В результате нам удалось полностью избавиться от файлов конфигурации на этом уровне и стать ближе к идеалам 12-тифакторных приложений. Исходя из этого, я бы советовал: Все секретные настройки, включая строки подключения к базам данных, логины и парол для отправки писем и прочее, брать из переменных окружения. Развёртывание приложения свести к запуску одной команды (для .NET это MSBuild). Переменные окружения и процесс развёртывания описать в README.md. Внедрение зависимостей реализовывать непосредственно в коде, предоставляя нескольк стратегий, которыми будет управлять администратор. Он скажет вам спасибо, если ему не придётся изучать детали приложения, и он сможет одной настройкой внедрить совершенно другой набор из трёх-пяти-десяти типов, не разбираясь в их взаимосвязях. Некоторые конфигурационные файлы на самом деле представляют из себя декларативну часть кода и не требуют изменения после развёртывания. Детали зависит от языка, думаю, что чаще это встречается в интерпретируемых языках. Такие файлы мы не должны считать истинно конфигурационными и можем оставить их в проекте как есть. Конфигурацию, которую может менять администратор и которая может сохраняться межд развёртываниями, вынести в БД. Можно и в файл, но в этом случае он может быть уничтожен при неаккуратном развёртывании. Значения в базе или в файле, если их нет при первом запуске системы, прописываются стандартные из кода.

Ответ 3



Я стараюсь делать следующим образом. Сначала программа пытается использовать конфигурацию специализированную для текущего хоста, из файла config-hostname.xml. Вся чувствительна информация хранится в нём, и в git он не попадает благодаря игнорированию по маске config-*.xml. Если же специализированная конфигурация отсутствует, то используется дефолтная из файла config.xml, который сохраняется в репозитории. По истории изменений этого файла очень удобно отслеживать, когда появились те или иные фичи. Часто удобнее, чем искать по сhangelog'у. В тех случаях, когда некоему параметру невозможно придумать осмысленное значени по умолчанию, но в то же время и убирать его совсем из дефолтной конфигурации не хочетс (должно быть понятно, что он вообще есть), я прописываю ему какое-нибудь заведомо невалидное специальное значение (-1 или строку "must be customized"). Программа при работе с таким параметром понимает это значение, выдаёт соответствующую диагностику и выходит.

Ответ 4



Я именно храню sample-версии конфиг-файлов. Чисто для того, чтобы почитать пример, как это может выглядеть. Настоящие конфиги собираются при помощи ansible. Именно он и подставляет критичную информацию типа паролей. Выгоды налицо: централизованное описание и хранение конфигураций, все файлы промаркированы. В ряде случаев для упрощения жизни пользуюсь следующим трюком: пароли dev-конфигураций представляют собой md5 от паролей на production. Как-то так: [mysql] host = "{{ databases_mysql[0].dbhost }}" dbname = "{{ databases_mysql[0].dbname }}" user = "{{ db_users_mysql[0].name }}" password = "{{ mask_pwd | ternary(db_users_mysql[0].password|hash("md5"),db_users_mysql[0].password) }}" , где mask_pwd - логическая переменная, маскировать или нет пароль (устанавливается в зависимости от вида окружения).

Ответ 5



Все описанное ниже относится к spring приложению, первый пункт можно отнести и другим технологиям, если возможно подстановка данных из переменных среды. Есть множество способов задания конфигурации настроек. Но действительно есть определенны чувствительные данные(пароли, credentials и т.д.), которые нельзя хранить в открыто доступе. В этом случае можно использовать вариант хранения скелета настроек в property файлов в git`е, но с подстановками из enviroment переменных. В этом случае чувствительные данные будут прописываться в OC. У первого пункта есть один существенный недостаток - синхронизация таких данных межд различными серверами. Данная ситуация может возникнуть при микросервисной и SOA архитектурах(одно или несколько приложений используют одни credentials). На этот случай есть spring cloud vault, который позволяет ограничить доступ к таким данным через авторизацию приложений. Официальное описание проекта. Spring Cloud Vault Config provides client-side support for externalized configuratio in a distributed system. With HashiCorp’s Vault you have a central place to manage externa secret properties for applications across all environments. Vault can manage static and dynamic secrets such as username/password for remote applications/resources and provide credentials for external services such as MySQL, PostgreSQL, Apache Cassandra, MongoDB, Consul, AWS and more.

Ответ 6



Как способ, наверно, решить эту проблему использование систем непрерывной интеграции которые сами будут тебе создавать конфигурацию с переменной среды. Переменная среды устанавливается в самой системе непрерывной интеграции. TeamCity так может, в других CI думаю присутствует такая возможность. Так же та есть возможность добавлять кроме переменных сред еще и параметры, системные свойства что очень удобно. Ко всему этому удобностью является написание скриптов сборки. Пример генерации конфигурации на примере js файла file=$(cat <

Ответ 7



Я храню дефолтную конфигурацию в файле .env в корне проекта. ENV_database_host=127.0.0.1 Этот файл - один и тот же для всех разработчиков, он попадает в git-репозиторий Файл загружается при запуске docker-compose up -d и значения попадают в контейнер через блок environment в описании сервиса docker services: php: environment: ENV_database_host: "${ENV_database_host}" Затем это значение загружается в параметры приложения на Symfony в файле parameters.yml parameters: database_host: "%env(ENV_database_host)%" И уже параметр database_host используется в сервисах DI контейнера Symfony "как обычно" На удалённом сервере значения из файла .env должны быть перекрыты другими. Для этог в настройках Pipeline CI\CD в репозитории GitLab создаются переменные для каждого из окружений со своим суффиксом. Например ENV_database_host_MASTER для staging и ENV_database_host_PRODUCTION для production. Чтобы на удалённый сервер попала правильная конфигурация, значения переменных⁠-⁠с⁠-⁠суффиксо переносятся в переменные без суффикса, файл docker-compose.yml компилируется с уже перекрытыми значениями и результат копируется на сервер docker-compose -f docker-compose-deploy.yml config > build/docker-compose.yml

Как организовать работу с системами контроля версий для разработки нескольких проектов с общей основой?


Стоит следующая задача: мне надо создать хранилище, где будут разные файлы скрипто
(например, A). Также будет хранилище, где будет стандартный набор файлов для начала программирования сайта (например, B). Когда я создаю новый проект — создается новое хранилище (например, C). 

Теперь мне нужно в С перенести стандартный набор из хранилища В. Потом мне нужн
из А перенести 2 скрипта в С. После этого я вижу, что в стандартных файлах (которые хранятся в В) есть ошибка. Я её исправляю и хочу залить как на В, так и на С. И так далее. То есть мне надо с ними 3-мя работать одновременно. 

Уже пробовал git и svn, ничего не получилось. Решение через git submodule не подходит
т.к. общие файлы нужно редактировать в конкретных проектах, и при этом иметь возможность подтягивать изменения в этих же файлах из основного набора.

В какой системе контроля версий и каким образом можно организовать хранилища дл
решения этой задачи? 
    


Ответы

Ответ 1



Важно: если для вашего языка есть хорошая система управления зависимостями, то приведённо здесь решение лучше не использовать. Потому что если она есть, гораздо проще сделать из основы отдельную библиотеку и устанавливать её, как зависимость. В Node.js — NPM-пакет, в Ruby — gem, в PHP — пакет Composer, в Rust — crate, и т. д. А то получится избыточность и могут добавиться хлопоты при обновлениях, которых можно избежать, изначально не используя систему контроля версий не по назначению. git может такое. Вообще у меня впечатление, что git может всё. Правда, механизм работы не слишко простой, нужно понимать, как он при этом будет работать. Поскольку git по природе своей распределённый, я сэмулирую ваш порядок работы в одно локальном репозитории на нескольких несвязанных ветках: a, b и master. Изменения в эти ветках могут запросто появляться из других репозториев (разные ветки могут следить за разными серверами!), но при использовании такой методики у вас локально должен быть репозиторий, в котором есть все три. Поехали по пунктам: Положим, что git init вы сделали, а С (сам проект) лежит в ветке master (что совершенно необязательно). создать хранилище, где будут разные файлы скриптов (например, A) Делаем "несвязанную ветку": git checkout --orphan a Зачищаем папку и индекс, чтобы начать с чистого листа: git reset && git clean -f Делаем коммит с фигнёй: echo 'скрипт' | tee script_a_1 script_a_2 git add . git commit # Тут вас попросят ввести сообщение для коммита хранилище, где будет стандартный набор файлов для начала программирования сайта (например, B) То же самое. git checkout --orphan b git reset && git clean -f echo 'скрипт' | tee script_b_1 script_b_2 git add . git commit # Сообщение для коммита Когда я создаю новый проект - создается новое хранилище (например, C). Будем считать, что это ветка master. И в настоящий момент она должна быть пуста для git это означает, что она не существует, поэтому придётся делать её заново: git checkout --orphan master git reset && git clean -f Теперь мне нужно в С перенести стандартный набор с хранилища В. Мёрдж: git merge b При этом произойдёт fast-forward до b, master будет совпадать с веткой b. Это нормально. Ведь на этом этапе состояния файловой системы проекта совпадают, верно? Потом мне нужно с А перенести 2 скрипта в С. Мёрдж с a, но на сей раз с "тормозами", чтобы прямо перед коммитом git остановился: git merge --no-commit --no-ff a Зачем? Затем, что вам не все файлы нужны. На этом этапе вы можете убрать из индекс ненужные вам файлы из индекса с помощью reset, зачистить оставшееся и закоммитить результат: git reset script_a_2 git clean -f git commit Теперь немного "поработаем", для вида: echo work > work git add work git commit в стандартных файлах (которые хранятся в В) есть ошибка. Я ей исправляю и хоч залить как на В... Поскольку у вас (семантически) master основан на b, а не наоборот, ошибку вам над починить именно в b, чтобы потом изменения "растеклись" (не автоматически!) по тем, кто ею пользуется. Идём в ветку b и чиним: git checkout b # clean уже не нужен, т. к. ветка не пустая echo script > script_b_1 # Ну, допустим, что кириллица не переварилась. Мало ли. git add script_b_1 git commit На этом этапе, если репозитории с b и master всё-таки разные, должен быть git pus ветки b в соответствующий репозиторий, а в репозитории проекта нужно сделать git pul --ff-only (--ff-only разрешает только перемотку ветки — чтобы ваши изменения не "затекли" в b) в ветке, которая за тем репозиторием следит. Это уже отдельная тема, если интересно, расскажу и об этом. ...так и на С. Переходим в ветку с проектом: git checkout master И делаем мердж ветки b в проект. git merge b Готово. Да, вот так просто! После проделывания вышеописанных манипуляций, я получил в master следующую схем из коммитов (git log --graph): * commit 2e9219cb2922f70382a8f069fdc917bdbfccd4b8 |\ Merge: 2cc463a 1fc0b61 | | Author: Имя <адрес> | | Date: Sun Dec 27 14:46:12 2015 +0300 | | | | мердж фикса | | | * commit 1fc0b61c1017acf4b4ef1941e1cdcb01a7e86be4 | | Author: Имя <адрес> | | Date: Sun Dec 27 14:41:23 2015 +0300 | | | | фикс основы | | * | commit 2cc463ae97500bff4a304990aa4e42159da96fe9 | | Author: Имя <адрес> | | Date: Sun Dec 27 14:38:37 2015 +0300 | | | | работа | | * | commit cfa122c954f77b3282f51511f94bc6d97c95d569 |\ \ Merge: 7da066c f9304d8 | |/ Author: Имя <адрес> |/| Date: Sun Dec 27 14:31:20 2015 +0300 | | | | мердж с удалением лишних | | | * commit f9304d82d89600add270544bec32cd6661a8c150 | Author: Имя <адрес> | Date: Sun Dec 27 13:46:39 2015 +0300 | | скриптики | * commit 7da066c234216057ff19775a355342ed501fe9a4 Author: Имя <адрес> Date: Sun Dec 27 13:54:01 2015 +0300 основа И для наглядности, перерисовал:

Ответ 2



Если не хочется делать несколько веток, отслеживающих разные сервера, и так дале как в другом ответе, то можно работать аналогично тому как разрабатываются крупные распределённые проекты вроде ядра Linux или языка Go - через файлы с патчами, с тем лишь отличием что ничего никому не нужно посылать по почте. Вносим изменения в файлы проекта C, которые нужно перенести обратно в A или B: git add -p; git commit У нас получился коммит в котором меняются файлы имеющие место только лишь в A или B, обязательно не одновременно. Проверяем это с помощью git show. Экспортируем этот коммит в файл: git format-patch -1 Команда создаёт файл с изменениями вида 0001-example.patch. Переходим в проект A или B, применяем там ранее полученный патч: git am ../ProjectC/0001-example.patch В лучшем случае ничего больше делать не надо. В худшем случае может потребоваться решить обычные конфликты, которые появляютс при слиянии. Например, так: find . -type f -name \*orig -print -delete find . -type f -name \*rej -print -delete patch -p1 < .git/rebase-apply/patch find . -name \*.rej | while read rej do echo $rej wiggle -r ${rej%.rej} $rej done Таким же образом изменения переносятся обратно. Вот и всё. Ограничение остаётся всё то же самое: для удобного и простого отслеживания истории файлы в проекте C должны оставаться там же где и в проектах A и B. То же относится к работе с несколькими проектами: чтобы переносить какое-то изменени из проекта-шаблона B в копии С1, С2, С3... При любом подходе вам нужно будет писать программу или скрипт. Недостатки такого подхода Недостатки очевидны - это относительно ручная работа для переноса изменений (которая в принципе поддаётся автоматизации), но и о достоинствах забывать не стоит. Достоинства такого подхода Самое очевидное достоинство такого подхода: простота при использовании и отсутстви необходимости помнить где какая ветка, а значит меньше шансов сделать merge не того не туда. Меньше ошибок - меньше времени на их исправление. Больше времени на более интересные занятия. Ещё одно достоинство: конфиденциальность. Если вам когда-либо нужно будет дать досту к Git посторонним (например, вашему подрядчику для проведения рутинных работ), то посторонний не увидит всей-всей истории изменений в проектах A и B, которая обязательно попадет в C при любом слиянии веток. Например, если вы начинаете новый проект из шаблона так: # начинаем новый проект git clone TemlateB NewProjectC cd NewProjectC git reset $(echo "NewProjectC Started" | git commit-tree HEAD^{tree}) git remote rm origin # спустя некоторое время git am ../TemlateB/0001-example-fix.patch То в такой ситуации в проекте C посторонний увидит только какой-то самый недавни коммит и коммиты-исправления, а не всю историю проектов A и B за всё время. Естественно, посторонний не увидит и изменений из других проектов, аналогичных C. Масштабируемость - ещё одно достоинство этого подхода. Поддерживать 30-50-80 копи проекта? Нет проблем! Делегировать работу над каким-то проектом подрядчику? Проще простого! Убрать какой-то проект в архив с глаз долой? Нет проблем! Вернуть из архива? Легко! Теперь представьте себе сколько экранов будут занимать 80+ веток по каждому из когда-либ начатых проектов. Даже и говорить не стоит о том чтобы убрать какую-то ветку в архив или делегировать что-то кому-то. Нет, нельзя сказать что это невозможно...