Git学习笔记

Posted by wangduo on 2017-03-27
Deep learning

Git notes:

%%%% Git教程 %%%%

%%%% Git简介 %%%%

%%%% Git的诞生 %%%%

%%%% 集中式vs分布式 %%%%

%%%% 安装Git %%%%

  1. git config –global user.name “Your Name” 配置名字
  2. git config –global user.email “email@example.com” 配置邮箱

%%%% 创建版本库 %%%%

  1. cd xxx 切换目录
  2. mkdir xxx 新建目录
  3. pwd 显示当前目录
  4. cat xxx 显示文件内容
  5. ls(dir) 显示目录内容

  6. git init 把目录变成git可以管理的仓库

  7. git add xxx 把文件xxx添加到仓库
  8. git commit -m “comments” 把文件提交到仓库,引号中为说明

初始化一个Git仓库,使用git init命令。
添加文件到Git仓库,分两步:
第一步,使用命令git add ,注意,可反复多次使用,添加多个文件;
第二步,使用命令git commit,完成。

%%%% 时光机穿梭 %%%%

  1. git status 仓库当前状态
  2. git diff xxx 查看修改内容

要随时掌握工作区的状态,使用git status命令。
如果git status告诉你有文件被修改过,用git diff可以查看修改内容。

%%%% 版本回退 %%%%

  1. commit id(版本号): 54e3922 e481592d7c63f19ae28f64882699d4b33
  2. git log [–pretty=oneline] 显示从最近到最远的提交日志[单行显示]
  3. git reset –hard commit_id 在版本的历史之间穿梭
    HEAD 当前版本
    HEAD^ 上一个版本
    HEAD^^ 上上一个版本
    HEAD~100 往上100个版本
  4. git reflog 记录在该仓库中执行的每一次命令

HEAD指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset –hard commit_id。
穿梭前,用git log可以查看提交历史,以便确定要回退到哪个版本。
要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本。

%%%% 工作区和暂存区 %%%%

工作区(Working Directory): 就是你在电脑里能看到的目录,比如我的learngit文件夹就是一个工作区。
版本库(Repository): 工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master。

%%%% 管理修改 %%%%

  1. git diff HEAD – readme.txt 查看工作区和版本库里面最新版本的区别
  2. vi xxx 进入文件编辑状态
    :wq 保存并退出
    :q 不保存退出
    :q! 强制不保存退出

%%%% 撤销修改 %%%%

  1. git checkout – file 丢弃工作区的修改
  2. git reset HEAD file 把暂存区的修改撤销掉(unstage),重新放回工作区

场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout – file。
场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD file,就回到了场景1,第二步按场景1操作。
场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本回退一节,不过前提是没有推送到远程库。

%%%% 删除文件 %%%%

  1. rm test.txt 删除文件(等于直接在文件管理器中删除文件)
  2. git rm test.txt 将删除文件的命令添加到版本库的暂存区中
  3. git checkout – test.txt 删错时(未执行2.时)恢复文件

命令git rm用于删除一个文件。如果一个文件已经被提交到版本库,那么你永远不用担心误删,但是要小心,你只能恢复文件到最新版本,你会丢失最近一次提交后你修改的内容。

%%%% 远程仓库 %%%%

  1. ssh-keygen -t rsa -C “youremail@example.com” 在用户主目录(C:\Users\wangduo)下生成.ssh目录,里面有id_rsa和id_rsa.pub两个文件。
    这两个就是SSH Key的秘钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。
  2. clear(ctrl+l) 这个命令将会刷新屏幕,本质上只是让终端显示页向后翻了一页,如果向上滚动屏幕还可以看到之前的操作信息。一般都会使用这个命令。

%%%% 添加远程库 %%%%

  1. git remote add origin git@github.com:wangduo2016/learngit.git 关联一个远程库,远程库的名字就是origin,这是Git默认的叫法,也可以改成别的,但是origin这个名字一看就知道是远程库。
  2. git push [-u] origin master 把本地master分支的最新修改推送到远程库上[第一次推送master分支时,加上-u参数]

要关联一个远程库,使用命令git remote add origin git@server-name:path/repo-name.git;
关联后,使用命令git push -u origin master第一次推送master分支的所有内容;
此后,每次本地提交后,只要有必要,就可以使用命令git push origin master推送最新修改;

%%%% 从远程库克隆 %%%%

  1. git clone git@github.com:wangduo2016/gitskills.git 克隆一个远程仓库到本地
  2. git –help These are common Git commands used in various situations:…

要克隆一个仓库,首先必须知道仓库的地址,然后使用git clone命令克隆。
Git支持多种协议,包括https,但通过ssh支持的原生git协议速度最快。

%%%% 分支管理 %%%%

%%%% 创建与合并分支 %%%%

  1. HEAD 严格来说不是指向提交,而是指向master,master才是指向提交的,所以,HEAD指向的就是当前分支。
  2. git checkout -b dev 创建dev分支,然后切换到dev分支
  3. git branch dev 创建dev分支
  4. git checkout dev 切换到dev分支
  5. git branch 列出所有分支,当前分支前面会标一个*号
  6. git merge dev 合并指定分支到当前分支
  7. git branch -d dev 删除dev分支

Git鼓励大量使用分支:
查看分支:git branch
创建分支:git branch
切换分支:git checkout
创建+切换分支:git checkout -b
合并某分支到当前分支:git merge
删除分支:git branch -d

%%%% 解决冲突 %%%%

  1. git log –graph –pretty=oneline –abbrev-commit 显示分支合并图

当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。
用git log –graph命令可以看到分支合并图。

%%%% 分支管理策略 %%%%

  1. git merge –no-ff -m “merge with no-ff” dev 在master分支上,合并dev分支,请注意–no-ff参数,表示禁用Fast forward。因为本次合并要创建一个新的commit,所以加上-m参数,把commit描述写进去。

通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。
如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。

Git分支十分强大,在团队开发中应该充分应用。
合并分支时,加上–no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。

%%%% Bug分支 %%%%

  1. git stash 把当前工作现场“储藏”起来,等以后恢复现场后继续工作
  2. git stash list 显示储藏起来的工作现场
  3. git stash apply stash@{0} 恢复工作现场,但是恢复后,stash内容并不删除
  4. git stash drop stash@{0} 删除stash内容
  5. git stash pop 恢复工作现场的同时把stash内容也删了(等于执行3. 4.)

修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;
当手头工作没有完成时,先把工作现场git stash一下,然后去修复bug,修复后,再git stash pop,回到工作现场。

%%%% Feature分支 %%%%

  1. git branch -D feature-vulcan 强行删除没有被合并的分支

开发一个新feature,最好新建一个分支;
如果要丢弃一个没有被合并过的分支,可以通过git branch -D 强行删除。

%%%% 多人协作 %%%%

  1. git remote 查看远程库的信息
  2. git remote -v 显示更详细的远程库信息

推送分支:

  1. git push origin master
  2. git push origin dev
    master分支是主分支,因此要时刻与远程同步;
    dev分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;
    bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;
    feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。

抓取分支:

  1. git clone git@github.com:michaelliao/learngit.git 模拟一个你的小伙伴,可以在另一台电脑(注意要把SSH Key添加到GitHub)或者同一台电脑的另一个目录下克隆
  2. git checkout -b dev origin/dev 你的小伙伴要在dev分支上开发,就必须创建远程origin的dev分支到本地
    从远程库克隆learngit库到另一个文件夹后,配置如下:
    git config user.name “Bob”
    git config user.email “Bob@example.com”
  3. git pull 你的小伙伴的最新提交和你试图推送的提交有冲突,用git pull把最新的提交从origin/dev抓下来,然后,在本地合并,解决冲突,再推送
  4. git branch –set-upstream dev origin/dev git pull失败了,原因是没有指定本地dev分支与远程origin/dev分支的链接,根据提示,设置dev和origin/dev的链接

  5. yy复制,dd剪切,p粘贴

多人协作的工作模式通常是这样:
首先,可以试图用git push origin branch-name推送自己的修改;
如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;
如果合并有冲突,则解决冲突,并在本地提交;
没有冲突或者解决掉冲突后,再用git push origin branch-name推送就能成功!
如果git pull提示“no tracking information”,则说明本地分支和远程分支的链接关系没有创建,用命令git branch –set-upstream branch-name origin/branch-name。

查看远程库信息,使用git remote -v;
本地新建的分支如果不推送到远程,对其他人就是不可见的;
从本地推送分支,使用git push origin branch-name,如果推送失败,先用git pull抓取远程的新提交;
在本地创建和远程分支对应的分支,使用git checkout -b branch-name origin/branch-name,本地和远程分支的名称最好一致;
建立本地分支和远程分支的关联,使用git branch –set-upstream branch-name origin/branch-name;
从远程抓取分支,使用git pull,如果有冲突,要先处理冲突。

%%%% 标签管理 %%%%

标签是版本库的一个快照。tag就是一个让人容易记住的有意义的名字,它跟某个commit绑在一起。

%%%% 创建标签 %%%%

  1. git tag 打一个新标签,默认标签是打在最新提交的commit上
  2. git tag 查看所有标签,标签不是按时间顺序列出,而是按字母排序的
  3. git log –pretty=oneline –abbrev-commit 显示历史提交的commit id
  4. git tag v0.9 commit_id 在历史提交的commit id上打标签
  5. git show 查看标签信息
  6. git tag -a v0.1 -m “version 0.1 released” commit_id 创建带有说明的标签,用-a指定标签名,-m指定说明文字
  7. git tag -s v0.2 -m “signed version 0.2 released” commit_id 通过-s用私钥签名一个标签

实验:创建标签->”还可以通过-s用私钥签名一个标签:” 未实验成功

命令git tag 用于新建一个标签,默认为HEAD,也可以指定一个commit id;
git tag -a -m “blablabla…”可以指定标签信息;
git tag -s -m “blablabla…”可以用PGP签名标签;
命令git tag可以查看所有标签。

%%%% 操作标签 %%%%

  1. git tag -d v0.1 在本地删除标签
  2. git push origin 推送某个标签到远程
  3. git push origin –tags 一次性推送全部尚未推送到远程的本地标签
  4. git push origin :refs/tags/v0.9 删除远程标签就麻烦一点,先从本地删除,然后,从远程删除。删除命令也是push

命令git push origin 可以推送一个本地标签;
命令git push origin –tags可以推送全部未推送过的本地标签;
命令git tag -d 可以删除一个本地标签;
命令git push origin :refs/tags/可以删除一个远程标签。

%%%% 使用GitHub %%%%

  1. git clone git@github.com:wangduo2016/bootstrap.git 点“Fork”在自己的账号下克隆了一个bootstrap仓库,然后,从自己的账号下clone。一定要从自己的账号下clone仓库,这样你才能推送修改。

在GitHub上,可以任意Fork开源仓库;
自己拥有Fork后的仓库的读写权限;
可以推送pull request给官方仓库来贡献代码。

%%%% 自定义Git %%%%

  1. git config –global color.ui true 让Git显示颜色,会让命令输出看起来更醒目。Git会适当地显示不同的颜色

%%%% 忽略特殊文件 %%%%

  1. .gitignore文件 GitHub已经为我们准备了各种配置文件(https://github.com/github/gitignore),示例如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    # Windows:
    Thumbs.db
    ehthumbs.db
    Desktop.ini
    # Python:
    *.py[cod]
    *.so
    *.egg
    *.egg-info
    dist
    build
    # Java
    *.class
    # My configurations:
    db.ini
    deploy_key_rsa
  2. git add -f App.class 添加一个文件到Git时发现添加不了,原因是这个文件被.gitignore忽略了。如果确实想添加该文件,可以用-f强制添加到Git

  3. git check-ignore -v App.class 或者发现可能是.gitignore写得有问题,需要找出来到底哪个规则写错了,可以用git check-ignore命令检查

忽略某些文件时,需要编写.gitignore;
.gitignore文件本身要放到版本库里,并且可以对.gitignore做版本管理。

%%%% 配置别名 %%%%

  1. –global参数 是全局参数,也就是这些命令在这台电脑的所有Git仓库下都有用
    git config –global alias.st status st就表示status
    git config –global alias.co checkout co表示checkout
    git config –global alias.ci commit ci表示commit
    git config –global alias.br branch br表示branch
    git config –global alias.unstage ‘reset HEAD’ 命令git reset HEAD file可以把暂存区的修改撤销掉(unstage),重新放回工作区。既然是一个unstage操作,就可以配置一个unstage别名
    git config –global alias.last ‘log -1’ 显示最近(后)一次的提交
    git config –global alias.lg “log –color –graph –pretty=format:’%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset’ –abbrev-commit” 用不同颜色显示从最近到最远的提交日志

配置文件:
配置Git的时候,加上–global是针对当前用户起作用的,如果不加,那只针对当前的仓库起作用。
每个仓库的Git配置文件都放在.git/config文件中。别名就在[alias]后面,要删除别名,直接把对应的行删掉即可。
当前用户的Git配置文件放在用户主目录下的一个隐藏文件.gitconfig中。配置别名也可以直接修改这个文件,如果改错了,可以删掉文件重新通过命令配置。

给Git配置好别名,就可以输入命令时偷个懒。我们鼓励偷懒。

%%%% 搭建Git服务器 %%%%

  1. 安装git:
    $ sudo apt-get install git

  2. 创建一个git用户,用来运行git服务:
    $ sudo adduser git

  3. 创建证书登录:
    收集所有需要登录的用户的公钥,就是他们自己的id_rsa.pub文件,把所有公钥导入到/home/git/.ssh/authorized_keys文件里,一行一个。

  4. 初始化Git仓库:
    先选定一个目录作为Git仓库,假定是/srv/sample.git,在/srv目录下输入命令:
    $ sudo git init –bare sample.git
    Git就会创建一个裸仓库,裸仓库没有工作区,因为服务器上的Git仓库纯粹是为了共享,所以不让用户直接登录到服务器上去改工作区,并且服务器上的Git仓库通常都以.git结尾。然后,把owner改为git:
    $ sudo chown -R git:git sample.git

  5. 禁用shell登录:
    出于安全考虑,第二步创建的git用户不允许登录shell,这可以通过编辑/etc/passwd文件完成。找到类似下面的一行:
    git:x:1001:1001:,,,:/home/git:/bin/bash
    改为:
    git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell
    这样,git用户可以正常通过ssh使用git,但无法登录shell,因为我们为git用户指定的git-shell每次一登录就自动退出。

  6. 克隆远程仓库:
    现在,可以通过git clone命令克隆远程仓库了,在各自的电脑上运行:
    $ git clone git@server:/srv/sample.git
    Cloning into ‘sample’…
    warning: You appear to have cloned an empty repository.
    剩下的推送就简单了。

如果出现 ssh: connect to host localhost port 22: Connection refused错误,请通过命令 sudo apt-get install openssh-server,安装SSH服务。

搭建Git服务器非常简单,通常10分钟即可完成;
要方便管理公钥,用Gitosis;
要像SVN那样变态地控制权限,用Gitolite。

%%%% 期末总结 %%%%

Git虽然极其强大,命令繁多,但常用的就那么十来个,掌握好这十几个常用命令,你已经可以得心应手地使用Git了。
Git的官方网站:http://git-scm.com,英文自我感觉不错的童鞋,可以经常去官网看看。
如果你学了Git后,工作效率大增,有更多的空闲时间健身看电影,那我的教学目标就达到了。

参考文献:https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000