一个团队协作开发一个项目,应该如何在团队中分享代码呢?在本章中我们将讨论这种实践。

首先我们来作以下假设:

  • 团队中有两位开发者:A与B
  • A与B都在自己的计算机上修改代码
  • A与B通过服务器上的代码仓库分享代码

3.1 创建服务器端代码仓库 #在服务器端操作

创建一个git用户并设置密码为git:

[root@localhost ]adduser git

[root@localhost ]password git

切换到git用户并进入用户跟目录

[root@localhost ]su git

[git@localhost ]cd /home/git

首先是安装

[root@localhost git]# yum install git git-svn git-email git-gui gitk
Loaded plugins: fastestmirror, refresh-packagekit, security
Loading mirror speeds from cached hostfile
* base: mirror.neu.edu.cn
* extras: mirror.neu.edu.cn
* updates: mirror.neu.edu.cn
base | 3.7 kB 00:00
extras | 3.4 kB 00:00
updates | 3.4 kB 00:00
Setting up Install Process
Package git-svn-1.7.1-3.el6_4.1.noarch already installed and latest version
Package git-email-1.7.1-3.el6_4.1.noarch already installed and latest version
Package git-gui-1.7.1-3.el6_4.1.noarch already installed and latest version
Package gitk-1.7.1-3.el6_4.1.noarch already installed and latest version
Nothing to do

========我已经安装过了,所以给出以上提示=========

创建git-test代码仓库

[git@localhost ~]$ pwd
/home/git
[git@localhost ~]$ git –bare init git-test

Initialized empty Git repository in /home/git/
[git@localhost ~]$ ls
branches Desktop git-test info Pictures Templates
config Documents HEAD Music Public Videos
description Downloads hooks objects refs
[git@localhost ~]$ clear

Git 将输出以下信息:

Initialized empty Git repository in /home/git/git-test/

我们将把git-test作为我们的git服务器端代码仓库使用。

至此

服务器端暂时操作完成。

3.2 创建A的代码仓库

首先需要在A的服务器上创建一个本地的工作空间:

[Jeffery@localhost ~]$ ls
Desktop Documents Downloads Music Pictures Public Templates Videos
[Jeffery@localhost ~]$ mkdir myworkplace
[Jeffery@localhost ~]$ ls
Desktop Documents Downloads Music myworkplace Pictures Public Templates Videos
创建完成后,最好先进行一下git的全局设置 设置一下A的基本信息,如下:
[Jeffery@localhost git-test]$ git config –global user.name “zhangwj”“zhangwj@crtvu.edu.cn”[Jeffery@localhost git-test]$ git config –global user.email

克隆命令:

git clone 目录> [<</span>目录>]

克隆A:

[Jeffery@localhost ~]$ cd myworkplace/
[Jeffery@localhost myworkplace]$ lsgit@202.205.161.48:/home/git/git-test[Jeffery@localhost myworkplace]$ git clone
Initialized empty Git repository in /home/Jeffery/myworkplace/git-test/.git/
The authenticity of host ‘202.205.161.48 (202.205.161.48)’ can’t be established.
RSA key fingerprint is 40:2a:10:80:c3:20:e6:ea:fe:4a:4d:cd:79:df:86:29.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added ‘202.205.161.48’ (RSA) to the list of known hosts.

输入git用户的密码git@202.205.161.48’s password:
如果代码仓库是一个空的仓库,则会提示一个警告:
warning: You appear to have cloned an empty repository.

此时,我们将服务器端的git-test仓库下载到了本地的myworkplace目录中。

检查远端仓库的配置:git remote

[Jeffery@localhost ~]$ cd myworkplace/
[Jeffery@localhost myworkplace]$ ls
git-test
[Jeffery@localhost myworkplace]$ cd git-test/
[Jeffery@localhost git-test]$ git remote

Git将会显示以下信息

origin

git remote命令的作用是显示本地所关联的远端仓库。因此,以上的输出意味着本地关联了一个叫做origin的远端

仓库。那么origin的地址是什么呢?我们可以进一步检查远端仓库的配置:

[Jeffery@localhost git-test]$ cat .git/config

可以看到如下内容:

[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote “origin”]
fetch = +refs/heads/*:refs/remotes/origin/*
url = git@202.205.161.48:/home/git/git-test
[branch “master”]
remote = origin
merge = refs/heads/master

origin其实是一个远端仓库的别名,它实际的地址是有.git/config 中的url来决定的。因此在A的仓库中,origin这

个别名实际上指向了’git@202.205.161.48:/home/git/git-test ‘这个服务器端的代码仓库。

3.3 创建B的代码仓库 在另一台服务器上操作

具体步骤与创建A的代码仓库一样。

git@Git-Ubutntu:~$ mkdir myworkplace
git@Git-Ubutntu:~$ ls
myworkplace
git@Git-Ubutntu:~$ cd myworkplace/
git@Git-Ubutntu:~/myworkplace$ ls
git@Git-Ubutntu:~/myworkplace$ git config –global user.naem “user” #进行全局设置
git@Git-Ubutntu:~/myworkplace$ git config –global user.email “user@qq.com”
git@Git-Ubutntu:~/myworkplace$ git clone git@202.205.161.48:/home/git/git-test #克隆到本地代码仓库
Cloning into ‘git-test’…
The authenticity of host ‘202.205.161.48 (202.205.161.48)’ can’t be established.
RSA key fingerprint is 40:2a:10:80:c3:20:e6:ea:fe:4a:4d:cd:79:df:86:29.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added ‘202.205.161.48’ (RSA) to the list of known hosts.git@202.205.161.48’s password:
warning: You appear to have cloned an empty repository.
此时,我们将服务器端的git-server仓库下载到了本地的B目录中。

3.4 A修改代码

切换到A的目录下面:在A的服务器上操作。

[Jeffery@localhost git-test]$ pwd

/home/Jeffery/myworkplace/git-test
[Jeffery@localhost git-test]$ vi file.txt

输入以下内容:

version 1.0 (A)

完成后保存退出。

[Jeffery@localhost git-test]$ git add file.txt
[Jeffery@localhost git-test]$ git commit -a -m “version 1.0 (zhangwj)”

此时file.txt被提交到本地的代码仓库中。

git commit -a 是把当前修改过的或者已经删除的文件提交到代码仓库。

现在我们将本地的修改推送到服务器端的代码仓库:

[Jeffery@localhost git-test]$ git push

此时,git将显示以下错误:

No refs in common and none specified; doing nothing.
Perhaps you should specify a branch such as ‘master’.
fatal: The remote end hung up unexpectedly
error: failed to push some refs to ‘git@202.205.161.48:/home/git/git-test’

这是因为我们第一次将本地的修改推送到服务器端,此时服务器端还不存在master分支。

我们需要通过以下的命令来重新推送:

[Jeffery@localhost git-test]$ git push origin master

Git会显示以下信息:

Counting objects: 3, done.
Writing objects: 100% (3/3), 247 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@202.205.161.48:/home/git/git-test
* [new branch] master -> master

推送成功。

git push命令的作用是将本地仓库中的分支推送到远端仓库并与远端分支合并,它的用法如下:

git push <</span>远端仓库> <</span>远端分支>或git push

当使用git push <</span>远端仓库> <</span>远端分支>的时候,git将当前的本地分支推送到<</span>远端仓库>中的<</span>远端分支>例如:

git push origin master

意味着将当前分支推送到origin中的master分支。

当使用git push的时候,git会使用哪个<</span>远端仓库>与<</span>远端分支>呢?

首先,我们再次查看.git/config文件

cat .git/config

[branch “master”]

remote = origin

我们发现对于本地的master分支,它的remote为origin。这意味着,当推送本地的master分支的时候,git会向

origin仓库推送。但是要推送到origin仓库中的哪个分支呢?答案是:git默认会推送到同名的分支中去,也就是说

git会将本地的master分支推送到远端的origin/master 中去。

因此,如果本地的分支为topic/a,那么git push等价于git push origin topic/a。

注意:

在大多数情况下,我们只需要使用git push

3.5 B提取代码

假设A推送代码之后通知B将服务器端的代码更新到本地,那么B可以通过以下操作来提取代码:

在B的服务器上进行操作:

git@Git-Ubutntu:~/myworkplace$ cd git-test/
git@Git-Ubutntu:~/myworkplace/git-test$ ls
git@Git-Ubutntu:~/myworkplace/git-test$ git pull
Git会显示以下信息:
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From 202.205.161.48:/home/git/git-test
* [new branch] master -> origin/master

git@Git-Ubutntu:~/myworkplace/git-test$ ls
file.txt
此时我们发现,在B的目录中出现了file.txt,而且file.txt的内容正是A推送的内容。

cat file.txt

version 1.0(A)

# git pull命令的作用是将远端仓库的远端分支下载到本地,并将下载的远端分支合并到本地分支中。它的

#用法如下:

#git pull <</span>远端仓库> <</span>远端分支>或git pull

当使用git pull <</span>远端仓库> <</span>远端分支>的时候,git将<</span>远端仓库>/<</span>远端分支>提取到本地,然后与当前分支合并。

例如:

git pull origin master

意味着git会:1)将origin/master下载到本地,2)再将origin/master与当前分支合并

当使用git pull的时候,git会从使用哪个<</span>远端仓库>与<</span>远端分支>呢?首先,我们再次查看.git/config

cat .git/config

[remote “origin”]

fetch = +refs/heads/*:refs/remotes/origin/*

url = git@218.246.35.250:/home/git/git-test

[branch “master”]

remote = origin

merge = refs/heads/master

remote = origin,意味着当前分支(master)会从origin远端仓库提取分支。

fetch = +refs/heads/*:refs/remotes/origin/*,意味着会将远端仓库中所有位于refs/heads目录下的分支下载到本地

的refs/remotes/origin目录下面

merge = refs/heads/master,意味着git会将远端仓库中refs/heads目录下的master分支与当前分支合并。

因此,在默认情况下,当使用git pull时,git会:1)从当前分支remote属性指定的远端仓库下载所有的分支2)

将当前分支merge属性所指定的远端分支合并到当前分支。

在本例中,git pull等价于git pull origin master。

注意:

在大多数情况下,我们只需要使用git pull

我们可以用git branch命令显示所有的本地分支

git branch

* master

我们可以用git remote命令显示所有的远端仓库。

git remote

origin

git branch -r来显示所有下载到本地的远端分支。

git branch -r

origin/master

现在,我们再来查看.git/config文件

[remote “origin”]

fetch = +refs/heads/*:refs/remotes/origin/*

url = git@202.205.161.48:/home/git/git-test

[branch “master”]

remote = origin

merge = refs/heads/master

[remote “origin”] – 表示此处配置一个远端仓库,本地名称为origin

fetch = +refs/heads/*:refs/remotes/origin/* – 表示在本地执行git pull origin的时候,git会先将远端仓库的

refs/heads/* (相对于远端仓库而言,这是它的本地分支) 下载到本地的refs/remotes/origin/*中。

url = git@202.205.161.48:/home/git/git-test – 表示origin远端仓库的内容来源于

git@202.205.161.48:/home/git/git-test

[branch “master”] – 表示此处配置一个本地分支,分支名称为master

remote = origin – 表示本地的master分支与origin远端仓库关联,因此:git push将向origin.url/refs/heads推送,

而git pull将从origin.url/refs/heads下载

merge = refs/heads/master – 表示在master分支执行git pull的时候,git会将origin.url/heads/master与本地的

master合并。我们知道,因为git pull会首先将origin.url/refs/heads/master下载到本地的

refs/remotes/origin/heads/master,因此git实际上是将refs/remotes/origin/heads/master与本地的master分支合并

3.6 B修改代码

现在我们再模拟B修改代码的场景:

git@Git-Ubutntu:~/myworkplace/git-test$ vi file.txt
做如下修改:
version 1.0 (zhangwj);
version 1.1 (user.qq);

git@Git-Ubutntu:~/myworkplace/git-test$ git commit -a -m “version1.1 user.qq”

Git会显示以下信息:

[master dfe7fea] version1.1 user.qq
1 file changed, 1 insertion(+)

现在我们将本地的修改推送到服务器端的代码仓库:

git@Git-Ubutntu:~/myworkplace/git-test$ git push
warning: push.default is unset; its implicit value is changing in
Git 2.0 from ‘matching’ to ‘simple’. To squelch this message
and maintain the current behavior after the default changes, use:

git config –global push.default matching

To squelch this message and adopt the new behavior now, use:

git config –global push.default simple

See ‘git help config’ and search for ‘push.default’ for further information.
(the ‘simple’ mode was introduced in Git 1.7.11. Use the similar mode
‘current’ instead of ‘simple’ if you sometimes use older versions of Git)

git@202.205.161.48’s password:

Git会显示以下信息:
Counting objects: 5, done.
Writing objects: 100% (3/3), 272 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@202.205.161.48:/home/git/git-test
7fdbd20..dfe7fea master -> master

===========================================================================================

3.7 A,B同时修改代码

3.7.1 A修改代码

cd A

vi file.txt

做如下修改:

version 1.0 (A)

version 1.1 (B)

version 1.2 (A)

git commit -a -m “version 1.2 (A)”

git push

3.7.2 B修改代码

cd B

vi file.txt

做如下修改:

version 1.0 (A)

version 1.1 (B)

version 1.2 (B)

git commit -a -m “version 1.2 (B)”

git push

Git会现实以下错误信息:

To /home/binyang/git-test/git-server

! [rejected] master -> master (non-fast forward)

error: failed to push some refs to ‘/home/binyang/git-test/git-server’

To prevent you from losing history, non-fast-forward updates were rejected

Merge the remote changes before pushing again. See the ‘non-fast forward’

section of ‘git push –help’ for details.

这个错误意味着,git-server中的refs/heads/master的版本比本地的refs/heads/master的版本新,因此不允许推

送。

此时,我们应该尝试提取服务器上最新的代码并将代码合并到本地的分支中:

© 2012 版权所有(杨彬保留所有权力) 11/38

商业机密 – Git 使用手册 杨彬 git-use-v1.0 v1.0

git pull

remote: Counting objects: 5, done.

remote: Total 3 (delta 0), reused 0 (delta 0)

Unpacking objects: 100% (3/3), done.

From git@218.246.35.250:/home/git/git-test

b0e2f52..4e626b3 master -> origin/master

Auto-merging file.txt

CONFLICT (content): Merge conflict in file.txt

Automatic merge failed; fix conflicts and then commit the result.

我们发现在合并代码的时候,发生了冲突”CONFLICT”,因此合并被终止了。

此时,我们首先应该查看哪些文件发生了冲突:

git status

# On branch master

# Your branch and ‘origin/master’ have diverged,

# and have 1 and 1 different commit(s) each, respectively.

#

# Changed but not updated:

# (use “git add …” to update what will be committed)

# (use “git checkout — …” to discard changes in working directory)

#

# unmerged: file.txt

#

no changes added to commit (use “git add” and/or “git commit -a”)

我们发现file.txt发生了冲突,因此必须手动编辑file.txt并解决冲突:

vi file.txt

内容如下:

version 1.0 (A)

version 1.1 (B)

<<<<<<< HEAD

version 1.2 (B)

=======

version 1.2 (A)

>>>>>>> 4e626b314b1f79ebc38c9121aa27dea4a2df4166

将代码修改如下:

version 1.0 (A)

version 1.1 (B)

© 2012 版权所有(杨彬保留所有权力) 12/38

商业机密 – Git 使用手册 杨彬 git-use-v1.0 v1.0

version 1.2 (B)

version 1.2 (A)

将修改加入index 并提交

git add file.txt

git commit

Git会显示如下信息:

git@218.246.35.250:/home/git/git-test[master aa1e89f] Merge branch ‘master’ of

将修改推送到远端仓库

git push

Git会显示如下信息:

Counting objects: 10, done.

Delta compression using up to 4 threads.

Compressing objects: 100% (3/3), done.

Writing objects: 100% (6/6), 593 bytes, done.

Total 6 (delta 0), reused 0 (delta 0)

Unpacking objects: 100% (6/6), done.

To /home/binyang/git-test/git-server

4e626b3..aa1e89f master -> master

3.7.3 A提取代码

cd ~/git-test/A

git pull

Git会显示如下信息:

remote: Counting objects: 10, done.

remote: Compressing objects: 100% (3/3), done.

remote: Total 6 (delta 0), reused 0 (delta 0)

Unpacking objects: 100% (6/6), done.

From /home/binyang/git-test/git-server

4e626b3..aa1e89f master -> origin/master

Updating 4e626b3..aa1e89f

Fast forward

file.txt | 1 +

1 files changed, 1 insertions(+), 0 deletions(-)

注意:

更新合并成功,因为B已经解决了冲突并将解决后的版本推送到了服务器。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐