└── readme.md /readme.md: -------------------------------------------------------------------------------- 1 | # Шпаргалка по консольным командам Git 2 | 3 | ### Добавляйте свои команды и остальные полезности через `Pull request`. 4 | 5 | 9 | 10 | 11 | 12 | ## Общее 13 | 14 | Git — система контроля версий (файлов). Что-то вроде возможности сохраняться в компьютерных играх (в Git эквивалент игрового сохранения — коммит). **Важно**: добавление файлов к «сохранению» двухступенчатое: сначала добавляем файл в индекс (`git add`), потом «сохраняем» (`git commit`). 15 | 16 | Любой файл в директории существующего репозитория может находиться или не находиться под версионным контролем (отслеживаемые и неотслеживаемые). 17 | 18 | Отслеживаемые файлы могут быть в 3-х состояниях: неизменённые, изменённые, проиндексированные (готовые к коммиту). 19 | 20 | ### Ключ к пониманию 21 | 22 | Ключ к пониманию концепции git — знание о «трех деревьях»: 23 | 24 | - Рабочая директория — файловая система проекта (те файлы, с которыми вы работаете). 25 | - Индекс — список отслеживаемых git-ом файлов и директорий, промежуточное хранилище изменений (редактирование, удаление отслеживаемых файлов). 26 | - Директория `.git/` — все данные контроля версий этого проекта (вся история разработки: коммиты, ветки, теги и пр.). 27 | 28 | Коммит — «сохранение» (хранит набор изменений, сделанный в рабочей директории с момента предыдущего коммита). Коммит неизменен, его нельзя отредактировать. 29 | 30 | У всех коммитов (кроме самого первого) есть один или более родительских коммитов, поскольку коммиты хранят изменения от предыдущих состояний. 31 | 32 | ### Простейший цикл работ 33 | 34 | - Редактирование, добавление, удаление файлов (собственно, работа). 35 | - Индексация/добавление файлов в индекс (указание для git какие изменения нужно будет закоммитить). 36 | - Коммит (фиксация изменений). 37 | - Возврат к шагу 1 или отход ко сну. 38 | 39 | ### Указатели 40 | 41 | - `HEAD` — указатель на текущий коммит или на текущую ветку (то есть, в любом случае, на коммит). Указывает на родителя коммита, который будет создан следующим. 42 | - `ORIG_HEAD` — указатель на коммит, с которого вы только что переместили `HEAD` (командой `git reset ...`, например). 43 | - Ветка (`master`, `develop` etc.) — указатель на коммит. При добавлении коммита, указатель ветки перемещается с родительского коммита на новый. 44 | - Теги — простые указатели на коммиты. Не перемещаются. 45 | 46 | 47 | 48 | ### Настройки 49 | 50 | Перед началом работы нужно выполнить некоторые настройки: 51 | 52 | ``` 53 | git config --global user.name "Your Name" # указать имя, которым будут подписаны коммиты 54 | git config --global user.email "e@w.com" # указать электропочту, которая будет в описании коммитера 55 | ``` 56 | 57 | Если вы в Windows: 58 | 59 | ``` 60 | git config --global core.autocrlf true # включить преобразование окончаний строк из CRLF в LF 61 | ``` 62 | 63 | 64 | ### Указание неотслеживаемых файлов 65 | 66 | Файлы и директории, которые не нужно включать в репозиторий, указываются в файле `.gitignore`. Обычно это устанавливаемые зависимости (`node_modules/`, `bower_components/`), готовая сборка `build/` или `dist/` и подобные, создаваемые при установке или запуске. Каждый файл или директория указываются с новой строки, [возможно использование шаблонов](http://git-scm.com/book/ru/v2/%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D1%8B-Git-%D0%97%D0%B0%D0%BF%D0%B8%D1%81%D1%8C-%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D0%B9-%D0%B2-%D1%80%D0%B5%D0%BF%D0%BE%D0%B7%D0%B8%D1%82%D0%BE%D1%80%D0%B8%D0%B9#Игнорирование-файлов). 67 | 68 | 69 | ### Консоль 70 | 71 | [Как использовать консоль Bash в Windows, основные команды](https://github.com/cyberspacedk/BASH-Commands). 72 | 73 | 74 | ### Длинный вывод в консоли: Vim 75 | 76 | Вызов некоторых консольных команд приводит к необходимости очень длинного вывода в консоль (пример: вывод истории всех изменений в файле командой `git log -p fileName.txt`). При этом прямо в консоли запускается редактор [Vim](https://ru.wikipedia.org/wiki/Vim). Он работает в нескольких режимах, из которых Вас заинтересуют режим вставки (редактирование текста) и нормальный (командный) режим. Чтобы попасть из Vim обратно в консоль, нужно в командном режиме ввести :q. Переход в командный режим из любого другого: Esc. 77 | 78 | Если нужно что-то написать, нажмите i — это переход в режим вставки текста. Если нужно сохранить изменения, перейдите в командный режим и наберите :w. 79 | 80 | # Vim (некоторые команды) 81 | 82 | ```bash 83 | # Нажатия кнопок 84 | ESC — переход в командный режим 85 | i — переход в режим редактирования текста 86 | ZQ (зажат Shift, поочередное нажатие) — выход без сохранения 87 | ZZ (зажат Shift, поочередное нажатие) — сохранить и выйти 88 | ```bash 89 | # Нажатия кнопок 90 | ESC — переход в командный режим 91 | i — переход в режим редактирования текста 92 | ZQ (зажат Shift, поочередное нажатие) — выход без сохранения 93 | ZZ (зажат Shift, поочередное нажатие) — сохранить и выйти 94 | 95 | # Ввод в командном режиме 96 | :q! — выйти без сохранения 97 | :wq — сохранить файл и выйти 98 | :w filename.txt — сохранить файл как filename.txt 99 | 100 | ``` 101 | 102 | 103 | ## Консольные команды 104 | 105 | ### Создать новый репозиторий 106 | 107 | ``` bash 108 | git init # создать новый проект в текущей директории 109 | git init folder-name # создать новый проект в указанной директории 110 | ``` 111 | 112 | 113 | ### Клонирование репозитория 114 | 115 | ``` bash 116 | # клонировать удаленный репозиторий в одноименную директорию 117 | git clone https://github.com/cyberspacedk/Git-commands.git 118 | 119 | # клонировать удаленный репозиторий в директорию «FolderName» 120 | git clone https://github.com/cyberspacedk/Git-commands.git FolderName 121 | 122 | # клонировать репозиторий в текущую директорию 123 | git clone https://github.com:nicothin/web-design.git . 124 | ``` 125 | 126 | 127 | ### Просмотр изменений 128 | 129 | ``` bash 130 | git status # показать состояние репозитория (отслеживаемые, изменённые, новые файлы и пр.) 131 | git diff # сравнить рабочую директорию и индекс (неотслеживаемые файлы ИГНОРИРУЮТСЯ) 132 | git diff --color-words # сравнить рабочую директорию и индекс, показать отличия в словах (неотслеживаемые файлы ИГНОРИРУЮТСЯ) 133 | git diff index.html # сравнить файл из рабочей директории и индекс 134 | git diff HEAD # сравнить рабочую директорию и коммит, на который указывает HEAD (неотслеживаемые файлы ИГНОРИРУЮТСЯ) 135 | git diff --staged # сравнить индекс и коммит с HEAD 136 | git diff master feature # посмотреть что сделано в ветке feature по сравнению с веткой master 137 | git diff --name-only master feature # посмотреть что сделано в ветке feature по сравнению с веткой master, показать только имена файлов 138 | git diff master...feature # посмотреть что сделано в ветке feature с момента (коммита) расхождения с master 139 | ``` 140 | 141 | 142 | ### Добавление изменений в индекс 143 | 144 | ``` bash 145 | git add . # добавить в индекс все новые, изменённые, удалённые файлы из текущей директории и её поддиректорий 146 | git add text.txt # добавить в индекс указанный файл (был изменён, был удалён или это новый файл) 147 | git add -i # запустить интерактивную оболочку для добавления в индекс только выбранных файлов 148 | git add -p # показать новые/изменённые файлы по очереди с указанием их изменений и вопросом об отслеживании/индексировании 149 | ``` 150 | 151 | 152 | ### Удаление изменений из индекса 153 | 154 | ``` bash 155 | git reset # убрать из индекса все добавленные в него изменения (в рабочей директории все изменения сохранятся), антипод git add 156 | git reset readme.txt # убрать из индекса изменения указанного файла (в рабочей директории изменения сохранятся) 157 | ``` 158 | 159 | 160 | ### Отмена изменений 161 | 162 | ``` bash 163 | git checkout text.txt # ОПАСНО: отменить изменения в файле, вернуть состояние файла, имеющееся в индексе 164 | git reset --hard # ОПАСНО: отменить изменения; вернуть то, что в коммите, на который указывает HEAD (незакомиченные изменения удалены из индекса и из рабочей директории, неотслеживаемые файлы останутся на месте) 165 | git clean -df # удалить неотслеживаемые файлы и директории 166 | ``` 167 | 168 | 169 | ### Коммиты 170 | 171 | ``` bash 172 | git commit -m "Name of commit" # зафиксировать в коммите проиндексированные изменения (закоммитить), добавить сообщение 173 | git commit -a -m "Name of commit" # проиндексировать отслеживаемые файлы (ТОЛЬКО отслеживаемые, но НЕ новые файлы) и закоммитить, добавить сообщение 174 | ``` 175 | 176 | 177 | ### Отмена коммитов и перемещение по истории 178 | 179 | Все коммиты, которые уже были отправлены в удалённый репозиторий, должны отменяться новыми коммитами (`git revert`), дабы избежать проблем с историей разработки у других участников проекта. 180 | 181 | ``` bash 182 | git revert HEAD --no-edit # создать новый коммит, отменяющий изменения последнего коммита без запуска редактора сообщения 183 | git revert b9533bb --no-edit # то же, но отменяются изменения, внесённые коммитом с указанным хешем (b9533bb) 184 | ``` 185 | 186 | **Все команды, приведённые ниже можно выполнять ТОЛЬКО если коммиты еще не были отправлены в удалённый репозиторий.** 187 | 188 | ``` bash 189 | # ВНИМАНИЕ! Опасные команды, можно потерять незакоммиченные изменения 190 | git commit --amend -m "Название" # «перекоммитить» изменения последнего коммита, заменить его новым коммитом с другим сообщением (сдвинуть текущую ветку на один коммит назад, сохранив рабочую директорию и индекс «как есть», создать новый коммит с данными из «отменяемого» коммита, но новым сообщением) 191 | git reset --hard @~ # передвинуть HEAD (и ветку) на предыдущий коммит, рабочую директорию и индекс сделать такими, какими они были в момент предыдущего коммита 192 | git reset --hard 75e2d51 # передвинуть HEAD (и ветку) на коммит с указанным хешем, рабочую директорию и индекс сделать такими, какими они были в момент указанного коммита 193 | git reset --soft @~ # передвинуть HEAD (и ветку) на предыдущий коммит, но в рабочей директории и индексе оставить все изменения 194 | git reset --soft @~2 # то же, но передвинуть HEAD (и ветку) на 2 коммита назад 195 | git reset @~ # передвинуть HEAD (и ветку) на предыдущий коммит, рабочую директорию оставить как есть, индекс сделать таким, каким он был в момент предыдущего коммита (удобнее, чем git reset --soft @~, если индекс нужно задать заново) 196 | # Почти как git reset --hard, но безопаснее: не получится потерять изменения в рабочей директории 197 | git reset --keep @~ # передвинуть HEAD (и ветку) на предыдущий коммит, сбросить индекс, но в рабочей директории оставить изменения, если возможно (если файл с изменениями между коммитами менялся, будет выдана ошибка и переключение не произойдёт) 198 | ``` 199 | 200 | 201 | ### Временно переключиться на другой коммит 202 | 203 | ``` bash 204 | git checkout b9533bb # переключиться на коммит с указанным хешем (переместить HEAD на указанный коммит, рабочую директорию вернуть к состоянию, на момент этого коммита) 205 | git checkout master # переключиться на коммит, на который указывает master (переместить HEAD на коммит, на который указывает master, рабочую директорию вернуть к состоянию на момент этого коммита) 206 | ``` 207 | 208 | 209 | ### Переключиться на другой коммит и продолжить работу с него 210 | 211 | Потребуется создание новой ветки, начинающейся с указанного коммита. 212 | 213 | ``` bash 214 | git checkout -b new-branch 5589877 # создать ветку new-branch, начинающуюся с коммита c хешем 5589877 (переместить HEAD на указанный коммит, рабочую директорию вернуть к состоянию, на момент этого коммита, создать указатель на этот коммит (ветку) с указанным именем) 215 | ``` 216 | 217 | 218 | ### Восстановление изменений 219 | 220 | ``` bash 221 | git checkout 5589877 index.html # восстановить в рабочей директории указанный файл на момент указанного коммита (и добавить это изменение в индекс) (git reset index.html для удаления из индекса, но сохранения изменений в файле) 222 | ``` 223 | 224 | 225 | ### Копирование коммита (перенос коммитов) 226 | 227 | ``` bash 228 | git cherry-pick 5589877 # скопировать на активную ветку изменения из указанного коммита, закоммитить эти изменения 229 | git cherry-pick master~2..master # скопировать на активную ветку изменения из master (2 последних коммита) 230 | git cherry-pick -n 5589877 # скопировать на активную ветку изменения из указанного коммита, но НЕ КОММИТИТЬ (подразумевается, что мы сами потом закоммитим) 231 | git cherry-pick master..feature # скопировать на активную ветку изменения из всех коммитов ветки feature с момента её расхождения с master (похоже на слияние веток, но это копирование изменений, а не слияние), закоммитить эти изменения; это может вызвать конфликт 232 | git cherry-pick --abort # прервать конфликтный перенос коммитов 233 | git cherry-pick --continue # продолжить конфликтный перенос коммитов (сработает только после решения конфликта) 234 | ``` 235 | 236 | 237 | ### Удаление файла 238 | 239 | ``` bash 240 | git rm text.txt # удалить отслеживаемый неизменённый файл и проиндексировать это изменение 241 | git rm -f text.txt # удалить отслеживаемый изменённый файл и проиндексировать это изменение 242 | git rm -r log/ # удалить всё содержимое отслеживаемой директории log/ и проиндексировать это изменение 243 | git rm ind* # удалить все отслеживаемые файлы с именем, начинающимся на «ind» в текущей директории и проиндексировать это изменение 244 | git rm --cached readme.txt # удалить из отслеживаемых индексированный файл (ФАЙЛ ОСТАНЕТСЯ НА МЕСТЕ) (часто используется для нечаянно добавленных в отслеживаемые файлов) 245 | ``` 246 | 247 | 248 | ### Перемещение/переименование файлов 249 | 250 | Для git не существует переименования. Переименование воспринимается как удаление старого файла и создание нового. Факт переименования может быть определен только после индексации изменения. 251 | 252 | ``` bash 253 | git mv text.txt test_new.txt # переименовать файл «text.txt» в «test_new.txt» и проиндексировать это изменение 254 | git mv readme_new.md folder/ # переместить файл readme_new.md в директорию folder/ (должна существовать) и проиндексировать это изменение 255 | ``` 256 | 257 | 258 | ### История коммитов 259 | 260 | Выход из длинного лога вывода: `q`. 261 | 262 | ``` bash 263 | git log master # показать коммиты в указанной ветке 264 | git log -2 # показать последние 2 коммита в активной ветке 265 | git log -2 --stat # показать последние 2 коммита и статистику внесенных ими изменений 266 | git log -p -22 # показать последние 22 коммита и внесенную ими разницу на уровне строк 267 | git log --graph -10 # показать последние 10 коммитов с ASCII-представлением ветвления 268 | git log --since=2.weeks # показать коммиты за последние 2 недели 269 | git log --after '2018-06-30' # показать коммиты, сделанные после указанной даты 270 | git log index.html # показать историю изменений файла index.html (только коммиты) 271 | git log -5 index.html # показать историю изменений файла index.html, последние 5 коммитов (только коммиты) 272 | git log -p index.html # показать историю изменений файла index.html (коммиты и изменения) 273 | git log -G'myFunction' -p # показать все коммиты, в которых менялись строки с myFunction (в кавычках регулярное выражение) 274 | git log -L '//','/<\/head>/':index.html # показать изменения от указанного до указанного регулярных выражений в указанном файле 275 | git log --grep fix # показать коммиты, в описании которых есть буквосочетание fix (регистрозависимо, только коммиты текущей ветки) 276 | git log --grep fix -i # показать коммиты, в описании которых есть буквосочетание fix (регистроНЕзависимо, только коммиты текущей ветки) 277 | git log --grep 'fix(ing|me)' -P # показать коммиты, в описании которых есть совпадения для регулярного выражения (только коммиты текущей ветки) 278 | git log --pretty=format:"%h - %an, %ar : %s" -4 # показать последние 4 коммита с форматированием выводимых данных 279 | git log --pretty=format:"%h %ad | %s%d [%an]" --graph --date=short # мой формат вывода, висящий на алиасе оболочки 280 | git log master..branch_99 # показать коммиты из ветки branch_99, которые не влиты в master 281 | git log branch_99..master # показать коммиты из ветки master, которые не влиты в branch_99 282 | git log master...branch_99 --boundary -- graph # показать коммиты из указанных веток, начиная с их расхождения (коммит расхождения будет показан) 283 | ``` 284 | 285 | ``` bash 286 | git show 60d6582 # показать изменения из коммита с указанным хешем 287 | git show HEAD~ # показать данные о предыдущем коммите в активной ветке 288 | git show @~ # аналогично предыдущему 289 | git show HEAD~3 # показать данные о коммите, который был 3 коммита назад 290 | git show my_branch~2 # показать данные о коммите, который был 2 коммита назад в указанной ветке 291 | git show @~:index.html # показать контент указанного файла на момент предыдущего (от HEAD) коммита 292 | git show :/"подвал" # показать самый новый коммит, в описании которого есть указанное слово (из любой ветки) 293 | ``` 294 | 295 | 296 | ### Кто написал строку 297 | 298 | ``` bash 299 | git blame README.md --date=short -L 5,8 # показать строки 5-8 указанного файла и коммиты, в которых строки были добавлены 300 | ``` 301 | 302 | 303 | ### История изменений указателей (веток, HEAD) 304 | 305 | ``` 306 | git reflog -20 # показать последние 20 изменений положения указателя HEAD 307 | git reflog --format='%C(auto)%h %<|(20)%gd %C(blue)%cr%C(reset) %gs (%s)' -20 # то же, но с указанием давности действий 308 | ``` 309 | 310 | 311 | ### Ветки 312 | 313 | ``` bash 314 | git branch # показать список веток 315 | git branch -v # показать список веток и последний коммит в каждой 316 | git branch new_branch # создать новую ветку с указанным именем на текущем коммите 317 | git branch new_branch 5589877 # создать новую ветку с указанным именем на указанном коммите 318 | git branch -f master 5589877 # переместить ветку master на указанный коммит 319 | git branch -f master master~2 # переместить ветку master на 2 коммита назад 320 | git checkout new_branch # перейти в указанную ветку 321 | git checkout -b new_branch # создать новую ветку с указанным именем и перейти в неё 322 | git checkout -B master 5589877 # переместить ветку с указанным именем на указанный коммит и перейти в неё 323 | git merge hotfix # влить в ветку, в которой находимся, данные из ветки hotfix 324 | git merge hotfix -m "Горячая правка" # влить в ветку, в которой находимся, данные из ветки hotfix (указано сообщение коммита слияния) 325 | git merge hotfix --log # влить в ветку, в которой находимся, данные из ветки hotfix, показать редактор описания коммита, добавить в него сообщения вливаемых коммитов 326 | git merge hotfix --no-ff # влить в ветку, в которой находимся, данные из ветки hotfix, запретить простой сдвиг указателя, изменения из hotfix «останутся» в ней, а в активной ветке появится только коммит слияния 327 | git branch -d hotfix # удалить ветку hotfix (используется, если её изменения уже влиты в главную ветку) 328 | git branch --merged # показать ветки, уже слитые с активной 329 | git branch --no-merged # показать ветки, не слитые с активной 330 | git branch -a # показать все имеющиеся ветки (в т.ч. на удаленных репозиториях) 331 | git branch -m old_branch_name new_branch_name # переименовать локально ветку old_branch_name в new_branch_name 332 | git branch -m new_branch_name # переименовать локально ТЕКУЩУЮ ветку в new_branch_name 333 | git push origin :old_branch_name new_branch_name # применить переименование в удаленном репозитории 334 | git branch --unset-upstream # завершить процесс переименования 335 | ``` 336 | 337 | 338 | ### Теги 339 | 340 | ``` bash 341 | git tag v1.0.0 # создать тег с указанным именем на коммите, на который указывает HEAD 342 | git tag -a -m 'В продакшен!' v1.0.1 master # создать тег с описанием на том коммите, на который смотрит ветка master 343 | git tag -d v1.0.0 # удалить тег с указанным именем(ами) 344 | git tag -n # показать все теги, и по 1 строке сообщения коммитов, на которые они указывают 345 | git tag -n -l 'v1.*' # показать все теги, которые начинаются с 'v1.*' 346 | ``` 347 | 348 | 349 | ### Временное сохранение изменений без коммита 350 | 351 | ``` bash 352 | git stash # временно сохранить незакоммиченные изменения и убрать их из рабочей директории 353 | git stash pop # вернуть сохраненные командой git stash изменения в рабочую директорию 354 | ``` 355 | 356 | 357 | ### Удалённые репозитории 358 | 359 | Есть два распространённых способа привязать удалённый репозиторий к локальному: по HTTPS и по SSH. Если SSH у вас не настроен (или вы не знаете что это), привязывайте удалённый репозиторий по HTTPS (адрес привязываемого репозитория должен начинаться с https://). 360 | 361 | ``` bash 362 | git remote -v # показать список удалённых репозиториев, связанных с локальным 363 | git branch -r # показать удаленные ветки 364 | git branch -a # показать все ветки(локальные и удаленные) 365 | git remote remove origin # убрать привязку удалённого репозитория с сокр. именем origin 366 | git remote add origin https://github.com:nicothin/test.git # добавить удалённый репозиторий (с сокр. именем origin) с указанным URL 367 | git remote rm origin # удалить привязку удалённого репозитория 368 | git remote show origin # получить данные об удалённом репозитории с сокращенным именем origin 369 | git fetch origin # скачать все ветки с удаленного репозитория (с сокр. именем origin), но не сливать со своими ветками 370 | git fetch origin master # то же, но скачивается только указанная ветка 371 | git checkout --track origin/github_branch # создать локальную ветку github_branch (данные взять из удалённого репозитория с сокр. именем origin, ветка github_branch) и переключиться на неё 372 | git push origin master # отправить в удалённый репозиторий (с сокр. именем origin) данные своей ветки master 373 | git pull origin # влить изменения с удалённого репозитория (все ветки) 374 | git pull origin master # влить изменения с удалённого репозитория (только указанная ветка) 375 | ``` 376 | 377 | 378 | ### Конфликт слияния 379 | 380 | Предполагается ситуация: есть ветка `master` и есть ветка `feature`. В обеих ветках есть коммиты, сделанные после расхождения веток. В ветку `master` пытаемся влить ветку `feature` (`git merge feature`), получаем конфликт, т.к. в обеих ветках есть изменения одной и той же строки в файле `index.html`. 381 | 382 | При возникновении конфликта, репозиторий находится в состоянии прерванного слияния. Нужно оставить в конфликтующих местах файлов только нужный код, проиндексировать изменения и закоммитить. 383 | 384 | ``` bash 385 | git merge feature # влить в активную ветку изменения из ветки feature 386 | git merge-base master feature # показать хеш последнего общего коммита для двух указанных веток 387 | git checkout --ours index.html # оставить в конфликтном файле (index.html) состояние ветки, В КОТОРУЮ мы вливаем (в примере — из ветки master) 388 | git checkout --theirs index.html # оставить в конфликтном файле (index.html) состояние ветки, ИЗ КОТОРОЙ мы вливаем (в примере — из ветки feature) 389 | git checkout --merge index.html # показать в конфликтном файле (index.html) сравнение содержимого сливаемых веток (для ручного редактирования) 390 | git checkout --conflict=diff3 --merge index.html # показать в конфликтном файле (index.html) сравнение содержимого сливаемых веток плюс то, что было в месте конфликта в коммите, на котором разошлись сливаемые ветки 391 | ``` 392 | 393 | ``` bash 394 | git reset --hard # прекратить это прерванное слияние, вернуть рабочую директорию и индекс как было в момент коммита, на который указывает HEAD, а я пойду немного поплачу 395 | git reset --merge # прекратить это прерванное слияние, но оставить изменения, не закоммиченные до слияния (для случая, когда слияние делается не на чистом статусе) 396 | git reset --abort # то же, что и строкой выше 397 | ``` 398 | 399 | 400 | ### «Перенос» ветки 401 | 402 | Можно «переместить» ответвление какой-либо ветки от основной на произвольный коммит. Это нужно для того, чтобы в «переносимой» ветке появились какие-либо изменения, внесённые в основной ветке (уже после ответвления переносимой). 403 | 404 | Нельзя «переносить» ветку, если она уже отправлена на удалённый репозиторий. 405 | 406 | ``` bash 407 | git rebase master # перенести все коммиты (создать их копии) активной ветки так, будто активная ветка ответвилась от master на нынешней вершине master (часто вызывает конфликты) 408 | git rebase --onto master feature # перенести коммиты активной ветки на master, начиная с того места, в котором активная ветка отделилась от ветки feature 409 | git rebase --abort # прервать конфликтный rebase, вернуть рабочую директорию и индекс к состоянию до начала rebase 410 | git rebase --continue # продолжить конфликтный rebase (сработает только после разрешения конфликта и индексации такого разрешения) 411 | ``` 412 | 413 | #### Как отменить rebase 414 | 415 | ``` bash 416 | git reflog feature -2 # смотрим лог перемещений ветки, которой делали rebase (в этом примере — feature), видим последний коммит ПЕРЕД rebase, на него и нужно перенести указатель ветки 417 | git reset --hard feature@{1} # переместить указатель ветки feature на один коммит назад, обновить рабочую директорию и индекс 418 | ``` 419 | 420 | 421 | ### Разное 422 | 423 | ``` bash 424 | git archive -o ./project.zip HEAD # создать архив с файловой структурой проекта по указанному пути (состояние репозитория, соответствующее указателю HEAD) 425 | ``` 426 | 427 | 428 | 429 | 430 | 431 | ## Примеры 432 | 433 | Собираем коллекцию простых и сложных примеров работы. 434 | 435 | 436 | ### Начало работы 437 | 438 | Создание нового репозитория, первый коммит, привязка удалённого репозитория с gthub.com, отправка изменений в удалённый репозиторий. 439 | 440 | ``` bash 441 | # указана последовательность действий: 442 | # создана директория проекта, мы в ней 443 | git init # создаём репозиторий в этой директории 444 | touch readme.md # создаем файл readme.md 445 | git add readme.md # добавляем файл в индекс 446 | git commit -m "Старт" # создаем коммит 447 | git remote add origin https://github.com:nicothin/test.git # добавляем предварительно созданный пустой удаленный репозиторий 448 | git push -u origin master # отправляем данные из локального репозитория в удаленный (в ветку master) 449 | ``` 450 | 451 | 452 | ### «Внесение изменений» в коммит 453 | 454 | Только если коммит ещё не был отправлен в удалённые репозиторий. 455 | 456 | ``` bash 457 | # указана последовательность действий: 458 | subl inc/header.html # редактируем и сохраняем разметку «шапки» 459 | git add inc/header.html # индексируем измененный файл 460 | git commit -m "Убрал телефон из шапки" # делаем коммит 461 | # ВНИМАНИЕ: коммит пока не был отправлен в удалённый репозиторий 462 | # сознаём, что нужно было еще что-то сделать в этом коммите. 463 | subl inc/header.html # вносим изменения 464 | git add inc/header.html # индексируем измененный файл (можно git add .) 465 | git commit --amend -m "«Шапка»: выполнена задача №34" # заново делаем коммит 466 | ``` 467 | 468 | 469 | ### Работа с ветками 470 | 471 | Есть master (публичная версия сайта), выполняем масштабную задачу (переверстать «шапку»), но по ходу работ возникает необходимость подправить критичный баг (неправильно указан контакт в «подвале»). 472 | 473 | ``` bash 474 | # указана последовательность действий: 475 | git checkout -b new-page-header # создадим новую ветку для задачи изменения «шапки» и перейдём в неё 476 | subl inc/header.html # редактируем разметку «шапки» 477 | git commit -a -m "Новая шапка: смена логотипа" # делаем коммит (работа еще не завершена) 478 | # тут выясняется, что есть баг с контактом в «подвале» 479 | git checkout master # возвращаемся к ветке master 480 | subl inc/footer.html # устраняем баг и сохраняем разметку «подвала» 481 | git commit -a -m "Исправление контакта в подвале" # делаем коммит 482 | git push # отправляем коммит с быстрым критическим изменением в master в удалённом репозитории 483 | git checkout new-page-header # переключаемся обратно в ветку new-page-header для продолжения работ над «шапкой» 484 | subl inc/header.html # редактируем и сохраняем разметку «шапки» 485 | git commit -a -m "Новая шапка: смена навигации" # делаем коммит (работа над «шапкой» завершена) 486 | git checkout master # переключаемся в ветку master 487 | git merge new-page-header # вливаем в master изменения из ветки new-page-header 488 | git branch -d new-page-header # удаляем ветку new_page_header 489 | ``` 490 | 491 | 492 | ### Работа с ветками, слияние и откат к состоянию до слияния 493 | 494 | Была ветка `fix`, в которой исправляли баг. Исправили, влили `fix` в `master`. но тут выяснилось, что это исправление ломает какую-то функциональность, Нужно откатить `master` к состоянию без слияния (наличие бага менее критично, чем порча функциональности). 495 | 496 | ``` bash 497 | # находимся в ветке fix, баг уже «исправлен» 498 | git checkout master # переключаемся на master 499 | git merge fix # вливаем изменения из fix в master 500 | # видим проблему: часть функциональности сломалась 501 | git checkout fix # переключаемся на fix (пока мы в master, git не даст ее двигать) 502 | git branch -f master ORIG_HEAD # передвигаем ветку master на коммит, указанный в ORIG_HEAD (тот, на который указывала master до вливания fix) 503 | ``` 504 | 505 | 506 | 507 | ### Работа с ветками, конфликт слияния 508 | 509 | Есть ветка `master` (публичная версия сайта), в двух параллельных ветках (`branch-1` и `branch-2`) было отредактировано одно и то же место одного и того же файла, первую ветку (`branch-1`) влили в master, попытка влить вторую вызывает конфликт. 510 | 511 | ``` bash 512 | # указана последовательность действий: 513 | git checkout master # переключаемся на ветку master 514 | git checkout -b branch-1 # создаём ветку branch-1, основанную на ветке master 515 | subl . # редактируем и сохраняем файлы 516 | git commit -a -m "Правка 1" # коммитим 517 | git checkout master # возвращаемся к ветке master 518 | git checkout -b branch-2 # создаём ветку branch-2, основанную на ветке master 519 | subl . # редактируем и сохраняем файлы 520 | git commit -a -m "Правка 2" # коммитим 521 | git checkout master # возвращаемся к ветке master 522 | git merge branch-1 # вливаем изменения из ветки branch-1 в текущую ветку (master), удача (автослияние) 523 | git merge branch-2 # вливаем изменения из ветки branch-2 в текущую ветку (master), КОНФЛИКТ автослияния 524 | # Automatic merge failed; fix conflicts and then commit the result. 525 | subl . # выбираем в конфликтных файлах те участки, которые нужно оставить, сохраняем 526 | git commit -a -m "Устранение конфликта" # коммитим результат устранения конфликта 527 | ``` 528 | 529 | 530 | 531 | ### Синхронизация репозитория-форка с мастер-репозиторием 532 | 533 | Есть некий репозиторий на github.com, он него нами был сделан форк, добавлены какие-то изменения. Оригинальный (мастер-)репозиторий был как-то обновлён. Задача: стянуть с мастер-репозитория изменения (которые там внесены уже после того, как мы его форкнули). 534 | 535 | ``` bash 536 | # указана последовательность действий: 537 | git remote add upstream https://github.com:address.git # добавляем удаленный репозиторий: сокр. имя — upstream, URL мастер-репозитория 538 | git fetch upstream # стягиваем все ветки мастер-репозитория, но пока не сливаем со своими 539 | git checkout master # переключаемся на ветку master своего репозитория 540 | git merge upstream/master # вливаем стянутую ветку master удалённого репозитория upstream в свою ветку master 541 | ``` 542 | 543 | 544 | 545 | ### Ошибка в работе: закоммитили в мастер, но поняли, что нужно было коммитить в новую ветку 546 | 547 | **ВАЖНО: это сработает только если коммит еще не отправлен в удалённый репозиторий.** 548 | 549 | ``` bash 550 | # указана последовательность действий: 551 | # сделали изменения, проиндексировали их, закоммитили в master, но ЕЩЁ НЕ ОТПРАВИЛИ (не делали git push) 552 | git checkout -b new-branch # создаём новую ветку из master 553 | git checkout master # переключаемся на master 554 | git reset HEAD~ --hard # сдвигаем указатель (ветку) master на 1 коммит назад 555 | git checkout new-branch # переключаемся обратно на новую ветку для продолжения работы 556 | ``` 557 | 558 | 559 | 560 | ### Нужно вернуть содержимое файла к состоянию, бывшему в каком-либо коммите (известен хеш коммита) 561 | 562 | ``` bash 563 | # указана последовательность действий: 564 | git checkout f26ed88 -- index.html # восстановить в рабочей директории состояние указанного файла на момент указанного коммита, добавить это изменение в индекс 565 | git commit -am "Navigation fixs" # сделать коммит 566 | ``` 567 | 568 | 569 | 570 | ### При любом действии с github (или другим удалённым сервисом) запрашивается логин и пароль 571 | 572 | Речь именно о запросе пары логин + пароль, а не ключевой фразы. Происходит это потому, что git по умолчанию не сохранит пароль для доступа к репозиторию по HTTPS. 573 | 574 | Простое решение: [указать git кешировать ваш пароль](https://help.github.com/articles/caching-your-github-password-in-git/). 575 | 576 | 577 | 578 | ## `.gitattributes` 579 | 580 | ``` 581 | * text=auto 582 | 583 | *.html diff=html 584 | *.css diff=css 585 | *.scss diff=css 586 | ``` 587 | --------------------------------------------------------------------------------