Skip to content
andyceo edited this page Nov 21, 2023 · 22 revisions

Git

Данная страница посвящена системе управлением версиями Git

Установка Git

Начиная с Ubuntu 12.04, вы можете установить Git так:

sudo aptitude install git

Подробная статья на Github про установку Git: Set Up Git

Настройка Git

Имейте в виду, что все настройки Git сохраняет для того пользователя, из-под которого вы запускаете эти команды, т.е. из-под текущего. Допустим, если пользователь - andyceo, то вся глобальная (для данного пользователя) конфигурация будет сохраняться в файл /home/andyceo/.gitconfig

Глобальная конфигурация (которая применяется по умолчанию для всех новых пользователей на данном хосте) хранится в /etc/gitconfig.

Посмотреть, откуда читается конфигурация Git для данного репозитория: git config --list --show-origin

Подпишем GIT под определенного пользователя (запишем в настройки)

git config --global user.name "andyceo"
git config --global user.email andyceo@yandex.ru

Настройка цветного вывода

git config --global color.ui auto

Настройка других параметров

git config --global color.diff no
git config --global color.status auto
git config --global color.branch auto
git config --global core.editor vim
git config --global core.pager "vim -"

Основные команды GIT

Извлечение (клонирование) репозитория

  • Извлечь репозиторий полностью в папку (latest development version): git clone путь-к-репозиторию папка-куда-извлечь.

      git clone /home/alice/project myrepo
    
  • Извлечь последний код без извлечения всего репозитория:

      git clone --depth 1 your_repo_url
      git clone --depth 1 git://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin pma.ruware.com
    

Обновление репозитория

  • Обновить (находясь в папке репозитория): git pull

Переключение между ветками, тегами, коммитами и т.п.

  • Извлечь определенную метку: git checkout имя_метки

  • Извлечь из ветки:

          git checkout origin/MAINT_3_3_5</code>или:<code bash>
          git branch --track MAINT_3_3_5 origin/MAINT_3_3_5
          git checkout MAINT_3_3_5
    

Работа с логами

  • Выводим ASCII-репрезентацию истории коммитов: git log --graph

Отменить последний коммит

  • удаляем только коммит (изменения останутся): git reset HEAD~
  • удаляем коммит и изменения: git reset --hard HEAD~
  • делаем коммит, отменяющий другой коммит (нужно передать хеш коммита, который мы отменяем): git revert aa600
  • удаление последнего коммита, даже если он был запушен: Git HowTo: revert a commit already pushed to a remote repository

Отмена незакоммиченных изменений

  • Отменить все изменения, которые произошли с файлами, находящимися под управлением Git: bash git checkout -f
  • Удалить все изменения (удалить файлы), которые произошли с файлами, НЕ находящимися под управлением Git (папки при этом не удаляются): bash git clean -f
  • Отменить все изменения (удалить файлы и папки), которые произошли с файлами И папками, НЕ находящимися под управлением Git: bash git clean -f -d
  • Удалить только игнорируемые файлы: bash git clean -f -X
  • Удалить игнорируемые и неигнорируемые файлы (обратите внимание на различие в последнем x в этом и предыдущем примерах!): bash git clean -f -x

Работа с удаленным репозиторием

  • Создание новой ветки на сервере: ```bash # Создание удаленной ветки git push origin origin:refs/heads/new_branch

    # Проверяем, создана ли удаленная ветка
    git pull origin
    git branch -r
    
    # Создаем локальную ветку, и закрепляем ее за удаленной
    git checkout -b new_branch origin/new_branch
    ```
    
  • Удалить ветку на сервере: git push origin :heads/new_branch

  • Сделать diff между незакомиченными локальными изменениями и последним коммитом, исключая все .info файлы в репозитории (полезно для выяснения, патчено ли ядро Drupal, например): bash git diff -- `git ls-files | grep -v '.info'`

Работа с субмодулями

submodule позволяет добавлять посторонние репозитории в отдельную папку проекта. Подробности: git help submodule. Недостатки:

  1. Команда git archive игнорирует подмодули
  2. в рабочей копии после git checkout надо выполнять git submodule update –init

Добавить подмодуль в текущий репозиторий (выполнять в папке репозитория):

git submodule add -b master git@github.com:andyceo/ansible-role-letsencrypt.git roles/andyceo.letsencrypt

Затем:

git submodule init

Скачаем подмодуль:

git submodule update

Обновим все подмодули:

git submodule foreach "(git checkout master; git pull; cd ..; git add '$path'; git commit -m 'Submodule Sync')"

Посмотреть все подмодули в репозитории можно несколькими способами:

  • cat .gitmodules - этот файл читает команда git submodule init
  • git submodule status - показать список и статус всех субмодулей в репозитории
  • git submodule status --recursive - то же самое, но рекурсивно. Упадет с ошибкой, если какой-то подмодуль не был извлечен

Удалить субмодуль:

git rm <path-to-submodule>

и закоммитить. Однако некоторые настройки субмодуля не удаляются из подпапки .git. Убрать их можно командами:

rm -rf .git/modules/<path-to-submodule>
git config --remove-section submodule.<path-to-submodule>

Обновить заданный субмодуль с перезаписью всех изменений внутри:

git submodule update --init --force --remote <module-name>

Работа с несколькими удаленными серверами (git remote) в одном репозитории

Добавим новый удаленный сервер и отправим туда все ветки, коммиты и теги:

git remote add ANOTHER_REMOTE ssh://git@NEW.REMOTE.COM:10022/user/project.git
git push ANOTHER_REMOTE --all
git push ANOTHER_REMOTE --tags

Не использовать опцию --mirror, а то она переподключит все локальные ветки к новому репозиторию.

А также можно сделать через опцию --mirror:

git clone --mirror <URL to my OLD repo location>
cd <New directory where your OLD repo was cloned>
git remote set-url origin <URL to my NEW repo location>
git push --mirror origin

Основные команды GIT - продолжение

  • git init: новый репозиторий
  • git status: состояние: что было редактировано, что добавлено в индекс для коммита
  • git add .: добавить в индекс все изменения. git add file.txt - добавить содержимое файла в индекс git add -i - интерактивное добавление, позволяет выбирать файлы, которые надо добавить. Для каждого файоа можно добавить некоторые изменения, другие оставить для следующего коммита. git add -p - про каждое изменение в файле спрашивает, добавить его в индекс или нет -p==patch
  • git commit -m «Initial commit»: сделать первый commit (некоторые команды криво работают, пока не сделать первый коммит)
  • git commit -am «comment»: add + commit, но новые файлы не будут добавлены
  • git commit –amend - докоммитить предыдущий коммит. если что еще надо в него добавить или изменить текст коммита: git commit –amend -m «new comment» git commit –amend -C HEAD - не менять текст коммита. Вместо HEAD может быть любая ссылка на коммит, например: - HEAD - последний коммит текущей ветки - sha1_hash коммита - имя ветки - имя_ветки2 - два коммита назад от HEAD'a ветки - тег - HEAD^2 - два коммита назад от HEAD - HEAD1 - тоже два коммита назад от HEAD
  • git log: логи коммитов
  • git log –all: лог со всех веток
  • git log –graph –all –oneline: все ветки, показать связь между ветками. информация об одном коммите должна влезать на одну строку
  • git log -p - патчи
  • git shortlog -sne -- - показать статистику в текущем репозитории. Можно указать папку, для которой соберется статистика: git shortlog -sne -- folder
  • git branch: список веток
  • git branch newfeature: создать ветку newfeature
  • git checkout newfeature или тоже самое одной командой: git checkout -b newfeature …редактирование (программирование фичи)
  • git commit -am «new feature done»: ее commit
  • git checkout master: переход в ветку master
  • git merge newfeature: объединение ветки newfeature с master теперь в master работает новая фича. Если при слиянии возникли конфликты, то посмотреть на них можно:
  • git status edit Press.pm: поправить git add Press.pm git commit - завершает процесс слияния Если надоело разрешать конфликты, то можно вернуть обе ветки в исходное состояние: git reset –hard HEAD А если commit завершен, то вернуть обратно можно так: git reset –hard ORIG_HEAD
  • git checkout -f: откатить незакоммиченные изменения
  • git checkout – file.txt: вынимает версию файла, подготовленную к коммиту (после git add file.txt)
  • git checkout <commit> file.txt: из указанного коммита
  • git tag v4.2: простой тег
  • git tag -a v4.2 -m «stable v4.2»: аннотированный тег (более подробный, вроде commit'a)
  • git tag -d v4.2: удалить тег
  • git tag - список тегов
  • git tag -l <pattern>: поиск по шаблону
  • git log v4.2: показать все коммиты, начиная с тега v4.2
  • git log v4.2 Press.pm - все коммиты, начиная с тега v4.2, включающие изменения файла Press.pm
  • git branch –contains v4.2: ветки с данным тегом
  • git show v4.2: на какой commit указывает тег, когда и кем был сделан
  • git describe: показывает сколько коммитов было с последнего тега: v4.2-g[хэш последнего коммита]
  • git reset: undo
  • git reset –hard <commit>: отменить самым радикальным и не поправимым образом все, что было сделано и закоммичено после коммита . Рабочая папка тоже будет содержать проект из этого коммита.
  • git reset –soft <commit> - делает последним коммитом (HEAD'ом). Рабочая папка остается не тронутой.

git giu - оконный интерфейс в windows gitk - оконный интерфейс в linux gitk –all - все ветки

git update-index - обновить индекс содержимого файлов git update-index –add - добавлять файлы с диска git update-index –remove - удалять файлы, если их нет на диске

git diff - все изменения от последнего commit'a git diff file.txt - изменения в одном файле git diff –cached - сравнение последнего commit'a и того, что подготовлено для нового коммита git diff - сравнение commit'a и рабочей папки, например git diff HEAD^2 file.txt git diff –stat sha1old..sha2new - список файлов и количество измененных строк между двумя коммитами Сравнение двух веток: git diff master..newfeature - сравнение двух последних коммитов веток git diff master…newfeature - показывает разницу между последним коммитом в newfeature и его последнего предка в master. Полезно, если ветка newfeature была объединена с master, а потом в ней еще что-то изменилось. Тогда эта команда покажет разницу с последнего merga.

git blame file.txt - кто и когда редактировал файл

Временные коммиты git stash - сделать временный коммит рабочей папки … поправить что-нибудь в другой ветке, переключиться обратно и git stash apply - вернуть рабочую папку обратно. git status list - выводит список стешей, их может быть много, например:

git stash save «comment» git stash apply stash@{1} - где stash@{1} - нужный стеш из git status list

Файл .gitignore - список шаблонов файлов, история по которым не ведется. То есть файлы, которые не попадают в репозиторий Например: #пароли к бд MyConfig.pm #temp files: .~ #все логи, кроме ошибок *.log !error.log

Или можно запретить все, кроме избранных файлов: . !.pl !.pm

Удаленные repo: git branch -a - список веток, включая удаленные (т.е. с исходного репозитория) git remote add remoteName remoteURL - добавить удаленную ветку. Все удаленные репозитории показываются в файле .git/config [remote «origin»] fetch = +refs/heads/:refs/remotes/origin/ - связи между ветками url = http://sn:@192.168.0.2/project/projectname.git

Забрать изменения с удаленного компьютера можно двумя способами: 1) git fetch origin master - забирает с удаленного компьютера изменения в ветке master git diff master..origin/master - посмотреть, что изменилось git checkout -b testbranch и git merge origin/master - объединить изменения с удаленного компьютера с веткой master …протестировать git checkout master git merge testbranch 2) все это одной командой (если не надо тестировать): git pull origin master

git push origin master - пихает изменения из текущей ветки в origin master. Желательно делать push только в bare репозитории, т.к. команда push портит содержимое рабочей папки.

git rebase master - на master накладывается текущая ветка (сначала будут идти все коммиты master, потом все коммиты текущей ветки). Если просто объединить, то коммиты будут перемешаны и получится не красиво. если возникли конфликты, их надо разрешить и запустить git rebase –continue Если надоест: git rebase –abort - отменить все git rebase –skip - пропустить один коммит

git rebase -i HEAD~10 - почистить историю последних 10 коммитов в текстовом редакторе (из переменной окружения EDITOR) откроется список коммитов в формате: pick hash message Чтобы удалить коммит - удалить строку, Поменять порядок коммитов - поменять порядок строк объединить коммит с предыдущим - pick поменять на squash для внесения изменений в коммит - pick на edit После этого, если отметили коммиты, то git commit –ament если нет, то git commit –continue Подробности в git help rebase

git filter-branch –tree-filter 'rm cgi-bin/MyConfig.pm' HEAD Удалить файлы из всех коммитов подробности в git help filter-branch

поиск коммита, в котором возникла ошибка: git bisect start git bisect bad sha1_bad_commit git bisect good sha1_good_commit git извлечет состояние по середине между хорошей и плохой версиями. Если в этом состоянии по прежнему есть ошибка: git bisect bad Если работает, то git bisect good После окончания изменения надо выполнить git bisect reset Можно автоматизировать процесс тестирования командой: git bisect run «perl testrun.pl» Скрипт testrun.pl должен возвращать 0, если все хорошо.

импорт-экспорт истории: git fast-import </tmp/history git fast-export >/tmp/history

subtree История коммитов из внешнего проекта перенаправляется в подпапку с использованием стандартного механизма работы с внешними ветками. git remote add -f creocms /path/to/creocms git merge -s ours –no-commit creocms/master git read-tree –prefix=creocms/ -u creocms/master git commit -m «Merge creocms» Изменения из creocms вытягиваются командой: git pull -s subtree creocms master В каждой рабочей копии надо выполнять git remote add -f creocmms /path/to/creocms И в каждой новой ветке: git fetch creocms

Источник: http://wiki.hasanov.ru/web-dev/git-help Также можно посмотреть: http://help.github.com/git-cheat-sheets/

Работа с Bitbucket & Github сервисами и форки

Предполагается, что вы уже форкнули какой-либо репозиторий на Bitbucket или Github, через веб-интерфейс.

Создание upstream-ветки

  • Создаем связь с upstream-репозиторием:

      git remote add upstream git@bitbucket.org:USER_LOGIN/UPSTREAM_REPO_NAME.git
    
  • Скачиваем данные из upstream-репозитория:

      git fetch upstream
    
  • Создаем локальную ветку upstream, которая будет связана с веткой master upstream-репозитория и сразу переключимся на нее:

      git checkout -b upstream upstream/master
    

Разрешение конфликтов форка с основным репозиторием

Предполагается, что вы ведете работу в ветке master, и у вас есть ветка upstream (см. Создание upstream-ветки)

# Обновим upstream до актуального состояния
git checkout upstream
git pull

# Сольем свой master с upstream
git checkout master
git merge upstream

# смотрим и решаем конфликты
git status
<<<Разрешить конфликт в редакторе, например PHPStorm>>>

# заканчиваем слияние
git add FILE_WITH_RESOLVED_CONFLICT
git commit
git push

Работа с Git при подготовке Pull Request для Bitbucket без истории коммитов

Предположим, вы всю работу делали в своей ветке master, а для подготовки пулл реквеста намерены создать ветку clean_code.

Также, мы исходим из предположения, что вы настроили себе локальную ветку upstream, которая синхронизирована с master-веткой upstream-репозитория (репозитория, который вы форкнули) (см. Создание upstream-ветки).

  1. Перед подготовкой пулл-реквеста, синхронизируйте ваш репозиторий с основным, разрешите все конфликты (если есть).

  2. Выполните следующее:

     git checkout master
     git pull
    
     git checkout -b clean_code upstream
    
     # удостоверьтесь, что изменения именно те, которые вы хотите отослать
     git diff clean_code..master
    
     git merge --squash master
     git commit
    
     git push -u origin clean_code
    
  3. В веб-интерфейсе Bitbucket (или Github) делаете пулл реквест из вашей ветки clean_code в основной репозиторий, ветку master

  4. Дальнейшую работу над замечаниями к данному пулл реквесту, производите в ветке clean_code. В зависимости от того, насколько много будет сделано изменений и насколько они будут большими, ответственный за принятие пулл реквеста попросит создать новый пулл реквест с чистой историей коммитов (по той же процедуре из пункта 2), либо примет ваш пулл реквест с историей из ветки clean_code.

  5. После принятия пулл реквеста:

    • ветку clean_code удалить, как локально, так и удаленно:

      git branch -D clean_code
      git push origin --delete clean_code
      
    • синхронизируйте ваш репозиторий с основным

Порядок работы над задачей (для разработчика)

Исходные данные: у вас должна быть настроена локальная копия для разработки, исходные коды проекта управляются Git, репозиторий лежит на Bitbucket. Для справки по Git-командам для подготовки Pull Request см. Работа с Git при подготовке Pull Request для Bitbucket без истории коммитов

  1. Взять задачу в работу (о чем в ней написать комментарий)
  2. [опционально] Создать в своем форкнутом репозитории ветку отдельно под задачу
  3. Как только достигнуто состояние кода, готовое к объединению с основным репозиторием, нужно создать Pull Request. Этот сценарий хорошо описан в документации Bitbucket: Fork a Repo, Compare Code, and Create a Pull Request. Перед созданием Pull Request необходимо провести подготовительные действия:
    1. Синхронизировать свой форкнутый репозиторий с основным. Если возникли конфликты, разрешить их в своем репозитории. См. Разрешение конфликтов форка с основным репозиторием
    2. Обновить Drupal 8, и если возникла такая необходимость после обновления, переустановить проект.
    3. Проверить работоспособность своего кода на актуальной версии Drupal 8 и основного (форкнутого) репозитория.
  4. Ответственным за принятие кода в основной репозиторий, проводится проверка вашей работы (вашего Pull Request) и оставляются комментарии о том, что нужно исправить. В случае фатальных ошибок, Pull request отклоняется насовсем (Decline). В случае, если по мнению проверяющего, Pull Request готов к вливанию в основной репозиторий, он принимается (Merge).
  5. В случае, если ваш Pull Request остался непринятым, и в нем присутствуют комментарии о том, что нужно исправить, то нужно исправить код и обновить Pull Request.
  6. Пункты 3-5 повторяются, пока ваш Pull Request не будет принят или отклонен.
  7. В случае принятия Pull Request, нужно прокомментировать задачу, в рамках которой он был сделан. В комментарии нужно:
    • оставить ссылку на Pull Request
    • кратко написать, что было сделано
    • написать, что осталось сделать, чтобы закрыть задачу. Если задача сделана полностью в рамках этого Pull Request, то написать, что задачу можно закрыть.
    • закрыть задачу (статус Resolved)

Git под Windows

Установка и настройка Git в Windows

  1. Скачать дистрибутив Git для Windows: https://git-scm.com/download/win

  2. Сгенерировать SSH-ключ: https://help.github.com/articles/generating-ssh-keys/#platform-windows

  3. В Git Bash, запустиь ssh-agent:

     eval `ssh-agent -s`
    
  4. Добавить ключ в ssh-agent:

     ssh-add ~/.ssh/id_rsa
    
  5. Скопировать ключ на все машины, куда с этой виндовой машины планируется заходить:

     ssh-copy-id your_login_on_example_com@example.com
    
  6. По необходимости, настроить ~/.ssh/config:

     Host example
     Hostname example.com
     User your_login_on_example_com
    
  7. После этого, можно будет логиниться на сервера: ssh example. Также, PhpStorm под виндой сможет выкачивать проекты, соединяясь по sftp по ключу.

Под Windows трудно проставить кооректные права на выполнение файлу. Обходной путь:

git update-index --chmod=+x foo.sh

Файл должен быть в индексе Git, поэтому, если файла там еще нет, добавьте:

git add foo.sh

Полезные ссылки про установку Git в Windows

Установка TorotoiseGIT под Windows XP

Разное

Сервисы наподобие Github, Bitbucket:

Дополнительная информация на русском

Sidebar is under construction

Clone this wiki locally