2.6. 版本控制系统Git教程

什么是版本控制系统 (Version Control System)? 版本 这一词大家都不陌生, 那么想必也能猜出来版本控制系统的含义: 能够自动管理文件版本的系统. 这句话似乎是废话, 举个例子来说, 平时在写文章或代码时, 经常会复制多个文件以保存不同版本的修改, 而且你还的重命名文件, 以告诉自己这一版本在哪里修改了, 是不是很繁琐, 不仅如此, 你还要存储不同的文件版本, 那么版本控制系统就是帮你完成这件事, 比如, 它可能会像下面这样自动记录每个版本的变动:

版本

用户

说明

日期

1

张三

删除了软件服务条款5

7/12 10:38

2

张三

增加了License人数限制

7/12 18:09

3

李四

财务部门调整了合同金额

7/13 9:51

4

王五

延长了免费升级周期

7/14 15:17

你可能还希望恢复不同的版本状态时的文件, 可以的, 就是说你有后悔药可以吃的. 怎么样? 是不是突然觉得自己要解放了, 不过你得先学会使用一款版本控制系统软件才行. 下面开始吧!!!

此教程部分内容参考了 Git教程 - 廖雪峰的官方网站 号称最浅显易懂的教程, 是吗? 是的, 至少我觉得是.

2.6.1. What is Git?

Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.

Git (读音/gɪt/) 是一个免费开源的分布式版本系统, 无论项目大小, 都能游刃有余地管理项目的版本. 我们还希望它是易学的, 是的, 它也确实如此! 右图为 Git 的 logo.

Logo of Git

图 2.6.1 Logo of Git

Git 与 GitHub: 我们知道 Git 是一个免费开源的分布式版本系统, 跟svn、cvs是同级的概念, 那么 GitHub 是什么呢? 是一个免费的远程仓库, 顾名思义就是用来存储你的文件的, 给用户提供git服务. 这样你就不用自己部署git系统, 直接用注册个账号, 用他们提供的git服务就可以. 右图为其吉祥物 Octocat .

Logo of Github

图 2.6.2 Github 吉祥物 Octocat

2.6.2. Why Git?

  • 免费开源

  • 分布式

  • 高效高速

  • 简单易学

2.6.3. How to

下面给出一些学习参考资料:

  • Git教程 - 廖雪峰的官方网站 自称最浅显易懂的Git教程.

  • Pro Git : 由 Scott Chacon and Ben Straub 写的一本书, 可以在线浏览, 也可以下载 PDF, epub, mobi, html 版本查看, 被翻译成多种语言, 简体中文版在 这里 查看与下载.

2.6.3.1. 安装Git

2.6.3.1.1. Windows

可以从 Git 官网 下载 Windows 版 Git 安装包 https://git-scm.com/download/win , 根据提示安装即可.

此外, Git for Windows 是一个轻量级且具有 Git SCM 全特性的 Git 软件 , 可以从 https://git-for-windows.github.io 下载安装.

Git for Windows focuses on offering a lightweight, native set of tools that bring the full feature set of the Git SCM to Windows while providing appropriate user interfaces for experienced Git users and novices alike.

2.6.3.1.2. Linux

Git 在 ubuntu 上的安装很简单, 首先终端 ( 快捷键 Ctrl + Alt + T ) 输入 git , 查看是否已安装, 如果没有, 对于 Ubuntu 系统通过如下命令安装即可:

sudo apt-get install git

其它系统可以根据 Git官网 提示下载安装.

2.6.3.2. 创建本地仓库

2.6.3.3. 版本库管理

2.6.3.3.1. 瘦身

对于一个git库, 提交次数多了, 特别是库中含有大文件时, 会使得库显得很臃肿, 如果直接删除 .git 文件夹会带来很多问题, 使用下面的命令可以清空提交历史缓存, 保持最新代码, 达到瘦身的效果.

# 1. Checkout

git checkout --orphan latest_branch

# 2. Add all the files

git add -A

# 3. Commit the changes

git commit -am "commit message"

# 4. Delete the branch

git branch -D master

# 5. Rename the current branch to master

git branch -m master

# 6. Finally, force update your repository

git push -f origin master

2.6.3.4. 远程仓库

2.6.3.5. 分支管理

2.6.3.6. 标签话管理

2.6.4. Git命令概览

初始化操作
    $ git config --global user.name <name> #设置提交者名字
    $ git config --global user.email <email> #设置提交者邮箱
    $ git config --global core.editor <editor> #设置默认文本编辑器
    $ git config --global merge.tool <tool> #设置解决合并冲突时差异分析工具
    $ git config -list #检查已有的配置信息
创建新版本库
    $ git clone <url> #克隆远程版本库
    $ git init #初始化本地版本库
修改和提交
    $ git add . #添加所有改动过的文件
    $ git add <file> #添加指定的文件
    $ git mv <old> <new> #文件重命名
    $ git rm <file> #删除文件
    $ git rm -cached <file> #停止跟踪文件但不删除
    $ git commit -m <file> #提交指定文件
    $ git commit -m “commit message” #提交所有更新过的文件
    $ git commit -amend #修改最后一次提交
    $ git commit -C HEAD -a -amend #增补提交(不会产生新的提交历史纪录)
查看提交历史
    $ git log #查看提交历史
    $ git log -p <file> #查看指定文件的提交历史
    $ git blame <file> #以列表方式查看指定文件的提交历史
    $ gitk #查看当前分支历史纪录
    $ gitk <branch> #查看某分支历史纪录
    $ gitk --all #查看所有分支历史纪录
    $ git branch -v #每个分支最后的提交
    $ git status #查看当前状态
    $ git diff #查看变更内容
撤消操作
    $ git reset -hard HEAD #撤消工作目录中所有未提交文件的修改内容
    $ git checkout HEAD <file1> <file2> #撤消指定的未提交文件的修改内容
    $ git checkout HEAD. #撤消所有文件
    $ git revert <commit> #撤消指定的提交
分支与标签
    $ git branch #显示所有本地分支
    $ git checkout <branch/tagname> #切换到指定分支或标签
    $ git branch <new-branch> #创建新分支
    $ git branch -d <branch> #删除本地分支
    $ git tag #列出所有本地标签
    $ git tag <tagname> #基于最新提交创建标签
    $ git tag -d <tagname> #删除标签
合并与衍合
    $ git merge <branch> #合并指定分支到当前分支
    $ git rebase <branch> #衍合指定分支到当前分支
远程操作
    $ git remote -v #查看远程版本库信息
    $ git remote show <remote> #查看指定远程版本库信息
    $ git remote add <remote> <url> #添加远程版本库
    $ git fetch <remote> #从远程库获取代码
    $ git pull <remote> <branch> #下载代码及快速合并
    $ git push <remote> <branch> #上传代码及快速合并
    $ git push <remote> : <branch>/<tagname> #删除远程分支或标签
    $ git push -tags #上传所有标签

2.6.4.1. 自定义快捷命令

alias gcommit='func() { git commit -m $1;}; func'
alias gpush='git push -u origin master'
alias gadd='git add -A'
# for my git server
alias gitclone='func() { git clone git@lab.ink:/home/git/repositories/$1;}; func'
#alias gitclone='func() { git clone git@$LABIP:/home/git/repositories/$1;}; func'
alias gitadd='func() { sudo /home/liu/sfw/zhi/gitadd.sh $1;}; func'
alias upd='func() { sudo /home/liu/sfw/zhi/updatedomain.sh $1;}; func'


# for git
alias gcommit='git commit -m'
alias gpush='func() { git push -u origin $1;}; func'
alias gpushm='git push -u origin master'
alias gpushp='git push -u origin gh-pages'
alias gadd='git add -A'
alias gstatus='git status'

2.6.5. 子模块

2.6.5.1. 自动下载

如果你在克隆含有子模块的库时, 没有使用 git clone --recursive xxx , 那么不要急, 可以这样把子模块克隆进去

cd [project]
git submodule init
git submodule update

2.6.6. 搭建Git服务器

2.6.6.1. 参考示例

2.6.6.2. 安装配置SSH服务端客户端

  1. 安装SSH: sudo apt-get install openssh-server openssh-client

  2. 配置SSH服务端(可选, 默认配置下需要输入密码): sudo gedit /etc/ssh/sshd_config –> StrictModes  no , RSAAuthentication yes (使用纯的RSA认证), PubkeyAuthentication yes (允许Public Key) , AuthorizedKeysFile     %h/.ssh/authorized_keys (公钥存储路径).

  3. 重启SSH服务: sudo /etc/init.d/ssh restartsudo service ssh restart

2.6.6.3. 安装配置Git服务端客户端

2.6.6.3.1. Git服务端配置

  1. 安装服务端: sudo apt-get install git git-core

  2. 新建用户用于git : sudo adduser git (或 sudo useradd -m gitsudo passwd git)

  3. 将git设为管理员(可选): sudo gedit /etc/sudoers –> 添加 git ALL=(ALL:ALL)  ALL

  4. 新建仓库目录并更改权限

    cd /home/git
    sudo mkdir repositories
    sudo chown git:git /home/git/repositories # 设定所有者
    sudo chmod 755 /home/git/repositories # 设置仓库访问权限
    cd repositories
    sudo git init --bare sample.git # 创建 sample 库
    sudo chown -R git:git sample.git # 更改 sample 权限
    

提示:

出于安全考虑,可以限制git用户通过ssh使用git,但无法登录shell。 打开编辑 /etc/passwd 文件并找到 类似 下面的一行(自行创建的用户名):

git:x:1001:1001:,,,:/home/git:/bin/bash

改为:

git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell

2.6.6.3.2. Git客户端配置

  1. 安装Git客户端(Windows,或Linux)

  2. 生成免密登录的秘钥(可选): 打开 gitbash (Windows) 或终端 (linux), 输入以下指令生成秘钥

bash    ssh-keygen -t rsa 生成的秘钥一般在 C:/Users/yourname/.ssh/id_rsa.pub (Windows), ~/.ssh/id_rsa.pub (Linux) 文件中.

  1. 秘钥上传到服务器: 方法1 –> 在/home/git/ 下 新建 .ssh/authorized_keys 文件 (如果没有), 复制上述生成的秘钥内容, 粘贴到 authorized_keys 中保存. 方法2 –> 客户端gitbash终端执行: ssh-copy-id git@yourhost

  2. 克隆服务端的仓库:

bash    git clone git@yourhost:/home/git/repositories/samples.git

  1. 提交到服务端:

bash    git push -u orig master

按上述步骤配置完即可

2.6.7. 简化命令

2.6.7.1. 自定义域名

通过修改 host 文件实现:

  • Windows: C:/Windows/System32/drivers/etc/hosts

  • Ubuntu : /etc/hosts

打开文件,添加域名解析条目即可:

# server at lab
# IP domain
xxx.xxx.xxx.xxx lab.ink

2.6.7.2. 克隆

采用 alias 实现命令的简化:

Windows与Linux命令相同, 只不过目录不一样:

  • Linux下在 ~/.bashrc

  • Windows下在 C:\Users\yourusername/.bashrc 里,如果没有,gitbash 终端执行 : touch .bashrc 即可

打开该文件,并输入:

alias gitclone='func() { git clone git@lab.ink:/home/git/$1;}; func'

重启终端,以后可以通过执行如下命令进行克隆:

# gitclone your_git_repository_name
gitclone sample

2.6.8. 错误解决

2.6.8.1. Clone过程

clone 时提示如下错误

gitclone sample
Cloning into 'sample'...
ssh: connect to host lab.ink port 33: Connection timed out
fatal: Could not read from remote repository.

通过将端口 33 改为 22 即可。 sudo gedit /etc/ssh/ssh_config 找到 Port 修改即可。

提示:

  • SSH服务端配置: sudo gedit /etc/ssh/sshd_config

  • SSH客户端配置: sudo gedit /etc/ssh/ssh_config

2.6.8.2. SSH秘钥

明明添加了秘钥,却提示:

sign_and_send_pubkey: signing failed: agent refused operation

解决办法:

eval "$(ssh-agent -s)"
ssh-add