Установка git

1. Установка, настройка
2. Описание серера gogs
3. Пример совместной работы

Термины

Репозиторий / репо - хранилище или архив. В каждом вашем проекте вы можете создать своё хранилище, для всех версий ваших файлов. Хранилище очень компактно и можно быстро извлекать из него, сравнивать разные версии проекта, объединять.

Рабочий каталог / working tree / working area - корневой каталог вашего проекта, например D:\home\user\site\www\ в котором вы создали репозиторий командой git init. Рабочий каталог сохраняется в репозитории командой git commit, а восстанавливается командой git checkout.

Индекс / stage - сохранение рабочего каталога происходит в два этапа: 1) индексация git add 2) фиксация или сохранение git commit. Индекс как буфер между репо и рабочим каталогом даёт больше возможности контроля над операциями.

Коммит / commit - фиксация изменений, слепок или архив всех файлов рабочего каталога. Коммит сохраняет (архивирует) в каталоге .git\ все новые/изменённые проиндексированные файлы, для каждого файла создавая хеш SHA-1. Хеш создаётся для каждого объекта (весь коммит или отдельный файл) и используется в качестве указателя. Если файл не изменился с прошлого коммита гит не архивирует его, а просто делает ссылку на файл прошлого коммита. Это быстрее и компактнее.

Ветка / branch - именованная цепочка коммитов, основная ветка по умолчанию называется master, ответвления называем сами dev, hotfix, feature и т.п. Когда мы раньше для разработки новой фичи чтобы не замусорить проект копировали весь каталог, то с гит нужно просто создать новую ветку git checkout -b feature и можно работать, мы уже, как бы, в новом каталоге и ничего не замусорится! При чём это очень быстро, ведь фактически в этом новом каталоге/ветке гит создаёт только указатели на родителя, а реально сохранять будет здесь только изменённые файлы.

HEAD - указатель на текущий коммит в репозитории из которого было извлечено текущее содержимое рабочего каталога. Если по назанию ветки адресуется только последний коммит ветки, то с помощью HEAD можно адресовать отдельные коммиты. Если HEAD перевести с последнего коммита на другой коммит то будет состояние "detached HEAD" (оторванная голова).

master - название по умолчанию основной ветки

origin - название по умолчанию удалённого репозитория

Установка, настройка

Установить гит можно отсюда, можно оставить по умолчанию все чекпоинты, нажать далее.

После установки, для удобства можно сделать авто переход в рабочий каталог после запуска bash-консоли для этого добавьте в строки в файл: C:\Users\ВашеИмя\.bashrc

cd D:\home\user\site\www\

Если такого файла нет, создайте его.

Редактор по умолчанию

Для Notepad++ нужно добавить в C:\Users\ВашеИмя\.gitconfig в раздел [core] строку:

[core]
	editor = 'C:\\Program Files\\Notepad++\\notepad++.exe' -multiInst -notabbar -nosession -noPlugin 

Устанавливаем Мелд

Скачать Мелд по этой ссылке.

Осторожно! не устанавливайте последнюю версию (3.20), с ней были проблемы.

Рабочий гит-конфиг (C:\Users\Ваше_имя\.gitconfig ) для Мелд

[diff]
	tool = meld
[difftool "meld"]
	cmd = 'C:/Program Files (x86)/Meld/Meld.exe' \"$LOCAL\" \"$REMOTE\"
[difftool]
	prompt = false 

Исключения

Если в проекте есть общие файлы, которые не надо отслеживать и удалять при смене ветки, можно добавить эти файлы в список исключений в файл .git\info\exclude вот пример:

D:\home\user\site\www\.git\info\exclude

fonts/
*.log
*.jpg
*.png
*.svg 
*.m4s
*.mp4
*.mpd 
*.woff2
*.ttf 
*.eot 
*.dat 
*.xlsx
favicon.ico
robots.txt
*.map
PHPExcel-1.8.2/
.gitignore 

Кроме файла .git\info\exclude можно в каждом отдельном каталоге создать файл .gitignore и в него добавить исключения для этого каталога

Ветки, переключение, создание

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

git checkout <имя ветки или id коммита> 

Создать новую ветку на основе master

git checkout -b feature/new-branch master 

Взять текущие изменения (после последнего коммита) и создать из них новую ветку:

git stash
git stash branch <имя-ветки> 

Способы адресации

С помощью хеша (достаточно нескольких первых символов) можно адресовать коммиты и файлы. Команда checkout с указанием ветки, адресует последний коммит ветки. Также при помощи HEAD можно использовать относительную адресацию:

HEAD~0 (равен HEAD)
HEAD~1 предпоследний коммит (-1). сокращённо HEAD~
HEAD~2 (-2)
Коммиты указыаются c помощью символа ~ , а ветки ^, счёт с нуля
HEAD~1^1 


Посмотреть историю коммитов

Выход из git log: нажать - "q". Листать можно с помощью PgUp, PgDown.

git log 
git log --graph --all Выводит подробную историю, последние коммиты вверху
git log --oneline --graph --all Сокращённый вариант

git log -m --name-only --oneline --follow имя файла 
git log -m --name-only --oneline показывает историю включая слияния

git commit --amend - Исправления коммита, вместо создания нового 

Слияние отдельных коммитов

git cherry-pick - используется для того чтобы взять изменения, внесённые каким-либо коммитом, и попытаться применить их заново в виде нового коммита наверху текущей ветки. Это может оказаться полезным чтобы забрать парочку коммитов из другой ветки без полного слияния с той веткой. git rebase - это "автоматизированный" cherry-pick. Он выполняет ту же работу, но для цепочки коммитов, тем самым как бы перенося ветку на новое место.

Посмотреть различия

Посмотреть различия между рабочим каталогом и индексом

git diff

С помощью Мелд

git difftool 
то же, но в виде списков всех файлов/директорий
git difftool --dir-diff 

Сравнение локальных файлов (рабочего каталога) и коммита на который указывает второй параметр, если не задан второй параметр сравнивает с индексом (stage)

git difftool [коммит/ветка]
Тоже но в виде списков всех файлов/директорий
git difftool --dir-diff [коммит/ветка] 

Сравнить два выборочных коммита

git diff da758 da761 
или
git diff HEAD~1 HEAD~2 

Почему консоль, а не графический интерфейс (GUI)?

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

Мы можем создавать цепочки команд, анализировать результат завершения, например после успешного коммита автоматом опубликовать файлы на тестовом сервере.

Работа в консоли

Чтобы посмотреть предыдущую команду, можно просто нажать стрелочку вверх на клавиатуре, посмотреть историю команд:

history
Найти в истории команды содержащие ssh
history | grep ssh 

Можно выделять мышкой нужную строку и вставлять Shift+Ins. Удобно!

В файл C:\Users\ВашеИмя\.bashrc можно добавить сокращения для команд.

alias init="git init"
alias stat="git status"
alias fix="git commit -a -m $1"
Теперь для коммита достаточно набрать:
fix "Первый коммит" 

Что нельзя сделать в рамках alias, можно сделать с помощью функций. Например добавим функцию поиска строки в истории с условием что если строка не задана, выводить всю историю, добавим функцию в .bashrc

his(){ 
if [ -z "$1" ]; then 
	history;
else
	history | grep $1;
fi
} 

Теперь можно набира в консоли his [строка поиска] и получим список нужных команд

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

Про совместную работу и как лучше сделать слияние написано тут .

Смотрим какие репо у нас уже добавлены:

git remote show 

Имена получили, можно полчить ещё инфы по имени:

git remote show имя 

Если удалённые репо не были добавлены, добавляем и придумываем ему имя:

git remote add придуманное_имя ssh://git@gogs.com/project/repo.git 

Получаем в индекс объекты из указанного репозитория. Рабочий каталог при этом не изменяется, только индекс:

git fetch придуманное_имя 

Получаем объекты только из явно указанной ветки репозитория:

git fetch придуманное_имя имя_ветки 

Пример проверки изменений на удалённом репо

1) Загружаем изменения из удалённого репо в локальный индекс (Ваши файлы при этом не изменяются, только индекс)

[git remote add remRepo git://server.com/someuser/somerepo.git] если не добавлен раньше
git fetch remRepo 

2)Создаём локальную временную ветку от ветки remRepo/somebranch и переходим на неё, сравниваем с помощью Мелд текущий коммит с предыдущим

git checkout -b temp remRepo/somebranch
git difftool --dir-diff HEAD~1 

3)Возвращаемся назад, удаляем временную ветку, объединяем наш мастер с somebranch

git checkout master
git branch -D temp
git merge remRepo/somebranch 

Другой способ показывает различия текущей локального индекса и origin/master в данном случае удалённого(origin)

git whatchanged origin/master -n 1 

fetch + merge это тоже самое что и pull, только даёт больше возможности контроля.

git clone выгрузит вам весь репо, а по pull выгружается только ветка.

Полезные ссылки

Основы Git 
Подружить git и meld