Пользователь
0,0
рейтинг
19 октября 2012 в 15:34

Разработка → Git up и все все все tutorial

Git*
Комманда 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?

Делитесь полезными алиасами!
Денис Чмель @denver
карма
104,5
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (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.

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