Comments 62
4 пункт можно исправить проще:
git checkout -B future-branch
git branch -f master HEAD~
При этом нет необходимости commit'ить или stash'ить локальные изменения
git checkout -b future-branch
git checkout master
git reset --hard origin/master
не нужно заново коммитить + работает если наклепал больше 1 го коммита
либо git push --force, что чревато потерей данных при работе с веткой нескольких человек…а как же --force-with-lease?
git push
на том же StackOverflow ответов с --force
сильно больше (справедливости ради, последнее время при этом делают пометку о возможной деструктивности такого решения). Поэтому решили лишний раз обратить внимание на то, что не следует бездумно этим пользоваться. А так решений и советов можно предложить гораздо больше, и
git pull
лучше делать с --rebase
для чистоты истории, и git rebase -i
, и прочее, прочее. Но это уже более глубокая тема, а тут всё-таки перевод с небольшими дополнениями.Я бросил бороться с упертыми коллегами которые предпочитают работать с rebase
+ push --force
в feature ветках. Но есть у нас один беспардонный человек, он как слон в посудной лавке гитпушфорсит в develop
, де мердж коммиты это кал а вот push --force
это прелесть она так выглаживает историю коммитов. Этот Джон Сноу скоро доиграется и ему братья коллеги устроят темную.
Я буду обновлять страницу перед отправкой комментария.
https://habr.com/company/flant/blog/419733/#comment_18981183
Я ненавижу новый хабр за то что после отправки комментария форма ввода остается на месте!
ну ещё из специфичного — в Visual Studio нужно сделать Save All, иначе изменения в проектых не попадут на диск.
Студия по умолчанию сохраняет изменения только в непосредственно отредактированных файлах. А *.csproj — не барское это дело, пусть юзер сам озаботится.
А просто при редактировании не сохраняет ни один редактор.
Есть контр-примеры.
я бы не сказал, что оно очевидно и удобно. когда ты редактируешь файл и в нем есть несохраненные изменения есть какая-то индикация этого, если изменил проектный файл ничего нет. добавил файл в проект нажал Ctrl-S, вроде бы должно хватать, а нет.
Что с этим делать?
git rebase -i
. Ну или в случае с Gitlab, он умеет делать squash коммитов MR при мёрже.Когда работал в компании где был развернут bitbucket server, то пользовался форками с удовольствием.
Про удаление remote — уже довольно долго можно делать git push origin --delete branch
, что куда понятнее.
Ой-ой. Начиная с пункта 4 — вещи, которые не следует делать, пока как следует не вкуришь git (а тогда эта статья уже не нужна).
Я после своего первого git reset, наверное, полдня потратил на изучение git только для того, чтобы больше так не делать (пропала история… удалось восстановить) и полюбил mercurial, в котором на такие грабли не наступал ("святость истории" — хотя, конечно, и там есть послабления).
Если же вы всё-таки коммитнули изменение, потребуется дополнительный предварительный шаг:
А если вы сделали уже несколько коммитов и тут заметили, что лишний файл там лежит? :)
Я в этом случае нашёл рецепт такой:
Удаление файла TeamControlClient.sdf из всех коммитов репозитория в e:\TeamControlClient.
Сначала удалим файл:
git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch TeamControlClient.sdf' \
--prune-empty --tag-name-filter cat — --all
Теперь создалась новая «ветка» с места появления файла.
А теперь клонируем репозиторий с этой веткой, не заходя в старую.
git clone file://e:/TeamControlClient e:/TeamControlClientNew
В новом репозитории файл будет физически удалён.
Уж не знаю, насколько это правильно. Но помогло.
git clone
там не нужен. Он правилен ровно настолько же, насколько любые другие манипуляции, приводящие к потере id коммитов, ребейз, например. На ветках, доступных другим разработчикам, использовать по возможности не стоит. Минус
filter-branch
— gpg-подписи теряются (rebase
же пробует переподписать новые коммиты, например).Слишком сложно, кмк. Можно сделать коммит с удалением файла, потом через интерактивный rebase передвинуть этот коммит ниже до нужного и объединить, можно через него же с отметкой нужного коммита "edit", можно вручную сделать ветку от нужного коммита, в ней commit --amend с исправлениями, потом через cherry-pick добавить все следующие коммиты.
Я для удаления файлов и sensitive info из истории использовал BFG Repo-Cleaner – неплохая штука.
Тот случай, когда чуть ли не с первого дня пользуешься этим в GUI, где оно делается просто и естественно, а оказывается с этим бывают проблемы.
На --amend
галочка в диалоге коммита, на файл галочка в списке файлов, причем git add
для untracked автоматически выполняется, на отмену изменений пункт меню "Revert", на переименование ветки F2 в списке веток, на удаление пункт меню там же, и для удаленной тоже, reset
на коммит пункт меню в списке коммитов, "Show reflog" вообще рядом с "Show log", и иногда случайно на него тыкаешь.
Коммит не в ту ветку требует аналогичных действий, нестандартный checkout
или reset
надо конечно в консоли делать.
PS: "Опять кто-то влез с GUI", но статья для неопытных пользователей, и кому-то это поможет сохранить время и нервы)
Это наверное самая полезная фича при работе в команде.
Я бы даже посоветовал сделать
git config --global pull.rebase true
Два человека работают с одной веткой, у обоих одинаковый набор изменений, первый делает коммит в мастер и делает пуш, следом второй делает в ту же ветку коммит, и при попытке запушить он получит режект. Вот git pull --rebase
позволяет сделать историю коммитов линейной, без merge-коммитов.
Trunk-based development, когда не надо делать 100500 веток, чтобы потом 100500 раз не мержить и не нарываться на конфликты в разных местах.
А во-вторых, количество ребейзов только возрастает. И, кроме этого, теперь надо ребейзиться не только с основной ветки разработки, но и со своей собственной. Количество работы и конфликтов возрастает в разы просто.
Не хочу обидеть, но мне кажется, что вы не до конца понимаете концепцию Git и продолжаете ее использовать, как Subversion.
Вы видимо меня не поняли) Trunk тут не про Subversion. Вот есть ветка master
. И все разработчики на проекте пользуются исключительно ей, совмещая свои пуши с ребейзом, чтобы с одной стороны история коммитов была линейной, а не засоренной коммитами типа merge branch with...
, а с другой стороны для того, чтобы не плодить кучу отдельных веток от master
. За которыми потом еще следить надо, а нужны ли они до сих пор, или их можно уже давно удалить.
У нас уже не раз бывало такое, что разработчики создавали отдельные ветки под какие-то свои задачи, отпачковываясь от master
, а потом, когда приходило время свои наработки вливать обратно, начинались танцы на колотом стекле из-за рассинхрона, конфликтов, случайно затёртых изменений (как в master
, так и в собственных ветках) и т.д.
Релизы можно делать и по тегам, это вполне вписывается в концепцию) Более того, концепция Git не заключается в одном лишь ветвлении.
потом, когда приходило время свои наработки вливать обратно, начинались танцы
Достаем калькулятор и начинаем считать. Я беру для простоты сценарии, где малая активность и ребейзятся только по окончании. В случае увеличения активности и частоты ребейзов, картина еще сильнее разойдется по цифрам.
Сценарий_1:
Есть мастер. Отпочковались 5 веток — каждый делает свое дело. Каждый, по окончании работы, заребейзился перед прогонкой тестов.
Итог: 5 ребейзов от мастера.
Сценарий_2:
Есть мастер. Отпочковались 2 ветки. Над одной работает 2-е парней, над второй 3-е. Все закончили работу. Каждый делает ребейз со своей ветки в ремоуте. Итого у нас 5 ребейзов. Пока все ок. Дальше первые двое парней отправляют свою поделку в мастер. Опа — у трех остальных несхождение с мастером — нужно ребейзиться перед тестами.
Итог: 5 ребейзов с ремоута и 1 с мастера.
Эта дельта в 17% будет сохраняться при любой активности и объемах работы. Но чем больше у вас будет людей и веток, тем больше эта дельта в 17% будет весить в абсолютных цифрах ресурсов.
В сухом итоге получается, что вы сказали примерно следующее:
Мы не любим решать конфликты при мерджах/ребейзах, поэтому мы увеличиваем количество этих конфликтов на 17%.
И это:
За которыми потом еще следить надо, а нужны ли они до сих пор, или их можно уже давно удалить.
Бренчи должны автоматически удаляться после мерджа. Это фича-бренч. Фича сделана и протестирована? Видимо да, раз отослали PR к мастеру. Если она сделана, зачем бренчу жить? Будет баг — будет другой бренч на баг.
Весь мой предыдущий комментарий был к тому, что мы практически не используем фича-бранчи. Пушим в мастер и релизим по тегам. Всем нравится, всем удобно. Делаем ветки в крайнем случае: для обкатки каких-то решений, для выполнения заданий новичками.
Вот я изначально имел ввиду второй сценарий. Либо пара разрабов сидит в мастере и пилит что-то, либо та же пара разрабов делает для себя фиче-ветку, и пилит в ней, и чтобы не было в рамках этой ветки мерж-коммитов и юзается git pull --rebase
.
Как сказал franzose — мы не используем фиче-бранчи. Точнее, используем, но именно для глобальных фич. Но бОльшее количество задач — это багфиксы, которые укладываются в один коммит, и нет никакого смысла пилить эти багфиксы в отдельный бранч, и потом его мержить в мастер.
В дополнение ко всему, у нас разработчики используют один центральный репозиторий, поэтому практика pull-requests у нас не пользуется популярностью, где допустимо пилить фичу например месяц, и периодически ребейзить свою ветку в своем репозитории с force-push без опаски сломать все основное. У нас же в "долгие" фичи-бранчи приходится подмерживать мастер, и в итоге мы имеем кучу мерж-коммитов в рамках одного репозитория, что в общем-то не очень приятно наблюдать при просмотре истории.
Открыл сейчас наш upsource, тыкнул в лог коммитов, у одного мерж-коммит из-за того, что он пилил на разных железках код в эту ветку, и сам с собой словил рассинхрон и сделал просто git pull, второй мерж-коммит синхронизация с мастером, следом третий мерж-коммит для синхронизации с мастером уже другой ветки от другого человека… Это мелочи, но напрягает.
У нас же в "долгие" фичи-бранчи приходится подмерживать мастер, и в итоге мы имеем кучу мерж-коммитов в рамках одного репозитория, что в общем-то не очень приятно наблюдать при просмотре истории.
Просто перед слиянием в мастер делается rebase+squash, в результате история получается приятная глазу и вполне укладывается в идеологию "одна задача – один коммит".
практика pull-requests у нас не пользуется популярностью, где допустимо пилить фичу например месяц
Как связан размер фичи с пулл реквестом? В чем проблема сделать ветку + пулл реквест пусть даже для однострочного коммита? Лишних действий почти нет, зато наглядно видно, что именно сейчас уйдет в мастер.
А пушить напрямую в мастер-ветку – это как-то отчаянно, на мой взгляд – это какие-то админы первого типа.
А пушить напрямую в мастер-ветку – это как-то отчаянно, на мой взгляд – это какие-то админы первого типа.
В этом нет ничего страшного, если релизы делаются по тегам. Так или иначе код перед релизом ревьювится.
А смысл в таком ревью?
- Кода много – явно больше одного таска => нормально отревьюить его будет на порядок сложнее.
- Код уже в мастере, т.е. на него потенциально завязан другой код, исправить его сложнее, и во многих случаях на это просто забьют.
Такой ревью будет больше для самообмана. Или для очковтирательства менеджеру.
Кода много – явно больше одного таска => нормально отревьюить его будет на порядок сложнее.
Задачи в коммитах можно помечать маркерами типа [TASK-999]
. Тогда проблем найти нужное не будет.
Такой ревью будет больше для самообмана. Или для очковтирательства менеджеру.
А при чем тут менеджер, если код ревьювится программистами для улучшения или исправления кода другими программистами?
Все зависит от проекта. Ну, у нас например. Есть те, где правки вносятся исключительно в ветки, и только мантейнер мержит их после ревью. Есть проекты где только только один девелопер, и вот будет он мержить все это дело… Поэтому в этих случаях пилится все в мастер.
У нас вот ребята пилили проект с нуля, они все делали можно сказать в мастере (ну, были бранчи по спринтам, по окончанию которого мержилось в мастер), ревьювить код на этапе разработки никто не собирался. Поэтому по окончанию разработки мы просто проревьювили весь код имея полное представление о всем проекте, а не только об измененной опечатке в каком-то классе.
Просто перед слиянием в мастер делается rebase+squash
Да, будет красиво, не спорю. Но вполне может быть такое что что-то поломается, находим с помощью bisect мы этот один чудесный коммит, а там изменений на пару десятков тысяч строк. Вот весело будет все это разбирать...
Как связан размер фичи с пулл реквестом? В чем проблема сделать ветку + пулл реквест пусть даже для однострочного коммита? Лишних действий почти нет, зато наглядно видно, что именно сейчас уйдет в мастер.
Цитата вырвана из контекста у вас. там было перед ней:
… у нас разработчики используют один центральный репозиторий, поэтому практика pull-requests ...
Git happens! 6 типичных ошибок Git и как их исправить