注意:这个问题的动机是git
更好地理解,而不是解决任何具体问题。IOW,“实现相同目标”的替代方法(即回避标题中的问题)将是无关紧要的。
命令
git pull
...应该等同于序列
git fetch
git merge
可以git pull <REMOTE> <BRANCH>
(即带有远程和从中提取的分支的显式参数)分解为类似的 afetch
后跟 a的序列merge
吗?
我想这部fetch
分会很简单
git fetch <REMOTE> <BRANCH>
...但是,如果是这样,我无法弄清楚git merge ...
遵循它的正确方法。
我已经尝试过“显而易见”的事情。例如,如果我运行git branch -r
,分支中的输出列表<REMOTE>/<BRANCH>
,所以我尝试了git merge -m 'some message' <REMOTE>/<BRANCH>
,但git
用 , 回复Already up-to-date.
,并git-log
显示它HEAD
保持在尝试之前的相同提交git merge
。为了确认这一点,我将git fetch ...
andgit merge ...
与对 的调用括起来git log ...
,如下所示:
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>
。
下面的玩具示例以/bin/sh
脚本的形式重现了我上面描述的结果。(该脚本在 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
如果运行它,输出将类似于以下内容:
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
从上面的输出可以看出,
- 接近末尾的 fetch + merge 序列对输出没有影响
git log...
- 该
git merge
命令的输出是Already up-to-date.
,即使不是这种情况(远程和本地存储库各有一个提交分歧)。 - 在此“合并”之后,本地分支 (
master
) 是跟踪分支 (remrepo/master
) 之前的一个提交。 - 与 fetch + merge 序列相比,pull 做的是正确的事情(即更新跟踪分支,并执行合并),即使两组命令都接收到完全相同的信息。