关于git远程版本库的一些问题之解决

Posted JasonXu徐晓峰

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于git远程版本库的一些问题之解决相关的知识,希望对你有一定的参考价值。

Part1:CentOS6.5免密码登录

修改/etc/ssh/sshd_config
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile /root/.ssh/authorized_keys
启用这三行,然后重启service sshd restart
设置.ssh目录权限
chmod 700 -R .ssh
如果你想要每台机子都无密码登录,那么把每台机子产生的密钥添加到文件中(这是在受控端机子上面执行的)
cat id_rsa.pub >> .ssh/authorized_keys

如果遇到登录失败的情况:我用的是centos版本是6.5,centos6.5对网络管理相当严格,需要在原来的基础上关闭selinux, 到/etc/selinux/config下,把SELINUX=enforcing修改为SELINUX=disabled,重启机器,ok

 

Part2:SSH私钥取消密码(passphrase)

搞定rsync多台机器之间同步文件之后发现以前使用的ssh密钥是有密码的,这样每次同步时候还需要手动输入一次密码才可以。

Google后有人提示可以使用.bash_profile配合ssh-agent来实现每次自动加载密钥到内存中,省去输入密码的环节,但.bash_profile有各种弊端,有人专门写了一个叫做keychain的小软件来解决ssh-agent 的不足。

但实际使用的时候依然不是很顺手,就干脆取消了私钥中的密码:

1. 使用openssl命令去掉私钥的密码openssl rsa -in ~/.ssh/id_rsa -out ~/.ssh/id_rsa_new

2. 备份旧私钥mv ~/.ssh/id_rsa ~/.ssh/id_rsa.backup

3. 使用新私钥mv ~/.ssh/id_rsa_new ~/.ssh/id_rsa

4. 设置权限chomd 600 ~/.ssh/id_rsa

取消掉原私钥的密码,配合cron计划任务定时同步文件就可以保证多台服务器文件自动更新了。而且只要注意私钥不泄漏出去,多台服务器之间无密码登录也方便很多。

 

Part3:git查看修改用户名和邮箱地址

GIT 查看/修改用户名和邮箱地址

用户名和邮箱地址的作用

用户名和邮箱地址是本地git客户端的一个变量,不随git库而改变。

每次commit都会用用户名和邮箱纪录。

github的contributions统计就是按邮箱来统计的。

查看用户名和邮箱地址:

$ git config user.name

$ git config user.email

修改用户名和邮箱地址:

$ git config --global user.name "username"

$ git config --global user.email "email"

 

Part4:SSH 登录时出现如下错误:Disconnected:No supported authentication methods available

问题现象

当您通过 SSH 客户端登录 ECS Linux 实例时,输入正确的账号密码,也会出现类似如下错误信息。

Symptom

Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
sshd[10826]: Connection closed by XX.XX.XX.XX.
Disconnected: No supported authentication methods available.
原因分析

参数 PasswordAuthentication 的默认值为 yes,SSH 服务将其值置为 no 以禁用密码验证登录,导致此类故障。需要修改 PasswordAuthentication 配置解决此问题。

解决方法

建议在修改配置文件之前 创建快照 备份数据。以 CentOS 6.8 为例:

通过 管理终端 连接并登录到 Linux 实例。

执行命令 cat /etc/ssh/sshd_config 查看 SSH 服务配置,并注意是否包含类似如下配置:

Config

执行命令 vi /etc/ssh/sshd_config,按下 i 编辑 SSH 服务配置文件,将参数 PasswordAuthentication 设置为 yes,或者在 PasswordAuthentication 参数前添加井号(#),按下 Esc 退出编辑模式,并输入 :wq 保存退出。

Shooting

执行命令 service ssh restart 重启 SSH 服务。

 

Part5:用 Git Hooks 进行自动部署

远程连接服务器

生成 SSH 密钥

密钥是免登录连接服务器的通行证,有种刷脸通行的感觉。如果本地已经存在并且不想另外生成的话,可以跳过此步。

cd ~/.ssh 切换目录后用 ssh-keygen -t rsa -C "用于区分密钥的标识" 生成一对具有相同名字的密钥(默认为 id_rsa 和id_rsa.pub):用于本地的私钥和用于服务器的公钥(有 .pub 扩展名)。

如果私钥名字不是默认的话,需要手动加入到被「认证」的私钥列表中,否则每次连接服务器都会提示输入服务器的密码。在遇到了一些坑(文后有说明)后,我觉得设置 SSH config 最为靠谱!

编辑 ~/.ssh/config 文件(如果不存在则 touch ~/.ssh/config 创建一下),添加以下内容:

Host HOST_ALIAS # 用于 SSH 连接的别名,最好与 HostName 保持一致
  HostName SERVER_DOMAIN # 服务器的域名或 IP 地址
  Port SERVER_PORT # 服务器的端口号,默认为 22,可选
  User SERVER_USER # 服务器的用户名
  PreferredAuthentications publickey
  IdentityFile ~/.ssh/PRIVATE_KEY # 本机上存放的私钥路径

如下所示
Host BRIDGE_REPO
  HostName xxx.xxx.xxx.xxx
  Port 22
  User git
  PreferredAuthentications publickey
  IdentityFile ~/.ssh/id_rsa
服务器端认证

#先用 pbcopy < ~/.ssh/PRIVATE_KEY.pub 将公钥复制到剪贴板;通过 ssh [email protected] 访问服务器,这时会提示输入密码(它也许只有这么一次「询问」的机会);成功登录后 vim ~/.ssh/authorized_keys,在合适的位置 cmd + V 并保存退出(同时 exit退出 SSH 连接)。
进入服务器直接 vi /root/.ssh/authorized_keys
将公钥内容复制进去

配置 Git 仓库

创建服务器端仓库

服务器上需要配置两个仓库,一个用于代码中转的远程仓库,一个用于用户访问的本地仓库。这里的「远程仓库」并不等同于托管代码的「中央仓库」,这两个仓库都是为了自动同步代码并部署网站而存在。

在存放远程仓库的目录中(假设是 /home/USER/repos)执行 git init --bare BRIDGE_REPO.git 会创建一个包含 Git 各种配置文件的「裸仓库」。

切换到存放用户所访问文件的目录(假设为 /home/USER/www,如果不存在则在 /home/USER 中执行 mkdir www):

git init
git remote add origin /home/USER/repos/BRIDGE_REPO.git
git fetch
git checkout master
配置 Git Hook

将目录切换至 /home/USER/repos/BRIDGE_REPO.git/hooks,用 cp post-receive.sample post-receive 复制并重命名文件后用 vim post-receive 修改。其内容大致如下:
下面的shell脚本自己摸索,可以并不相同
#!/bin/sh

unset GIT_DIR #这一句是非常重要的

NowPath=`pwd`
DeployPath="../../www"

cd $DeployPath
git pull origin master

cd $NowPath
exit 0
使用 chmod +x post-receive 改变一下权限后,服务器端的配置就基本完成了。

更新本机的仓库源

在原有的(托管代码的)仓库上加入刚才所配置的服务器上的远程仓库的地址为源,以后往那个源推送代码后就会自动部署了。

总结

在搭建环境时并没有一帆风顺,磕磕绊绊遇到不少问题,虽然很多不值得一提,但有的点还是有记录并分享的价值的!

SSH 私钥「认证」

将生成的私钥进行「认证」有不止一种方式,然而,起初我用的是最挫最不靠谱的 ssh-add ~/.ssh/PRIVATE_KEY——只是在当前 session 有效,一重启就又会被「询问」了!

 

错误处理
remote: error: cannot open .git/FETCH_HEAD: Permission denied
将整个项目文件夹配置用户和用户组
chown -R git:git BRIDGE_REPO

 

Part6:git 删除本地分支和远程分支、本地代码回滚和远程代码库回滚

【git 删除本地分支】

git branch -D br

 

【git 删除远程分支】

git push origin :br (origin 后面有空格)

 

git代码库回滚: 指的是将代码库某分支退回到以前的某个commit id

【本地代码库回滚】:

git reset --hard commit-id :回滚到commit-id,讲commit-id之后提交的commit都去除

git reset --hard HEAD~3:将最近3次的提交回滚

 

【远程代码库回滚】:

这个是重点要说的内容,过程比本地回滚要复杂

应用场景:自动部署系统发布后发现问题,需要回滚到某一个commit,再重新发布

原理:先将本地分支退回到某个commit,删除远程分支,再重新push本地分支

操作步骤:

1、git checkout the_branch

2、git pull

3、git branch the_branch_backup //备份一下这个分支当前的情况

4、git reset --hard the_commit_id //把the_branch本地回滚到the_commit_id

5、git push origin :the_branch //删除远程 the_branch

6、git push origin the_branch //用回滚后的本地分支重新建立远程分支

7、git push origin :the_branch_backup //如果前面都成功了,删除这个备份分支

如果使用了gerrit做远程代码中心库和code review平台,需要确保操作git的用户具备分支的push权限,并且选择了 Force Push选项(在push权限设置里有这个选项)

另外,gerrit中心库是个bare库,将HEAD默认指向了master,因此master分支是不能进行删除操作的,最好不要选择删除master分支的策略,换用其他分支。如果一定要这样做,可以考虑到gerrit服务器上修改HEAD指针。。。不建议这样搞

 

有时候并行的开发了很多的特性,建了很多的分支,时间长了分支就多了,想要把不用的分支删除,怎么办呢?
#查看本地都有哪些分支
git branch

#查看所有的分支,包括远程的
git branch -a

#删除本地的某个分支
git branch -D hongchangfirst

#删除远程的分支
git branch -r -d origin/hongchangfirst

#注意这个只是删除本地的索引,而不是真正删除远程分支的内容,要想真正删除远程分支上的内容,可以这样:
git push origin :hongchangfirst

注意,冒号前面的空格不能少,相当于把一个空分支push到server上,等于删除该分支。


做为一名程序员,除了写写代码外,还负责公司的GIT库的日常维护工作。GIT日常操作不是很多,掌握这些技能就够了,在这里主要是分享一下GIT分支的删除操作,希望可以帮到刚学习GIT的同学。这里的删除操作主要是服务器本地操作和远端删除操作。


GIT
方法/步骤
前提条件,必须下载安装了GIT客户端软件,以下操作仅限于Windows操作。
右键点击GIT库,选择Git Bash选项。
GIT如何删除分支
这时会弹出如下窗口,默认就进入当前GIT库。
GIT如何删除分支
如下图所示,先看一下当前库中有哪些分支:
git branch -a
GIT如何删除分支
要删除服务器远端的分支,则执行如下所示的命令:
git push origin –delete 分支名
GIT如何删除分支
如果是要删除本地已经合并了的分支,则执行:
git branch –d 分支名
GIT如何删除分支
下图中的命令是为了删除本地未合并的分支:
git branch –D 分支名

 

Part7:git命令之git remote的用法

要 参与任何一个 Git 项目的协作,必须要了解该如何管理远程仓库.远程仓库是指托管在网络上的项目仓库,可能会有好多个,其中有些你只能读,另外有些可以写.同他人协作开发某 个项目时,需要管理这些远程仓库,以便推送或拉取数据,分享各自的工作进展.管理远程仓库的工作,包括添加远程库,移除废弃的远程库,管理各式远程库分 支,定义是否跟踪这些分支,等等.本节我们将详细讨论远程库的管理和使用.

  查看当前的远程库

  要查看当前配置有哪些远程仓库,可以用 git remote 命令,它会列出每个远程库的简短名字.在克隆完某个项目后,至少可以看到一个名为 origin 的远程库,Git 默认使用这个名字来标识你所克隆的原始仓库:

  $ git clone git://github.com/schacon/ticgit.git

  Initialized empty Git repository in /private/tmp/ticgit/.git/

  remote: Counting objects: 595, done.

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

  remote: Total 595 (delta 255), reused 589 (delta 253)

  Receiving objects: 100% (595/595), 73.31 KiB | 1 KiB/s, done.

  Resolving deltas: 100% (255/255), done.

  $ cd ticgit

(1)git remote 不带参数,列出已经存在的远程分支

  $ git remote

  origin

(2)git remote -v | --verbose 列出详细信息,在每一个名字后面列出其远程url

此时, -v 选项(译注:此为 –verbose 的简写,取首字母),显示对应的克隆地址:

  $ git remote -v

  origin git://github.com/schacon/ticgit.git如果有多个远程仓库,此命令将全部列出.比如在我的 Grit 项目中,可以看到:

  $ cd grit

  $ git remote -v

  bakkdoor git://github.com/bakkdoor/grit.git

  cho45 git://github.com/cho45/grit.git

  defunkt git://github.com/defunkt/grit.git

  koke git://github.com/koke/grit.git

  origin 这样一来,我就可以非常轻松地从这些用户的仓库中,拉取他们的提交到本地.请注意,上面列出的地址只有 origin 用的是 SSH URL 链接,所以也只有这个仓库我能推送数据上去(我们会在第四章解释原因).

  添加远程仓库

  要添加一个新的远程仓库,可以指定一个简单的名字,以便将来引用,运行 git remote add [shortname] [url]:

  $ git remote

  origin

  $ git remote add pb git://github.com/paulboone/ticgit.git

  $ git remote -v

  origin git://github.com/schacon/ticgit.git

  pb git://github.com/paulboone/ticgit.git现在可以用字串 pb 指代对应的仓库地址了.比如说,要抓取所有 Paul 有的,但本地仓库没有的信息,可以运行 git fetch pb:

  $ git fetch pb

  remote: Counting objects: 58, done.

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

  remote: Total 44 (delta 24), reused 1 (delta 0)

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

  From git://github.com/paulboone/ticgit

  * [new branch] master -> pb/master

  * [new branch] ticgit -> pb/ticgit

现在,Paul 的主干分支(master)已经完全可以在本地访问了,对应的名字是 pb/master,你可以将它合并到自己的某个分支,或者切换到这个分支,看看有些什么有趣的更

 

二.通过git remote 建立远程仓库


建立远程仓库
最近一直在学习使用git来管理自己的程序,总是今天东学一点,明天西凑一点,到用的时候,总是有些茫然不知所措。

在博客园里看见一篇老好的文章,教我们做笔记啦,但是做完笔记还是要记得总结哦!

来吧,让我们一起来总结吧,今天先来看看git远程的仓库是怎么建立的。

当然,使用git嘛,第一步肯定是得新建一个git仓库,总得有个操作的空间吧,巧妇难为无米之炊嘛。

1.初始化一个空的git仓库

1 [email protected]:~$ mkdir yafeng
2 [email protected]:~$ cd yafeng/
3 [email protected]:~/yafeng$ ls
4 [email protected]:~/yafeng$ git init
5 Initialized empty Git repository in /home/software/yafeng/.git/
6 [email protected]:~/yafeng$
命令注释:

在上面的命令中,真正去初始化的是第四行的那句---git init

当然,还有很多同学会看见加了参数--bare的命令,这个命令会在我们以后慢慢给大家解释,对于不是作为共享仓库,而是作为一个自己操作的仓库,上面这样就足够了。

好了,现在yafeng目录就是我们的据点---git仓库了哦。

下面我们总要做点什么的吧,入宝山总不能光看着哦:

2.向仓库提交我们写的文件

1 [email protected]:~/yafeng$ echo "our first git repository" >> file
2 [email protected]:~/yafeng$ ls
3 file
4 [email protected]:~/yafeng$ git add file
5 [email protected]:~/yafeng$ git commit -m "the first file to commit" file
6 [master (root-commit) 0c72641] the first file to commit
7 1 files changed, 1 insertions(+), 0 deletions(-)
8 create mode 100644 file
9 [email protected]:~/yafeng$
命令解释:
我们在仓库中新建了一个文件file,作为我们的示例文件。

第4行:将file文件的信息添加到git仓库的索引库中,并没有真正添加到库。当然上例中的file文件只是我们的示例,它是一个路径,因此,可以是文件,更可以是目录。

第5行:将索引库中的内容向git仓库进行提交。这步之后文件file才算真正提交到拉git仓库中。双引号中的内容是根据每次修改的不同内容,由我们自己去填写的,

很多人会看见

  git commit -a -m “ ”

这条的命令是在你已经add了一个或多个文件过之后,然后修改了这些文件,就可以使用该命令进行提交。

好了,不管怎么样,终于是将文件提交到库了。可是现在的仓库只是一个本地的仓库,我们的目标是变成远程仓库哦,继续吧。

3.在本地仓库添加一个远程仓库,并将本地的master分支跟踪到远程分支

1 [email protected]:~/yafeng$ git remote add origin ssh://[email protected]/~/yafeng/.git
2 [email protected]:~/yafeng$ git push origin master
3 [email protected]‘s password:
4 Everything up-to-date
5 [email protected]:~/yafeng$
命令注释:

第1行:在本地仓库添加一个远程仓库,当然ssh后面的地址是我们本地仓库的地址.

第2行:将本地master分支跟踪到远程分支,在git仓库建立之初就会有一个默认的master分支,当然你如果建立了其他分支,也可以用同样的方法去跟踪.

对于分支的事情,我们会在以后细细的讲述.

做到拉这一步了吗?我告诉你,你已经完成目的了哦,现在的git仓库已经是一个远程仓库了,

不相信吗?我们来测试一次阿:

4.测试

现在本机上看看:


1 [email protected]:~/yafeng$ git remote show origin
2 [email protected]‘s password:
3 * remote origin
4 Fetch URL: ssh://[email protected]/~/yafeng/.git
5 Push URL: ssh://[email protected]/~/yafeng/.git
6 HEAD branch: master
7 Remote branch:
8 master tracked
9 Local ref configured for ‘git push‘:
10 master pushes to master (up to date)
11 [email protected]:~/yafeng$

代码注释:

第1行:显示远程信息

很多看见这还是会不以为然的,这又能说明什么呢?好,那就来点实际的:

在另一个机子上,远程clone

1 [email protected]:~# ls
2 bin gittest read_temp
3 [email protected]:~# git clone ssh://[email protected]/~/yafeng/.git
4 Cloning into yafeng...
5 [email protected]‘s password:
6 remote: Counting objects: 9, done.
7 remote: Compressing objects: 100% (3/3), done.
8 remote: Total 9 (delta 0), reused 0 (delta 0)
9 Receiving objects: 100% (9/9), done.
10 [email protected]:~# ls
11 bin gittest read_temp yafeng
12 [email protected]:~# cd yafeng/
13 [email protected]:~/yafeng# ls
14 file
15 [email protected]:~/yafeng#

代码注释:

第3行:就是远程clone仓库.很明显的对比可以知道多了yafeng目录,而这个yafeng目录里的内容和我们另外一台机子上的内容一样

至此,一个简单的git远程仓库就建好了,简单不,试试吧!!

 

part8:SSH下know_hosts的作用

ssh会把你每个你访问过计算机的公钥(public key)都记录在~/.ssh/known_hosts。当下次访问相同计算机时,OpenSSH会核对公钥。如果公钥不同,OpenSSH会发出警告, 避免你受到DNS Hijack之类的攻击。我在上面列出的情况,就是这种情况。

原因:一台主机上有多个Linux系统,会经常切换,那么这些系统使用同一ip,登录过一次后就会把ssh信息记录在本地的~/.ssh/known_hsots文件中,切换该系统后再用ssh访问这台主机就会出现冲突警告,需要手动删除修改known_hsots里面的内容。

有以下两个解决方案:
1. 手动删除修改known_hsots里面的内容;
2. 修改配置文件“~/.ssh/config”,加上这两行,重启服务器。
StrictHostKeyChecking no
UserKnownHostsFile /dev/null

优缺点:
1. 需要每次手动删除文件内容,一些自动化脚本的无法运行(在SSH登陆时失败),但是安全性高;
2. SSH登陆时会忽略known_hsots的访问,但是安全性低;

 

Part9:git diff命令详解

git diff命令详解

diff里面a表示前面那个变量,b表示第二个变量

HEAD commit版本
Index staged版本

a、查看尚未暂存的文件更新了哪些部分,不加参数直接输入
git diff
此命令比较的是工作目录(Working tree)和暂存区域快照(index)之间的差异
也就是修改之后还没有暂存起来的变化内容。

b、查看已经暂存起来的文件(staged)和上次提交时的快照之间(HEAD)的差异
git diff --cached
git diff --staged
显示的是下一次commit时会提交到HEAD的内容(不带-a情况下)


c、显示工作版本(Working tree)和HEAD的差别
git diff HEAD


d、直接将两个分支上最新的提交做diff
git diff topic master 或 git diff topic..master

e、输出自topic和master分别开发以来,master分支上的changed。
git diff topic...master
Changes that occurred on the master branch since when the topic
branch was started off it
f、查看简单的diff结果,可以加上--stat参数
git diff --stat

g、查看当前目录和另外一个分支的差别
git diff test
显示当前目录和另一个叫‘test‘分支的差别
git diff HEAD -- ./lib
显示当前目录下的lib目录和上次提交之间的差别(更准确的说是在当前分支下)

h、比较上次提交commit和上上次提交
git diff HEAD^ HEAD

i、比较两个历史版本之间的差异
git diff SHA1 SHA2

 

Part10:git push出现的错误

$ git push
Enter passphrase for key ‘/f/wamp64/www/.ssh/id_rsa‘:
Counting objects: 6, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (6/6), done.
Writing objects: 100% (6/6), 827 bytes | 206.00 KiB/s, done.
Total 6 (delta 4), reused 0 (delta 0)
remote: error: insufficient permission for adding an object to repository database ./objects
remote: fatal: failed to write object
error: remote unpack failed: unpack-objects abnormal exit
To ssh://xxx.xxx.xxx.xxx/data/gitshare/erp.git
! [remote rejected] master -> master (unpacker error)
error: failed to push some refs to ‘ssh://[email protected]/data/gitxxx/xxx.git‘

解决:
chown -R git:git xxx.git

 

Part11:git查询某次修改的内容

Git 查询某次历史提交的修改内容
在工作时,有时候想查看某次的提交修改了哪些的内容。
我们首先可以git log显示历史的提交列表:
之后我们用git show <commit-hashId> 便可以显示某次提交的修改内容
同样 git show <commit-hashId> filename 可以显示某次提交的某个内容的修改信息。

 

Part12:Git 本地的撤销修改和删除操作

一:撤销操作

比如我现在在readme.txt文件里面增加一行 内容为555555555555,我们先通过命令查看如下: 


在我未提交之前,我发现添加5555555555555内容有误,所以我得马上恢复以前的版本,现在我可以有如下几种方法可以做修改: 


第一:如果我知道要删掉那些内容的话,直接手动更改去掉那些需要的文件,然后add添加到暂存区,最后commit掉。 


第二:我可以按以前的方法直接恢复到上一个版本。使用 git reset –hard HEAD^ 


但是现在我不想使用上面的2种方法,我想直接想使用撤销命令该如何操作呢?首先在做撤销之前,我们可以先用 git status 查看下当前的状态。如下所示:

 


可以发现,Git会告诉你,git checkout — file 可以丢弃工作区的修改,如下命令: 


git checkout – readme.txt,如下所示:

 


命令 git checkout –readme.txt 意思就是,把readme.txt文件在工作区做的修改全部撤销,这里有2种情况,如下:

  1. readme.txt自动修改后,还没有放到暂存区,使用 撤销修改就回到和版本库一模一样的状态。
  2. 另外一种是readme.txt已经放入暂存区了,接着又作了修改,撤销修改就回到添加暂存区后的状态。

其实也就是撤销到最后一次没有放入暂存区的状态。 


对于第二种情况,我想我们继续做demo来看下,假如现在我对readme.txt添加一行 内容为6666666666666,我git add 增加到暂存区后,接着添加内容7777777,我想通过撤销命令让其回到暂存区后的状态。如下所示: 


 


注意:命令git checkout — readme.txt 中的 — 很重要,如果没有 — 的话,那么命令变成创建分支了。 


二:删除文件。

假如我现在版本库testgit目录添加一个文件b.txt,然后提交。如下: 


 


如上:一般情况下,可以直接在文件目录中把文件删了,或者使用如上rm命令:rm b.txt ,如果我想彻底从版本库中删掉了此文件的话,可以再执行commit命令 提交掉,现在目录是这样的 


 


只要没有commit之前,如果我想在版本库中恢复此文件如何操作呢? 


可以使用如下命令 git checkout — b.txt,如下所示:

 


再来看看我们testgit目录,添加了3个文件了。如下所示:

 

 

 

Part13:git命令之git clone用法

git命令之git clone用法

转:http://blog.csdn.net/wangjia55/article/details/8818845
在使用git来进行版本控制时,为了得一个项目的拷贝(copy),我们需要知道这个项目仓库的地址(Git URL). Git能在许多协议下使用,所以Git URL可能以ssh://, http(s)://, git://,或是只是以一个用户名(git 会认为这是一个ssh 地址)为前辍.
有些仓库可以通过不只一种协议来访问,例如,Git本身的源代码你既可以用 git:// 协议来访问:
git clone git://git.kernel.org/pub/scm/git/git.git
也可以通过http 协议来访问:
git clone http://www.kernel.org/pub/scm/git/git.git
git://协议较为快速和有效,但是有时必须使用http协议,比如你公司的防火墙阻止了你的非http访问请求.如果你执行了上面两行命令中的任意一个,你会看到一个新目录: ‘git‘,它包含有所的Git源代码和历史记录.
在默认情况下,Git会把"Git URL"里最后一级目录名的‘.git‘的后辍去掉,做为新克隆(clone)项目的目录名: (例如. git clone http://git.kernel.org/linux/kernel/git/torvalds/linux-2.6.git 会建立一个目录叫‘linux-2.6‘)
另外,如果访问一个Git URL需要用法名和密码,可以在Git URL前加上用户名,并在它们之间加上@符合以表示分割,然后执行git clone命令,git会提示你输入密码。
示例
git clone [email protected]://www.kernel.org/pub/scm/git/git.git
这样将以作为robin.hu用户名访问http://www.kernel.org/pub/scm/git/git.git,然后按回车键执行git clone命令,git会提示你输入密码。
另外,我们可以通过-b <name>来指定要克隆的分支名,比如
$ git clone -b master2 ../server .
表示克隆名为master2的这个分支,如果省略-b <name>表示克隆master分支。

GIT URLS

In general, URLs contain information about the transport protocol, the address of the remote server, and the path to the repository. Depending on the transport protocol, some of this information may be absent.
Git natively supports ssh, git, http, https, ftp, ftps, and rsync protocols. The following syntaxes may be used with them:
ssh://[[email protected]]host.xz[:port]/path/to/repo.git/
git://host.xz[:port]/path/to/repo.git/
http[s]://host.xz[:port]/path/to/repo.git/
ftp[s]://host.xz[:port]/path/to/repo.git/
rsync://host.xz/path/to/repo.git/
An alternative scp-like syntax may also be used with the ssh protocol:
[[email protected]]host.xz:path/to/repo.git/
The ssh and git protocols additionally support ~username expansion:
ssh://[[email protected]]host.xz[:port]/~[user]/path/to/repo.git/
git://host.xz[:port]/~[user]/path/to/repo.git/
[[email protected]]host.xz:/~[user]/path/to/repo.git/
For local repositories, also supported by git natively, the following syntaxes may be used:
/path/to/repo.git/
file:///path/to/repo.git/

Examples

Clone from upstream:
$ git clone git://git.kernel.org/pub/scm/.../linux-2.6 my2.6 $ cd my2.6 $ make
Make a local clone that borrows from the current directory, without checking things out:
$ git clone -l -s -n . ../copy $ cd ../copy $ git show-branch
Clone from upstream while borrowing from an existing local directory:
$ git clone --reference my2.6 \ git://git.kernel.org/pub/scm/.../linux-2.7 \ my2.7 $ cd my2.7
Create a bare repository to publish your changes to the public:
$ git clone --bare -l /home/proj/.git /pub/scm/proj.git
Create a repository on the kernel.org machine that borrows from Linus:
$ git clone --bare -l -s /pub/scm/.../torvalds/linux-2.6.git \ /pub/scm/.../me/subsys-2.6.git

Part14:Git远程操作详解

Git远程操作详解

Git是目前最流行的版本管理系统,学会Git几乎成了开发者的必备技能。

Git有很多优势,其中之一就是远程操作非常简便。本文详细介绍5个Git命令,它们的概念和用法,理解了这些内容,你就会完全掌握Git远程操作。

  • § git clone
  • § git remote
  • § git fetch
  • § git pull
  • § git push

本文针对初级用户,从最简单的讲起,但是需要读者对Git的基本用法有所了解。同时,本文覆盖了上面5个命令的几乎所有的常用用法,所以对于熟练用户也有参考价值。

 

一、git clone

远程操作的第一步,通常是从远程主机克隆一个版本库,这时就要用到git clone命令。

 

$ git clone <版本库的网址>

比如,克隆jQuery的版本库。

 

$ git clone https://github.com/jquery/jquery.git

该命令会在本地主机生成一个目录,与远程主机的版本库同名。如果要指定不同的目录名,可以将目录名作为git clone命令的第二个参数。

 

$ git clone <版本库的网址> <本地目录名>

git clone支持多种协议,除了HTTP(s)以外,还支持SSH、Git、本地文件协议等,下面是一些例子。

 

$ git clone http[s]://example.com/path/to/repo.git/

$ git clone ssh://example.com/path/to/repo.git/

$ git clone git://example.com/path/to/repo.git/

$ git clone /opt/git/project.git

$ git clone file:///opt/git/project.git

$ git clone ftp[s]://example.com/path/to/repo.git/

$ git clone rsync://example.com/path/to/repo.git/

SSH协议还有另一种写法。

 

$ git clone [[email protected]]example.com:path/to/repo.git/

通常来说,Git协议下载速度最快,SSH协议用于需要用户认证的场合。各种协议优劣的详细讨论请参考官方文档

二、git remote

为了便于管理,Git要求每个远程主机都必须指定一个主机名。git remote命令就用于管理主机名。

不带选项的时候,git remote命令列出所有远程主机。

 

$ git remote

origin

使用-v选项,可以参看远程主机的网址。

 

$ git remote -v

origin  git@github.com:jquery/jquery.git (fetch)

origin  git@github.com:jquery/jquery.git (push)

上面命令表示,当前只有一台远程主机,叫做origin,以及它的网址。

克隆版本库的时候,所使用的远程主机自动被Git命名为origin。如果想用其他的主机名,需要用git clone命令的-o选项指定。

 

$ git clone -o jQuery https://github.com/jquery/jquery.git

$ git remote

jQuery

上面命令表示,克隆的时候,指定远程主机叫做jQuery。

git remote show命令加上主机名,可以查看该主机的详细信息。

 

$ git remote show <主机名>

git remote add命令用于添加远程主机。

 

$ git remote add <主机名> <网址>

git remote rm命令用于删除远程主机。

 

$ git remote rm <主机名>

git remote rename命令用于远程主机的改名。

 

$ git remote rename <原主机名> <新主机名>

三、git fetch

一旦远程主机的版本库有了更新(Git术语叫做commit),需要将这些更新取回本地,这时就要用到git fetch命令。

 

$ git fetch <远程主机名>

上面命令将某个远程主机的更新,全部取回本地。

git fetch命令通常用来查看其他人的进程,因为它取回的代码对你本地的开发代码没有影响。

默认情况下,git fetch取回所有分支(branch)的更新。如果只想取回特定分支的更新,可以指定分支名。

 

$ git fetch <远程主机名> <分支名>

比如,取回origin主机的master分支。

 

$ git fetch origin master

所取回的更新,在本地主机上要用"远程主机名/分支名"的形式读取。比如origin主机的master,就要用origin/master读取。

git branch命令的-r选项,可以用来查看远程分支,-a选项查看所有分支。

 

$ git branch -r

origin/master

 

$ git branch -a

* master

  remotes/origin/master

上面命令表示,本地主机的当前分支是master,远程分支是origin/master。

取回远程主机的更新以后,可以在它的基础上,使用git checkout命令创建一个新的分支。

 

$ git checkout -b newBrach origin/master

上面命令表示,在origin/master的基础上,创建一个新分支。

此外,也可以使用git merge命令或者git rebase命令,在本地分支上合并远程分支。

 

$ git merge origin/master

# 或者

$ git rebase origin/master

上面命令表示在当前分支上,合并origin/master。

四、git pull

git pull命令的作用是,取回远程主机某个分支的更新,再与本地的指定分支合并。它的完整格式稍稍有点复杂。

 

$ git pull <远程主机名> <远程分支名>:<本地分支名>

比如,取回origin主机的next分支,与本地的master分支合并,需要写成下面这样。

 

$ git pull origin next:master

如果远程分支是与当前分支合并,则冒号后面的部分可以省略。

 

$ git pull origin next

上面命令表示,取回origin/next分支,再与当前分支合并。实质上,这等同于先做git fetch,再做git merge。

 

$ git fetch origin

$ git merge origin/next

在某些场合,Git会自动在本地分支与远程分支之间,建立一种追踪关系(tracking)。比如,在git clone的时候,所有本地分支默认与远程主机的同名分支,建立追踪关系,也就是说,本地的master分支自动"追踪"origin/master分支。

Git也允许手动建立追踪关系。

 

git branch --set-upstream master origin/next

上面命令指定master分支追踪origin/next分支。

如果当前分支与远程分支存在追踪关系,git pull就可以省略远程分支名。

 

$ git pull origin

上面命令表示,本地的当前分支自动与对应的origin主机"追踪分支"(remote-tracking branch)进行合并。

如果当前分支只有一个追踪分支,连远程主机名都可以省略。

 

$ git pull

上面命令表示,当前分支自动与唯一一个追踪分支进行合并。

如果合并需要采用rebase模式,可以使用--rebase选项。

 

$ git pull --rebase <远程主机名> <远程分支名>:<本地分支名>

如果远程主机删除了某个分支,默认情况下,git pull 不会在拉取远程分支的时候,删除对应的本地分支。这是为了防止,由于其他人操作了远程主机,导致git pull不知不觉删除了本地分支。

但是,你可以改变这个行为,加上参数 -p 就会在本地删除远程已经删除的分支。

 

$ git pull -p

# 等同于下面的命令

$ git fetch --prune origin

$ git fetch -p

五、git push

git push命令用于将本地分支的更新,推送到远程主机。它的格式与git pull命令相仿。

 

$ git push <远程主机名> <本地分支名>:<远程分支名>

注意,分支推送顺序的写法是<来源地>:<目的地>,所以git pull是<远程分支>:<本地分支>,而git push是<本地分支>:<远程分支>。

如果省略远程分支名,则表示将本地分支推送与之存在"追踪关系"的远程分支(通常两者同名),如果该远程分支不存在,则会被新建。

 

$ git push origin master

上面命令表示,将本地的master分支推送到origin主机的master分支。如果后者不存在,则会被新建。

如果省略本地分支名,则表示删除指定的远程分支,因为这等同于推送一个空的本地分支到远程分支。

 

$ git push origin :master

# 等同于

$ git push origin --delete master

上面命令表示删除origin主机的master分支。

如果当前分支与远程分支之间存在追踪关系,则本地分支和远程分支都可以省略。

 

$ git push origin

上面命令表示,将当前分支推送到origin主机的对应分支。

如果当前分支只有一个追踪分支,那么主机名都可以省略。

 

$ git push

如果当前分支与多个主机存在追踪关系,则可以使用-u选项指定一个默认主机,这样后面就可以不加任何参数使用git push。

 

$ git push -u origin master

上面命令将本地的master分支推送到origin主机,同时指定origin为默认主机,后面就可以不加任何参数使用git push了。

不带任何参数的git push,默认只推送当前分支,这叫做simple方式。此外,还有一种matching方式,会推送所有有对应的远程分支的本地分支。Git 2.0版本之前,默认采用matching方法,现在改为默认采用simple方式。如果要修改这个设置,可以采用git config命令。

 

$ git config --global push.default matching

# 或者

$ git config --global push.default simple

还有一种情况,就是不管是否存在对应的远程分支,将本地的所有分支都推送到远程主机,这时需要使用--all选项。

 

$ git push --all origin

上面命令表示,将所有本地分支都推送到origin主机。

如果远程主机的版本比本地版本更新,推送时Git会报错,要求先在本地做git pull合并差异,然后再推送到远程主机。这时,如果你一定要推送,可以使用--force选项。

 

$ git push --force origin

上面命令使用--force选项,结果导致远程主机上更新的版本被覆盖。除非你很确定要这样做,否则应该尽量避免使用--force选项。

最后,git push不会推送标签(tag),除非使用--tags选项。

 

$ git push origin --tags

(完)

 

以上是关于关于git远程版本库的一些问题之解决的主要内容,如果未能解决你的问题,请参考以下文章

如何检查远程 git 存储库的配置?

GIT学习随笔

关于git的一些基本操作:

git commit时权限被否定问题解决

git学习心得之远程仓库

关于git 操作