Comments 63
Я предпочитаю работать в консоли и большая часть команд и советов в этой заметке будет про консольный клиент. Это своего рода первая рекомендация — используйте консольный клиент для ежедневной работы с репозиторием и регулярно его обновляйте. В консольном клиенте в первую очередь появляются новые возможности и исправления ошибок.
Какая-то странная у вас аргументация.
Ни разу не сталкивался с ошибками git клиента
А вот то что в VS 2019 появился squash, мне во многом облегчило жизнь
Но я не навязываю кому-то инструмент, вполне возможно у Вас другие сценарии использования.
Ни разу не сталкивался с ошибками git клиента
Ooo, вот только что нарвался. В Windows 10 на одной машине вдруг стала сбоить команда git subtree add. Три дня на ушах стоял. Потом обнаружил, что глюки имеют место только при запуске из-под Far'а. Не только напрямую, но даже если из него Pycharm запустить. В конце концов выяснилось, что по непонятной причине Far запускается в режиме совместимости с Windows 8.1.
Не используйте команду pull
Категорически поддерживаю. Эта команда делает две совершенно разные вещи: fetch + merge, причем с непредсказуемым результатом, not the unix way. Очень жаль, что она есть, без нее было бы меньше магии и меньше путаницы.
Советую вместо git pull делать примерно так:
git fetch
git status -sb
И после этого уже merge или rebase.
Есть потрясающая опция git config --global pull.ff only
— пулл делает только fast-forward и фейлится, если он этого не может сделать. Это избавляет от необходимости контролировать каждый fetch+merge и при этом защищает от пулла не в ту ветку.
Ну и `ff-only` будет фейлиться если над проектом работают много разработчиков и основная ветвь двигается часто.
ff-only
будет фейлиться
В этом-то и задумка. А ещё если локальные изменения не пересекаются с входящими (затронуты разные файлы, и в вашей ветке сверху нет незапушенных коммитов), то по идее такой pull должен прокатывать как fast-forward.
Этот подход успешно работает вместе с правилом: что бы ни делал (ну, за исключением коммитов на одну строчку) — создавай новую ветку. Пришла пора вмержить основную к себе или свою в основную — да пожалуйста. Надо срочно переключиться на основную не вливаясь — делаешь в текущей сверху коммит wip
в который включаешь все текущие изменения, спокойно переключаешься на основную. А когда возвращаешься, этот wip
откатываешь и продолжаешь как ни в чём не бывало.
А про fetch
, кстати, многие забывают или не знают про такую классную опцию как --prune
— вместе с выкачиванием новых веток/коммитов, она удаляет те, которые были удалены на сервере (имеются в виду remote-ветки. Ваши локальные чекауты останутся нетронутыми).
Опция pull.ff only
очень хороша, но не все про нее знают, и мало у кого она установлена. В моем конфиге она есть, но я в принципе не делаю git pull. Для таких случаев у меня есть алиас git fff
, что значит fetch fast-forward, вот кусочек моего конфига:
[alias]
s = !git status -sb
f = !git fetch origin --tags --prune && git s
ff = !git merge @{u} --ff-only && git l1 && git s
fff = !git f && git ff
Так что я бы добавил «изучи инструмент полностью». Проблема в том, что многие возможности это «о, прикольно» — но применяться не будет почти никогда. Но… представим что я программист. Что от меня требуется? Написать код, протестировать, и закоммитить. А потом вылить на удаленный сервер для тестов сервером, другими людьми. При этом голова чем занята? Почему этот баг не воспроизводится в отладчике, как сделать новую фишку максимально быстро и красиво и проверить все граничные случаи… А не о том, что я должен делать fetch (который бывает разный, смотря какие опции), потом merge… и подобное.
Это так, мысли вслух.
"wip" — аббревиатура от "work in progress", используется как плейсхолдер и на гит никак не завязано. Да, это я как-то погорячился, упомянув его без расшифровки.
В общем, гит может много. Это его и сила и слабость, большинство останавливаются на clone-pull-commit-push.
ЗЫ Про stash уже увидел чуть ниже, отвечал по мере чтения, простите.
Оставить там коммент — не смогу, ответ раз в час.
… я программист. Что от меня требуется? Написать код…
А вот это утверждение очень спорное, но повод для следующей заметки.
Надо срочно переключиться на основную не вливаясь — делаешь в текущей сверху коммит wip в который включаешь все текущие изменения, спокойно переключаешься на основную. А когда возвращаешься, этот wip откатываешь и продолжаешь как ни в чём не бывало.
git stash делает фейспалм
А вот не всё так однозначно.
Есть несколько моментов. Если пытаться работать одновременно с несколькими ветками и делать stash в нескольких, то после переключения на исходную ветку сильно задумываешься, что нужно применить вместо git stash pop
. Если стешить совсем небольшие изменения, то можно вообще не вспомнить, что делал стеш, и потом сидишь и удивляешься, почему результат не тот. А окончательно я решил для себя вопрос, когда как-то раз stash сохранил изменения только в модифицированных файлах, а те которые были untracked — безвовратно протерялись (про то, что их надо было отдельно включать через --include-untracked
я тогда не знал). Так что текущие изменения в ветке, которые в любом случае в неё попадут, проще сразу коммитить, пусть даже во временный коммит.
А вот stash удобно пользоваться для хранения хаков, которые можно применить к любой ветке и потом не жалко откатить перед "настоящим" коммитом.
я пришёл к выводу, что stash скорее мне мешает чем помогает, если у меня есть контекст к которому я хочу вернуться в ветке, при этом это не завершённая функциональность — я её просто комичу, а потом делаю ребейз и оставляю только нужное и завершённое
Вот-вот, поддерживаю.
Я помечаю такие временные бекап-коммиты крестиком, примерно так:
[x] Temp
Хотя можно использовать другие маркеры или слова. Это сделано, чтобы никто не подумал, что это настоящий коммит и не закомиттил поверх. Но все равно бывает, что кто-то это делает, в результате получается кривая история. Поэтому было бы хорошо запрещать коммиты поверх на уровне гита, т.е. оставить допустимыми только команды резет или аменд. Может уже есть что-то подобное?
Ну и да stash — это фигня, хотя бы потому что он локальный и не позволяет синхронизировать ветки между разными машинами. А если он локальный, то можно обходиться и временными коммитами.
UPD: Увидел новые сообщения. Причина использования временного коммита понятна, но всё же на вкус и цвет.
git pull --rebase
?Отвечу более развернуто.
Фундаментальное преимущество git — его распределенность: вся история есть локально, и можно полноценно работать даже когда нет сети, поэтому он такой быстрый. Сеть нужна всего в двух случаях: скачать новые коммиты с удаленного сервера (git fetch) [причем для всех веток сразу], отправить свои коммиты на удаленный сервер (git push).
С этой точки зрения команда git pull (с какими угодно опциями) — это "супер-команда", которая скачивает новые коммиты [также для всех веток сразу] и сразу же пытается автоматически интегрировать их с локальными коммитами на текущей ветке.
Для меня это две совершенно разные задачи. Отказ от этой "супер-команды" дает следующие преимущества:
- Логическое разделение двух несвязанных операций.
- Возможность увидеть и сравнить все изменения до их интеграции.
- Возможность самому решать как делать интеграцию (--no-ff, --ff-only, standard rebase, rebase-via-merge, --squash).
- Не запускать лишний раз скачивание коммитов с сервера. Именно поэтому git pull — всегда такая медленная операция, тогда как сами по себе merge и rebase быстрые, потому что им не нужна сеть.
- Есть ясное понимание того, что происходит, без каких-либо сюрпризов. Не надо полагаться на какие-то опции этой "супер-команды".
Странно, что совсем не упомянуты хуки. Инструмент, которым я пользуюсь каждый день — привычка называть ветки единообразно, типа "my_feature_PRJ-001
", где PRJ-001 — номер задачи в жире/редмайне, плюс миниатюрный скрипт commit-msg
, который номер задачи подставляет в начало сообщения коммита. Если есть интеграция с ишью трекером, очень удобно смотреть что делают другие и вспоминать, а что делал сам.
О, о, а ещё есть такая суперская вещь как git update-index --assume-unchanged <path to file>
— изменённый файл перестаёт отображаться как изменённый и соответственно нигде в гите не всплывает до тех пор, пока не приходят коммиты с этим же файлом или вы не решаете отредактировать его ещё раз. Очень помогает, если в вашем репозитории есть отслеживаемые конфиги, а вы у себя хотите держать их альтерированную версию и не хотите, чтобы они мозолили вам глаза.
Я обожаю гит и его возможности для упрощения себе жизни, простите. >_<
А вот интересно было бы послушать, на самом деле. Про "базовые" лайфхаки много пишут, а про продвинутые меньше. У гита есть ещё порох много заначек; про тот же git commit --fixup
я например только из этой статьи узнал.
Вам спасибо за поднятие интересной и полезной темы.)
Не используйте команду pull, это составная команда и делает несколько действий сразу
Какой-то крайне сомнительный совет :) Во-первых, не дофига ли чести для рутинного действия, которое почти всегда fast forward, как уже выше отметили для тех, когда это не так, есть опция в конфиге. Во-вторых,
git pull -r
Сделает то ж самое, что приведено в примере, только автоматически
Правильный совет — разберитесь уже как работает git pull и как решать проблемы, которые он создаёт)
У меня даже так: pura = pull --rebase --autostash
Но тут всё-таки надо понимать, когда нужен pull с мержем — иногда бывает.
Про isteadOf я писал когда-то заметку, настройка удобна, особенно когда работаешь с разными ремоутами
И горячо поддерживаю, то что нужно работать из консоли, т.к. есть люди, кто познакомился с git используя ide'шки, для них мысль об обычном merge панику вызывает. Т.е. консоль это то, что надо уметь, GUI лучше осваивать, когда освоил CLI.
Надо бы ещё совет «Пользуйтесь ключом -p».
Это который у git add
?
Штука полезная, но я ей не пользуюсь каждый день, может потому что люблю фиксировать комиты часто, а потом перебазировать так как мне больше нравится семантически :)
Такой подход требует большей дисциплины, чем я могу расчитывать :)
Но в нём определённо есть плюсы!
Я придерживаюсь практики — больше комитов, потом агрегация в атомарные и стабильные состояния с правильным описанием.
Дисциплину я понимаю так — думать о том что и почему ты комитишь, хотя бы так :)
Ух, вот в командной практике я стараюсь отговаривать сковшить PR, мне кажется минусы от этой практики превышают её плюсы
И тогда не очень понятно зачем заморачиваться с add -p
и подобным если потом всё в одну кучу схлопываете?
-p позволяет коммитить только то, что нужно закоммитить. А PR под фичу. В истории потом понятно, кто когда и зачем реализовывал. Неудобно только, что связь с dev ветками теряется, но по факту она редко нужна.
не очень понятен флоу, было бы интересно подискутировать по этому поводу :)
Более того, я обычно использую даже не add -i или -p, а add -e — с редактированием диффа. У него есть некоторые маргинальные ограничения (например, добавление нового файла не проходит по частям), но в >99.9% случаев помогает разделить две категории изменений, даже если они перекрылись в одной строке.
у меня такой подход не очень прижился, мне мешали переключения между ветками (теряется то что не закомичено), мешали отрыв от контекста — то что не закомичено, не существует :)
потому мой флоу скорее — атомарно комитить дебаг, чаще ребейзиться и в конце выбрасывать дебаг из истории комитов
для них мысль об обычном merge панику вызывает
Это скорее от неумения работать, чем от GUI
И потом, до сих пор не понимаю, как можно говорить про «Обзорность» и консоль в одном предложении. Пытаться построить псевдо-дерево в консоли, чтобы сымитировать возможности GUI.
¯ \ _ (ツ) _ / ¯
Его так часто используют с опциией --rebase, что в самом git можно переопределить поведение команды pull:
git config --global branch.autosetuprebase always
После выполнения этой команды все команды git pull будут интегрироваться с помощью команды git rebase, а не git merge.
Признаюсь, сам только что об этом узнал, когда полез смотреть что за ключ -r у команды pull
GitHub будет показывать вашу активность, даже если вы смените место работы.
Это разве что если вы ведете свои проекты на github. Многие же кампании поднимают свой enterprise gitlab и магической публикации активности в гитхаб не происходит.
А уж ничего разрушительнее commit --all --amend --no-edit в алиасах я представить не могу
git config --global core.editor "code --wait"
а для чего это нужно?
15 базовых советов по Git для эффективной работы каждый день