'git pull origin mybranch' залишає місцеві mybranch N, що здійснює операції попереду походження. Чому?


92

Я щойно спостерігав щось дивне git pull, чого я не розумію.

У п’ятницю я працював у місцевому відділенні. назвемо це mybranch. Перед тим як покинути кабінет , я штовхнув його походження (який є моїм GitHub репо) git push origin mybranch.

Вчора вдома я pullпідключив свою гілку до свого ноутбука, ще трохи кодував, а потім повернув свої зміни до 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 комітів вперед, коли я навіть не торкнувся його у вихідні дні, А просто витягнув з місця походження? Тож я запустив a, git diff origin/mybranchі різниці - це саме 6 змін, які я щойно витягнув з пульта.

Я міг "виправити" це лише запустивши git fetch origin:

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

Очевидно, у моєму локальному репо не вистачало деяких об’єктів посилань, але як це може бути? Я маю на увазі, що тяга вже робить вибірку, і я не працював ні над чим, крім цієї гілки, тому a git fetch originі git fetch origin mybranchповинен мати той самий результат?

Чи завжди мені використовувати git pull originзамість git pull origin branchname?

Я збентежений.


Я теж це помітив; a git pushтакож, здається, це вирішить (звітування "все в курсі").
Ben James

4
git config --get-regexp br.*може сказати вам, чи у вашій конфігурації локальна гілка відстежує іншу гілку
VonC

3
Чи можете ви ввести git config branch.master.remote yourGitHubRepo.gitу своєму workRepo та перевірити (на наступному git pull origin), чи залишається статус із попередженням "вперед"?
VonC

він не встановлений (порожній вихід). але git remote show originпоказує мені, що origin вказує на мій репозиторій GitHub, тож це, мабуть, має бути добре?
Маттіас

1
одного лише git remote (показуючи правильну адресу для репозиторію GitHub) недостатньо . Щоб уникнути " Your branch is ahead" попереджувального повідомлення після " " git pull, спочатку потрібно також визначити віддалене ім'я для гілки . Звідси моя пропозиція: введіть git config branch.master.remote yourGitHubRepo.git, а потім спробуйте a git pullта a git statusі подивіться, чи проблема залишається.
VonC

Відповіді:


115

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«робити правильні речі».


4
+1 Це справді гарне пояснення! Я знав, що пояснення ховалося десь усередині `` git help fetch '', але не зміг його дістати ...
Stefan Näwe

1
+1. Хороший пост, з підходом, подібним до gitster.livejournal.com/28309.html
VonC

1
Тож чи git fetchпісля git pull <repository> <ref>виправлення проблеми, оскільки завантаження оновить стандартні гілки відстеження? Крім того, спасибі за цю відповідь, починаючи мати сенс :)
Барт Єдроча 02.03.12

1
Я теж зіткнувся з цим питанням, і вам потрібно буде зробити, git fetchа потім git merge origin/master master.
user1027169

3

Що git remote -v showповертається, коли йдеться про походження?

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

У будь-якому випадку, щоб цього уникнути, чітко визначте віддалене репо головного відділення:

$ git config branch.master.remote yourGitHubRepo.git

потім a git pull origin master, за яким слідує a, git statusповинні повернути статус чистого стану (без попередньої).
Чому? оскільки master fetch origin master (включений до майстра початкового джерела git pull) не просто оновлюється FETCH_HEAD(як пояснює Чарльз Бейлі у своїй відповіді ), але й оновлює "віддалену головну гілку" у вашому локальному сховищі Git.
У такому випадку ваш локальний майстер, здається, вже не випереджав віддаленого майстра.


Я можу перевірити це за допомогою git1.6.5:

Спочатку я створюю робоче репо:

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 згадує майстер 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.


Дякуємо, що знайшли час вивчити це. Пульт дистанційного відправлення вже вказує на моє репозиторій GitHub. Я клонував цей проект з URL-адреси GitHub, і моя локальна гілка відстежує відстеження походження / майстра. Що стосується mybranch, то я впевнений, що створив його з гілки origin / mybranch, яка повинна відстежувати його автоматично. Але все-таки, може, в цьому проблема? Що місцева mybranch насправді не відстежує походження / mybranch? PS: Я використовую git 1.6.1 (через MacPorts).
Маттіас

Чи існує команда git, яка дозволить мені побачити, чи локальна гілка відстежує іншу гілку? Я не можу знайти його на сторінках керівництва.
Маттіас

Ви можете бачити, за якими віддаленими гілками відстежується git remote show origin.
Тед Персіваль

2

Ви обережно додаєте весь свій пульт дистанційного керування (крім того, originякий постачається з оригінальним клоном) за допомогою git remote add NAME URL? Я бачив цю помилку, коли їх щойно додали до конфігурації git.


Я зробив це під час клонування репо. Однак я не робив цього з кожною гілкою. Наприклад, наприклад, для моєї гілки, спочатку я б взяв її з походження git checkout -b mybranch origin/mybranch. Згідно з довідковою сторінкою git-branch, початком / початковою точкою є початок / mybranch, і, крім того, в ньому зазначається --track: "... Використовуйте це, якщо ви завжди тягнете з тієї ж гілки вище за новою гілкою, і якщо ви не хочете явно використовувати "git pull <repository> <refspec>". Ця поведінка є типовою, коли початковою точкою є віддалена гілка. "
Маттіас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.