Simplestory's Blog

GIT使用基础教程

Git的一些基本操作

Word count: 3.7kReading time: 14 min
2017/07/04

Git是一个极其优秀的分布式版本控制系统。该系统可以记录用户文件的每一次变动,还具有强大的团队协同工作能力,每个人都可以提交对文本的改动,而不必担心会覆盖他人的操作。Github更是一个通过Git进行版本控制的软件源代码托管服务。截至到2015年,Github已经有超过九百万注册用户和2110万代码库。Github已经成为了世界上最大的代码存放网站和开源社区。

GIT使用教程

创建版本库

选择一个合适的地方,创建一个空目录

1
2
3
4
$ mkdir <dir-name>
$ cd <dir-name> #在仓库中进行操作
$ pwd #可查看当前目录
$ git init #将目录变为Git可以管理的仓库,即初始化仓库

之后会在当前目录下产生一个.git的目录,该目录是Git用来跟踪管理版本库,也可以选用一个非空目录创建Git仓库

编写保存文件

编写文件并存放至<dir-name>目录下(或子目录)

用纯文本方式编辑并保存文件,文件编码格式保存为UTF-8编码格式

1
2
3
4
5
6
$ git add <filename1> <filename2> ...  #告知Git将文件添加至仓库
$ git commit -m "..." #将文件提交到仓库 -m后面输入本次提交的说明,可以一次提交多个文件
$ git status #可查看仓库当前的状态,告知用户是否有文件被修改
$ git diff #查看文件具体修改了什么,或对比文件
$ git log #显示从最近到最远的提交日志(可加上参数--pretty=oneline改变显示视图)
$ git reset --hard HEAD^ #文件回退至上一版本

Git中,用HEAD表示当前版本,上一版本就是HEAD,上上版本为HEAD^,往上N个版本可写为HEAD~N

1
2
$ git reset --hard <fileID>  #文件版本跳至版本ID为<fileID>的文件
$ git reflog #记录用户的每一次操作,可借由此查看文件回退前的版本号

工作区与暂存区

  • 工作区

    在计算机里可以看到的目录就是工作区,用于存放文件

  • 版本库与暂存区

    工作区下有一个隐藏目录.git,这个是git的版本库,版本库里存有暂存区(stage/index)

  • Git大致工作原理

    文件添加至Git版本库分为两步:

  1. git add将文件添加进暂存区,即把对文件的修改或相关操作添加到暂存区
  2. git commit提交更改,即把暂存区的全部内容提交到当前分支

文件撤销操作

$ git checkout -- <filename>在工作区的修改全部撤销,命令--很重要,没有--就变成了切换到另一个分支的命令

文件撤销情况

关于文件需要撤销操作的,大致有两种情况: + <filename>自修改后还没放到暂存区,则命令执行后文件撤销修改就回到和版本库一模一样的状态 + <filename>已经添加到暂存区后,又作了修改,则命令执行后文件撤销修改就回到添加到暂存区后的状态 总之,就是让文件回到最近一次git commitgit add时的状态

撤销与回退小结

  1. 当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令 git checkout -- <filename>
  2. 当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步:用命令 git reset HEAD <filename>,就回退到1中,然后继续1的操作
  3. 当你已经提交了不合适的修改到版本库时,想要撤销本次提交,可参考版本回退,不过前提时没有推送到远程库

版本回退:git reset --hard <ID>,将文件跳至版本号ID的文件,HEAD表示最新的文件版本

Git撤销删除

Git中删除也是一种修改操作

一般情况下,在提交至版本库后,我们直接在文件管理器中删除文件(或通过rm命令),git status会告知那些文件被删除,这时有两种选择: 1. 确实要从版本库中删除,可执行git rm命令删除,并git commit 2. 手误删除文件,这时可执行git checkout -- <filename>命令把误删的文件恢复到最新版本 * git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以"一键还原", 命令git rm用于删除一个文件,如果一个文件已经被提交到版本库,那永远不用担心误删,但你只能恢复文件到最新版本,你会丢失最近一次修改提交后的内容

创建SSH Key

1
$ ssh-keygen -t rsa -C "youremail@example.com"

创建后,可在用户主目录里找到.ssh目录,里面有id_rsaid_rsa.pub两个文件,这两个文件就是SSH Key的秘钥对,id——rsa是私钥,不能泄露,id_rsa.pub是 公钥,可以公布。之后登陆Github进行设置,进入"SSH Key"页面,点击"Add SSH Key",填上任意标题,在Key文本框里粘贴id_rsa.pub文件里的内容

Github允许添加多个Key

关联远程库

首先在Github上新建一个仓库(或者使用已有的仓库),在本地的一个仓库中运行以下命令:

1
$ git remote add origin git@github.com:<accountname>/<localreponame>.git

添加后,远程库名字Git默认为origin,可以更改:

1
$ git push -u origin master

git push命令,实际是把当前分支master推送到远程, 如果这是你第一次推送master分支,你需要加上-u参数,Git不但会把本地的master分支内容推送到远程的新的master分支,还会把本地的master分支和远程的master分支关联起来, 在以后的推送或者拉取时可简化命令,之后只要本地作了提交,就可以通过命令:$ git push origin master完成提交 在第一次使用Git的clonepush命令时会得到一个SSH警告,输入yes即可

1
2
#关联一个远程库
$ git remote add origin git@server-name:path/repo-anme.git

克隆远程库到本地

在Github中新建库后,可以使用git clone克隆一个本地库 $ git clone git@github.com:<git库地址>

Git支持多种协议,包括https

windows系统:$ git clone <Git远程库的url>

Git分支

1
2
3
4
5
6
$ git branch  #查看分支
$ git branch <name> #创建分支
$ git checkout <name> #切换分支
$ git checkout -b <name> #创建+切换分支
$ git merge <name> #合并某分支到当前分支
$ git branch -d <name> #删除分支

多个分支是共用暂存区,即如果在分支1上仅add而不commit,实际暂存区中已经记录该次修改,哪怕之后切换到分支2上再进行commit也是有效操作 当Git无法自动合并分支时,需要首先解决冲突。解决冲突后再提交, 用git log --graph命令可以看到分支合并图,git status也可以查看冲突的文件

e.g:$ git log --graph --pretty=oneline --abbrev-commit

Git分支管理

合并分支时,加上--no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出曾经做过合并,而fast-forward合并就看不出曾经做过合并

1
$ git merge --no-ff -m"..." <name>

以普通方式合并分支(即禁用fast forward)因为本次合并要创建一个新的commit,所以加上-m参数,把commit描述写进去`

分支策略:

  • 在实际开发中,我们应该按照几个基本原则进行分制管理:
  • master分支应该是非常稳定的,也就是仅用来发布新版本,平时不在上面干活;
  • 干活都在dev分支,即devd分支是不稳定的,到某个时候,再把dev分支合并到master分支上;
  • 每个人都在dev分支上工作,每个人都有自己的分支,要保存时往dev分支上合并就可以了

Bug分支

$ git stash命令相当于对当前工作环境做一个快照,等以后恢复环境后继续工作

在哪个分支上修复bug,就在从哪个分区创建临时分支

修复完后再提交并删除分支

1
2
3
4
$ git stash list  #查看是否存在stash
$ git stash apply #恢复stash内容,该命令执行后并不删除stash内容
$ git stash drop #删除stash内容
$ git stash pop #恢复stash内容,在恢复的同时也删除内容

修复Bug时,当手头工作没有完成时,先把工作现场git stash一下,然后再去修复Bug,修复后,再git stash pop回到工作现场

Feature分支(添加新功能)

在开发新功能时最好新建一个分支, 若要丢弃一个没有被合并过的分支,可以通过git branch -D <name>强行删除

多人协作

$ git remote查看远程库的信息

$ git remote -v查看远程库详细的信息(上面显示了抓取和推送的<远程库名字>的地址,如果没有推送权限,就看不到push的地址)

  • 推送分支:

推送分支就是把该分支上的所有本地提交推送远程库。推送时,要指定本地分支

1
2
$ git push <远程库名字> <本地库名字>
$ git pull #把最新的提交从远程库中抓取下来

抓取后在本地合并并解决冲突后再推送

  • 工作模式:
  1. 首先,可以试图用git push origin branch-name推送自己的修改
  2. 如果推送失败,则因为远程分支比你的本地版本新,需要先用git push试图合并
  3. 如果合并有冲突,则解决冲突,并在本地提交
  4. 没有冲突或者解决掉冲突后,再用git push origin branch-name推送就能成功

如果git pull提示"no tracking information",则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream branch-name origin/branch-name(该命令用于建立本地分支和远程分支的关联)

标签管理

发布一个版本时,我们通常先在版本库中打一个标签tag,这样,就唯一确定了打标签时的版本。在将来的某个时候,取某一个标签的某一版本,就是把那个打标签的时刻对应的版本取出。标签也是版本库的一个快照

Git标签虽然是版本库的快照,但其实它是指向某个commit的指针(分支可以移动,标签不能移动)

Tag就是一个让人容易记住的名字,它与某个commit绑定在一起

1
2
3
$ git tag <name>  #在git中打标签应先切换至需要打标签的分支
$ git tag #查看所有标签默认标签是打在最新提交的commit上的
$ git tag <name> <commit ID> #给对应ID的commit打上标签

标签不是按时间顺序列出,而是按字母排序的,可以用git show <tagname>查看标签信息

1
2
3
4
$ git tag -a <tagname> -m "..."  #创建带说明的标签,-a指定标签名,-m指定说明文字
$ git tag -d <tagname> #删除本地标签,因为创建的标签都只储存在本地,不会自动推送至远程
$ git push <远程库名字> <tagname> #推送某个标签到远程
$ git push <远程库名字> --tags #一次性推送全部尚未推送到远程的本地标签

其中在上面第一行代码中若用参数-s替换-a则可以用PGP签名标签

已推送到远程的标签的删除:

1
$ git push <远程库名字> :refs/tags/<tagname>

在Github上,可以任意Fork开源仓库;

自己拥有Fork后的仓库的读写权限;

可以推送Pull request给他人仓库来贡献代码;

Fork他人仓库之后再在自己的账号下clone仓库,这样才能推送修改

自定义Git

1
$ git config --global color.ui true  #git会适当显示不同的颜色
  • 忽略文件

在Git工作区的根目录下有一个.gitignore文件(没有可创建),然后把要忽略的文件名填进去,Git就会自动忽略这些文件

忽略文件的原则:

  1. 忽略操作系统自动生成的文件,比如缩略图等;
  2. 忽略编译生成的中间文件、可执行文件等,也就是一个文件通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库;
  3. 忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件

之后将.gitignore也提交到Git,就完成了忽略文件设置

1
2
$ git check-ignore  #检查.gitignore文件
$ git add -f <filename> #强制添加文件

我们可以对.gitignore进行版本管理

  • 设置别名

$ git config --global alias <别名> <命令原名> --global参数是全局参数,也就是这些命令在电脑的所有Git仓库下都有效

配置Git时,加上--global是针对当前用户启作用,如果不加,则只针对当前仓库起作用。 每个仓库的Git配置文件都放在.git/config文件中, 别名在[alias]后面,删除别名则直接删除对应行即可。 当前用户的Git配置文件在用户主目录的一个隐藏文件.gitconfig中

搭建Git服务器(linux ubuntu or debian)

  1. 安装git:$ sudo apt-get install git;
  2. 创建一个git用户,用来运行git服务:$ sudo adduser git;
  3. 创建证书登录:收集所有需要登录的用户的公钥,即他们的id_rs.pub文件,将所有公钥导入到/home/git/.shh/authorized_keys文件中(可改名);
  4. 初始化Git仓库:$ sudo git init --bare <reponame>;参数--bare为创建一个裸仓库,即没有工作区(服务器上的Git仓库通常都以.git结尾,创建后把owner改为git $ sudo chown -R git:git <reponame>
  5. 禁用shell登录:出于安全考录,2中创建的git用户不允许登录shell,可通过编辑/etc/passwd文件实现 找到类似一行:git:x:1001:1001:,,,:/home/git:/bin/bash 改为:git:x:1001:1001:,,,:/home/git:/usr/bin/got-shell 这样当用户用shell登录时会自动退出;
  6. 克隆远程仓库:$ git clone git@server:/srv/<reponame>;在各自的电脑中运行

致谢:

廖雪峰的Git教程(转载请保留连接)

CATALOG
  1. 1. GIT使用教程
    1. 1.1. 创建版本库
    2. 1.2. 编写保存文件
    3. 1.3. 工作区与暂存区
      1. 1.3.1. 工作区
      2. 1.3.2. 版本库与暂存区
      3. 1.3.3. Git大致工作原理
    4. 1.4. 文件撤销操作
      1. 1.4.1. 文件撤销情况
      2. 1.4.2. 撤销与回退小结
    5. 1.5. Git撤销删除
    6. 1.6. 创建SSH Key
    7. 1.7. 关联远程库
    8. 1.8. 克隆远程库到本地
    9. 1.9. Git分支
    10. 1.10. Git分支管理
      1. 1.10.1. 分支策略:
    11. 1.11. Bug分支
    12. 1.12. Feature分支(添加新功能)
    13. 1.13. 多人协作
    14. 1.14. 标签管理
    15. 1.15. 自定义Git
    16. 1.16. 搭建Git服务器(linux ubuntu or debian)
    17. 1.17. 致谢: