#版本管理

1 介绍

Git 是一个开源的分布式版本控制系统,现在管理代码一般都用它,一方面是管理各种软件版本,同时也提供对多人并行开发支持。有的在公司内部搭建 Git 服务器,更多情况下是使用 GitHub,GitHub 是一个软件项目托管平台,可以在其上建立公开项目或者私有项目。

在对 Git 工具不太熟悉的情况下,进行复杂操作时,常怕误操作,不敢多做尝试,本篇我们将从零开始,在 GitHub 上建立一个自己的项目,并介绍一些最常用的命令和场景,比如合并代码。

2 在 github 上建立自己的仓库

https://github.com/, 登录,点 new repository 构建新项目

点击 create repository 后项目就新建成功了,这时点 clone or Download 按钮,可看到下载地址。

3 把远程代码的下载到本地

1
2
3
$ git clone 地址
形如:
$ git clone https://github.com/xieyan0811/xxx.git

  也可以用 -b 指定分支名

4 分支操作

(1) 列出当前分支:本地/远程

1
$ git branch -a

(2) 列出本地分支

1
$ git branch

可以看到,不指定分支时,“拉”的是主分支 maste

(3) 切换分支

1
$ git checkout -b 本地名 远程名

形如:

1
2
$ git checkout -b dev origin/dev
# 从远程分支dev拉到本地分支dev
1
2
$ git checkout -b test1
# 以当前分支为基础,建立新的分支test1,并切换到该分支
1
2
$ git checkout master 
# 切换回主分支

(4). 删除分支

1
2
$ git branch -D test1
# 删除名为test1的分支

5 编辑代码

(1) 查看当前状态

1
2
3
4
$ touch a.txt
$ touch b.txt
$ git add a.txt
$ git status
图片.png

git 本地分三个区:工作区(已修改的)、暂存区(修改且 add 的)、版本区(修改,add 且 commit 的)。从上图可以看到被 add 之后的数据 a.txt 进入了暂存区(绿色),当前修改但还未 add 的 b.txt 仍在工作区。

(2) 从工作区到暂存区

1
2
$ git add b.txt # 把b.txt提到暂存区 
$ git add . # 把当前目录下所有修改提交到暂存区

(3) 从暂存区到版本库

1
$ git commit -m "说明文字"

6 查看历史

(1) 版本历史

1
$ git log 

注意其中的长串数字即版本号,越在上面的时间越近。

(2) 查看操作记录

1
$ git reflog

(3) 回退版本

1
$ git reset --hard HEAD 

上例是回上一个版本, 回其它版本使用:"git reset --hard $COMMIT 号 "

(4) 查看远程仓库(默认名是 origin)

1
2
$ git remote # 查看远程仓库名 
$ git remote -v # 查看远程仓库地址

7 储藏操作

有时需要切换分支,但又不想提交当前代码,可以使用 stash 保存当前的中间状态,以便之后再切换回来。

1
2
3
$ touch xx.txt
$ git add xx.txt
$ git stash save "log info"

储藏当前的变更,运行之后,看到当前目录回到分支未修改过的状态。

1
2
3
$ git stash log # 查看储藏,越在上面的时间越近
$ git stash apply stash@{0} # 恢复第0个储藏
$ git stash pop # 恢复上一个储藏,并从堆栈中移除

8 下拉代码

(1). 拉远程分支的最新代码到本地分支

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

(2). 冲突解决

当本地和远程修改了同一文件时,可能提示:“您尚未结束您的合并(存在 MERGE_HEAD)”

1
2
3
$ git checkout --ours 文件名 # 使用当前版本

$ git checkout --theirs 文件名 # 使用远程版本

然后再使用 commit, pull, push 即可

9 查看前次 commit

1
2
3
4
5
6
# 查看前次版本号
git show --stat HEAD
# 查看之前版本号
git log
# 查看改了什么
git show --stat COMMIT_ID

10 恢复代码

  • 恢复单个文件

    丢弃自己之前的修改

1
$ git checkout -- 文件名

11 提交代码

(2). 上传本地代码到远程分支

1
2
3
4
5
6
#查看工作区代码相对于暂存区的差别
$ git status
#将当前目录下修改的所有代码从工作区添加到暂存区 . 代表当前目录
$ git add .
$ git commit -m 'message'
$ git push <远程主机名> <本地分支名>: <远程分支名>

把本地 master 推到远程 xieyan 分支,形如:

1
$ git push origin master:xieyan

(3). pull request

用于将一个分支的修改合并到另一分支(如主分支),在网页界面操作:先进入自己的分支,点右上角的 pull request,选择要提交到的分支,在右侧选让谁 review。他在那边同意之后,你和他都可以选择 merge pull request,就可以合并了。

(4). pull request 之后需要修改再提交

  • 正常修改代码
  • 正常提交到待合并的分支上(add,commit,push...)
  • 此时再看 pull request,有两个 commit
  • 正常 approve,然后 merge 即可
  • 总结:不需要特别的撤回处理,只要再正常提交一次,在 pull request 里就可看到前后两次提交,然后正常处理合并即可。

12 打标签

  • 列出所有版本号
1
git tag 
  • 本地打标签
1
git tag 标签名
  • 切换到标签
1
git checkout 版本号
  • 本地标签推到远程
1
git push origin 标签名
  • 查看远程标签
1
git ls-remote --tags origin

13 排除无需上传的文件

1
vi .gitignore

把文件或目录路径(从 git 根目录开始的相对路径)加入其中,一行一个

14 解决冲突

14.1 问题

git push 出现以下提示:

1
2
提示:更新被拒绝,因为您当前分支的最新提交落后于其对应的远程分支。
提示:再次推送前,先与远程变更合并...

14.2 解决方法

拉最新版本

1
2
git config pull.rebase false
git pull

可能出现以下提示:

1
2
3
自动合并 xxxx
冲突(内容):合并冲突于 xxx
自动合并失败,修正冲突然后提交修正的结果。

手动修改文件 xxxx,找其中 <<<< >>>> 关键字,对比差异并修改

修改后,再一次提交

1
2
3
git add xxxx
git commit -m '处理版本差异'
git push

15 恢复 commit 之前状态

commit 错了,恢复到 commit 之前的状态

1
git reset --soft HEAD^

16 修改默认编辑器

改 vi 作为 commit 内容的默认编辑器

1
git config --global core.editor vi

注意:在编辑器里写 commit 时,第一行的标题,空一行是正文,如果内容较多,最好在标题和正文间空一行。

17 远程分支

推到远程 xieyan 分支

1
git push origin master:xieyan

将远程 xieyan 分支拉到本地 master

1
git pull origin xieyan:master

18 综合示例

(1) 新建分支并做修改

在 github 网页上左侧点 master 钮,按提示新建一个分支 test1,并切换到这个分支,并且在新分支中修改 README.txt 文件内容。

(2) 在本地修改 Readme.txt

(3) 储藏修改

1
$ git stash save "log" # 此时工作目录中的修改看不到了,恢复成了“干净的状态”。

(4) 拉下远程仓库

1
$ git fetch origin 

更新远程代码到本地仓库,可以认为它是针对于版本区的操作

1
$ git checkout -b test1 origin/test1 

如果本地有些修改,既没提交,也没储藏,那么 checkout 时会失败,因为 git 不能确定你是不是要丢弃当前修改。

(5) 切回到本地修改的分支

1
$ git checkout master

(6) 合并代码

1
$ git merge test1 # 其中test1是分支名

(7) 恢复储藏

1
$ git stash pop

此时就看到了冲突被特殊字符标出了,解决完冲突后重新提交代码即可。

19 问题与解答

(1) Pull 和 Fetch 区别是什么?

Pull 包含 fetch 和 merge 两个过程,如果可能代码有冲突,尽量不用 pull,因为它会自动合并代码,可能出现一些奇怪的问题,推荐用上例中的方法手动合并代码。

(2) Github 在 Ubuntu 终端使用时中文显示乱码

在 Ubuntu 终端使用 github 命令,如 git status, git add 时中文显示成乱码,形如:

1
"\346\250\241\345\236\213\347\273\

解决方法

1
git config --global core.quotepath false

Git_下载太慢的改进方法