“git pull origin mybranch”使本地 mybranch N 次提交提前于原点。为什么?

发布于 2024-08-11 10:13:13 字数 1157 浏览 8 评论 0原文

我刚刚观察到关于 git pull 的一些奇怪的事情,我不明白。

星期五,我在当地的一家分公司工作。我们将其命名为 mybranch。在离开办公室之前,我将其推送到 origin(这是我的 github 存储库):git push origin mybranch

昨天在家里,我将我的分支拉到我的笔记本电脑上,做了一些更多的编码,然后将我的更改推送回 github(原始)。

现在我又开始工作了,并尝试将昨天的更改拉到我的工作机器上(周末我没有更改工作地点的本地存储库中的任何内容):

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 个提交呢?所以我运行了 git diff origin/mybranch ,差异正是我刚刚从远程拉取的 6 个更改。

我只能通过运行 git fetch origin 来“修复”这个问题:

From [email protected]:me/project
af8be00..88b0738  mybranch -> origin/mybranch

显然,我的本地存储库缺少一些引用对象,但这怎么可能呢?我的意思是,拉取已经执行了提取,并且除了该分支之外我没有处理任何内容,因此 git fetch origingit fetch origin mybranch 应该具有相同的结果?

我应该始终使用 git pull origin 代替 git pull originbranchname 吗?

我很困惑。

I just observed something odd about git pull, which I don't understand.

On Friday, I worked on a local branch. let's call it mybranch. Before leaving the office I pushed it to origin (which is my github repo): git push origin mybranch.

Yesterday at home, I pulled mybranch to my laptop, did some more coding, and then pushed my changes back to github (origin).

Now I'm at work again, and tried to pull the changes from yesterday to my work machine (I didn't change anything in my work place's local repo over the weekend):

git pull origin mybranch

that caused a fast forward merge, which is fine. I then did a git status, and it said:

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

Huh? How can it be 6 commits ahead when I didn't even touch it over the weekend, AND just pulled from origin? So I ran a git diff origin/mybranch and the diffs were exactly the 6 changes I just pulled from remote.

I could only "fix" this by running git fetch origin:

From [email protected]:me/project
af8be00..88b0738  mybranch -> origin/mybranch

Apparently, my local repo was missing some reference objects, but how can that be? I mean, a pull does a fetch already, and I didn't work on anything except that branch, so a git fetch origin and git fetch origin mybranch should have the same result?

Should I always use git pull origin instead of git pull origin branchname?

I'm confused.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

可爱咩 2024-08-18 10:13:13

在将显式获取的头(或者如果没有配置合并的远程分支)合并到当前分支之前,git pull 使用适当的参数调用git fetch

语法:git fetch; 其中 只是一个不带冒号的分支名称,是“一次性”提取,不会对所有跟踪的分支进行标准提取指定的远程,而是仅将指定分支提取到 FETCH_HEAD 中。

更新:对于 1.8.4 以后的 Git 版本,如果有一个远程跟踪分支跟踪您要求获取的引用,那么该跟踪分支现在将由 fetch 更新。此更改是专门为了避免先前行为造成的混乱而进行的。

当您执行 git pullFETCH_HEAD 按上述方式更新,然后合并到您签出的 HEAD 中,但远程存储库的标准跟踪分支都不会更新(Git <1.8.4)。这意味着在本地,它看起来就像您领先于远程分支,而实际上您是最新的。

就我个人而言,我总是先执行 git fetch ,然后执行 git merge/因为在合并之前我会看到有关强制更新的任何警告,并且我可以预览我要合并的内容。如果我使用 git pull 的次数比我多一点,我会在大多数情况下执行不带参数的普通 git pull,依赖在 branch..remotebranch..merge 上“做正确的事”。

git pull calls git fetch with the appropriate parameters before merging the explicitly fetched heads (or if none the remote branch configured for merge) into the current branch.

The syntax: git fetch <repository> <ref> where <ref> is just a branch name with no colon is a 'one shot' fetch that doesn't do a standard fetch of all the tracked branches of the specified remote but instead fetches just the named branch into FETCH_HEAD.

Update: for Git versions since 1.8.4, if there is a remote tracking branch which tracks the ref that you asked to fetch then the tracking branch will now be updated by fetch. This change has been made specifically to avoid the confusion that the previous behaviour caused.

When you perform git pull <repository> <ref>, FETCH_HEAD is updated as above, then merged into your checked out HEAD but none of the standard tracking branches for the remote repository will be updated (Git <1.8.4). This means that locally it looks like you are ahead of of the remote branch, whereas in fact you are up to date with it.

Personally I always do git fetch followed by git merge <remote>/<branch> because I get to see any warnings about forced updates before I merge, and I can preview what I'm merging in. If I used git pull a bit more than I do, I would do a plain git pull with no parameters most of the time, relying on branch.<branch>.remote and branch.<branch>.merge to 'do the right thing'.

紫南 2024-08-18 10:13:13

当涉及到原点时,git remote -v show 返回什么?

如果 origin 指向 github,则状态应该是最新的,并且不领先于任何远程存储库。至少,我用Git1.6.5进行了快速测试。

无论如何,为了避免这种情况,请显式定义 master 分支的远程存储库:

$ git config branch.master.remote yourGitHubRepo.git

然后 git pull origin master ,后跟 git status 应该返回一个干净的状态(没有前面) .
为什么?因为 get fetch origin master (包含在 git pull origin master 中)不仅仅会更新 FETCH_HEAD (如 Charles Bailey他的答案),但它也会更新本地 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 存储库,

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

我向我的工作存储库添加一个修改,然后将其推送到 github repo(添加为远程)

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,则 git1.6.5 的 status 将会是干净的.
对于早期的 git 可能会出现“提前”警告,但无论如何,明确定义的 git configbranch.master.remote yourGitHubRepo.git 应该能够解决这个问题,即使是早期版本的吉特。

What does git remote -v show returns when it comes to origin?

If origin points to github, the status should be up to date, and not ahead of any remote repo. At least, with the Git1.6.5 I am using for a quick test.

Anyway, to avoid this, define explicitly the remote repo of master branch:

$ git config branch.master.remote yourGitHubRepo.git

then a git pull origin master, followed by a git status should return a clean status (no ahead).
Why? because the get fetch origin master (included in the git pull origin master) would not just update FETCH_HEAD (as Charles Bailey explains in his answer), but it would also update the "remote master branch" within your local Git repository.
In that case, your local master would not seem anymore to be "ahead" of the remote master.


I can test this, with a git1.6.5:

First I create a 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"

I simulate a GitHub repo by creating a bare repo (one which can receive push from anywhere)

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

I add a modif to my working repo, that I push to github repo (added as a remote)

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

I create a home repo, cloned of GitHub, in which I make a couple of modifications, pushed to 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

I then clone workrepo for a first experiment

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(-)

In that repo, git status does mention master geing ahead of '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)

But that is only origin is not 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)

But if I repeat the sequence in a repo which has an origin to github (or no origin at all, just a remote 'github' defined), status is clean:

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)

If I had only origin pointing on github, status would be clean for git1.6.5.
It may be with a 'ahead' warning for earlier git, but anyway, a git config branch.master.remote yourGitHubRepo.git defined explicitly should be able to take care of that, even with early versions of Git.

岁月静好 2024-08-18 10:13:13

您是否小心地使用 git remote add NAME URL 添加所有远程(除了原始克隆附带的origin)?当它们刚刚添加到 git 配置中时,我就看到了这个错误。

Are you careful to add all of your remote (except origin which comes with your original clone) using git remote add NAME URL? I've seen this bug when they've just been added to the git config.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文