Git up и все все все

  • Tutorial
Комманда git up (аналог svn up) добавляется так:
git config --global alias.up '!(git add . && git stash && git pull --rebase >&2) | grep -v "No local changes to save" && git stash pop'

git up при надобности ныкает все ещё незакоммиченные изменения в stash, обновляет локальную ветку до свежайшей и восстанавливает локальные изменения назад. В том числе переносит ещё неотправленные локальные коммиты в самый конец, делая историю линейной как в Subversion, т.е. избегая лишних веток и merge-коммитов.

Если всё прошло гладко (без конфликтов) можно сразу же делать git push. В редких случаях конфликтов (вы и кто-то меняли одну и ту же строку) rebase остановится и далее, конечно, придется разбираться самому и завершать апдейт с помощью git rebase --continue сколько нужно раз и git stash apply чтобы вернуть заныканные изменения.

Есть много аналогов, но в большинстве своем это нелаконичные скрипты. Алиас легко добавить на любом сервере вместе с другими просто вставив в консоль всё это:

# git up
git config --global alias.up '!(git add . && git stash && git pull --rebase >&2) | grep -v "No local changes to save" && git stash pop'

# git in / git out — смотреть какие коммиты придут/уйдут перед выполнением pull/push
git config --global alias.in '!git remote update -p; git log ..@{u}'
git config --global alias.out 'log @{u}..'

# git addremove - добавить в индекс новые файлы/изменения и удалить всё что удалилось
git config --global alias.addremove \!"git add . && git ls-files --deleted | xargs --no-run-if-empty git rm"

# git unstage - убрать всё из индекса (чтобы например добавить/закоммитить сначала что-то другое)
git config --global alias.unstage "reset HEAD --"

# git backup - заархивировать весь локальный репозиторий перед экспериментированием
git config --global alias.backup \!'file=../`git describe`.tar && echo "Creating `readlink -f $file`" && tar cf $file .'

# Просто удобные сокращения
git config --global alias.st "status -sb"
git config --global alias.ci commit
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.bra "branch -a"
git config --global alias.chp cherry-pick
git config --global alias.pr "pull --rebase"
git config --global alias.bl "blame -b -w"
git config --global alias.cia "commit --amend"
git config --global alias.lg "log --pretty=format:'%h was %an, %ar, message: %s' --graph"
git config --global alias.who "shortlog -s --"

# what else?

Делитесь полезными алиасами!
Поделиться публикацией
Похожие публикации
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 64
  • –10
    git up при надобности ныкает все ещё незакоммиченные изменения в stash
    «Спасибо, всё очень понятно.»
    В смысле, тем, кто глубоко в теме — понятно, но даже и им приятнее было бы читать более опрятный русский текст. А код — кто в курсе, тому понятно, остальные просто остерегутся применять.
    • +19
      Да вроде все понятно, и очень полезно. Спасибо автору.
    • +2
      А разве обязательно делать add перед stash?
      • 0
        По идее, можно заюзать -u.
        • 0
          Ага, но -u появился только с версии 1.7.7, так что на всякий случай не использую.
      • +2
        Это скорее не в туториал, в tips&tricks;)
        • 0
          Еще хотел узнать как вы делаете deployment, по help.github.com/articles/deploying-with-capistrano принципу?
          • 0
            Блин, не туда :(
            • 0
              Нет, делаем по своему в силу специфики софта и его распространения.
            • +2
              Ещё зачем делать rebase когда у нас чистенько всё и будет, по идее fastforward?
              • +2
                А если локальные коммиты были?
                • 0
                  merge.
                  • +2
                    Merge будет делать лишние merge коммиты и историю нелинейной. Это неудобно если нужно просто получить новые коммиты (не пушать свои еще). Ну и неприятно видеть лишние коммиты в истории (неудобно в случае поиска плохого коммита).
                    • –5
                      окей. а объективные аргументы имеются?
                      • +3
                        Объективный аргумент, если вы не сделаете push, а через некоторое время запустите опять git up. И в истории образуется несколько merge commit, что сложно для отката, переноса и review
                        • +11
                          В большинстве команд в которых я работал, тоже всегда делают merge с локальными изменениями, история выглядит ужасающе, особенно когда работают более 3 человек.
                          Вообще в конфиге есть опции для того чтобы rebase делался по дефолту.
                          За то что я бью линейкой по рукам за таки merge commits меня прозвали gitлером =/
                          image
                          • 0
                            Зато понятно, что из какой ветки прилетело.
                            • 0
                              история выглядит ужасающе
                              ужасающе
                              это вы сами себе запретили считать историю с merge красивой, вот и всё.
                              • +3
                                Такую историю и правда неудобно читать. Более того, информация о таких мержах — сплошной шум, ничего полезного.
                                • 0
                                  Когда каждая фича в своей ветке, очень даже полезно.
                                  • +6
                                    Ни что вам не мешает делать отдельную ветку для каждой фичи и держать историю изменений «чистой».

                                    Так на самом деле и должно быть:
                                    1. новая фича — новая ветка.
                                    2. фича готова, делаем pull ветки куда будем мержить, пусть будет master
                                    3. делаем rebase фича_ветки относительно master
                                    4. делает мерж фича_ветки в master.
                                    • +3
                                      Причем здесь фича-ветки?
                                • +4
                                  У обоих подходов есть свои объективные плюсы и минусы. Выбрав один, не обязательно категорично считать другой полным ужасом.
                          • 0
                            Да, верно.
                          • 0
                            Вот мне интересно, если fastforward + merge + еще один дополнительный комит для вас это «чистенько», что же для вас тогда НЕ чистенько?
                          • 0
                            addremove — это случем не то же самое, что «git add -A»?
                            • 0
                              Думаю, да. Спасибо :)
                            • 0
                              Я ещё некоторое количество алиасов в баше для гита делаю:
                              #### file ~/.profile
                              
                              alias gpull="git pull origin" # usage: gpull master
                              alias gpush="git push origin" # usage: gpush master
                              
                              function gitcb() # getting git current branch
                              {
                              	git status 2>/dev/null | head -1 | cut -d ' ' -f 4
                              }
                              
                              alias gpullcb="gpull $(gitcb)"
                              alias gpushcb="gpush $(gitcb)"
                              


                              Для быстрого пулла и пуша.
                              • +1
                                git branch -u origin/foo foo

                                После этого git push/pull из локальной ветки foo будет эквивалентен git push/pull origin foo.

                                Аналогичный эффект будет если один раз сделать пуш таким образом:

                                git push -u origin foo
                                • 0
                                  Для частого переключения веток это не пойдёт, придётся каждый раз при переключении это вызывать.
                                  Или я недокурил мануалы?
                                  • 0
                                    Для каждой ветки достатчно вызвать это по одному разу.
                                    Т.е. если мы сделали

                                    git branch -u origin/foo foo
                                    git branch -u origin/bar bar
                                    


                                    То как бы мы не переключались между ветками в последствии pull/push из локальной ветки foo будет работать c origin/foo, а из ветки bar — c origin/bar
                                    • 0
                                      Это да, но ветки ведь и создаются часто.
                                      И, кроме того, это надо проделывать для всех проектов, что тоже не очень удобно.

                                      А так — запомнил «gpushcb» — и всё! Ещё функция gitcb иногда может в скриптах пригодиться.
                                • +1
                                  Тоже решил поделиться :)
                                  https://github.com/Microfed/Git-bash-alisases
                                • НЛО прилетело и опубликовало эту надпись здесь
                                  • +1
                                    Раз уж пошла такая пьянка, то грех не поделиться своими шоткатами (+ несколькими взятыми из oh-my-zsh): gist.github.com/3430432
                                    • +1
                                      Небольшой хинт к вашей функции gitcb, если позволите:

                                      $ git symbolic-ref -q HEAD | sed s:refs/heads/::
                                      • 0
                                        Спасибо, работает как надо! =)
                                    • +5
                                      Может не в тему. а в чем проблема с неленейностью истории?
                                      • +3
                                        Да вообще проблемы с ней нет, да и rebase штука потенциально опасная при мёрже в обе стороны. Но идея со stash-pull занятная.
                                        • +2
                                          идея со stash-pull занятная
                                          более того, в IDEA (и производных IDE) используется на полную катушку (см. т.н. «Smart Checkout»)
                                        • +4
                                          Ничего особенного, но сложно понять кто после кого что сделал (когда git log --graph показывает мешанину), сложно оттрекать кто когда добавил проблему (надоест делать git blame HEAD~1^2~4), неудобно ревьювить код (кроме того кто-то может поменять что-то лишнее в merge коммите). Да и просто некрасиво, мусорно.

                                          Rebase же штука опасная, но когда: 1) если меняешь уже пушнутые коммиты (табу, и здесь такое не делается), и 2) при конфликтном ребэйсе не создастся мердж коммит, а изменятся оригинальные. Согласен — перемерджить изменения уже не выйдет. Но это проблема если ребэйс делается очень редко, если делать часто — много не поломаешь (в том числе и вероятность конфликта маленькая).
                                          • +1
                                            А если вдруг еще по каким либо причинам понадобится перенести все патчи, один за одним на новое дерево. То то будет веселья, если история с кучами мержей…

                                            p.s. почему то когда такое случается, любители «мержей», куда то пропадают…
                                        • +1
                                          git config --global alias.in
                                          git request-pull
                                          git backup
                                          чем-то не подходит reflog или bundle?
                                          git up
                                          да не может быть, чтобы кому-то мешало требование убрать незакоммиченные изменения перед pull.
                                          • +4
                                            Часто использую сокращение dc для «diff --cached», чтобы убедиться, что сейчас буду коммитить именно то, что планировал.

                                            И ещё сотрудник как-то поделился длинной строчкой, которую я теперь таскаю между всеми компами, где требуется работать с гитом (привожу не командой, а строкой из файла gitconfig):
                                            gr = "log --all --graph --pretty=format:'%Cred%h%Creset%x09%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative"

                                            Позволяет просматривать дерево коммитов в очень удобном виде.
                                            • +3
                                              У меня подобная строчка, только цветовая схема помягче и элементы расположены иначе:

                                              alias gha='git log --graph --date=relative --all --topo-order --pretty=format:'\''%C(cyan)[%an]%Creset %C(green bold)%d%Creset %C(yellow)%h%Creset : %s %C(cyan)[%ad]%Creset'\'''
                                              


                                            • 0
                                              Алиас легко добавить на любом сервере

                                              Не очень понятно зачем такой алиас нужен на сервере. Вы прямо на серверах разрабатываете что ли?
                                              • 0
                                                Хм… ну да. С гитом часто работаю в консоли на серверах — общий dev-сервер (среда близко к продакшн), свой локальный (побыстрее), CI сервер, домашний. Да, на продакшне именно git up не пригодится :)
                                              • +3
                                                git branch -u? Что это?

                                                git-scm.com/docs/git-branch — тут нету
                                                • +1
                                                  Могу предположить, что это git branch --set-upstream.
                                                  А данная ошибка(описка) могла возникнуть из-за того, что в git push [-u | --set-upstream].
                                                • +4
                                                  Сначала переходим на гит, потом делаем, чтобы все было как в старом-добром svn ^___^
                                                  На мой взгляд эта статья еще раз подтверждает тезис о быстрорастущей популярности IT и необходимости адаптации инфраструктуры к требованиям новичков. ИТ уже не торт.
                                                  • +3
                                                    сначала переходим на git, затем пытаемся сделать из него mercurial
                                                    fixed
                                                    • 0
                                                      В каком смысле не торт? Вы имеете ввиду, что слишком много людей вертится во всём это хозяйстве, а не избранные, многим это всё уже не кажется магией? И поэтому уже не торт? :)
                                                      • 0
                                                        Ну да. Раньше избранных на руках носили, а сейчас приходится работать :)
                                                    • 0
                                                      есть такая штука: ZSH и к ней есть такая: oh-my-zsh github.com/robbyrussell/oh-my-zsh
                                                      и там есть плагин для git. Посмотрите, очень удобно!

                                                      gl = git pull
                                                      gp = git push
                                                      ga=git add
                                                      gm=git merge

                                                      но это я просто детский пример привёл, лучше посмотрите сами!
                                                      github.com/robbyrussell/oh-my-zsh/blob/master/plugins/git/git.plugin.zsh
                                                      • 0
                                                        Вброшу свои 5 копеек (файл ~/.gitconfig)
                                                        [alias]
                                                                co = checkout
                                                                ci = commit
                                                                st = status
                                                                br = branch
                                                                di = diff --color
                                                                hist = log --pretty=format:\"%h %ad | %s%d [%an]\" --graph --date=short
                                                                llog = log --all --graph --decorate=full --date-order --color
                                                                
                                                        
                                                        • +2
                                                          Моё:

                                                          st = status
                                                          ci = commit
                                                          ca = commit --amend
                                                          co = checkout
                                                          chp = cherry-pick

                                                          ri = rebase -i
                                                          ri2 = rebase -i HEAD~2
                                                          ri3 = rebase -i HEAD~3
                                                          ri4 = rebase -i HEAD~4

                                                          sc = svn dcommit
                                                          sf = show --pretty=«format:» --name-only
                                                          sr = svn rebase

                                                          Уже не помню моё или собрано где-то:

                                                          d = diff -C
                                                          ds = diff -C --stat
                                                          dsp = diff -C --stat -p
                                                          dw = diff -C --color-words
                                                          dp = diff --patch -U --no-prefix

                                                          l = log -C --decorate
                                                          ls = log -C --stat --decorate
                                                          lsp = log -C --stat -p --decorate
                                                          lg = log --graph '--pretty=tformat:%Cblue%h%Creset %Cgreen%ar%Creset %Cblue%d%Creset %s'
                                                          lga = log --graph '--pretty=tformat:%Cblue%h%Creset %Cgreen%ar%Creset %Cblue%d%Creset %s' --all
                                                          l19 = log --graph '--pretty=tformat:%Cblue%h%Creset %Cgreen%ar%Creset %Cblue%d%Creset %s' --all -19
                                                          # для сложных ветвлений
                                                          lsd = log --graph '--pretty=tformat:%Cblue%h%Creset %Cgreen%ar%Creset %Cblue%d%Creset %s' --all --simplify-by-decoration
                                                          ru = remote update
                                                          sb = show-branch --sha1-name
                                                          ls-del = ls-files -d
                                                          ls-mod = ls-files -m # включая удалённые файлы
                                                          ls-new = ls-files --exclude-standard -o
                                                          ls-ign = ls-files --exclude-standard -o -i
                                                          ka = !gitk --all
                                                          kdo = !gitk --date-order
                                                          kado = !gitk --all --date-order
                                                          kasd = !gitk --all --simplify-by-decoration
                                                          • +1
                                                            # для сложных ветвлений
                                                            lsd =…

                                                            Ну, название говорит само за себя ;)
                                                          • +2
                                                            Забавы ради:

                                                            fix = "!am() { curl -s http://whatthecommit.com/ | grep '<p>' | cut -c4-; }; git commit -em \"# $(am)\" \"$@\""
                                                            • +1
                                                              Кстати, IntelliJ и другие IDE от JetBrains уже давно это умеют делать: Update Project (pull from tracked branch), Checkout и Merge.
                                                              • 0
                                                                id = log -1 --format='commit %C(green)%h%C(white) by %C(yellow)%an%C(white), %ar (%ad)%n%n%B'
                                                                • НЛО прилетело и опубликовало эту надпись здесь
                                                                  • 0
                                                                    В какой версии git?
                                                                  • 0
                                                                    Похожий алиас (вернее скрипт) входит в состав git-friendly.

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