问题描述
注意::该问题的动机是更好地理解 git
,而不是解决任何特定问题.IOW,达成相同目标"的替代方法(即在标题中回避问题)将不在重点之列.
NOTE: The motivation for this question is to understand git
better, and not to solve any specific problem. IOW, alternative ways "to achieve the same thing" (i.e. side-stepping the question in the title) would be beside the point.
命令
git pull
...应该等同于序列
...is supposed to be equivalent to the sequence
git fetch
git merge
可以 git pull< REMOTE>< BRANCH>
(即具有远程和分支要从中提取的显式参数)分解为类似的 fetch
序列,然后是 merge
?
Can git pull <REMOTE> <BRANCH>
(i.e. with explicit arguments for the remote and the branch to pull from it) be decomposed into a similar sequence of a fetch
followed by a merge
?
我想 fetch
部分将很简单
git fetch <REMOTE> <BRANCH>
...但是,如果是这样,我将无法找出正确的 git merge ...
跟在其后.
...but, if so, I can't figure out the correct git merge ...
to follow it with.
我已经尝试了显而易见"的事情.例如,如果我运行 git branch -r
,则输出会在分支之间列出< REMOTE>//< BRANCH>
,因此我尝试了 git merge -m某些消息"< REMOTE>/< BRANCH>
,但是 git
回复已经是最新的
和 git-日志
显示 HEAD
保持与尝试进行 git merge
之前的提交相同的提交.为了确认这一点,我将 git fetch ...
和 git merge ...
放在括号内,并调用了 git log ...
,如下所示:
I've tried the "obvious" things. E.g., if I run git branch -r
, the output lists <REMOTE>/<BRANCH>
among the branches, so I tried git merge -m 'some message' <REMOTE>/<BRANCH>
, but git
replies with Already up-to-date.
, and git-log
shows that HEAD
remains at the same commit it was before the attempted git merge
. To confirm this I bracketed the git fetch ...
and git merge ...
with calls to git log ...
, like this:
git log --all --oneline --graph --decorate -10
git fetch <REMOTE> <BRANCH>
git merge -m 'some message' <REMOTE>/<BRANCH>
git log --all --oneline --graph --decorate -10
两次调用 git log ...
所产生的输出是相同的,它们都显示本地的< BRANCH>
在< REMOTE>/< BRANCH>
之前.
The outputs produced by the two calls to git log ...
are identical, and they both show the local <BRANCH>
as being ahead of <REMOTE>/<BRANCH>
.
下面的玩具示例以/bin/sh
脚本的形式再现了我上面描述的结果.(该脚本已在Ubuntu Linux; YMMV上进行了测试.)
The following toy example, in the form of a /bin/sh
script reproduces the results I've described above. (The script was tested on Ubuntu Linux; YMMV.)
#!/bin/sh
BASEDIR=/tmp/gittest
REMOTENAME=remrepo
REMOTEURL="$BASEDIR/$REMOTENAME"
BRANCHNAME=test
BRANCHNAME=master
rm -rf $REMOTEURL
mkdir -p $REMOTEURL
rm -rf $BASEDIR/clone1 $BASEDIR/clone2
git init --bare -q $REMOTEURL/.git
git clone -q -o $REMOTENAME $REMOTEURL $BASEDIR/clone1
git clone -q -o $REMOTENAME $REMOTEURL $BASEDIR/clone2
pushd $BASEDIR/clone1 >/dev/null
git checkout -qb $BRANCHNAME
echo $RANDOM >> random1.txt
git add .
git commit -qam "$(date -Ins)"
git push -q $REMOTENAME $BRANCHNAME
pushd $BASEDIR/clone2 >/dev/null
git pull -q $REMOTENAME
git checkout -q $BRANCHNAME
echo $RANDOM >> random2.txt
git add .
git commit -qam "$(date -Ins)"
git push -q $REMOTENAME $BRANCHNAME
echo
echo 'git log --all --oneline --decorate --graph :'
git log --all --oneline --decorate --graph
echo
pushd >/dev/null
git checkout -q $BRANCHNAME
echo $RANDOM >> random1.txt
git commit -qam "$(date -Ins)"
echo 'git log --all --oneline --decorate --graph :'
git log --all --oneline --decorate --graph
echo
git fetch -q $REMOTENAME $BRANCHNAME
git merge -m "$(date -Ins)" $REMOTENAME/$BRANCHNAME
echo
echo 'git log --all --oneline --decorate --graph :'
git log --all --oneline --decorate --graph
git pull -q --no-edit $REMOTENAME $BRANCHNAME
echo
echo 'git log --all --oneline --decorate --graph :'
git log --all --oneline --decorate --graph
如果运行它,输出将类似于以下内容:
If you run it, the output will resemble the following:
warning: You appear to have cloned an empty repository.
warning: You appear to have cloned an empty repository.
git log --all --oneline --decorate --graph :
* 2326793 (HEAD, remrepo/master, master) 2013-03-19T10:56:42,838038000-0400
* 34ea848 2013-03-19T10:56:42,360743000-0400
git log --all --oneline --decorate --graph :
* 81cb43f (HEAD, master) 2013-03-19T10:56:43,057198000-0400
* 34ea848 (remrepo/master) 2013-03-19T10:56:42,360743000-0400
Already up-to-date.
git log --all --oneline --decorate --graph :
* 81cb43f (HEAD, master) 2013-03-19T10:56:43,057198000-0400
* 34ea848 (remrepo/master) 2013-03-19T10:56:42,360743000-0400
git log --all --oneline --decorate --graph :
* e60b993 (HEAD, master) Merge branch 'master' of /tmp/gittest/remrepo
|\
| * 2326793 2013-03-19T10:56:42,838038000-0400
* | 81cb43f 2013-03-19T10:56:43,057198000-0400
|/
* 34ea848 (remrepo/master) 2013-03-19T10:56:42,360743000-0400
从上面的输出中可以看到,
As you can see from the output above,
- 接近末尾的获取+合并序列对
git log ...
的输出没有影响 -
git merge
命令的输出是最新的
.即使不是这种情况(远程和本地存储库也已分开一个)提交每个.) - 此合并"之后,本地分支(
master
)是跟踪分支(remrepo/master
)之前的一个提交. - 与获取+合并序列相反,即使两组命令都收到了完全相同的信息,拉取也可以做正确的事情(即,它会更新跟踪分支并执行合并).
- The fetch + merge sequence near the end has no effect on the output of
git log...
- The output of the
git merge
command isAlready up-to-date.
, even this is not the case (the remote and the local repos have diverged by one commit each). - After this "merge", the local branch (
master
) is one commit ahead of the tracking branch (remrepo/master
). - In contrast to the fetch + merge sequence, the pull does the right thing (i.e. it updates the tracking branch, and carries out the merge), even though both sets of commands have received exactly the same information.
推荐答案
我认为问题在于您的玩具示例使用了 git fetch< repository>< branch>
— refspec 仅由分支名称组成,将其解释为获取后的远程分支的名称,并将其尖端提交的SHA-1名称写入 .git/FETCH_HEAD
文件;没有任何本地分支被更新,因为refspec错过了:destination"部分(要用获取的内容更新哪个本地分支).因此,基本上,您的git fetch可以进行空运行.
I think the problem is that your toy example uses git fetch <repository> <branch>
— the refspec consisting solely of a branch name is interpreted as the name of a branch on the remote, which is fetched, and the SHA-1 name of its tip commit is written to the .git/FETCH_HEAD
file; no local branch is updated as the refspec misses the ":destination" part (what local branch to update with what was fetched). So basically your git fetch does a dry run.
请重新阅读 git-fetch手册.
这篇关于如何分解git pull< REMOTE& gt;< BRANCH& gt;进入获取+合并?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!