Урок курса
Fetch: получить историю, не менять файлы
Git и GitHub с нуля: бесплатный курс с практикойВ прошлом уроке вы отправляли коммиты в origin командой git push и настраивали tracking-связь. После push origin знает о ваших коммитах — но это работает только в одну сторону: другие клоны не получают новую историю автоматически. Чтобы забрать чужие изменения, не смешивая их со своей работой, есть отдельная команда.
Что делает git fetch: remote-tracking ссылка против локальной ветки
Когда вы делаете git fetch origin, Git связывается с origin, получает недостающую историю и обновляет remote-tracking ссылки согласно настройкам клона. Их может быть несколько. В свежем учебном remote этого опыта изменяется только ветка main, поэтому в клоне продвигается origin/main. Локальная ветка main, индекс и рабочие файлы остаются нетронутыми.
Чтобы понять, почему это важно, полезно держать в голове три независимых указателя:
origin/main— remote-tracking ссылка: локальная копия того, где находитсяmainв origin. Git обновляет её сам при fetch.- Локальная
main— ваша ветка, которую вы переключаете, коммитите в неё, продвигаете вперёд своими действиями. - Рабочий файл — то, что лежит в папке и открывается в редакторе.
В этом опыте git fetch origin обновляет первую из этих трёх позиций, а две остальные сохраняет.
Предположим, что общая история выглядела так: оба клона видели коммит A, и origin/main, и main указывали на него. Затем коллега создал коммит B и отправил его в origin командой push. Первый клон об этом ничего не знает — origin не рассылает уведомления. После git fetch origin в первом клоне:
origin/main→ B (fetch принёс коммит и сдвинул ссылку)main→ A (не изменилась)- README в рабочей папке → содержимое из коммита A (не изменилось)
Fetch — это именно получение истории, не объединение. Ваши файлы и ветка остаются такими, как были до команды. Это даёт возможность сначала посмотреть, что именно принёс коллега, и только потом решать, что делать с его изменениями.
Выполнение git fetch origin и чтение результата: log, graph, show
Чтобы убедиться, что fetch сделал именно то, что ожидалось, удобно фиксировать состояние до команды и сравнивать его с состоянием после.
До fetch — запишите:
git log --oneline main
git log --oneline origin/main
git status
Оба лога показывают один и тот же верхний ID (коммит A). git status сообщает чистое рабочее дерево. Откройте README в редакторе и запомните его текст — он пригодится для сравнения.
Сам fetch:
git fetch origin
При продвижении ссылки Git может показать такую строку (ID ниже условные; сравнивайте свои ID):
a1b2c3d..e4f5a6b main -> origin/main
Эта строка говорит: remote-tracking ссылка origin/main продвинулась с одного ID до другого. Локальная main в этом сообщении не упоминается — потому что её Git не трогал.
После fetch — повторите проверки:
git log --oneline origin/main
git log --oneline main
git log --graph --oneline --all
git status
git log --oneline origin/main теперь показывает вверху новый коммит (B), а git log --oneline main — по-прежнему старый (A). Граф --all отображает обе ссылки: B над A, обе на одной линии.
Чтобы прочитать, что именно принёс коммит коллеги, используйте:
git show origin/main
Здесь origin/main — имя ссылки, Git находит коммит B и показывает его сообщение плюс diff: какие строки были удалены и какие добавлены. Важно: git show только читает объект из базы данных Git. Рабочий файл он не перезаписывает. После этой команды откройте README в редакторе — текст совпадёт с тем, что вы записали до fetch.
git status после fetch остаётся чистым. Если ветка main настроена как tracking за origin/main, Git может дополнительно сообщить «Your branch is behind 'origin/main' by 1 commit» — это нормальное состояние: fetch принёс историю, но объединения не было.
Опыт двух клонов: зафиксировать коммит коллеги, не изменив свой README
Стартовая точка — свежая копия git_practice.zip, распакованная в новую отдельную папку. Откройте терминал в распакованной папке git_practice; если терминал уже открыт, перейдите туда командой cd "полный путь к новой папке/git_practice", подставив свой путь. Папки my_clone и colleague_clone ещё не должны существовать. Не используйте remote предыдущего опыта. Внутри git_practice находится remote/shared.git с одним коммитом A. README содержит три строки:
# Командный справочник Контакт: команда Статус: черновик
Подготовка двух клонов. Создайте оба клона из папки git_practice:
git clone remote/shared.git my_clone
git clone remote/shared.git colleague_clone
Перейдите в первый клон и настройте идентичность:
cd my_clone
git config user.name "Учебный автор"
git config user.email "student@example.invalid"
git status
git log --oneline main
git log --oneline origin/main
Оба лога показывают одинаковый верхний ID — это коммит A. Запишите его куда-нибудь вне клона. Откройте my_clone/README.md в редакторе и запишите текст — он совпадёт с содержимым выше. В первом клоне не создавайте коммитов.
Действие коллеги. Перейдите во второй клон:
cd ../colleague_clone
git config user.name "Учебный коллега"
git config user.email "colleague@example.invalid"
git status
Проверьте On branch main и чистую рабочую папку. Клоны сохраняют обычную настройку upstream origin/main, установленную при clone; других отправок в remote в этом опыте нет.
Откройте README.md в редакторе, замените строку Статус: черновик на Статус: проверен и сохраните. Затем:
git add README.md
git commit -m "Проверить статус справочника"
git push -u origin main
git log --oneline main
Верхняя строка в логе — новый коммит B. Запишите его ID. Теперь в origin есть B, а первый клон об этом ещё не знает.
Наблюдение в первом клоне. Вернитесь:
cd ../my_clone
git log --oneline origin/main
Вывод всё ещё начинается с A — первый клон не знает о B. Выполните fetch:
git fetch origin
Теперь проверьте все три состояния:
git log --oneline origin/main
git log --oneline main
git log --graph --oneline --all
git show origin/main
git status
Конкретные наблюдения, которые должны совпасть с вашими записями:
git log --oneline origin/main— верхний ID равен записанному B.git log --oneline main— верхний ID равен записанному A.- Граф показывает B над A; обе ссылки подписаны явно.
git show origin/mainвыводит сообщение «Проверить статус справочника» и diff с заменой строки статуса: удаленаСтатус: черновик, добавленаСтатус: проверен.git status— рабочее дерево чистое.
Откройте my_clone/README.md в редакторе (не изменяя). Там по-прежнему Статус: черновик — весь текст совпадает с тем, что вы записали до fetch. Git принёс историю коллеги, но не прикоснулся к файлу.
Это и есть инвариант fetch: после команды origin/main указывает на B, main указывает на A, рабочий README содержит черновик. Три указателя, три независимых состояния.
Задача 1
Самостоятельная практика:
Настоящая локальная практика Git на своём компьютере. Площадка не запускает команды и не проверяет ваш репозиторий.
Входные данные и явная подготовка:
Для отдельного опыта распаковать git_practice.zip в новую отдельную папку и перейти в её git_practice. Используется выданный remote/shared.git: ветка main, один исходный коммит A; README содержит «# Командный справочник», «Контакт: команда», «Статус: черновик». Не использовать старые клоны и remote предыдущего опыта.
Подготовка двух участников известными командами:
git clone remote/shared.git my_clone
git clone remote/shared.git colleague_clone
cd my_clone
git config user.name "Учебный автор"
git config user.email "student@example.invalid"
git status
git log --oneline main
git log --oneline origin/main
Записать верхние ID main и origin/main из своего вывода; оба относятся к A. Открыть my_clone/README.md обычным редактором и записать его текст, не изменяя. Начальное состояние чистое. Записи наблюдений сохранять вне клона. В первом клоне не делать коммитов.
Отдельная подготовка действия коллеги:
cd ../colleague_clone
git config user.name "Учебный коллега"
git config user.email "colleague@example.invalid"
git status
Убедиться, что ветка main и состояние чистое. Обычным редактором заменить только «Статус: черновик» на «Статус: проверен» и сохранить README, затем:
git add README.md
git commit -m "Проверить статус справочника"
git push -u origin main
git log --oneline main
Записать ID нового коммита B из вывода коллеги. Это единственный новый коммит, его родитель A. Первый клон создан до отправки B.
Задача в первом клоне: получить отправленный коммит коллеги и собрать собственные свидетельства изменения origin/main и сохранности main и рабочего файла.
Вернуться в первый клон: cd ../my_clone. До получения данных git log --oneline origin/main ещё начинается с A, хотя коллега уже отправил B.
Выполнить:
git fetch origin
git log --graph --oneline --all
git log --oneline origin/main
git show origin/main
git log --oneline main
git status
Сравнить верхние ID со своими записями: история origin/main начинается с B, история main всё ещё с A; граф показывает B над A на одной линии. git show origin/main показывает сообщение B и diff README с заменой строки статуса. Повторно открыть именно my_clone/README.md обычным редактором, не редактируя: там по-прежнему «Статус: черновик»; весь текст совпадает с записью до fetch. git status сообщает чистое рабочее дерево; при tracking main за origin/main может дополнительно показать отставание на один коммит. Чистота файлов и отставание истории совместимы. Завершить опыт в этом состоянии.
Результат: сохраните вывод fetch, graph, show origin/main и обеих историй до/после; рядом запишите содержимое рабочего README до/после и clean/dirty состояние. В коротком отчёте сопоставьте A/B со своими ID и назовите продвинувшуюся ссылку. Конкретный заранее заданный SHA не нужен.
Доступные команды: cd, git clone, git config user.name/user.email, git status, git add README.md, git commit -m, git push -u origin main, git fetch origin, git log --oneline main, git log --oneline origin/main, git log --graph --oneline --all, git show origin/main; файлы читаются и редактируются обычным редактором.
Платформа проверяет только ответ ниже; действия в своём репозитории и письменные ответы вы проверяете самостоятельно.
Контрольный случай:
В другом проекте две линии уже разошлись: локальная main содержит коммит А с «Версия: 2», а main в origin — коммит Б с «Версия: 3»; оба коммита имеют общего родителя. В чистой локальной main выполнили только git fetch origin и git show origin/main. Show выводит изменение версии в Б. Что верно о рабочем README этого clone?
Задача 2
Письменное объяснение:
Два обычных клона учебного remote сначала были на коммите A. Во втором коллега сделал единственный коммит B поверх A и успешно отправил его в main. После отправки первый клон ещё не связывался с origin: в нём git log --oneline origin/main начинается с A, а рабочее дерево чистое. Ученик заключил: «Мой журнал origin/main показывает A, значит в общем репозитории коммита B нет». Оцените этот вывод. Укажите действие в первом клоне, которое даст актуальное наблюдение без изменения его main и README, и назовите, какое различие двух локальных историй подтвердит получение B. Отделите факт о записи первого клона от факта об общей ветке; конкретные SHA не нужны.
Платформа проверяет только ответ ниже; действия в своём репозитории и письменные ответы вы проверяете самостоятельно.
Контрольный случай:
Коллега отправил Б после создания вашего clone. С тех пор вы не обменивались с origin; местная origin/main показывает А. Доказывает ли это отсутствие Б в общем репозитории?
Продолжить с сохранением прогресса
Перейдите к уроку в учебном кабинете.
