Перейти к содержимому

git fetch

Определение

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

git fetch

Как это работает с удалёнными ветками

Git хранит локальные и удалённые коммиты и разделяет их с помощью ссылок на ветки. Ссылки для локальных веток хранятся в /.git/refs/heads/. Чтобы увидеть список ссылок локальных веток, выполните команду git branch.

git branch

bash
git branch
* master
  crossword
  solver

Если просмотреть содержимое каталога /.git/refs/heads/, будет следующий вывод:

ls ./.git/refs/heads/

bash
ls ./.git/refs/heads/
master
crossword
solver

Ссылки удалённых веток хранятся в каталоге ./.git/refs/remotes/. Чтобы увидеть удалённые ветки, используйте флаг -r с git branch. Вот вывод после получения данных из удалённого репозитория:

git branch -r

bash
git branch -r
  origin/master
  origin/crossword
  origin/solver
  remote-repo/master
  remote-repo/other-feature

Вывод показывает удалённые ветки с префиксом origin/. Вы можете просматривать удалённые ветки с помощью команд git checkout и git log. После одобрения изменений удалённой ветки вы можете слить её с локальной веткой с помощью команды git merge. Вместо этого используйте команду git pull, чтобы сократить процесс.

Общие параметры

--allЗагружает все удалённые ветки.
-k or --keepСохраняет загруженный pack.
-p or --pruneУдаляет ссылки отслеживания удалённых веток, которых не было на удалённом репозитории до выполнения fetch.
--depth=<depth>Ограничивает количество коммитов, загружаемых с вершины истории каждой удалённой ветки.

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

bash
git fetch --prune

Как выполнить git fetch удалённой ветки

Здесь мы покажем шаги получения удалённой ветки и обновления локального рабочего состояния в соответствии с содержимым удалённого репозитория. В следующем примере у нас есть центральный репозиторий origin, из которого локальный репозиторий был клонирован с помощью команды git clone. Есть ещё один удалённый репозиторий с именем test_repo, содержащий feature_branch, который нужно настроить и получить.

Первый шаг — настроить удалённый репозиторий с помощью git remote:

git remote

bash
git remote add test_repo git@hostname:test/test_repo.git

Используя URL репозитория коллеги, мы создали на него ссылку. Для загрузки содержимого выполните git fetch для тестовой feature_branch:

git fetch

bash
git fetch test_repo feature_branch
From hostname:test/test_repo
* [new branch]      feature_branch -> test_repo/feature_branch

Это интегрирует содержимое test/feature_branch в локальный репозиторий. Теперь используйте команду git checkout, чтобы переключиться на загруженную удалённую ветку:

git checkout test_repo/feature_branch

bash
git checkout test_repo/feature_branch
Note: checking out 'test_repo/feature_branch'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can drop all the commits you make in this
state without influencing branches by executing another checkout.

If you want to generate a new branch for maintaining commits you create, you may
do so (now or later) if you use -b with the checkout command again. Example:

git checkout -b &lt;new-branch-name&gt;

Вывод показывает, что мы находимся в состоянии detached HEAD, что означает, что ссылка HEAD указывает напрямую на коммит, а не на ветку.

С помощью команды git checkout можно создать новую локальную ветку из ссылки test/feature_branch:

git checkout -b local_feature_branch test_repo/feature_branch

bash
git checkout -b local_feature_branch test_repo/feature_branch

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

Синхронизация origin с помощью git fetch

Следующий пример показывает, как синхронизировать локальный репозиторий с веткой master центрального репозитория:

git fetch origin

bash
git fetch origin

В выводе будут показаны загруженные ветки:

git fetch origin output

bash
b341bc3..32a45b1  master     -> origin/master
b341bc3..7a52a22  develop    -> origin/develop
* [new branch]      some-feature -> origin/some-feature

Вызовите git log, используя origin/master в качестве фильтра, чтобы показать коммиты, добавленные в upstream master:

git log --oneline master..origin/master

bash
git log --oneline master..origin/master

Проверьте изменения и слейте их с локальной веткой master:

git checkout master && git log origin/master

bash
git checkout master
git log origin/master

Выполните git merge origin/master, чтобы синхронизироваться с изменениями upstream:

git merge

bash
git merge origin/master

Пример типичного сценария:

Вот сценарий, который поможет вам лучше понять эту концепцию:

Предположим, что есть небольшая команда разработки из двух разработчиков — Alice и Bob. Они работают над проектом, размещённым в удалённом Git-репозитории под названием origin. Alice клонирует репозиторий на свой локальный компьютер и начинает работать в ветке main, а Bob работает в отдельной ветке под названием feature-branch.

1- Alice создаёт новый файл с именем README.md и вносит в него некоторые изменения. Затем она фиксирует и отправляет свои изменения в ветку main репозитория origin:


bash
$ git add README.md
$ git commit -m "Add README file"
$ git push origin main

2- Тем временем Bob внёс некоторые изменения в feature-branch и отправил их в репозиторий origin:


bash
$ git add some_file.txt
$ git commit -m "Add new feature"
$ git push origin feature-branch

3- Alice понимает, что ей нужно включить изменения Bob в свою работу, поэтому она получает изменения из репозитория origin:


bash
$ git fetch origin

4- После получения изменений Alice видит, что в feature-branch появились новые изменения:


bash
$ git branch -r
  origin/HEAD -> origin/main
  origin/main
  origin/feature-branch

5- Теперь Alice может слить изменения Bob в свою ветку main:


bash
$ git merge origin/feature-branch

6- Alice разрешает все конфликты слияния, а затем отправляет свои изменения в репозиторий origin:


bash
$ git push origin main

7- Теперь Bob может получить изменения, внесённые Alice:


bash
$ git fetch origin

8- Теперь Bob видит, что в ветке main появились новые изменения:


bash
$ git branch -r
  origin/HEAD -> origin/main
  origin/main
  origin/feature-branch

9- Bob может слить изменения, внесённые Alice, в свою ветку feature-branch:


bash
$ git merge origin/main

10- Bob разрешает все конфликты слияния, а затем отправляет свои изменения в репозиторий origin:


bash
$ git push origin feature-branch

И так цикл продолжается: и Alice, и Bob используют git fetch, чтобы отслеживать изменения друг друга и отправлять свои собственные изменения в репозиторий origin. Используя git fetch, они могут поддерживать свой локальный репозиторий в актуальном состоянии с изменениями, внесёнными их коллегами, что помогает избежать конфликтов и обеспечивает более плавный процесс совместной работы.

Git fetch vs git pull

И git fetch, и git pull используются для загрузки содержимого из удалённого репозитория. Команда git fetch не сливает изменения автоматически в ваши локальные ветки; она лишь обновляет ваши удалённые отслеживаемые ветки. Полученное содержимое не влияет на ваш локальный рабочий каталог, что позволяет безопасно просматривать коммиты перед их слиянием. Команда git pull загружает новое содержимое и автоматически сливает его с вашей текущей веткой. Это может привести к конфликтам слияния, поэтому рекомендуется запускать git pull только тогда, когда ваша рабочая копия чиста.

Practice

What are the correct statements about the `git fetch` command as described in the W3Docs Git Tutorial?

Считаете ли это полезным?

Предпросмотр dual-run — сравните с маршрутами Symfony на продакшене.