# GIT

## Основы

### git add

`git add --all` добавит в коммит все что есть в папка и подпапках

Следующие две команды добавляют в коммит все измененные файлы кроме file.cpp

`git add -u`

`git reset -- path/file.cpp`

Аналогично можно создать коммит, используя все файлы, кроме одной директории:

`git add -u`

`git reset -- mydir/*`

### Знакомство с Git Commit

Git не копирует всю директорию каждый раз, а ужимает (когда это возможно) коммит в набор изменений или «дельту» между текущей версией и предыдущей. Очевидно, что для первого коммита он копирует весь репозиторий. Также Git хранит всю историю о том, когда какой коммит был сделан

`git commit -m "first commit"`

Каждый коммит имеет своего родителя(кроме первого), это показано стрелочками.

![](https://2997537489-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHlGytXJgp5s5oJT0tl%2Fsync%2F03e6957b9e9da4428106f3e24f25bfe5ddbd0c93.png?generation=1603557400627680\&alt=media)

### Ветвление в Git(Ветки в git)

Мы находились на втором коммите и создали новую ветку newImage

`git branch newImage`

![](https://2997537489-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHlGytXJgp5s5oJT0tl%2Fsync%2F533d64961d0f1367fe2f86112cfa5b0e3470b75e.png?generation=1603557402028939\&alt=media)

Чтобы сменить нашу ветку нужно сделать

`git checkout newImage`

Сделаем коммит

`git commit`

![](https://2997537489-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHlGytXJgp5s5oJT0tl%2Fsync%2F8dc419a4106dadc69905c1fa89e186feefafb906.png?generation=1603557402045961\&alt=media)

Создание новой ветки и переключение на нее

`git checkout -b yourbranchname`

`git commit`

`git checkout -b bugfix`

`git commit`

![](https://2997537489-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHlGytXJgp5s5oJT0tl%2Fsync%2F89350e665c0d8fa4badd5edb324527f217c312ce.png?generation=1603557400897523\&alt=media)

### Слияние веток

#### merge

Вот у нас две ветки, каждая содержит по одному уникальному коммиту. Это означает, что ни одна из веток не содержит полный набор "работ", выполненных в этом репозитории. Можно исправить эту ситуацию, выполнив слияние.

![](https://2997537489-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHlGytXJgp5s5oJT0tl%2Fsync%2F9acc6e21e6a6afb6194b10daac0825368a65352a.png?generation=1603557401984992\&alt=media)

`git merge bugfix`

Ветка master теперь указывает на коммит, у которого два родителя. Если проследовать по стрелкам от этого коммита, вы пройдёте через каждый коммит в дереве прямиком к началу. Это означает, что теперь в ветке master содержатся все изменения репозитория.

![](https://2997537489-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHlGytXJgp5s5oJT0tl%2Fsync%2Fc32c9170fc077b173544b7d6eb189a50380584c6.png?generation=1603557400514046\&alt=media)

![](https://2997537489-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHlGytXJgp5s5oJT0tl%2Fsync%2F73f5608fb38e778f13356ea4915a0da77f46a55b.png?generation=1603557403053825\&alt=media)

`git checkout bugfix`

`git merge master`

![](https://2997537489-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHlGytXJgp5s5oJT0tl%2Fsync%2F0f8c741c9f7125310dac3cc0082e676d09a887d9.png?generation=1603557400799122\&alt=media)

Теперь каждая ветка содержит все изменения репозитория

#### rebase

![](https://2997537489-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHlGytXJgp5s5oJT0tl%2Fsync%2F47fd6997a53fdaf111727956521a3bbe14226a98.png?generation=1603557401335379\&alt=media)

`git rebase master`

![](https://2997537489-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHlGytXJgp5s5oJT0tl%2Fsync%2Ff84f83a91d25fefc49952118c5553c192a3e35bc.png?generation=1603557400757993\&alt=media)

Теперь изменения из bugFix находятся в конце ветки master и являют собой линейную последовательность коммитов. Коммит С3 до сих пор существует где-то, а С3' - это его "копия" в ветке master. Единственная проблема - ветка master не обновлена до последних изменений.

![](https://2997537489-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHlGytXJgp5s5oJT0tl%2Fsync%2F6d14703dd3091f15be3c033244e2b3bb4493d024.png?generation=1603557401928622\&alt=media)

`git rebase bugfix`

![](https://2997537489-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHlGytXJgp5s5oJT0tl%2Fsync%2F55a3a28d158fb3d3f0f36413d55fb0aec22f6c56.png?generation=1603557402676953\&alt=media)

### Detached HEAD

HEAD - это символическое имя текущего выбранного коммита — это, по сути, тот коммит, над которым мы в данным момент работаем. HEAD всегда указывает на последний коммит из вашего локального дерева. Большинство команд Git, изменяющих рабочее дерево, начнут с изменения HEAD.

![](https://2997537489-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHlGytXJgp5s5oJT0tl%2Fsync%2F93f52f836db2e5c682dddda030c01d2c2527ebee.png?generation=1603557401186053\&alt=media)

`git checkout C1`

`git checkout master`

`git commit`

`git checkout C2`

![](https://2997537489-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHlGytXJgp5s5oJT0tl%2Fsync%2Fcdd9af473e14076d6699a2808c54d5dd7e859763.png?generation=1603557402117673\&alt=media)

Отделение (detaching) HEAD означает лишь присвоение его не ветке, а конкретному коммиту. Посмотрим, что было до отделения:

HEAD -> master -> C1

![](https://2997537489-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHlGytXJgp5s5oJT0tl%2Fsync%2F93f52f836db2e5c682dddda030c01d2c2527ebee.png?generation=1603557401186053\&alt=media)

`git checkout C1`

![](https://2997537489-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHlGytXJgp5s5oJT0tl%2Fsync%2Fc5266d2038595ca33a6532646821ba38acb73c4e.png?generation=1603557401438424\&alt=media)

А вот что получилось теперь

HEAD -> C1

### Относительные ссылки (^)

Относительные ссылки - мощный инструмент, но мы покажем два простых способа использования:

Перемещение на один коммит назад ^

Перемещение на num коммитов назад \~

![](https://2997537489-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHlGytXJgp5s5oJT0tl%2Fsync%2F76256c616ea4a6c1c7ab8062587e9c952b9a70f5.png?generation=1603557402199837\&alt=media)

`git checkout master^`

![](https://2997537489-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHlGytXJgp5s5oJT0tl%2Fsync%2Fdd86d6570eb9123a03636bdd0f59eda076da6ef8.png?generation=1603557402637115\&alt=media)

### Перемещение веток

![](https://2997537489-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHlGytXJgp5s5oJT0tl%2Fsync%2Fd45b6404291f53d3204a72d4ab4a985550cf454d.png?generation=1603557400659565\&alt=media)

`git branch -f master HEAD~3`

![](https://2997537489-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHlGytXJgp5s5oJT0tl%2Fsync%2F12f1173b8e2bb0e9ddccbf6dff204db9ae05280d.png?generation=1603557401046481\&alt=media)

### Отмена изменение в git

Есть два основных способа отмены изменений в Git: первый - это git reset, а второй - git revert.

git reset отменяет изменения, перенося ссылку на ветку назад, на более старый коммит. Это своего рода "переписывание истории"; git reset перенесёт ветку назад, как будто некоторых коммитов вовсе и не было.

![](https://2997537489-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHlGytXJgp5s5oJT0tl%2Fsync%2Fc9422af50047b1471d6462918acb6e9be86602f3.png?generation=1603557402989160\&alt=media)

`git reset HEAD~1`

![](https://2997537489-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHlGytXJgp5s5oJT0tl%2Fsync%2F93c5f3dc6c2b72d445f818dbfaa926914159c8a7.png?generation=1603557401297326\&alt=media)

Git просто перенёс ссылку на master обратно на коммит C1. Теперь наш локальный репозиторий в состоянии, как будто C2 никогда не существовал. Reset отлично работает на локальных ветках, в локальных репозиториях. Но этот метод переписывания истории не сработает на удалённых ветках, которые используют другие пользователи. Чтобы отменить изменения и поделиться отменёнными изменениями с остальными, надо использовать git revert.

![](https://2997537489-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHlGytXJgp5s5oJT0tl%2Fsync%2Ff7631fddf09169dafde882f4cf463afa49b4ead8.png?generation=1603557402448786\&alt=media)

`git revert HEAD`

![](https://2997537489-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHlGytXJgp5s5oJT0tl%2Fsync%2F2e8fab1dbd67b1af6cd64ddd68dd3dd85b9aef3b.png?generation=1603557403323024\&alt=media)

Появился новый коммит. Дело в том, что новый коммит C2' просто содержит изменения, полностью противоположные тем, что сделаны в коммите C2. После revert можно сделать push и поделиться изменениями с остальными.

### Введение в Cherry-pick

`git cherry-pick <Commit1> <Commit2> <...>`

Это очень простой и прямолинейный способ сказать, что ты хочешь копировать несколько коммитов на место, где сейчас находишься (HEAD).

![](https://2997537489-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHlGytXJgp5s5oJT0tl%2Fsync%2F3404e6b7d977f1643f43791248708d924bc354ee.png?generation=1603557401989345\&alt=media)

`git cherry-pick C2 C4`

![](https://2997537489-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHlGytXJgp5s5oJT0tl%2Fsync%2Fada90aa22f27feaab0d9d91e95f20a621b7b771a.png?generation=1603557402189655\&alt=media)

### Введение в интерактивный rebase

![](https://2997537489-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHlGytXJgp5s5oJT0tl%2Fsync%2F01186b4da54f007f3ced6a12167f8b7567134233.png?generation=1603557402907573\&alt=media)

`git rebase -i HEAD~4`

![](https://2997537489-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHlGytXJgp5s5oJT0tl%2Fsync%2Fc8429d9ff6cf3d3710b0e04b457be34b5572a14e.png?generation=1603557402750548\&alt=media)

### Rebase over 9000 раз

## Удаленные репозитории

### Push & Pull - удалённые репозитории в Git!

### Продвинутое использование Git Remotes
