Skip to content

Vinnjy/git

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

41 Commits
 
 

Repository files navigation

Основы:

Base:


Base-Pro:


Pro:


Рабочии ситуации:




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

Pull & Push


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




  • Коммит в git репозитории хранит снимок всех файлов в директории = огромная копия, только лучше.

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

  • Git хранит всю историю о том, когда какой коммит был сделан. Вот почему большинство коммитов имеют предков - мы указываем на предков стрелками при визуализации. Поддержка истории коммитов более чем важна для всех, кто работает над проектом.

Пример.

  1. Визуализация небольшого git репозитория.

  2. Сейчас в нём два коммита: первый, исходный коммит С0 и один коммит С1 после него, содержащий изменения.

image

Решение.

  1. Пропишем команду:
git commit

Результат:

image
  • Только что внесли изменения в репозиторий и сохранили их как коммит. У коммита, который мы только что сделали, есть родитель, С1, который указывает на предыдущий коммит.

Пример.

Дано:

image
  1. Сделайте 2 коммита, чтобы получить визулизацию, как на картинке.
image

Решение.

  1. Пропишем в командной строке:
git commit
git commit

Результат:

image


  • Ветки в Git, как и коммиты, невероятно легковесны. Это просто ссылки на определённый коммит — ничего более. Вот почему многие фанаты Git повторяют мантру: "делай ветки сразу, делай ветки часто".

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

  • Cозданная ветка хранит изменения текущего коммита и всех его родителей.

Пример.

Создадим новую ветку с именем newImage.

image

Решение.

  1. Пропишем команду (создание ветки):
git branch newImage

Результат:

image
  • Ветка newImage указывает на коммит С1.
  1. Теперь сделаем коммит. Пропишем команду:
git commit

Результат:

image
  • Ветка main сдвинулась, тогда как ветка newImage - нет. Всё из-за того, что мы не переключились на новую ветку, а остались в старой, о чём говорит звёздочка около ветки main.
  1. Чтобы сделать коммит для ветки newImage, нужно переключиься на ветку, а затем сделать коммит. Вернёмся к пукнту 1:
image
  1. Пропишем 2 команды:
git checkout newImage
git commit

Результат:

image

Пример.

Дано:

image
  1. Создай ветку с именем bugFix и переключись на неё.

  2. Нужно получить визулизацию, как на картинке.

image

Решение.

  1. Пропишем команду:
git checkout -b bugFix
  • Создаст ветку и переключиться на неё.

Результат:

image


  • Как объединять изменения из двух разных веток.

    • Очень удобно создать ветку, сделать свою часть работы в ней и потом объединить изменения из своей ветки с общими.
  • Первый способ объединения изменений, который мы рассмотрим - git merge - слияние.

    • Слияния в Git создают особый вид коммита, который имеет сразу двух родителей. Коммит с двумя родителями обычно означает, что мы хотим объединить изменения из одного коммита с другим коммитом и всеми их родительскими коммитами.

Пример.

  1. Две ветки, каждая содержит по одному уникальному коммиту.

  2. Это означает, что ни одна из веток не содержит полный набор "работ", выполненных в этом репозитории.

  3. Можно исправить эту ситуацию, выполнив слияние.

image

Решение.

  1. Пропишем комвнду (слияние bugFix в main):
git merge bugFix

Результат:

image
  • Ветка main теперь указывает на коммит, у которого два родителя.

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

    • Это означает, что теперь в ветке main содержатся все изменения репозитория.

    • У каждой ветки — свой цвет. Каждый коммит становится того цвета, какого его ветка.

    • Если в нём изменения сразу двух веток - он становится цветом, смешанным из цветов родительских веток.

    • Цвет ветки main подмешан к каждому коммиту, а ветки bugFix - нет.

Продлжим пример.

Cделаем слияние ветки main в ветку bugFix.

  1. Пропишем комвнды:
git checkоut bugFix
git merge main

Результат:

image
  • Так как ветка bugFix была предшественницей main, Git не делал ничего, только сдвинул bugFix на тот же коммит, где находится main.

  • Теперь все коммиты одного цвета, что означает, что каждая ветка содержит все изменения репозитория.

Пример.

Дано:

image
  1. Создай новую ветку под названием bugFix.

  2. Переключись на новую ветку bugFix командой git checkout bugFix.

  3. Сделай один коммит.

  4. Вернись на ветку main при помощи git checkout.

  5. Сделай ещё один коммит.

  6. Слей ветку bugFix с веткой main при помощи git merge.

  7. Нужно получить визулизацию, как на картинке.

image

Решение.

  1. Пропишем команды:
git checkout -b bugFix
git commit
git checkout main
git commit
git merge bugFix

Результат:

image


  • Oбъединения изменений в ветках - это rebasing. При ребейзе Git по сути копирует набор коммитов и переносит их в другое место.

  • Преимущество rebase в том, что c его помощью можно делать чистые и красивые линейные последовательности коммитов. История коммитов будет чище, если вы применяете rebase.

Пример.

  1. Две ветки.

  2. Выбрана ветка bugFix (отмечена звёздочкой).

  3. Сдвинуть наши изменения из bugFix прямо на вершину ветки main.

  4. Благодаря этому всё будет выглядеть, как будто эти изменения делались последовательно, хотя на самом деле - параллельно.

image

Решение.

  1. Пропишем командцу:
git rebase main

Результат:

image
  • изменения из bugFix находятся в конце ветки main и являют собой линейную последовательность коммитов.

  • С3' - это его "копия" в ветке main.

  • Ветка main не обновлена до последних изменений
  1. Пропишем команду:
git checkout main

Результат:

image
  1. Пропишем команду:
git rebase bugFix

Результат:

image
  • Так как ветка main был предком bugFix, git просто сдвинул ссылку на main вперёд.

Пример.

Дано:

image
  1. Переключись на ветку bugFix.

  2. Сделай коммит.

  3. Вернись на main и сделай коммит ещё раз.

  4. Переключись на bugFix и сделай rebase на main.

  5. Нужно получить визулизацию, как на картинке.

image

Решение.

  1. Пропишем команды:
git checkout -b bugFix
git commit
git checkout main
git commit
git checkout bugFix
git rebase main

Результат:

image


  • HEAD - это символическое имя текущего выбранного коммита — это, по сути, тот коммит, над которым мы в данный момент работаем.

  • HEAD всегда указывает на последний коммит из вашего локального дерева.

  • Большинство команд Git, изменяющих рабочее дерево, начнут с изменения HEAD.

  • Обычно HEAD указывает на имя ветки (например, main). Когда вы делаете коммит, статус ветки main меняется и это изменение видно через HEAD.

Пример.

Смотрим, где находится HEAD до коммита и после при выполненных командах (в решении).

ДО:

image

Решение.

  1. Пропишем команды:
git checkout C1
git checkout main
git commit
git checkout C2

ПОСЛЕ:

image
  • HEAD скрывался за ветке main.

Detaching HEAD.

  • Отделение HEAD = присвоение не ветке, а конкретному коммиту.

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

  • Новые коммиты, сделанные в этом состоянии, будут "осиротевшими", так как они не принадлежат ни одной ветке, и их сложнее найти.

Зачем это нужно ?

  • Изучение истории: позволяет посмотреть на состояние проекта в прошлом, например, чтобы найти ошибку или изучить код определенного коммита.

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

Когда следует быть осторожным ?

  • Создание коммитов: если вы создадите новые коммиты в состоянии "отсоединенного HEAD", они не будут прикреплены к какой-либо ветке. Это может привести к их потере.

  • Потеря данных: Это может быть опасно, если вы забудете, что находитесь в "отсоединенном" состоянии, и случайно сделаете коммиты. Чтобы избежать этого, лучше сразу создать новую ветку для любых изменений.

Пример.

ДО:

  • HEAD -> main -> C1.
image

Решение.

  1. Пропишем команду:
git checkout C1

Результат:

image

ПОСЛЕ:

  • HEAD -> C1.

Пример.

Дано:

image
  1. Отделим HEAD от ветки bugFix и присвоим его последнему коммиту в этой же ветке.

  2. Укажи коммит при помощи его идентификатора (hash). Hash для каждого коммита указан в кружке на схеме.

  3. Нужно получить визулизацию, как на картинке.

image

Решение.

  1. Пропишем команду:
git checkout C4

Результат:

image


  • Передвигаться по дереву Git при помощи указания хешей коммитов так себе.

  • В реальной ситуации у вас вряд ли будет красивая визуализация дерева в терминале, так что придётся каждый раз использовать git log = чтобы найти хеш нужного коммита.

  • Более того, хеши в реальном репозитории Git намного более длинные. Например, хеш для коммита, который приведён в предыдущем уровне - fed2da64c0efc5293610bdd892f82a58e8cbc5d8.

  • Git достаточно умён в работе с хешами. Ему нужны лишь первые несколько символов для того, чтобы идентифицировать конкретный коммит. Так что можно написать просто fed2 вместо колбасы выше.

С относительными ссылками можно начать с какого-либо удобного места (например, с ветки bugFix или от HEAD) и двигаться от него.

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

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

    • Перемещение на несколько коммитов назад = ~.

Пример.

  1. Когда мы добавляем ^ к имени ссылки, Git воспринимает это как указание найти родителя указанного коммита.
  • Так что main^ означает "первый родитель ветки main".

  • main^^ означает прародитель (родитель родителя) main

  1. Давайте переключимся на коммит Выше main
image

Решение.

  1. Пропишем команду:
git checkout main^

Результат:

image

Вместо ветки, как относительная ссылка, можно использовать HEAD.

Пример.

  1. Пройдёмся несколько раз по дереву коммитов.
image

Решение.

  1. Пропишем команды:
git checkout C3
git checkout HEAD^
git checkout HEAD^
git checkout HEAD^

Результат:

image

Пример.

Дано:

image
  1. Переместись на первого родителя ветки bugFix. Это отделит HEAD от ветки.

  2. Нужно получить визулизацию, как на картинке.

image

Решение.

  1. Пропишите команду:
git checkout HEAD^

Результат:

image

Пример.

Переместиться на 4 коммита назад.

image

Решение.

  1. Пропишите команды:
git checkout HEAD~4

Результат:

image


  • Одна из наиболее распространённых целей, для которых используются относительные ссылки - перемещение веток.

  • Можно напрямую прикрепить ветку к коммиту при помощи опции -f, n - количество шагов назад.

  1. Пропишем команду:
git branch -f main HEAD~n
  • Переместит (принудительно) ветку main на n родителей назад от HEAD.

Пример.

Переместить ветку main на 3 родителя назад.

image

Решение.

  1. Пропишем команду:
git branch -f main HEAD~3

Результат:

image
  • Относительная ссылка дала нам возможность просто сослаться на C1, а branch forcing (-f) позволил быстро переместить указатель ветки на этот коммит.

Пример.

Дано:

image

Передвинь HEAD, main и bugFix так, как показано на визуализации.

image

Решение.

  1. Пропишем команды:
git branch -f main C6
git branch -f bugFix HEAD~2
git checkout HEAD~1

Результат:

image


  • Есть много путей для отмены изменений в Git.

  • На низком уровне = добавление в коммит отдельных файлов и наборов строк.

  • На высоком = как изменения реально отменяются.

2 способа:

git reset
git revert

git reset.

  • Отменяет изменения, перенося ссылку на ветку назад, на более старый коммит.

  • Это своего рода "переписывание истории".

  • git reset перенесёт ветку назад, как будто некоторых коммитов вовсе и не было.

Пример.

Посмотрим, как это работает.

image

Решение.

  1. Пропишем команду:
git reset HEAD~1

Результат:

image
  • Git просто перенёс ссылку на main обратно на коммит C1. Теперь наш локальный репозиторий в состоянии, как будто C2 никогда не существовал.

git revert.

  • Reset отлично работает на локальных ветках, в локальных репозиториях. Но этот метод переписывания истории не сработает на удалённых ветках, которые используют другие пользователи.

  • Чтобы отменить изменения и поделиться отменёнными изменениями с остальными = git revert.

Пример.

Посмотрим, как это работает.

image

Решение.

  1. Пропишем команду:
git revert HEAD

Результат:

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

Пример.

Дано:

image
  1. Отмени самый последний коммит на ветках local и pushed. Всего будет отменено два коммита (по одному на ветку).

  2. Помни, что pushed - это remote ветка, а local - это локальная ветка.

  3. Нужно получить визулизацию, как на картинке.

image

Решение.

  1. Пропишем команды:
git reset local~1
git checkout pushed
git revert pushed

Результат:

image


Итак, мы уже освоили основы Git:

  • коммиты
  • ветки
  • перемещение по дереву изменений.

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

  • Cherry pick = копировать несколько коммитов на место, где сейчас находишься (HEAD).

Делается с помощью команды:

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

Пример.

  1. Вот репозиторий, где есть некие изменения в ветке side, которые мы хотим применить и в ветку main.

  2. Мы можем сделать это при помощи команды rebase, которую мы уже прошли, но давай посмотрим, как cherry-pick справится с этой задачей.

image

Решение.

  1. Пропишем команду:
git cherry-pick C2 C4

Результат:

image
  • Копии С2 и С4 теперь в ветке, где был HEAD.

Пример.

Дано:

image
  1. Cкопируй изменения из этих трёх веток в мастер. Чтобы понять, какие коммиты копировать, посмотри на визуализацию уровня.
image

Решение.

  1. Пропишем команду:
git cherry-pick C3 C4 C7

Результат:

image


  • Git cherry-pick прекрасен = когда точно известно, какие коммиты нужны = известны их точные хеши.

  • Когда нет, то интерактивный rebase = опция -i.

  • Git откроет интерфейс просмотра того, какие коммиты готовы к копированию на цель rebase (target).

  • Показываются хеши коммитов и комментарии к ним, так что можно легко понять что к чему.

Для "реального" Git, этот интерфейс означает просто открытие файла в редакторе типа vim. Редактор заменит диалоговое окно (делают одно и тоже).

После открытия окна интерактивного rebase есть три варианта для каждого коммита:

  • Сменить положение коммита по порядку, переставив строчку с ним в редакторе.

  • "Выкинуть" коммит из ребейза. Для этого есть pick - переключение его означает, что нужно выкинуть коммит.

  • Соединить коммиты.

Пример.

  1. Появится окно интерактивного rebase.

  2. Переставляем несколько коммитов (или удали кое-какие) и посмотри, что получится в итоге.

image

Решение.

  1. Пропишем команду:
git rebase -i HEAD~4

Результат:

image image
  • Скопировали коммиты, как сами и указали.

Пример.

Дано:

image
  1. Переставь коммиты при помощи интерактивного rebase в таком порядке, как указано на визуализации.
image

Решение.

  1. Пропишем команду:
git rebase -i HEAD~4

Результат:

image
  1. Удаляем С2 через фиолетовую кнопку, переставляем С5 и С4 и нажимаем "Подтвержить".
image image


Вот ситуация, которая часто случается при разработке: мы пытаемся отследить ошибку, но она не очень очевидна.

Для того, чтобы достичь успеха на этом поприще, мы используем несколько команд для отладки и вывода.

Каждая отладочная команда (команды) вывода находится в своём коммите.

В итоге мы нашли ошибку, исправили её и порадовались!

Но проблема в том, что мы хотим добавить в main только исправление ошибки из ветки bugFix. Если мы воспользуемся простым fast-forward, то в main попадут также отладочные команды. Должен быть другой способ...

Пример.

Дано:

image
  1. Git копировать только один из коммитов.

  2. Убедись, что в ветку main попал коммит, на который ссылается bugFix.

  3. Нужно получить визулизацию, как на картинке.

image

Решение.

  1. Пропишем команды:
git rebase -i HEAD~3
git branch -f main HEAD (или bugFix или С4)
git checkout main
git cherry-pick C4 (или bugFix)

Результат:

image


git rebase -i.

Есть некоторые изменения "newImage" и другие изменения "caption", которые связаны так, что находятся друг поверх друга в репозитории.

Штука в том, что иногда нужно внести небольшие изменения в более ранний коммит. В таком случае надо немного поменять newImage, несмотря на то, что коммит уже в прошлом.

Пример.

Дано:

image
  1. Переставить коммит так, чтобы нужный находился наверху при помощи = git rebase -i.

  2. Внести изменения при помощи = git commit --amend = позволяет добавить новые изменения в последний коммит.

  3. Переставить всё обратно при помощи = git rebase -i.

  4. Переместить main на изменённую часть дерева, чтобы закончить уровень.

  5. Нужно получить визулизацию, как на картинке.

image

Решение.

  1. Пропишем команды:
git rebase -i HEAD~2 (переставляем С3 и С2 местами при интерактивном окне) (после выполенния ветка caption вместе с HEAD указывает на C2')
git commit --amend (получим коммит С2'')  (C2' и C2'' имеют одного родителя C3')
git rebase -i HEAD~2 (переставляем С3' и С2'' местами при интерактивном окне)
git branch -f main HEAD (перемещаем ветку main в HEAD)

Результат:

image

git cherry-pick.

До этого использовали rebase -i для перестановки коммитов. Как только нужный нам коммит оказывался в конце, мы могли спокойно изменить его при помощи --amend и переставить обратно.

Такой подход может спровоцировать конфликты. Посмотрим, как справиться с этим cherry-pick.

  • Cherry-pick = поместит любой коммит сразу после HEAD (только если этот коммит не является предком HEAD).

Пример.

image

Решение.

  1. Пропишем команду:
gir cherry-pick C2

Результат:

image

Пример.

Дано:

image
  1. Та же самая задача. Нужно получить визулизацию, как на картинке.
image

Решение.

  1. Пропишем команды:
git checkout main
git cherry-pick C2
git branch -f main HEAD~1
git cherry-pick C2' C3

Результат:

image


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

  • Ветки просто изменить, часто временны, постоянно меняют своё состояние.

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

  • Git предоставляет нам теги.

  • Основная задача – ссылаться постоянно на конкретный коммит.

  • После создания никогда не сменят своего положения, так что можно с лёгкостью сделать checkout конкретного момента в истории изменений.

Пример.

Создадим тег на C1, который будет нашей версией 1.

image

Решение.

  1. Пропишем команду:
git tag v1 C1

Результат:

image
  • Тег v1 = ссылается на C1 явным образом.

  • Если конкретный коммит не указан, гит пометит тегом HEAD.

Пример.

Дано:

image
  1. Создайте теги так, как показано на визуализации, и потом перейди на тег v1. Обрати внимание, что ты перейдёте в состояние detached HEAD, так как нельзя сделать коммит прямо в тег v1.
image

Решение.

  1. Пропишем команды:
git checkout C2
git tag v1 C2
git tag v0 C1

Результат:

image


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

Git describe помогает сориентироваться после отката на много коммитов по истории изменений. Такое может случиться, когда вы сделали git bisect или если вы недавно вернулись из отпуска.

git describe <ref>
  • ref — это что-либо, что указывает на конкретный коммит. Если не указать ref, то git будет считать, что указано текущее положение (HEAD).

Вывод команды выглядит примерно так:

<tag>-<numCommits>-g<hash>
  • tagближайший тег в истории изменений.

  • numCommitsна сколько далеко мы от этого тега.

  • hashхеш коммита, который описывается.

Пример.

image

Решение.

  1. Пропишем команду:
git tag v2 C3

Результат:

image
  • git describe main выведет:

    • v1-2-gC2
  • git describe side выведет:

    • v2-1-gC4

Пример.

Дано:

image
  1. Нужно получить визулизацию, как на картинке.
image

Решение.

  1. Пропишем команды:
git commit
git describe main
git describe bugFix

Результат:

image image


Пример.

Дано:

image
  1. У нас тут куча веток! Было бы круто перенести все изменения из них в мастер.

  2. Но начальство усложняет нашу задачу тем, что желает видеть все коммиты по порядку. Так что коммит С7' должен идти после коммита С6' и так далее.

  3. Нужно получить визулизацию, как на картинке.

image

Решение.

  1. Пропишем команды:
git checkout bugFix
git rebase main
git checkout side
git rebase -i bugFix
git checkout another
git rebase -i side
git branch -f main HEAD

Результат:

image


  • Так же как тильда (~), каретка (^) принимает номер после себя.

Но в отличие от количества коммитов, на которые нужно откатиться назад (как делает ~).

  • Номер после ^ определяет, на какого из родителей мерджа надо перейти. Учитывая, что мерджевый коммит имеет двух родителей, просто указать ^ нельзя.

  • Git по умолчанию перейдёт на "первого" родителя коммита.

Пример.

image

Решение.

  1. Пропишем команду:
git checkout main^2

Результат:

image

Пример.

image

Решение.

  1. Пропишем команды:
git checkout HEAD~
git checkout HEAD^2
git checkout HEAD~2
git checkout HEAD~^2~2

Результат:

image

Пример.

Дано:

image
  1. Cоздай ветку в указанном месте.

  2. Нужно получить визулизацию, как на картинке.

image

Решение.

  1. Пропишем команду:
git branch -f bugWork HEAD~^2^

Результат:

image


Пример.

Дано:

image
  1. У нас тут по несколько коммитов в ветках one, two и three. Не важно почему, но нам надо видоизменить эти три ветки при помощи более поздних коммитов из ветки main.

  2. Ветка one нуждается в изменении порядка и удалении C5. two требует полного перемешивания, а three хочет получить только один коммит.

  3. Нужно получить визулизацию, как на картинке.

image

Решение.

  1. Пропишем команды:
git checkout one
git cherry-pick C4 C3 C2
git checkout two
git cherry-pick C5 C4' C3' C2'
git branch -f three C2

Результат:

image


  • Удалённые репозитории — копии репозитория, хранящиеся на другом компьютере. Можете связываться с этим компьютером через Интернет, что позволяет вам передавать коммиты туда и сюда.

Свойства:

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

  • процесс разработки более социальным. Когда копия проекта размещена в другом месте, коллеги запросто могут внести свой вклад в ваш проект или забрать последние и актуальные изменения.

git clone.

  • git clone в реальной жизни - создаст локальную копию удалённого репозитория (например, с GitHub).

  • В тренажёре - создаёт удалённый репозиторий на основе вашего локального репозитория. На самом деле, это является полной противоположностью реальной команды.

Пример.

image

Решение.

  1. Пропишем команду:
git clone

Результат:

image


  • В локальном репозитории по предыдущему примеру появилась новая ветка с именем o/main = удалённой веткой.

Свойтва:

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

  • Отслеживать разницу между вашими локальными наработками и тем, что было сделано другими участниками.

  • Извлечение их, отделяет = detaching HEAD. Git делает это потому, что не можете работать непосредственно в этих ветках; сперва вам необходимо сделать наработки где-либо, а уж затем делиться ими с удалёнными репозиториями (после чего удалённые ветки будут обновлены).

Что такое "o/" в названии ветки?

  • o/ в названии ветки = обозначениe удалённых веток.

Формате:

<удалённый репозиторий>/<имя ветки>
  • Имя ветки o/main:

    • *main = имя ветки.

    • o = имя удалённого репозитория.

  • В работе не как o, а как origin.

Пример.

  1. Извлечём (check out) удалённую ветку и посмотрим что произойдёт.
image

Решение.

  1. Пропишем команды:
git checkout o/main
git commit

Результат:

image
  • Отделил detached HEAD и не обновил o/main, когда мы добавили новый коммит. Всё потому, что o/main обновится тогда и только тогда, когда обновится сам удалённый репозиторий.

Пример.

Дано:

image
  1. Выполните коммит единожды на main, а затем на o/main (предварительно переключившись на эту ветку). Это наглядно продемонстрирует поведение удалённых веток, а также покажет, как изменения влияют на состояние удалённых репозиториев.

  2. Нужно получить визулизацию, как на картинке.

image

Решение.

  1. Пропишем команды:
git commit
git checkout o/main
git commit

Результат:

image


Работа с удалёнными git репозиториями сводится к передаче данных "в и из" других репозиториев.

Отправляя коммиты туда-обратно, можем делиться любыми изменениями, которые отслеживает git (следовательно, делиться новыми файлами, свежими идеями, любовными письмами и т.д.).

git fetch.

  • Извлечение данных из удалённого репозитория = git fetch.

  • Как только изменим представление удалённого репозитория, удалённые ветки обновятся соответствующим образом и отобразят это представление.

Пример.

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

image

Решение.

  1. Пропишем команду:
git fetch

Результат:

image
  • Коммиты C2 и C3 были успешно скачаны в локальный репозиторий.

  • Удалённая ветка o/main отобразила эти изменения соответствующим образом.

Что делает fetch.

git fetch выполняет две операции:

  1. Cвязывается с указанным удалённым репозиторием и забирает все те данные проекта, которых у вас ещё нет, при этом...

  2. Должны появиться ссылки на все ветки из этого удалённого репозитория (например, o/main).

Фактически, git fetch синхронизирует локальное представление удалённых репозиториев с тем, что является актуальным на текущий момент времени.

  • git fetch 'общается' с удалёнными репозиториями посредством Интернета (через такие протоколы, как http:// или git://).

Чего fetch не делает

  • git fetch забирает данные в ваш локальный репозиторий, но не сливает их с какими-либо вашими наработками и не модифицирует то, над чем вы работаете в данный момент.

Важно это помнить и понимать, потому что многие разработчики думают, что, запустив команду git fetch, они приведут всю свою локальную работу к такому же виду, как и на удалённом репозитории. Команда всего лишь скачивает все необходимые данные, но вам потребуется вручную слить эти данные с вашими, когда вы будете готовы.

  • git fetch = процедура скачивания новые данные из удаленного репозитория, но не сливает их с вашими локальными файлами.

Пример.

Дано:

image
  1. Запустите git fetch и скачайте все коммиты!

  2. Нужно получить визулизацию, как на картинке.

image

Решение.

  1. Пропишем команду:
git fetch

Результат:

image


git pull состоит из двух команд:

  • git fetch = загрузка изменений из удаленного репозитория. Cкачивает новые данные из удаленного репозитория, но не сливает их с вашими локальными файлами.

  • git merge = слияние загруженных изменений с локальной веткой. Объединяет новые изменения из удаленной ветки с текущей локальной веткой.

  • Коммит слияния: Если слияние происходит успешно, git автоматически создаст новый "коммит слияния" для фиксации этих изменений. Этот коммит будет иметь два родительских элемента: родительский коммит из вашей локальной ветки и коммит из ветки, которую вы скачали.

Пример.

image

Решение.

  1. Пропишем команды:
git fetch
git merge
git pull

Результат:

image
  • Cкачали C3 с помощью команды fetch и затем объединяем эти наработки с помощью git merge o/main.

  • Ветка main отображает изменения с удалённого репозитория (в данном случае — с репозитория origin).

  • git pull существенно уменьшает работу, если бы использовали git fetch и слияние (merging) скачанной ветки.

Пример.

Дано:

image
  1. Нужно получить визулизацию, как на картинке.
image

Решение.

  1. Пропишем команду:
git pull

Результат:

image


Cкачивать наработки и изменения, которые были сделаны в удалённом репозитории.

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

git fakeTeamwork.

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

Пример.

image

Решение.

  1. Пропишем команду:
git fakeTeamwork

Результат:

image
  • Удалённый репозиторий был изменён при помощи добавления нового коммита.

Пример.

image

Решение.

  1. Пропишем команду:
git fakeTeamwork foo 3

Результат:

image
  • Добавление трёх коммитов в ветку foo на удалённом репозитории.

Пример.

Дано:

image
  1. Склонируйте удалённый репозиторий (с помощью git clone), симулируйте любые изменения на этом удалённом репозитории, сделайте какие-нибудь коммиты и затем скачайте "чужие" изменения.

  2. Нужно получить визулизацию, как на картинке.

image

Решение.

  1. Пропишем команды:
git clone
git fakeTeamwork main 2
git commit
git pull

Результат:

image


Cкачали изменения с удалённого репозитория и включили их в локальные наработки.

Но как нам поделиться своими наработками и изменениями с другими участниками проекта?

Способ противоположным тому, которым пользовались ранее для скачивания наработок = git pull. Cпособ - использование команды git push.

  • git push отвечает:

    • за загрузку ваших изменений в указанный удалённый репозиторий.

    • включение локальных коммитов в состав удалённого репозитория.

  • git push = "публикацию" своей работы.

Замечание.

Поведение команды git push без аргументов варьируется в зависимости от значения push.default, указанной в настройках git. Значение по умолчанию зависит от версии git, которую вы используете. Здесь используется значение = upstream.

Пример.

  1. У нас имеются изменения, которых нет в удалённом репозитории. Давайте же закачаем их туда!
image

Решение.

  1. Пропишем команду:
git push

Результат:

image
  • Удалённый репозиторий получил новый коммит C2.

  • Ветка main на удалённом репозитории теперь указывает на C2.

  • Локальное отображение удалённого репозитория (o/main) изменилось соответственно. Всё синхронизировалось.

Пример.

Дано:

image
  1. Просто поделитесь своими двумя новыми коммитами с удалённым репозиторием

  2. Нужно получить визулизацию, как на картинке.

image

Решение.

  1. Пропишем команды:
git commit
git commit
git push

Результат:

image


  • Как забирать = pull = чужие коммиты.

  • Как закачивать = push = свои наработки и изменения.

Нюансы возникают тогда, когда история репозитория расходится.

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

  2. В пятницу вечером готовы опубликовать фичу.

  3. Но, о нет! Ваш коллега в течение недели написал кучу кода, который делает все наработки устарелыми. Код был также закоммичен и опубликован на удалённом репозитории, поэтому код базируется на устаревшей версии проекта и более не уместен.

    • В этом случае использование команды git push является сомнительным.

    • Как поведёт себя команда git push, если вы её выполните?

    • Может быть, она изменит удалённый репозиторий и вернёт всё к тому состоянию, которое было в понедельник?

    • Может, команда попробует добавить ваш код, не удаляя при этом новый? Или же она проигнорирует ваши изменения, так как они уже устарели?

  4. По причине того, что в данной ситуации (когда история расходится) слишком много двусмысленностей и неопределённостей, git не даст закачать (push) ваши изменения.

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

Пример.

image

Решение.

  1. Пропишем команду:
git push

Результат:

image
  • Ничего не произошло.

  • Всё потому, что команда git push не выполнилась успешно.

  • Дело в том, что ваш последний коммит C3 основан на удалённом коммите C1. В свою очередь, удалённый репозиторий уже изменился под воздействием C2. Вот почему git отклонил ваш push.

Вариант 1.

  • Перебазировать свою работу на самую последнюю версию удалённой ветки.

Существует множество способов сделать это, но наиболее простой способ 'сдвинуть' свои наработки - через перебазировку или rebasing.

Пример.

image

Решение.

  1. Пропишем команды:
git fetch
git rebase o/main
git push

Результат:

image
  • Обновили локальный образ удалённого репозитория средствами git fetch.

  • Перебазировали наработки, чтобы отражали все изменения с удалённого репозитория.

  • Опубликовали их с помощью git push.

Вариант 2.

  • git merge не передвигает ваши наработки = создаёт новый коммит, в котором Ваши и удалённые изменения объединены.

  • Такой способ помогает указать git на то, что собираетесь включить в состав ваших наработок все изменения с удалённого репозитория = ваш коммит отразится на всех коммитах удалённой ветки, поскольку удалённая ветка является предком вашей собственной локальной ветки.

Пример.

Если мы объединим (merge) вместо перебазирования (rebase)..

image

Решение.

  1. Пропишем команды:
git fetch
git merge o/main
git push

Результат:

image
  • Обновили локальное представление удалённого репозитория с помощью git fetch.

  • Объединили ваши новые наработки с нашими наработками (чтобы отразить изменения в удалённом репозитории).

  • Затем опубликовали их с помощью git push.

Вариант 3.

  • git pull --rebase = аналог для совместно вызванных fetch и rebase.

Пример.

image

Решение.

  1. Пропишем команды:
git pull --rebase
git push

Результат:

image
  • Тот же результат, как и ранее, но намного короче вызов команд.

Вариант 4.

Пример.

image

Решение.

  1. Пропишем команды:
git pull
git push

Результат:

image
  • И снова - результат такой же, как и ранее.

Пример.

Дано:

image
  1. Рабочий процесс получения изменений (fetching), перебазирования/объединения (rebase/merging) и публикации изменений (pushing):

    • Склонируйте репозиторий.

    • Сфабрикуйте командную работу (1 коммит).

    • Сделайте свой собственный коммит (1 коммит).

    • Опубликуйте свои наработки посредством перебазировки (rebasing).

  2. Нужно получить визулизацию, как на картинке.

Решение.

  1. Пропишем команды:
git clone
git fakeTeamwork main 1
git commit
git pull --rebase
git push

Результат:

image


Remote Rejected!

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

Для внесения изменений в неё в git существует понятие запроса на слияние Pull Request. В такой ситуации если закоммитите свои наработки непосредственно в main ветвь, а после выполните git push, то будет сгенерировано сообщение об ошибке:

! [remote rejected] main -> main (TF402455: Pushes to this branch are not permitted; you must use a pull request to update this branch.)
! [удалённо отклонено] main -> main (TF402455: Изменение этой ветви запрещены; вы можете использовать pull request для обновления этой ветви.)

Почему произошло отклонение моих изменений?

Удалённый репозиторий отклонил загруженные коммиты непосредственно в main ветку потому, что на main настроена политика, которая требует использование Pull request вместо обычного git push:

  • Политика подразумевает процесс создания новой ветви разработки, внесение в неё всех необходимых коммитов, загрузка изменений в удалённый репозиторий и открытие нового Pull request.

Пример.

Дано:

image
  1. Создайте ещё одну ветвь под названием feature.

  2. Отправьте изменения на удалённый репозиторий.

  3. Не забудьте вернуть локальную main ветвь в исходное состояние (чтобы она была синхронизирована с удалённой). В противном случае у вас могут возникнуть проблемы при следующем выполнении git pull.

  4. Нужно получить визулизацию, как на картинке.

image

Решение.

  1. Пропишем команды:
git branch -f main o/main
git checkout -b feature C2
git push 

Результат:

image


Слияние фича-бранчей (веток)

Workflow

Среди разработчиков, вовлечённых в большой проект, довольно распространённ приём — выполнять всю свою работу в так называемых фича-бранчах (вне main). А затем, как только работа выполнена, разработчик интегрирует всё, что было им сделано.

  • Ряд разработчиков делают push и pull лишь на локальную ветку main = таким образом ветка main всегда синхронизирована с тем, что находится на удалённом репозитории (o/main).

Для этого рабочего процесса совместили две вещи:

  • Интеграция фича-бранчей в main.

  • Закачку (push) и скачку (pull) с удалённого репозитория.

Пример.

Быстренько вспомним, как нам обновить main и закачать выполненную работу.

image

Решение.

  1. Пропишем команды:
git pull --rebase
git push 

Результат:

image
  • Перебазировали нашу работу на новенький коммит, пришедший с удалённого репозитория.

  • Закачали свои наработки в удалённый репозиторий.

Пример.

Дано:

image
  1. Есть три фича-бранчи (фича-ветки) - side1 side2 и side3.

  2. Нам необходимо закачать каждую из них по очереди на удалённый репозиторий.

  3. При этом удалённый репозиторий хранит в себе какие-то наработки, которые также следует скачать к себе.

  4. Нужно получить визулизацию, как на картинке.

image

Решение.

  1. Пропишем команды:
git fetch (main останется на месте, если и использовали pull, то сметилась бы вместе с o/main)
git rebase o/main side1 (side1, указывающая на коммит С2 = перебазирется на ветку o/main и добавит копию С2 к этому коммиту, side1 укажет на С2')
git rebase side1 side2
git rebase side2 side3
git rebase side3 main
git push

Результат:

image


  • Чтобы закачать (push) новые изменения в удалённый репозиторий, всё, что вам нужно сделать = это смешать последние изменения из удалённого репозитория.

Можем выполнить rebase или merge на удалённом репозитории (например, o/main).

За:

  • Rebasing делает дерево коммитов более чистым и читабельным, потому что всё представляется единой прямой линией.

Против:

  • Метод rebasing явно изменяет историю коммитов в дереве. Пример:

  • Коммит C1 может быть перебазирован после C3. Соответственно, в дереве работа над C1' будет отображаться как идущая после C3, хотя на самом деле она была выполнена раньше.

Некоторые разработчики любят сохранять историю и предпочитают слияние (merging). Другие предпочитают иметь чистое дерево коммитов, и пользуются перебазировкой (rebasing). Всё зависит от ваших предпочтений и вкусов.

Пример.

Дано:

image
  1. Решите предыдущие задачи, но с помощью слияния (merging). Может быть, получится слегка неказисто, однако такое упражнение хорошо отразит суть различий.

  2. Нужно получить визулизацию, как на картинке.

image

Решение.

  1. Пропишем команды:
git checkout main
git pull
git merge side1
git merge side2
git merge side3
git push

Результат:

image


Удалённые-отслеживаемые ветки

  • git знает, что ветка main соответствует o/main. Ветки имеют схожие имена и связь между локальной и удалённой ветками main выглядит вполне логично, однако, связь наглядно продемонстрирована в двух сценариях:
  1. Во время операции pull коммиты скачиваются в ветку o/main и затем соединяются в ветку main. Подразумеваемая цель слияния определяется исходя из этой связи.

  2. Во время операции push наработки из ветки main закачиваются на удалённую ветку main (которая в локальном представлении выглядит как o/main). Пункт назначения операции push определяется исходя из связи между main и o/main.

Связь между main и o/main объясняется не иначе как свойство "удалённое отслеживание" веток:

  • Ветка main настроена так, чтобы следить за o/main -- это подразумевает наличие источника для merge и пункта назначения для push в контексте ветки main. Когда вы клонируете репозиторий, это слежение включается автоматически.

  • В процессе клонирования git локально создаёт удалённые ветки для каждой ветки с удалённого репозитория (такие как o/main).

  • Затем git создаёт локальные ветки, которые отслеживают текущую, активную ветку на удалённом репозитории. В большинстве случаев - это main.

К тому моменту как git clone завершит своё выполнение = будет лишь одна локальная ветка, но можете увидеть все удалённые ветки.

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

local branch "main" set to track remote branch "o/main" (локальная ветка "main" теперь следит за удалённой веткой "o/main")

Можно сделать самостоятельно

Cпособ 1 = git checkout -b векта o/main

Можете сказать любой из веток, чтобы отслеживала o/main, и если так сделать, ветка будет иметь такой же пункт назначения для push и merge как и локальная ветка main.

  • Значит, что можете выполнить git push, находясь на ветке totallyNotMain, и наработки с ветки totallyNotMain будут закачены на ветку main удалённого репозитория!

Выполнить checkout для новой ветки, указав удалённую ветку в качестве ссылки. Для этого необходимо выполнить команду:

git checkout -b totallyNotMain o/main
  • Cоздаст новую ветку с именем totallyNotMain и укажет ей следить за o/main.

Пример.

Выполним checkout для новой ветки foo и укажем ей, чтобы она отслеживала main с удалённого репозитория.

image

Решение.

  1. Пропишем команды:
git checkout -b foo o/main
git pull

Результат:

image
  • использовали o/main, чтобы обновить ветку foo.

Пример.

image

Решение.

  1. Пропишем команды:
git checkout -b foo o/main
git commit
git push

Результат:

image
  • Закачали наработки на ветку main удалённого репозитория. Докальная ветка называется абсолютно по-другому.

Способ 2 = git branch -u o/main ветка

Указать ветке отслеживать удалённую ветку — это просто использовать команду git branch -u. Выполнив команду:

git branch -u o/main foo
  • Укажете ветке foo следить за o/main.

Если вы ещё при этом находитесь на ветке foo, то её можно не указывать:

git branch -u o/main

Пример.

image

Решение.

  1. Пропишем команды:
git branch -u o/main foo
git commit
git push

Результат:

image

Пример.

Дано:

image
  1. Выполним push наших наработок в ветку main на удалённом репозитории, при этом не скачивая и не создавая ветку main локально. Вместо этого вам следует создать ветку с именем side.

  2. Нужно получить визулизацию, как на картинке.

image

Решение.

  1. Пропишем команды:
git checkout -b side o/main
git commit
git pull --rebase
git push

Результат:

image


Команда:

git push <удалённый_репозиторий> <целевая_ветка>

Что за такой параметр <целевая_ветка>?

Пример.

Выполняем такую команду:

git push origin main

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

  • Перейди в ветку с именем "main" в локальном репозитории, возьми все коммиты и затем перейди на ветку "main" на удалённом репозитории "origin". На удалённую ветку скопируй все отсутствующие коммиты, которые есть у меня, и скажи, когда закончишь.

Указывая main в качестве аргумента "целевая_ветка", тем самым говорим git:

  • откуда будут приходить и куда будут уходить наши коммиты.

  • Аргумент "целевая_ветка" или "местонахождение" = синхронизация между двумя репозиториями.

Пример.

  1. Указаны оба этих аргумента. Обратите внимание на местоположение, в котором мы находимся после чекаута.
image

Решение.

  1. Пропишем команды:
git checkout С0
git push origin main

Результат:

image
  • Обновили main на удалённом репозитории, принудительно указав аргументы в push.

Пример.

  1. Тоже самое.
image

Решение.

  1. Пропишем команды:
git checkout С0
git push 

Результат:

image
  • Команда -, так как HEAD потерялся и не находится на удалённо-отслеживаемой ветке.

Пример.

Дано:

image
  1. Обновим обе ветки foo и main на удалённом репозитории.

  2. Нужно получить визулизацию, как на картинке.

image

Решение.

  1. Пропишем команды:
git push origin foo
git push origin main

Результат:

image

Подробности аргумента <пункт назначения>

  • Источник и получатель коммитов были различными?

  • Что, еслизапушить коммиты из локальной ветки foo в ветку bar на удалённом репозитории?

Разделить источник и получатель аргумента <пункт назначения>, соедините их вместе, используя двоеточие:

git push origin <источник>:<получатель>
  • Обычно это называется refspec.

  • Refspec — это всего лишь модное имя для определения местоположения, которое git может распознать (например, ветка foo или просто HEAD~1).

Пример.

  • Источник = местоположение, которое git должен понять.
image

Решение.

  1. Пропишем команду:
git push origin foo^:main

Результат:

image
  • git видит в foo^ не что иное, как местоположение, закачивает все коммиты, которые не присутствуют на удалённом репозитории, и затем обновляет получателя.

А что если пункт назначения, в который запушить, не существует? Без проблем! Укажите имя ветки, и git сам создаст ветку на удалённом репозитории для вас.

Пример.

image

Решение.

  1. Пропишем команду:
git push origin main:newBranch

Результат:

image

Пример.

Дано:

image
  1. Нужно получить визулизацию, как на картинке.
image

Решение.

  1. Пропишем команды:
git push origin foo^:foo
git push origin foo:main
git push origin main^:foo
git push origin main^:foo
git push origin foo:main

Результат:

image


Параметр <пункт назначения>

Если указываете пункт назначения в команде git fetch, например так, как в следующем примере:

git fetch origin foo
  • Git отправится в ветку foo на удалённом репозитории, соберёт с собой все коммиты, которые не присутствуют локально, и затем поместит их в локальную ветку под названием o/foo.

Пример.

image

Решение.

  1. Пропишем команду:
git fetch origin foo

Результат:

image
  • Cкачали только коммиты с ветки foo и поместили их в o/foo.

Зачем git поместил экоммиты в ветку o/foo вместо того, чтобы разместить их в локальной ветке foo ?

Думали о параметре <пункт назначения>, как о месте, ветке, которая существует в обоих - локальном и удалённом репозитории. Верно?

На самом деле:

В данном случае git делает исключение, потому что вы, возможно, работаете над веткой foo, которую не хотите привести в беспорядок. Об этом упоминалось в ранних уроках по git fetch - эта команда не обновляет локальные 'не удалённые', она лишь скачивает коммиты (соответственно, можете инспектировать / объединять их позже).

"Что же тогда произойдёт, если я явно укажу оба параметра: и источник и получатель, пользуясь синтаксисом <источник>:<получатель> ?"

Если уверены в том, что закачать коммиты прямиком в вашу локальную ветку, тогда да, можете явно указать источник и получатель через двоеточние = таким приёмом лишь для ветки, на которой не находитесь в настоящий момент checkout. Теперь:

  • <источник> - это место на удалённом репозитории.

  • <получатель> - место в локальном репозитории, в который следует помещать коммиты.

Как уже было сказано, разработчики редко используют такой подход на практике.

Пример.

image

Решение.

  1. Пропишем команду:
git fetch origin C2:bar

Результат:

image
  • git распознал C2 как место в origin и затем скачал эти коммиты в bar, которая является локальной веткой.

Если ветка-получатель не существует на момент запуска команды?

Поведение будет такое же, как и у git push.

А если вообще без аргументов ?

Если команда git fetch выполняется без аргументов, она скачивает все-все коммиты с удалённого репозитория и помещает их в соответствующие удалённо-локальные ветки в локальном репозитории...

Пример.

image

Решение.

  1. Пропишем команду:
git fetch

Результат:

image

Пример.

Дано:

  1. Cкачайте лишь определённые коммиты так, как представлено в визуализации цели. Cледует явно указывать источник и получателя для обеих команд fetch.

  2. Нужно получить визулизацию, как на картинке.

Решение.

  1. Пропишем команды:
git fetch origin C3:foo
git fetch origin C6:main
git checkout foo
git merge main

Результат:

image


Git использует параметр <источник> странным образом. Странность заключается в том, что Вы можете оставить пустым параметр <источник> для команд git push и git fetch:

git push origin :side
git fetch origin :bugFix

Пример.

Что же будет с веткой, на которую мы делаем git push с пустым аргументом <источник>?

Она будет удалена.

image

Решение.

  1. Пропишем команду:
git push origin :foo

Результат:

image
  • Удалили ветку foo в удаленном репозитории, попытавшить протолкнуть(git push) в неё "ничего".

Пример.

  1. Если попытаемся притянуть изменения (git fetch) из "ничего" к нам в локальный репозиторий, то это создаст новую ветку:
image

Решение.

  1. Пропишем команду:
git fetch origin :bar

Результат:

image
  • Появилась локальная ветка bar.

Пример.

Дано:

image
  1. Удалить одну ветку в удаленном репозитории и создать новую ветку в локальном

  2. Нужно получить визулизацию, как на картинке.

image

Решение.

  1. Пропишем команды:
git push origin :foo (удалит)
git fetch origin :bar (добавит)

Результат:

image


  • git pull:

    • Cначала выполняет git fetch

    • Cледом сразу git merge с той веткой, в которую притянулись обновления командой fetch.

Другими словами, это все равно, что выполнить git fetch с теми же аргументами, которые вы указали для pull, а затем выполнить git merge с веткой, указанной в аргументе <приемник> команды pull.

Эквивалентны:

git pull origin foo
git fetch origin foo
git merge o/foo

Эквивалентны:

git pull origin bar:bugFix
git fetch origin bar:BugFix
git merge bugFix

Пример.

Cначала выполнится fetch с аргументом указанным к pull, а merge выполняется с теми изменениями, которые будут скачаны командой fetch.

image

Решение.

  1. Пропишем команду:
git pull origin main

Результат:

image
  • Указали main, поэтому как обычно все обновления притянулись на ветку o/main. Затем мы слили (merge) обновленную ветку o/main с веткой, на которой мы находимся.

Пример.

Будет ли это работать, если указать <источник> и <приемник>? Проверим:

image

Решение.

  1. Пропишем команду:
git pull origin main:foo

Результат:

image
  • Cоздали новую ветку foo в локальном репозитории, скачали на неё изменения с ветки main удаленного репозитория, а затем слили ветку с веткой bar, на которой находились.

Пример.

Дано:

image
  1. Cкачать несколько изменений, создать несколько новых веток, слить одни ветки в другие.

  2. Нужно получить визулизацию, как на картинке.

image

Решение.

  1. Пропишем команды:
git pull origin C3:foo
git pull origin C2:main

Результат:

image

About

Команды

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published