元のアドレス:http://blog.csdn.net/forever_wind/article/details/37506389
最近ブログをgithubとgitcafeに同期し、いくつかの問題が発生したため、次の点を分析します。
リモートブランチを同じサーバーにプッシュする
たとえば、最初にgitサーバーを確立し、ところで2つのコピーを複製します
mkdir server
cd server
git init --bare
cd ..
git clone server git1
git clone server git2
gitブランチは現在空です。masterブランチを確立するために何かを送信します。
cd git1
touch a.txt
git add .
git commit -m "init"
git push origin master
これでgitブランチ-aが表示されます:
* master
remotes/origin/master
現在のシステムはマスターブランチにあり、リモートオリジンのリポジトリにもマスターブランチがあります。どちらも追跡しています。git2以下にカット
cd ../git2
git pull origin
この時点で、git2とgit1は完全に同期されています。次に、別のブランチを構築してサーバーにプッシュしようとします。慣れましたが、まだgit1に戻ります
cd ../git1
git checkout -b source
この時点ですでにローカルブランチがあります。このブランチを共有する必要がない場合は、常にこのブランチでコミットできますが、このブランチがメインブランチにマージされるか破棄されるまで、サーバーにプッシュできません。gitブランチは次のように表示されます。
master
* source
次のように、最終的にこのブランチをサーバーにプッシュして他のユーザーと共有することにしました。
git push origin source:source
この時点で、git branch -aは、2つのローカル、2つのリモート、ローカルとリモートを含む現在のリポジトリ内のすべてのブランチがトラッキング状態であることを確認できます。
master
* source
remotes/origin/master
remotes/origin/source
別のコピーに切り取ります。
cd ../git2
git pull origin
表示は次のとおりです。
* [新分支] source -> origin/source
git branch -aは、リモートブランチへのポインターがすでにローカルにあることを示していますが、このブランチを追跡するローカルブランチはありません。
* master
remotes/origin/master
remotes/origin/source
同様に、ブランチの名前は.git / refs / remotes / originで確認できますが、refs / headsでは確認できません。このリモートブランチをチェックしてみましょう:
git checkout -b source origin/source
現時点では、gitブランチの-a表示はgit1と一貫しています。ソースブランチはgit2で編集および同期することもできます。これらは比較的一般的な操作です。マルチブランチのデフォルトパラメータに注意を払う必要があります。たとえば、両方のブランチで何かを変更します。
cd ../git1
git checkout master
//modify
git add .
git commit -m "master modify"
git checkout source
//modify
git add .
git commit -m "source modify"
現時点では、git push originは現在のブランチ用であるため、2つのブランチは同時にのみ更新できます。
git push origin
git checkout master
git push origin
プル更新時
cd ../git2
git checkout master
git pull origin
这会同时更新两个分支的指针,但是不会merge另一个分支,我们去另一个分支下
git checkout source
git pull origin
但是出错如下:
You asked to pull from the remote 'origin', but did not specify
a branch. Because this is not the default configured remote
for your current branch, you must specify a branch on the command line.
问题在于没有给当前分支配置merge的路径,git不知道去merge哪个分支。(虽然我觉得既然是tracking的不应该不知道啊)。
如果你有 1.6.2 以上版本的 Git,—track 选项可以同时配置merge的路径:
git checkout --track origin/serverfix
这里我们修改配置文件加入branch “source”:
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
[remote "origin"]
url = /media/cxh/backup/work/ceshi/git/server
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master"这里指server上的refs/heads/master
[branch "source"]
remote = origin
merge = refs/heads/source
这意味着每次fetch origin的时候更新所有remotes/origin的头指针到refs/heads/下面,具体可以去.git下查阅这个目录,但是头指针都是只读的。merge是由所在branch定义的。
我们加了branch “source”的配置指定当前source的merge策略是使用服务器端的refs/heads/source来合并到当前分支。这样就可以顺利的git pull origin了。
推送远程分支到不同服务器
我们先建立新的repo:
cd ..
mkdir server2
cd server2
git init --bare
加入git1副本,并提交
git remote add server xxx/server2
git push server
上面过程的本质是提交当前分支头指针到server,相当于拷贝refs/head/xxx到refs/remotes/server/下并提交。git push server会被展开成
git push server 当前分支名:当前分支名
我们可以在git2副本同样加入该repository并更新引用
git remote add server xxx/server2
git fetch server
可以看到refs下目录结构如下:
├── heads
│ ├── master
│ └── source
├── remotes
│ ├── origin
│ │ ├── master
│ │ └── source
│ └── server
│ └── source
└── tags
总结一下
-
update
-
fetch操作的本质是更新repo所指定远程分支的头指针(server->refs/remotes/xxx/)
-
merge操作的本质是合并当前分支和指定的头指针(refs/remotes/xxx->refs/heads)
-
pull操作的本质是fetch + merge
-
-
commit
-
commit的本质是修改了当前分支的头指针(refs/heads)
-
push操作本质是提交当前分支头指针到server,顺便也修改了本地存储的server头指针(refs/remotes/xxx)
-
-
checkout
-
复制本地分支的本质是拷贝了refs/heads/下的一个头指针
-
push本地分支到server的本质是把这个头指针上传服务器,顺便拷贝了本地存储的server头指针(refs/remotes/xxx)
-
tracking远程分支的本质是把refs/remotes/下的指针拷贝到了refs/heads下
-
注:以上过程都没有涉及数据流。
参考文献:
[1] Git 分支 – 远程分支, http://git-scm.com/book/zh/Git-%E5%88%86%E6%94%AF-%E8%BF%9C%E7%A8%8B%E5%88%86%E6%94%AF
[2] The Configuration File – “Branch” Section, http://www.gitguys.com/topics/the-configuration-file-branch-section/