'git pull origin mybranch' оставляет локальные коммиты mybranch N перед origin.Почему?

StackOverflow https://stackoverflow.com/questions/1741143

  •  20-09-2019
  •  | 
  •  

Вопрос

Я только что заметил кое-что странное в git pull, чего я не понимаю.

В пятницу я работал в местном филиале.давайте назовем это mybranch.Прежде чем покинуть офис, я отправил его в origin (который является моим репозиторием на github).: git push origin mybranch.

Вчера дома я pullотредактировал mybranch на моем ноутбуке, сделал еще немного кодирования, а затем отправил мои изменения обратно на github (origin).

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

git pull origin mybranch

это вызвало быстрое слияние с перемоткой вперед, и это нормально.Затем я сделал git status, и в нем говорилось:

# On branch mybranch
# Your branch is ahead of 'origin/mybranch' by 6 commits.
#
nothing to commit (working directory clean)

А?Как это может быть на 6 коммитов вперед, когда я даже не прикасался к нему на выходных, А просто извлек из origin?Поэтому я запустил git diff origin/mybranch и различия были именно теми 6 изменениями, которые я только что извлек из remote.

Я мог только "исправить" это, запустив git fetch origin:

From git@github.com:me/project
af8be00..88b0738  mybranch -> origin/mybranch

По-видимому, в моем локальном репозитории отсутствовали некоторые ссылочные объекты, но как это может быть?Я имею в виду, что pull уже выполняет выборку, и я не работал ни над чем, кроме этой ветки, так что git fetch origin и git fetch origin mybranch должен ли быть тот же результат?

Должен ли я всегда использовать git pull origin вместо того , чтобы git pull origin branchname?

Я в замешательстве.

Это было полезно?

Решение

git pull звонки git fetch с соответствующими параметрами перед объединением явно выбранных заголовков (или, если таковых нет, удаленной ветви, настроенной для слияния) в текущую ветвь.

Синтаксис: git fetch <repository> <ref> где <ref> просто имя ветви без двоеточия - это выборка "одним выстрелом", которая не выполняет стандартную выборку всех отслеживаемых ветвей указанного удаленного, а вместо этого извлекает только названную ветвь в FETCH_HEAD.

Обновить: для версий Git начиная с 1.8.4, если существует ветвь удаленного отслеживания, которая отслеживает ссылку, которую вы просили получить, то ветвь отслеживания теперь будет обновлена с помощью fetch.Это изменение было внесено специально для того, чтобы избежать путаницы, вызванной предыдущим поведением.

Когда вы выполняете git pull <repository> <ref>, FETCH_HEAD обновляется, как указано выше, затем объединяется с вашим извлеченным HEAD но ни одна из стандартных ветвей отслеживания для удаленного репозитория не будет обновлена (Git <1.8.4).Это означает, что локально это выглядит как будто вы опережаете удаленную ветку, в то время как на самом деле вы в курсе событий с ней.

Лично я всегда так делаю git fetch за которым следует git merge <remote>/<branch> потому что я вижу любые предупреждения о принудительных обновлениях перед слиянием, и я могу просмотреть то, что я объединяю.Если бы я использовал git pull немного больше, чем я делаю, я бы сделал простой git pull без каких-либо параметров большую часть времени, полагаясь на branch.<branch>.remote и branch.<branch>.merge чтобы "поступать правильно".

Другие советы

Что делает git remote -v show возвращается, когда дело доходит до происхождения?

Если источник указывает на github, статус должен быть актуальным, а не предшествовать какому-либо удаленному репозиторию.По крайней мере, с помощью Git1.6.5, который я использую для быстрого тестирования.

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

$ git config branch.master.remote yourGitHubRepo.git

затем a git pull origin master, за которым следует git status должен вернуть чистый статус (без опережений).
Почему?потому что get fetch origin master (включенный в git pull origin master) не будет просто обновляться FETCH_HEAD (как Чарльз Бейли объясняет в его ответ), но это было бы также обновите "удаленную главную ветку" в вашем локальном репозитории Git.
В этом случае ваш локальный мастер, по-видимому, больше не будет "опережать" удаленный мастер.


Я могу протестировать это с помощью git1.6.5:

Сначала я создаю workrepo:

PS D:\git\tests> cd pullahead
PS D:\git\tests\pullahead> git init workrepo
Initialized empty Git repository in D:/git/tests/pullahead/workrepo/.git/
PS D:\git\tests\pullahead> cd workrepo
PS D:\git\tests\pullahead\workrepo> echo firstContent > afile.txt
PS D:\git\tests\pullahead\workrepo> git add -A 
PS D:\git\tests\pullahead\workrepo> git commit -m "first commit"

Я имитирую репозиторий GitHub, создавая голый репозиторий (тот, который может получать push из любого места).

PS D:\git\tests\pullahead\workrepo> cd ..
PS D:\git\tests\pullahead> git clone --bare workrepo github

Я добавляю модификацию к своему рабочему репозиторию, которую отправляю в репозиторий github (добавлен как удаленный).

PS D:\git\tests\pullahead> cd workrepo
PS D:\git\tests\pullahead\workrepo> echo aModif >> afile.txt
PS D:\git\tests\pullahead\workrepo> git ci -a -m "a modif to send to github"
PS D:\git\tests\pullahead\workrepo> git remote add github d:/git/tests/pullahead/github
PS D:\git\tests\pullahead\workrepo> git push github

Я создаю домашний репозиторий, клонированный с GitHub, в который вношу пару модификаций, перенесенных на GitHub:

PS D:\git\tests\pullahead\workrepo> cd ..
PS D:\git\tests\pullahead> git clone github homerepo
PS D:\git\tests\pullahead> cd homerepo
PS D:\git\tests\pullahead\homerepo> type afile.txt
firstContent
aModif

PS D:\git\tests\pullahead\homerepo> echo aHomeModif1  >> afile.txt
PS D:\git\tests\pullahead\homerepo> git ci -a -m "a first home modif"
PS D:\git\tests\pullahead\homerepo> echo aHomeModif2  >> afile.txt
PS D:\git\tests\pullahead\homerepo> git ci -a -m "a second home modif"
PS D:\git\tests\pullahead\homerepo> git push github

Затем я клонирую workrepo для первого эксперимента

PS D:\git\tests\pullahead\workrepo4> cd ..
PS D:\git\tests\pullahead> git clone workrepo workrepo2
Initialized empty Git repository in D:/git/tests/pullahead/workrepo2/.git/
PS D:\git\tests\pullahead> cd workrepo2
PS D:\git\tests\pullahead\workrepo2> git remote add github d:/git/tests/pullahead/github
PS D:\git\tests\pullahead\workrepo2> git pull github master
remote: Counting objects: 8, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (6/6), done.
From d:/git/tests/pullahead/github
 * branch            master     -> FETCH_HEAD
Updating c2763f2..75ad279
Fast forward
 afile.txt |  Bin 46 -> 98 bytes
 1 files changed, 0 insertions(+), 0 deletions(-)

В этом репозитории git status действительно упоминает master geing перед 'origin':

PS D:\git\tests\pullahead\workrepo5> git status
# On branch master
# Your branch is ahead of 'origin/master' by 2 commits.
#
nothing to commit (working directory clean)

Но это всего лишь origin это не github:

PS D:\git\tests\pullahead\workrepo2> git remote -v show
github  d:/git/tests/pullahead/github (fetch)
github  d:/git/tests/pullahead/github (push)
origin  D:/git/tests/pullahead/workrepo (fetch)
origin  D:/git/tests/pullahead/workrepo (push)

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

PS D:\git\tests\pullahead\workrepo2> cd ..
PS D:\git\tests\pullahead> git clone workrepo workrepo4
PS D:\git\tests\pullahead> cd workrepo4
PS D:\git\tests\pullahead\workrepo4> git remote rm origin
PS D:\git\tests\pullahead\workrepo4> git remote add github d:/git/tests/pullahead/github
PS D:\git\tests\pullahead\workrepo4> git pull github master
remote: Counting objects: 8, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (6/6), done.
From d:/git/tests/pullahead/github
 * branch            master     -> FETCH_HEAD
Updating c2763f2..75ad279
Fast forward
 afile.txt |  Bin 46 -> 98 bytes
 1 files changed, 0 insertions(+), 0 deletions(-)
PS D:\git\tests\pullahead\workrepo4> git status
# On branch master
nothing to commit (working directory clean)

Если бы у меня только origin указывая на github, status было бы чисто для git1.6.5.
Это может быть с предупреждением "вперед" для более раннего git, но в любом случае, git config branch.master.remote yourGitHubRepo.git определенный явно, должен быть в состоянии позаботиться об этом, даже с ранними версиями Git.

Тщательно ли вы добавляете все свои удаленные (за исключением origin который поставляется с вашим оригинальным клоном), используя git remote add NAME URL?Я видел эту ошибку, когда они только что были добавлены в конфигурацию git.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top