В чем различия между git branch, fork, fetch, merge, rebase и clone?
=====================================================================

 Я хочу понять разницу между веткой, вилкой и клоном в Git?

  Точно так же, что это значит, когда я делаю `git fetch` а не `git pull`?

  Кроме того, что означает `rebase` по сравнению со `merge`?

  Как я могу раздавить человека, совершающего себя вместе?

  Как они используются, почему они используются и что они представляют?

  Как фигурирует GitHub?

 

Клон - это просто копия репозитория. На первый взгляд его результат эквивалентен `svn checkout`, где вы загружаете исходный код из какого-либо другого репозитория. Разница между централизованными VCS, такими как Subversion и DVCS, такими как Git, заключается в том, что в Git, когда вы клонируете, вы фактически копируете весь исходный репозиторий, включая всю историю и ветки. Теперь у вас есть новый репозиторий на вашем компьютере, и любые коммиты, которые вы делаете, входят в этот репозиторий. Никто не увидит никаких изменений до тех пор, пока вы не нажмете эти коммиты в другой репозиторий (или оригинальный) или пока кто-то не вытащит коммиты из вашего репозитория, если он общедоступен.

Ветвь - это нечто, находящееся в репозитории. Концептуально он представляет собой поток развития. Обычно у вас есть ведущая ветвь, но у вас также может быть ветка, где вы работаете над некоторой функцией xyz, а другая - для исправления ошибки abc. Когда вы проверили ветку, любые сделанные вами фиксации останутся на этой ветке и не будут использоваться совместно с другими ветвями, пока вы их не объедините или не замените на соответствующую ветку. Конечно, Git кажется немного странным, когда дело касается ветвей, пока вы не посмотрите на базовую модель того, как реализуются ветки. Вместо того, чтобы объяснять это сам (я уже сказал слишком много, говорит), я свяжусь с "информатикой", объясняя, как Git моделирует ветки и фиксации, взятые с веб-сайта Git:

 <http://eagain.net/articles/git-for-computer-scientists/>

 (function(w, d, n, s, t) {
 w[n] = w[n] || [];
 w[n].push(function() {
 Ya.Context.AdvManager.render({
 blockId: "R-A-248011-3",
 renderTo: "yandex\_rtb\_R-A-248011-3",
 async: true
 });
 });
 t = d.getElementsByTagName("script")[0];
 s = d.createElement("script");
 s.src = "//an.yandex.ru/system/context.js";
 s.async = true;
 t.parentNode.insertBefore(s, t);
 })(this, this.document, "yandexContextAsyncCallbacks");

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

EDIT: поскольку я не знал о современном определении "fork", используемом сайтами GitHub, пожалуйста, взгляните на комментарии, а также [Ответ Майкла Дарранта](/questions/124/git-branch-fork-fetch-merge-rebase-and-clone-what-are-the-differences/2475#2475) ниже моей для получения дополнительной информации.

 

 Гит
====

  Этот ответ включает в себя GitHub, как многие люди спрашивали об этом тоже.

  Локальные репозитории
----------------------

  Git (локально) имеет каталог (`.git`), в который вы фиксируете свои файлы, и это ваш "локальный репозиторий". Это отличается от систем, подобных SVN, где вы сразу добавляете и фиксируете удаленный репозиторий.

  Git хранит каждую версию файла, которая изменяется, сохраняя весь файл. В этом отношении он также отличается от SVN, поскольку вы можете перейти к любой отдельной версии, не "воссоздавая" ее с помощью дельта-изменений.

  Git вообще не "блокирует" файлы и, таким образом, избегает функциональности "эксклюзивной блокировки" для редактирования (вспоминаются более старые системы, такие как pvcs), поэтому все файлы всегда можно редактировать, даже когда они находятся в автономном режиме. На самом деле он выполняет потрясающую работу по объединению изменений файла (в одном и том же файле!) Вместе во время извлечения или извлечения/передачи в удаленный репозиторий, такой как GitHub. Единственный раз, когда вам нужно внести изменения вручную (фактически редактирование файла), это если два изменения затрагивают одну и ту же строку (и) кода.

 

---

 ветки
------

  Ветви позволяют вам сохранить основной код (ветвь 'master'), сделать копию (новую ветвь) и затем работать в этой новой ветке. Если работа занимает некоторое время или мастер получает много обновлений с тех пор, как была создана ветвь, то следует выполнить слияние или перестановку (часто предпочтительнее для лучшей истории и более простого разрешения конфликтов) с основной ветвью. Когда вы закончите, вы объедините изменения, сделанные в ветке, с главным репозиторием. Многие организации используют ветки для каждой части работы, будь то функция, ошибка или работа по дому. Другие организации используют ветки только для серьезных изменений, таких как обновление версий.

  Вилка: с помощью ветки вы контролируете и управляете ветвью, тогда как с помощью вилки кто-то еще контролирует принятие кода обратно.

  Вообще говоря, есть два основных подхода к созданию веток. Первый - сохранить большинство изменений в основной ветке, используя только ветки для больших и длинных -r, и таких вещей, как изменения версий, где вы хотите иметь две ветки, доступные для разных нужд. Во-вторых, вы делаете ветку для каждого запроса, исправления ошибки или рутинной работы, а затем вручную решаете, когда на самом деле объединить эти ветки с основной веткой master. Хотя это звучит скучно, это общий подход, который я в настоящее время использую и рекомендую, потому что он обеспечивает чистоту главной ветки и мастер, который мы продвигаем в производство, поэтому нам нужен только законченный, проверенный код, через перебазирование и слияние ветвей.

  Стандартный способ привести ветку "в" к мастеру - выполнить `merge`. Ветви также могут быть "перебазированы", чтобы "очистить" историю. Это не влияет на текущее состояние и делается для того, чтобы "очистить" историю.

  По сути, идея заключается в том, что вы разветвляетесь с определенной точки (обычно от мастера). С тех пор как вы разветкились, сам "мастер" с тех пор продвинулся вперед от этой точки ветвления. Это будет "чище" (легче решать проблемы, а историю будет легче понять), если все изменения, которые вы сделали в ветке, будут воспроизводиться в соответствии с текущим состоянием мастера со всеми его последними изменениями. Итак, процесс таков: сохранить изменения; получить "новый" мастер, а затем повторно применить (это часть rebase) снова изменения против этого. Имейте в виду, что rebase, так же как и merge, может привести к конфликтам, которые вы должны будете разрешить вручную (т.е. отредактировать и исправить).

  Одно замечание:   
**Только перебазировать, если ветка локальная, а вы еще не перешли на удаленную!**   
 Это происходит главным образом потому, что перебазирование может изменить историю, которую видят другие люди, что может включать и их собственные коммиты.

 ###  Отслеживание веток

  Это ветки с именем `origin/branch_name` (в отличие от просто `branch_name`). Когда вы загружаете и извлекаете код из/в удаленные репозитории, это фактически механизм, посредством которого это происходит. Например, когда вы `git push` на ветку с именем `building_groups`, ваша ветвь сначала переходит к `origin/building_groups` а затем - в удаленный репозиторий. Аналогично, если вы выполняете `git fetch building_groups`, извлекаемый файл помещается в вашу ветку `origin/building_groups`. Затем вы можете объединить эту ветку с вашей локальной копией. Наша практика заключается в том, чтобы всегда делать `git fetch` и ручное слияние, а не просто `git pull` (который выполняет оба вышеупомянутых действия за один шаг).

 ###  Получение новых веток.

  Получение новых веток: в начальной точке клона у вас будут все ветки. Однако, если другие разработчики добавляют ветки и отправляют их на удаленный компьютер, необходимо найти способ "узнать" об этих ветвях и их названиях, чтобы можно было их локально свернуть. Это делается с помощью `git fetch` который получает все новые и измененные ветки в локальный репозиторий, используя отслеживающие ветки (например, `origin/`). После `fetch` изд можно `git branch --remote` в список веток и отслеживания `git checkout [branch]` на самом деле переключиться на любой заданной.

  сращивание
-----------

  Объединение - это процесс объединения изменений кода из разных веток или из разных версий одной и той же ветки (например, когда локальная ветка и удаленная не синхронизированы). Если кто-то разработал работу в филиале и работа завершена, готова и протестирована, то она может быть объединена с `master` веткой. Это делается `git checkout master` чтобы переключиться на `master` ветку, а затем `git merge your_branch`. Объединение объединит все разные файлы и даже разные изменения в одни и те же файлы. Это означает, что он фактически изменит код внутри файлов, чтобы объединить все изменения.

  При выполнении `checkout` `master` также рекомендуется выполнить `git pull origin master` чтобы получить самую последнюю версию удаленного мастера, объединенную с вашим локальным мастером. Если удаленный мастер изменился, т.е. `moved forward`, вы увидите информацию, которая отражает это во время этого `git pull`. Если это так (мастер изменен), вам рекомендуется выполнить `git checkout your_branch` а затем `rebase` его на master, чтобы ваши изменения действительно воспроизводились поверх "нового" мастера. Затем вы продолжите получать мастер-версию, как показано в следующем параграфе.

  Если нет конфликтов, то в master будут добавлены новые изменения. Если есть конфликты, это означает, что в тех же файлах есть изменения в похожих строках кода, которые он не может автоматически объединить. В этом случае `git merge new_branch` сообщит, что существует конфликт для разрешения. Вы "решаете" их, редактируя файлы (в них будут оба изменения), выбирая нужные изменения, буквально удаляя строки изменений, которые вам не нужны, и затем сохраняя файл. Изменения отмечены разделителями, такими как `========` и `<<<<<<<<`.

  После того, как вы разрешите все конфликты, вы еще раз `git commit` `git add` и `git commit` эти изменения, чтобы продолжить объединение (в течение этого процесса вы получите отзыв от git, который поможет вам).

  Если процесс не работает `git merge --abort` вы обнаружите, что `git merge --abort` очень удобен для сброса настроек.

  Интерактивный перебазирование и сжатие/изменение порядка/удаление коммитов
---------------------------------------------------------------------------

  Если вы выполнили много маленьких шагов, например, вы каждый день фиксируете код как "work -i n-progress", вы можете захотеть "раздавить" эти многочисленные небольшие коммиты в несколько больших коммитов. Это может быть особенно полезно, когда вы хотите делать обзоры кода с коллегами. Вы не хотите воспроизводить все "шаги", которые вы предприняли (с помощью коммитов), вы просто хотите сказать, что это конечный эффект (diff) всех моих изменений для этой работы в одном коммите.

  Ключевой фактор, который необходимо оценить при рассмотрении вопроса о том, следует ли делать это, заключается в том, многократные коммиты направлены против одного и того же файла или файлов более одного раза (в этом случае лучше использовать коммит-фиксации). Это делается с помощью интерактивного инструмента перебазирования. Этот инструмент позволяет сдавить коммиты, удалить коммиты, переформулировать сообщения и т.д. Например, `git rebase -i HEAD~10` (обратите внимание: что `~`, а не `-`) вызывает следующее:

  [![interactive rebasing in Git]()](/img/90122f3ea28bc1c89fffba8290defede.png)

  Будьте осторожны и используйте этот инструмент осторожно. Выполняйте по одному сквошу/удаляйте/переупорядочивайте за раз, выходите и сохраняйте этот коммит, затем снова вводите инструмент. Если коммиты не являются смежными, вы можете изменить их порядок (и затем при необходимости раздавить). Здесь вы также можете удалить коммиты, но вам действительно нужно быть уверенным в том, что вы делаете, когда делаете это!

  вилки
------

 (function(w, d, n, s, t) {
 w[n] = w[n] || [];
 w[n].push(function() {
 Ya.Context.AdvManager.render({
 blockId: "R-A-248011-4",
 renderTo: "yandex\_rtb\_R-A-248011-4",
 async: true
 });
 });
 t = d.getElementsByTagName("script")[0];
 s = d.createElement("script");
 s.src = "//an.yandex.ru/system/context.js";
 s.async = true;
 t.parentNode.insertBefore(s, t);
 })(this, this.document, "yandexContextAsyncCallbacks");

 Существует два основных подхода к сотрудничеству в репозиториях Git. Первый, подробно описанный выше, напрямую связан с ветками, которые люди тянут и толкают из/в. Эти соавторы имеют свои SSH-ключи, зарегистрированные в удаленном хранилище. Это позволит им напрямую перейти в этот репозиторий. Недостатком является то, что вы должны вести список пользователей. Другой подход - разветвление - позволяет любому "разветвлять" репозиторий, в основном делая локальную копию в своей учетной записи Git-репозитория. Затем они могут вносить изменения и по окончании отправлять "запрос на извлечение" (на самом деле это скорее "подталкивание" от них и "запрос на извлечение" для фактического сопровождающего хранилища), чтобы получить принятый код.

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

 

---

 GitHub
=======

  GitHub (удаленный репозиторий) - это удаленный источник, к которому вы обычно добавляете и извлекаете те зафиксированные изменения, если у вас есть (или добавлены) такой репозиторий, поэтому локальный и удаленный объекты на самом деле совершенно различны. Еще один способ представить себе удаленный репозиторий - это структура каталогов `.git` которая находится на удаленном сервере.

  Когда вы "форк" - в GUI веб-браузера GitHub вы можете нажать на эту кнопку ![Image of fork button]() - вы создаете копию ("клон") кода в вашей учетной записи GitHub. Когда вы делаете это в первый раз, это может быть немного незаметно, поэтому не забудьте посмотреть, в чьем репозитории находится кодовая база - либо его первоначальный владелец, либо "ответвление от", и вы, например, так:

  ![Image of name of forked repository]()

  Получив локальную копию, вы можете вносить изменения по своему усмотрению (вытягивая и отправляя их на локальный компьютер). Когда вы закончите, вы отправите "запрос на извлечение" первоначальному владельцу/администратору хранилища (звучит странно, но на самом деле вы просто нажимаете на это: ![Image of pull request button]()), и они "вытягивают" его.

  Для команды, работающей над кодом, чаще всего используется "клонирование" хранилища (щелкните значок "Копировать" на главном экране хранилища). Затем локально наберите `git clone` и вставьте. Это настроит вас локально, и вы также можете нажать и вытащить (общее) расположение GitHub.

  Клоны
------

  Как указано в разделе о GitHub, клон является копией репозитория. Когда у вас есть удаленный репозиторий, вы `git clone` команду `git clone` его URL, а затем получаете локальную копию или клон репозитория. У этого клона есть **все**, файлы, основная ветвь, другие ветки, все существующие коммиты, весь шебанг. Именно с этим клоном вы делаете свои добавления и коммиты, а затем сам удаленный репозиторий является тем, к чему вы подталкиваете эти коммиты. Именно эта локальная/удаленная концепция делает Git (и системы, подобные ему, такие как Mercurial) DVCS (**распределенной** системой контроля версий), в отличие от более традиционных CVS (систем управления версиями кода), таких как SVN, PVCS, CVS и т.д., Где Вы фиксируете непосредственно в удаленном хранилище.

  Визуализация
-------------

  Визуализация основных понятий можно увидеть на   
[http://marklodato.github.com/visual-git-guide/index-en.html](https://marklodato.github.com/visual-git-guide/index-en.html) и   
[http://ndpsoftware.com/git-cheatsheet.html#loc=index](http://ndpsoftware.com/git-cheatsheet.html#loc=index%23loc=index)

  Если вы хотите наглядно показать, как работают изменения, вы не можете превзойти визуальный инструмент `gitg` (`gitx` для macOS) с графическим интерфейсом, который я называю "карта метро" (особенно London Underground), отлично `gitx` для того, чтобы показать, кто это сделал. что, как все меняется, расходится и сливается и т.д.

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

  [![Image of gitg/gitx interface]()](/img/6ba455ef9fc93fcff0b7a91cca0f848b.png)

  Хотя gitg/gitx довольно минимален, количество инструментов с графическим интерфейсом продолжает расширяться. Многие пользователи Mac используют братбард-форк gitx и для Linux, отличным вариантом является smart-git с интуитивно понятным и мощным интерфейсом:

  [![Image of smart-git GUI]()](/img/1ed5c5830912095633877cd9cb0dd12f.png)

  Обратите внимание, что даже с инструментом GUI вы, вероятно, будете выполнять много команд в командной строке.

  Для этого у меня есть следующие псевдонимы в моем файле `~/.bash_aliases` (который вызывается из моего файла `~/.bashrc` для каждой терминальной сессии):

 
```
# git
alias g='git status'
alias gcob='git checkout -b '
alias gcom='git checkout master'
alias gd='git diff'
alias gf='git fetch'
alias gfrm='git fetch; git reset --hard origin/master'
alias gg='git grep '
alias gits='alias | grep "^alias g.*git.*$"'
alias gl='git log'
alias gl1='git log --oneline'
alias glf='git log --name-status'
alias glp='git log -p'
alias gpull='git pull '
alias gpush='git push '

  И в моем файле ~/.gitconfig есть следующие "псевдонимы git" - почему они есть?   
 Так что завершение ветки (с клавишей TAB) работает!

  Итак, это:

 
[alias]
  co = checkout
  cob = checkout -b

  Пример использования: git co [branch] <- будет работать завершение вкладки для веток.

  GUI Learning Tool
------------------

  Вы можете найти [https://learngitbranching.js.org/](https://learngitbranching.js.org) полезным для изучения некоторых базовых концепций. [Снимок](/img/e7f03e736236f4f0aabea9ac9002999e.png) экрана: [![enter image description here]()](/img/e7f03e736236f4f0aabea9ac9002999e.png)   
 Видео: <https://youtu.be/23JqqcLPss0>

  Наконец, 7 ключевых спасателей!
--------------------------------

 1. Вы вносите изменения, добавляете и фиксируете их (но не нажимаете), а затем - о! вы понимаете, что вы мастер!

 
git reset [filename(s)]
git checkout -b [name_for_a_new_branch]
git add [file(s)]
git commit -m "A useful message"

Voila!  You've moved that 'master' commit to its own branch !

Вы испортили некоторые файлы, работая в локальной ветке, и просто хотите вернуться к тому, что было в прошлый раз, когда вы выполняли git pull:

 
git reset --hard origin/master  # You will need to be comfortable doing this!

Вы начинаете вносить изменения локально, вы редактируете полдюжины файлов, а затем, о черт, вы все еще находитесь в основной (или другой) ветке:

 
git checkout -b new_branch_name  # just create a new branch
git add .                      # add the changes files
git commit -m"your message"    # and commit them

Вы испортили один конкретный файл в вашей текущей ветке и хотите просто "сбросить" этот файл (потерять изменения) на то, каким он был в последний раз, когда вы извлекали его из удаленного репозитория:

 
git checkout your/directories/filename

  Это на самом деле сбрасывает файл (как и многие команды Git, он не очень хорошо назван для того, что он здесь делает).
Вы вносите некоторые изменения локально, вы хотите убедиться, что вы не потеряете их во время git reset или rebase: я часто делаю ручную копию всего проекта (cp -r../my_project ~/), когда я Я не уверен, что могу запутаться в Git или потерять важные изменения.
Вы перебиваете, но все портится:

 
git rebase --abort # To abandon interactive rebase and merge issues

Добавьте свою ветку Git в приглашение PS1 (см. [Https://unix.stackexchange.com/a/127800/10043](https://unix.stackexchange.com/a/127800/10043)), например,

  [![Image of prompt]()](/img/74324b5607d513a0acfd76e5ce655aa7.png)

  Ветвь является selenium_rspec_conversion.

 

Вот образ Оливера Стил, как все это сочетается:

 ![enter image description here]()

 

 Вилка против Клон - два слова, которые оба означают копию

  Пожалуйста, смотрите эту [диаграмму.](https://i.stack.imgur.com/6PP4e.png) (Первоначально из <http://www.dataschool.io/content/images/2014/Mar/github1.png>).

 
.-------------------------.     1. Fork     .-------------------------.
| Your GitHub repo        | <-------------- | Joe GitHub repo       |
| github.com/you/coolgame |                 | github.com/joe/coolgame |
| ----------------------- | 7. Pull Request | ----------------------- |
| master -> c224ff7       | --------------> | master -> c224ff7 (c)   |
| anidea -> 884faa1 (a)   |                 | anidea -> 884faa1 (b)   |
'-------------------------'                 '-------------------------'
    |                 ^
    | 2. Clone        |
    |                 |
    |                 |
    |                 |
    |                 |
    |                 | 6. Push (anidea => origin/anidea)
    v                 |
.-------------------------.
| Your computer           |  3. Create branch 'anidea'
| $HOME/coolgame          |
| ----------------------- |  4. Update a file
| master -> c224ff7       |
| anidea -> 884faa1       |  5. Commit (to 'anidea')
'-------------------------'

(a) - after you have pushed it
(b) - after Joe has accepted it
(c) - eventually Joe might merge 'anidea' (make 'master -> 884faa1')

```
  **вилка**

 * Копия в ваше удаленное хранилище (облако), которая связывает его с Джо
* Копия, которую вы можете затем клонировать в локальный репозиторий и F *% $ -up
 Когда вы закончите, вы можете нажать на свой пульт
 Затем вы можете спросить Джо, хочет ли он использовать его в своем проекте, нажав pull-request.

 клон

  копия в локальный репо (жесткий диск)

 

Просто для добавления к другим, примечания, относящиеся к forking.

Хорошо понимать, что технически клонирование репо и разворачивание репо - это одно и то же. У:

git clone $some_other_repo

```

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

 Git, как VCS, на самом деле представляет собой разметку  cloning. Помимо "простого просмотра" с использованием удаленного пользовательского интерфейса, такого как cgit, существует очень мало общего с репо git, которое не включает в себя  forking, клонируя репо в какой-то момент.

Однако

* когда кто-то говорит  **я разблокировал репо X**, они означают, что они создали
клон репо где-то еще с намерением разоблачить его
другие, например, чтобы показать некоторые эксперименты или применять разные
механизм контроля доступа (например, чтобы люди, не имеющие доступа к Github,
с внутренней учетной записью компании для совместной работы).

Факты, которые: репо, скорее всего, создано с другой командой, чем
`git clone`, что он, скорее всего, размещен где-то на сервере, как
против кого-то ноутбука, и, скорее всего, немного отличается
формат (это "голый репо", т.е. без рабочего дерева) все просто
технические детали.

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

(Что Github делает, когда вы нажимаете "fork", просто клонируется с добавлением
сахар: он клонирует репо для вас, ставит его под ваш счет, записывает
где-то "разветвлено", добавляет удаленный названный "вверх по течению", и большинство
важно, играет приятную анимацию.)
* Когда кто-то говорит **, я клонировал репо X**, они означают, что они создали
клонировать репо на локальном компьютере или на рабочем столе с намерением
изучать его, играть с ним, вносить свой вклад или создавать что-то из источника
кода в нем.

Красота git заключается в том, что она делает все это идеально подходящим: все эти репозиции разделяют общую часть блока  block, чтобы можно было безопасно (см. примечание ниже) слияние изменений назад и между всеми этими репозиториями, как вы сочтете нужным.

---

Примечание: "безопасно", если вы не переписываете общую часть цепочки, и пока изменения не противоречат друг другу.