
Nov 25, 2016 - advice.c:114 builtin/merge.c:1181 msgid 'You have not concluded. 'binary patch does not apply to '%s' msgstr 'не удалось применить. 'Not a valid commit name%s' msgstr 'Недопустимое имя коммита. N nЗапустите n n git config --global user.email 'you@example.com ' n git config --global.
Год назад мы с командой решили перейти с SVN на Git. Зачем это было надо — писать не буду, т.к. На эту тему уже и так много написано. А хочу я описать типичные алгоритмы работы, понятные человеку, который долгое время пользовался SVN. Ниже — памятка, написанная для команды год назад, чтобы легче было мигрировать. Надеюсь, кому-нибудь пригодится.
Немного об устройстве Git (упрощённо). Git — распределённая VCS. Это значит, что мы работаем не с одним репозитарием на сервере, а каждый имеет у себя локальную копию репозитария. Соответственно, такие операции, как checkout и commit производятся с локальным репозитарием. Друг с другом же (или с тем, что на сервере) репозитарии синхронизируются специально предназначенными командами pull (fetch) и push.
Это позволяет коммитить столь часто, сколь угодно, даже если в данный момент отсутствует соединение с сервером. Важное преимущество Git'а — внятная работа с ветками и удобный механизм слияний (merge). В SVN мы, как правило, работали с одной веткой trunk (в git ветка, с которой мы работаем по умолчанию, называется master). Эта же ветка заливалась на продакшн. Главное неудобство здесь — то, что если мы производим какие-то изменения, или разрабатываем новый функционал, мы вынуждены либо сидеть и не коммитить до тех пор, пока задача не будет доделана до конца, либо (если нам нужна помощь коллеги), закоммитить недоделанный функционал, как есть, сделав таким образом trunk непригодным к заливке на продакшн. Особенно это неприятно, если новый функционал делается не один день, а в это время возникает необходимость что-нибудь срочно починить в рабочей системе.
Надо отметить, что в SVN, конечно, есть ветки, но сделаны они, видимо, для другого, и поэтому плохо приспособлены для того, чтобы их сливать в trunk. В git операция merge сделана изящно и удобно, что позволяет нам существенно изменить workflow на более оптимальный. Ещё одно отличие git в том, что он хранит не изменения, а текущее состояние проекта в каждый момент времени.
master — это та ветка, которая всегда, в любой (!) момент должна быть готова к деплою на продакшн. Поэтому мы никогда не делаем новые фичи и багфиксы сразу в master, используем для этого ветки. Полезно будет изучить статьи и, возможно, даже. В статье №2 сформулировал очень важный принцип: одна фича — одна ветка.
Один багфикс (если предполагается длиннее двух коммитов) — одна ветка. Один эксперимент — одна ветка.
Одна фича внутри эксперимента — ветка от ветки. Всегда пишем вразумительные комментарии к коммитам. После того, как фича (багфикс) написаны, оттестированы и готовы к продакшну, мержим ветку в master. Когда мы можем коммитить прямо в master? Только тогда, когда мы точно уверены в том, что наше мелкое изменение однозначно решит проблему и не создаст новых.
Когда уверены, что не понадобится потом делать bugfix для bugfix'а. При этом, изменения должны быть минимальными.
Поэтому, хорошим правилом будет, всё же, создание отдельной ветки (за исключением совсем уж простых случаев). $ git config -global user.name «First Last» $ git config -global user.email «email@example.com» $ git config -global color.diff «auto» $ git config -global color.status «auto» $ git config -global color.branch «auto» Дополнительно можно настроить shell-alias'ы, как описано в статье №2. Cтандартный workflow. Начало работы — клонирование репозитария. Предполагается, что у вас уже есть и настроен gitosis, на котором лежит проект. Git clone gitosis@git.yourserver.com:yourproject.git — этот шаг делается один раз.
Результатом будет папка yourproject с проектом у вас на жёстком диске. Команда clone делает следующие вещи: клонирует удалённый репозитарий в новую папку (yourproject в данном случае), создаёт в локальном репозитарии remote-tracking ветки для всех веток удалённого репозитария, создаёт локальную копию активной в данный момент удалённой ветки и делает из неё checkout. Написание нового кода или багфикс. Git branch — смотрим, какие ветки у нас есть в данный момент в репозитарии. Сразу после клонирования у вас будет видна только одна, активная в данный момент в удалённом репозитарии, ветка (в нашем случае это по умолчанию master, т.к.
Удалённый репозитарий находится на сервере и в нём ветки никто не переключает). Если в репозитарии есть другие ветки, их можно увидеть, добавив ключ -a (активная ветка обозначена звёздочкой): $ git branch -a. master origin/HEAD origin/master origin/feature 2. Допустим, мы хотим заимплементить фичу feature. Создаём локально новую ветку с помощью команды branch. Командой checkout можно переключаться между ветками: $ git branch feature $ git checkout feature Switched to branch 'feature' Или, что тоже самое, только короче: $ git checkout -b feature Switched to a new branch 'feature' 3.
В git есть такое понятие как индекс. Например, команда commit добавляет в репозитарий только те файлы, которые есть в данный момент в индексе. Поэтому, во время работы не забываем добавлять (git add ) или удалять (git rm ) файлы в/из индекса репозитария.
Обратите внимание, что, в отличие от SVN, если вы изменили файл, его заново нужно добавить в индекс командой git add. Например: $ git add file1 file2 $ $ git commit -m 'adding file1 & file2' Created initial commit 8985f44: adding file1 & file2 2 files changed, 2 insertions(+), 0 deletions(-) create mode 100644 file1 create mode 100644 file2 Здесь есть полезности: команда git add. Добавляет все untracked файлы в индекс (рекурсивно), а ключ -a у команды commit позволяет автоматически добавить все модифицированные (но не новые!) файлы.
Текущее состояние индекса можно посмотреть командой git status: $ git status # On branch feature # Changes to be committed: # (use 'git reset HEAD.' To unstage) # # new file: file1 # new file: file2 # Коммиты в репозитарии смотрятся командой git log. Если мы хотим разрабатывать новый функционал совместно, нам нужно опубликовать нашу ветку на сервере, чтобы другие могли с ней работать. Вот как это делается (перед этим необходимо закоммитить все изменения в данной ветке): $ git push origin feature:refs/heads/feature Counting objects: 4, done. Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 273 bytes, done.
Total 3 (delta 0), reused 0 (delta 0) Unpacking objects: 100% (3/3), done. To gitosis@git.yourserver.com:yourproject.git. new branch feature - feature (в новых версиях git можно просто git push origin feature:feature) Команда push отправляет изменения в удалённый репозитарий (origin) из локальной ветки feature в удалённую ветку featurе, предварительно создав её там (refs/heads/feature нужно как раз для создания ветки). В дальнейшем можно будет использовать git push origin feature (по умолчанию git push публикует изменения из всех веток).
Но при таком способе публикации, не устанавливается связь между локальной версией ветки и опубликованной. Если кто-то закоммитит изменения в эту удаленную ветку и вы сделаете git pull, то будет ошибка: $ git pull remote: Counting objects: 3, done. Remote: Compressing objects: 100% (2/2), done. Remote: Total 2 (delta 1), reused 0 (delta 0) Unpacking objects: 100% (2/2), done. From gitosis@git.yourproject.com:yourproject d23a39c.b0a86e0 feature - origin/feature You asked me to pull without telling me which branch you want to merge with, and 'branch.feature.merge' in your configuration file does not tell me either. Please name which branch you want to merge on the command line and try again (e.g. 'git pull ').
See git-pull(1) for details on the refspec. If you often merge with the same branch, you may want to configure the following variables in your configuration file: branch.feature.remote = branch.feature.merge = remote.url = remote.fetch = See git-config(1) for details. Гит не знает с какой ветки ему мерджить. Поэтому можно либо каждый раз указывать это руками: git pull origin feature Либо прописать в конфиге: git config branch.feature.remote origin git config branch.feature.merge refs/heads/feature Кроме того можно воспользоваться от William Morgan и делать git publish-branch feature вместо всего остального. Как присоединиться к работе над веткой.
Предполагается, что вы уже склонировали себе репозитарий. Главное здесь — правильно подключить удалённую ветку. Сделать это можно с помощью ключа -track команды git checkout. Команда, приведённая ниже, создаёт локальную ветку feature и подключает её к удалённой ветке origin/feature, после чего переключается в эту ветку. $ git checkout -track -b feature origin/feature Branch feature set up to track remote branch refs/remotes/origin/feature. Switched to a new branch 'feature' Это важно на данном этапе, поскольку просто команда pull смержит удалённую ветку к нам в master, а это не то, что нам нужно. Далее можно работать аналогично описанному в шаге 2а, синхронизируя репозитарий в каждой из веток командами git pull и git push.
Как переключиться в другую ветку, когда в текущей есть изменения и коммитить их рано. Иногда возникает необходимость срочно переключиться в другую ветку, например для багфикса. Но на полноценный коммит в этой ветке еще не хватает. Для этого существует команда git stash: $ git status # On branch feature # Changes to be committed: # (use 'git reset HEAD.' To unstage) # # new file: somefile # $ git stash Saved working directory and index state 'WIP on feature: b0a86e0. Blabla' HEAD is now at b0a86e0 blabla (To restore them type 'git stash apply') $ git status # On branch feature nothing to commit (working directory clean) Теперь можно смело переключаться в другую ветку и работать там.
По возвращению в эту ветку, необходимо сделать git stash apply: $ git stash apply # On branch feature # Changes to be committed: # (use 'git reset HEAD.' To unstage) # # new file: somefile # Шаг 3.
Merge и rebase. Использовать какую-либо из этих команд вам понадобится в 2-х случаях:.
Вы хотите подлить свежие изменения из master к себе в ветку;. Вы хотите слить свою ветку в master. Общее правило такое: если мы работаем с веткой самостоятельно и не планируем публиковать её на сервере — то выгоднее использовать rebase. Если же мы публикуем ветку командой push, то использовать rebase НЕЛЬЗЯ, иначе мы автоматически инвалидируем работу коллег. Разница между merge и rebase хорошо показана на иллюстрациях в Git book:.
Вкратце: rebase запоминает коммиты из ветки в виде патчей, «перематывает» текущую ветку (как будто и не было никакого branch) и применяет патчи, оформляя их в виде коммитов. В отличие от rebase, merge делает слияние двух веток в одну. Примеры: Подливаем изменения из master в рабочую ветку feature, ветку feature нигде не публикуем, работаем с ней только локально: $ git checkout feature Switched to branch 'feature' $ git rebase master First, rewinding head to replay your work on top of it. HEAD is now at 89f6a20 file2 Applying feature1 Сливаем изменения из рабочей ветки feature в master, ветка feature нигде не публиковалась, никто из коллег с ней не работал: $ git checkout master Switched to branch 'master' $ git rebase feature First, rewinding head to replay your work on top of it. HEAD is now at 9bfac0a feature1 Applying file2 Подливаем изменения из master в рабочую ветку feature, ветка feature опубликована на удалённом репозитарии, с ней также работают коллеги: $ git checkout feature Switched to branch 'feature' $ git merge master Merge made by recursive. File2 1 + 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 file2 Сливаем изменения из рабочей ветки feature в master, ветка feature публиковалась на удалённом репозитарии для совместной работы: $ git checkout master Switched to branch 'master' $ git merge feature Merge made by recursive. Feature1 1 + 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 feature1 Шаг 4.
Удаление ветки. После того, как мы закончили работать с веткой и слили изменения в master (или в другую ветку), можно удалить ветку. Для удаления локальной ветки: $ git branch -d feature Deleted branch feature. Для удаления remote tracking ветки: $ git push origin:feature - deleted feature Вот, вроде, и всё. Этого должно быть достаточно в первое время при миграции с SVN на Git. Отдельное спасибо хабраюзеру за всяческие дополнения и улучшения данного текста.
Метки:. Добавить метки Пометьте публикацию своими метками Метки необходимо разделять запятой. Например: php, javascript, адронный коллайдер, задача трех тел. Ну, можно хуки использовать. Там на каждое событие (коммит/пуш/мерж/еще там что) есть отдельный скрипт-обработчик. В него можно нужные команды положить. У меня таким образом подобие CI сделано: — один мастер-репозиторий, две ветки — продакшн/стейдж.
— на www два репозитория, которые следят каждый за своей веткой на мастер-репозитории — хук, который при коммите в мастер-репозиторий говорит git pull для соответсвующего www-репозитория (да, если кому интересно — могу написать все подробно и пошагово) Правда, не уверен, что это 100% ОС-независимо, под виндами скорее всего либо баш ставить придется, либо переписывать на батники. Статья интересна. Я очень приваетствую использование DVCS. В нашей организации перевел весь it на Bazaar и очень доволен. Был удивлен, касательно, как мне показалось, некоторых лишних телодвижений в git Например:«Обратите внимание, что, в отличие от SVN, если вы изменили файл, его заново нужно добавить в индекс командой git add.» Если файл объявлен «версионным» — зачем его опять добавлять? Я не в упрек, просто непонятно.
Из моего личного опыта — перебрал много DVCS и выбрал bazaar как самый логичный. Я вообще ничего не знающему о dvcs работнику на пальцах объясняю и он просто начинает работать. Даже не возвращаясь в дальнейшем к печатным инструкциям. На втором месте был hg.
Bzr init — создали репозиторий bzr add — добавили все файлы, кроме тех, которые описаны (можно масками) в.bzrignore bzr ci -m «Initial release» — сделали commit bzr log — посмотрели что как bzr branch откудасделатькопию — делаем ветку bzr push — сбросили в центр bzr pull — взяли из центра (естественно есть масса других вариантов организации работы типа update, merge, еще:) Предугадывая комментарии — слухи о медленной работе bzr сильно устарели) Извините, если это никому не покажется интересным — хотел просто поделиться. Если интересно — могу написать о реальном опыте установки и запуска Bazaar Было интересно прочитать о реальном использовании git.
Интересна именно организация работы используя DVCS, ведь именно от этого зависит насколько удобно и полезно будет его использование. Автору спасибо. Или, что у меня гораздо чаще случается, чем описанное оратором выше: часто начинаешь делать изменения, а потом замечаешь, что коммиттить их в будущем надо будет не в эту, а в другую ветку. Для этого делаешь git add, потом, вроде git reset -soft (я пользуюсь GUI-интерфейсом gitk для этого, не знаю точных ключей) и дальше продолжаешь модифицировать изменения, после чего комиттишь. Кстати, пользуясь svn я часто тоже делаю аналог git add: есть специальный скриптик, который запускается командой «sv» перед коммитом для того, что бы отследить изменения в текущем каталоге, которые будут закоммитчены. В тестировании bzr 1.12 Текущая версия 1.17 готовится 2.0, где много внимания уделено именно скорости работы.
Базар изначально проектировался как замена dvcs (GNU Arch) и главной целью было создание удобного и дружественного интерфейса пользователя. Оптимизацией скорости работы этой системы начали заниматься несколько позднее, используя в качестве наглядного примера Гит и Меркуриал. Так что в первую очередь было удобство, а скорость уже оптимизируют. Не скажу, что догнали hg по скорости на данный момент, но bzr очень активно развивается — в среднем минорный релиз раз в месяц. Я не агитирую, просто попробовав hg и bzr — последний меня устроил значительно больше.
Огромных репозиториев у меня нет и затраты на производительность вполне окупаются легкостью обучения разработчиков и удобством пользования. Естественно, это субьективное мнение. Не будем спорить. Спасибо за ссылку, я это видел, когда выбирал систему. На данный момент она уже не соответствует действительности (по скорости).
Git разделяет изменение индекса и коммит. Значение файлов сохраняется при добавлении в индекс, соответственно есть три варианта git diff.
$ echo 'created' file $ git add file $ echo 'updated' file $ git diff file # относительно индекса @@ -1 +1 @@ -created +updated $ git diff -cached # в индексе @@ -0,0 +1 @@ +created $ git diff HEAD # от последнего коммита diff -git a/file b/file @@ -0,0 +1 @@ +updated При коммите сохраняется текущий индекс. Команда git commit -a эквивалентна git add -u # добавляем в индекс измененные файлы git commit. Надо отметить, что в SVN, конечно, есть ветки, но сделаны они, видимо, для другого, и поэтому плохо приспособлены для того, чтобы их сливать в trunk. Ключевое слово выделено жирным. Как бы надо немного разобраться с трехсторонним мерджем и все становится просто супер. Эта же ветка заливалась на продакшн. Главное неудобство здесь — то, что если мы производим какие-то изменения, или разрабатываем новый функционал, мы вынуждены либо сидеть и не коммитить до тех пор, пока задача не будет доделана до конца, либо (если нам нужна помощь коллеги), закоммитить недоделанный функционал, как есть, сделав таким образом trunk непригодным к заливке на продакшн.
Особенно это неприятно, если новый функционал делается не один день, а в это время возникает необходимость что-нибудь срочно починить в рабочей системе. Я бы таких горе-разработчиков уволил на хер. Это НЕ вопрос используемой системы контроля версий, а построенного процесса и дисциплины. К сожалению, иногда увольнять надо и горе-менеджеров: часто задача достижения определённого «километрового столба» ставится приоритетной, в trunk происходит активная интеграция, а потом вдруг всё глохнет, а актуальной задачей становится, например, релиз с новой, необходимой бизнесу, функциональностью.
С Subversion`овским мерджем в таком сценарии использования остаётся только курить бамбук и реализовывать в новой интеграционной ветке, в том числе, часть функциональности, которая уже замерджена в заглохший trunk. Даже после версии 1.5, чей мердж иногда сглюкивает (в частности, на репозиториях, которые родились до 1.5 или на которых активно поколдовали с помощью svk) и приходится откатываться на покоммитный мердж.:( А когда заказчик trunk-а оживёт, придётся синхронить изменения, сделанные в релизной ветке с trunk. Я больше не о терминологии (в некотором смысле, trunk — это «следующий/планируемый/текущий/нестабильный релиз»). А о том, что на Subversion в силу того, что встроенный механизм слияния имеет серьёзные ограничения и того, что замердживаемые изменения сами могут быть замерджены (причём, возможно, пофайлово, а не целым деревом), сложнее вести два релиз-бренча одновременно. Приходится либо реализовывать идентичные изменения независимо (что потом приведёт к конфликтам), либо мерджить изменения поштучно (что приведёт к большой ручной работе, если засбоит новый механизм автомерджа в Subversion). Не согласен — у нас в SVN репозитории сейчас 3 активных релиз бранча 0908 — это на продакшн сервере 0909 — в выходные будет go-live 0910 — это на следующий месяц, был ответвлён из trunk в эти выходные по одному на каждый месяц. Release maitainer каждое утро сливает все change setы — конфликтов за несколько лет работы практически не было.
Выглядит это просто: утром запускается автоматические merges 0910-trunk-0909,0908 0909-trunk-0910,0908 0908-trunk-0909,0910 притом из-за специфика SVN мы переносим все changesets как одну ревизию кода. Все разработки ведутся не в trunk а в отдельных ветках, которые потом вливаниются в trunk перед тем как создаётся новая релиз ветка. 1) Ситуация исключена на организационном уровне. Клиентов готовят к тому, что их проект будет частью определённого релиза. 2) Релиз ветки, как явление, не содержат изменений вообще, только баг-фиксы. Все изменения в отдельных ветках, которые попадаю в trunk.
Из него раз в месяц ответвляется новый релиз. Баг фиксы, соответственно, делаются только в релиз ветках (один раз) и пропагируют оттуда в trunk и другие ветки. Этим занимаются branch managers. Вообще это стандартная практика. Release Driven Development.
Я как раз и писал (выше по треду), что определённые орг. Проблемы порождают определённые сложности при работе с Subversion, которые перестают быть таковыми при использовании Git. Проблемы, конечно, решаются, но слишком уж мелкими шажками. Собственно, я для основных проектов git использую в совокупности с оставшимся в наследство svn хранилищем. При этом перенос коммитов между ветками делается без потери семантики «коммит»/«изменение»/«фича» с помощью rebase. И в этом и заключается основная крутизна Git, как DVCS/DSCM: независимость своей ветки кода от чужой. И этим активно пользуются open source проекты, т.к.
У них ситуация, когда «пропадает» разработчик (он же часто и заказчик) той или иной фичи, случается гораздо чаще, чем в процессе «нормальной разработки». И семь остальных фич заглохшую ждать при релизе не будут. Кстати, в приведённом в (1) сценарии использования основная засада — не «быстро-быстро» внедрить 0910 (любой мало-мальски грамотный руководитель такого никогда не попросит, хотя у нас и так бывает иногда), а отказаться в ближайшей версии (и в trunk) от некоторых изменений, которые уже оттестированы (и замерджены в trunk) в ближайшем накате (см. Пункт 0909-trunk-0910,0908). Этот сценарий гораздо более част в жизни из-за real life забот (политика, юр.
Обязательства и т.п.). В Subversion этому поможет только политика «стабильный trunk», когда изменения в trunk попадают только после успешного деплоя фича-брэнча (спасибо за картинку в комменте внизу — как раз иллюстрирует этот подход). Иначе в trunk придётся делать малокрасивый коммит «обратного диффа». С которым потом (когда части заблокированных изменений, наконец, дадут зелёный свет) непонятно, что делать, т.к. Всё, что при этом остаётся в trunk — это коммит с текстовым changelog (в лучшем случае) и кучей каких-то непонятных изменений: какие изменения надо накатывать из «забаненного» фича-бренча — непонятно.
(2) Релиз ветки, как явление, не содержат изменений вообще, только баг-фиксы. У вас, на самом деле, изменения не автоматические, как на картинке, а выполняются SCM-инженером (или тимлидом) по необходимости. Тогда понятно — это единственный нормальный подход при наличии хотя бы минимального управления/vision/предсказания у проекта (и описано везде, включая svn book). Проблема, что не все проекты такие — в частности, многие задачи поддержки/эксплуатации существующих систем жёстко привязаны к реальной жизни и изменения, происходящие в ней мгновенно сказываются на проекте, не позволяя ждать следующего цикла.
Да, я читал, хороший текст. Но, тем не менее, описанный подход всё равно требует определённого разумного планирования, к примеру, в том, что бы Stories не пересекались. Вообще, может, по комменту, на который вы отвечали, не очень заметно, но в комментах habrahabr.ru/blogs/development/68341/#comment1939100 habrahabr.ru/blogs/development/68341/#comment1939795 речь пошла о том, что вопросы плохой организации/проектирования/архитектуры осложняют работу с Subversion. Конечно, такие моменты осложнят и работу с git, но, как мне кажется, с конкретной задачей подготовки двух релизов в условиях гонки лучше справляется git, чем svn, т.к.
Встроенные механизмы rebase и merge сохраняют семантику «коммит» и благодаря этому людям, ответственным за каждый из релизов проще управлять изменениями, наработанными во время гонки другой командой (для другого релиза). А подскажите, пожалуйста, меня, как человека, настраивавшего гит, мучают вопросы по более приземленным вещам, чем просто работа с ним: Есть проект на некотором удаленном сервере. Есть ряд разработчиков, которым предпочтителен HTTP/HTTPS-доступ.
И есть необходимость ограничивать различным разработчикам доступ в различные ветки(т.е., например, в master что-то коммитить может только head developer). Доступ через DAV не позволяет ограничивать доступ какими-то ветками, т.е. Любой может спокойно накоммитить всякого куда угодно, если у него вообще есть права на запись. Я не понял, предоставляет ли возможность делать такие ограничения gitosis, но в любом случае не хотелось бы связываться с доступом через ssh, введением ключей вместо паролей и т.п. Можно ли как-нибудь реализовать такие ограничения? Ну, у меня работа с DAV идёт средствами апачевского moddav, приблизительно так: Dav on Order Allow,Deny Allow from all AuthType Basic AuthName Git AuthUserFile '/path/to/davgit.passwd' Require valid-user То есть, DAV позволяет разрешить чекауты всем, но любая операция коммита требует авторизации из файла паролей.
Насколько я вижу в access-логе апача, для ограничения коммита мне придётся на '/myrepo.git/refs/heads/master' поставить ограничение на LOCK отдельным файлом паролей. Это довольно неудобно и требует перечитывания конфига апача при каждом добавлении/изменении веток с ограничениями. В davsvn я могу в authz-файле указать права просто как: myrepo:/trunk headdev=rw seconddev=rw.=r myrepo:/branches/mybranch headdev=rw someoneelse=rw.=r И изменять права доступа к любым веткам, не касаясь апача.
А у гита получается непосредственная работа с апачевским конфигом, плюс дублирование записей о паролях для каждого отдельного проекта/каталога, к которому разработчик имеет доступ. Если второе еще можно пережить, то первое как-то очень неудобно. Вам, может, будет проще прописать не полные урлы для ограничения, а маски путей. Тогда не придётся менять конфиг каждый раз. Или посмотрите на другие DAV сервера, например на nginx`овский (я с ним не работал, но судя по примерам конфигов в гугле, он довольно тонко настраивается). Ещё попробуйте посмотреть, как это сделано в github/gitweb для mob веток (я не смотрел). В общем, это не проблема git, а проблема выбранного способа доступа к файлам.
Лучше, конечно, сделать, как предложил maxcom ниже — это и нагляднее, и привычнее (вспомним систему интеграции, которой придерживается проект linux ядра). разрабатывайте, как хотите, а мне присылайте патчи В общем-то, Торвальдс так и сделал, за исключением того, что у него есть доверенные замы (как он выражается, лейтенанты) по разным подсистемам, с которых он мерджит. Кстати, ваши люди вполне могут сами работать с master демократичным образом, но «официальная» версия master будет только у вас и вы её будете регулярно накатывать на репозиторий (push -f).

Это, конечно, плохо тем, что тем разработчикам, кто ранее склонировал master с общего сервера придётся rebase-ить его на за-push-еный вами. В общем, если сложно настроить DAV, то выходов куча. Я бы всё-таки сделал иерархию ref`ов с ограничением доступа в конфиге апача, если ничего лучшего нет. Либо найдите перловика, который ограничит доступ через modperl. Ещё лучше, конечно поставить ssh, а для людей, сидящих под файрволом вывесить ssh на 443 порту. Честно говоря меня ветки в svn полностью устраивают.
Trunk всегда готов к загрузке на продакшн, любые серьёзные изменения делаются в ветках, мердж, за исключением некоторых ситуаций, происходит без проблем. При необходимости версию на продакшн можно отделить от транка. При этом в ветку можно комитить часто, даже если результат будет не совсем стабильным.
Правда у нас над одной веткой редко работает больше двух человек, иначе подобное было бы невозможно. Если же требуется показать изменения коллеге, можно воспользоватся патчем. Надо отметить, что в SVN, конечно, есть ветки, но сделаны они, видимо, для другого, и поэтому плохо приспособлены для того, чтобы их сливать в trunk.
Это вы какую-то фигню написали. Вся суть репозитория — в ветках.
Всем разработчикам сидеть в транке — дурдом. К правилам создания веток хочу так же добавить ветки релизов, как без этого работать мне сложно понять. SVN прекрасно работает с ветками во всех направлениях, дайте мне кейс, кто она с ними не справляется как должно. В пользу GIT говорит только распределённость.