git经常使用知识整理

分布式和集中版本控制的区别

分布式版本控制系统与集中式版本控制系统有何不一样呢?首先,分布式版本控制系统根本没有“中央服务器”,每一个人的电脑上都是一个完整的版本库,这样,你工做的时候,就不须要联网了,由于版本库就在你本身的电脑上。既然每一个人电脑上都有一个完整的版本库,那多我的如何协做呢?比方说你在本身电脑上改了文件A,你的同事也在他的电脑上改了文件A,这时,大家俩之间只需把各自的修改推送给对方,就能够互相看到对方的修改了。git

和集中式版本控制系统相比,分布式版本控制系统的安全性要高不少,由于每一个人电脑里都有完整的版本库,某一我的的电脑坏掉了没关系,随便从其余人那里复制一个就能够了。而集中式版本控制系统的中央服务器要是出了问题,全部人都无法干活了。github

在实际使用分布式版本控制系统的时候,其实不多在两人之间的电脑上推送版本库的修改,由于可能大家俩不在一个局域网内,两台电脑互相访问不了,也可能今天你的同事病了,他的电脑压根没有开机。所以,分布式版本控制系统一般也有一台充当“中央服务器”的电脑,但这个服务器的做用仅仅是用来方便“交换”你们的修改,没有它你们也同样干活,只是交换修改不方便而已。数据库

安装git

Windows下要使用不少Linux/Unix的工具时,须要Cygwin这样的模拟环境,Git也同样。Cygwin的安装和配置都比较复杂,就不建议你折腾了。不过,有高人已经把模拟环境和Git都打包好了,名叫msysgit,只须要下载一个单独的exe安装程序,其余什么也不用装,绝对好用。安全

msysgit是Windows版的Git,从http://msysgit.github.io/下载,而后按默认选项安装便可。服务器

安装完成后,在开始菜单里找到“Git”->“Git Bash”,蹦出一个相似命令行窗口的东西,就说明Git安装成功!ssh

安装完成后,还须要最后一步设置,在命令行输入:编辑器

$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"

由于Git是分布式版本控制系统,因此,每一个机器都必须自报家门:你的名字和Email地址。你也许会担忧,若是有人故意冒充别人怎么办?这个没必要担忧,首先咱们相信你们都是善良无知的群众,其次,真的有冒充的也是有办法可查的。分布式

注意git config命令的--global参数,用了这个参数,表示你这台机器上全部的Git仓库都会使用这个配置,固然也能够对某个仓库指定不一样的用户名和Email地址工具

建立版本库

切换到相应的目录 而后执行 fetch

$ git init

瞬间Git就把仓库建好了,并且告诉你是一个空的仓库(empty Git repository),细心的读者能够发现当前目录下多了一个.git的目录,这个目录是Git来跟踪管理版本库的,没事千万不要手动修改这个目录里面的文件,否则改乱了,就把Git仓库给破坏了。

初始化一个Git仓库,使用git init命令。

添加文件到Git仓库,分两步:

第一步,使用命令git add <file>,注意,可反复屡次使用,添加多个文件;

第二步,使用命令git commit,完成。

要随时掌握工做区的状态,使用git status命令。

若是git status告诉你有文件被修改过,用git diff能够查看修改内容。

版本回退

HEAD指向的版本就是当前版本,所以,Git容许咱们在版本的历史之间穿梭,使用命令git reset --hard commit_id

穿梭前,用git log能够查看提交历史,以便肯定要回退到哪一个版本。

要重返将来,用git reflog查看命令历史,以便肯定要回到将来的哪一个版本。

工做区和暂存区

Git和其余版本控制系统如SVN的一个不一样之处就是有暂存区的概念。

先来看名词解释。

工做区(Working Directory):就是你在电脑里能看到的目录,好比个人learngit文件夹就是一个工做区:

working-dir

版本库(Repository):工做区有一个隐藏目录.git,这个不算工做区,而是Git的版本库。

Git的版本库里存了不少东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为咱们自动建立的第一个分支master,以及指向master的一个指针叫HEAD

git-repo

分支和HEAD的概念咱们之后再讲。

前面讲了咱们把文件往Git版本库里添加的时候,是分两步执行的:

第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区;

第二步是用git commit提交更改,实际上就是把暂存区的全部内容提交到当前分支。

由于咱们建立Git版本库时,Git自动为咱们建立了惟一一个master分支,因此,如今,git commit就是往master分支上提交更改。

你能够简单理解为,须要提交的文件修改统统放到暂存区,而后,一次性提交暂存区的全部修改。

俗话说,实践出真知。如今,咱们再练习一遍,先对readme.txt作个修改,好比加上一行内容:

Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.

而后,在工做区新增一个LICENSE文本文件(内容随便写)。

先用git status查看一下状态:

$ git status
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   readme.txt
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       LICENSE
no changes added to commit (use "git add" and/or "git commit -a")

Git很是清楚地告诉咱们,readme.txt被修改了,而LICENSE还历来没有被添加过,因此它的状态是Untracked

如今,使用两次命令git add,把readme.txtLICENSE都添加后,用git status再查看一下:

$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   LICENSE
#       modified:   readme.txt
#

如今,暂存区的状态就变成这样了:

git-stage

因此,git add命令实际上就是把要提交的全部修改放到暂存区(Stage),而后,执行git commit就能够一次性把暂存区的全部修改提交到分支。

$ git commit -m "understand how stage works"
[master 27c9860] understand how stage works
 2 files changed, 675 insertions(+)
 create mode 100644 LICENSE

一旦提交后,若是你又没有对工做区作任何修改,那么工做区就是“干净”的:

$ git status
# On branch master
nothing to commit (working directory clean)

如今版本库变成了这样,暂存区就没有任何内容了:

git-stage-after-commit

git add 是把工做区的改动推送到暂存区

git commit 是把暂存区的内容提交到版本库

撤销修改

场景1:当你改乱了工做区某个文件的内容,想直接丢弃工做区的修改时,用命令git checkout -- file

场景2:当你不但改乱了工做区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD file,就回到了场景1,第二步按场景1操做。

场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本回退一节,不过前提是没有推送到远程库。

撤销删除

删错了,能够很轻松地把误删的文件恢复到最新版本,由于版本库里还有呢:

$ git checkout -- test.txt

git checkout实际上是用版本库里的版本替换工做区的版本,不管工做区是修改仍是删除,均可以“一键还原”。

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

远程仓库

注册github账号,并建立仓库

第1步:建立SSH Key。在用户主目录下,看看有没有.ssh目录,若是有,再看看这个目录下有没有id_rsaid_rsa.pub这两个文件,若是已经有了,可直接跳到下一步。若是没有,打开Shell(Windows下打开Git Bash),建立SSH Key:

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

你须要把邮件地址换成你本身的邮件地址,而后一路回车,使用默认值便可,因为这个Key也不是用于军事目的,因此也无需设置密码。

若是一切顺利的话,能够在用户主目录里找到.ssh目录,里面有id_rsaid_rsa.pub两个文件,这两个就是SSH Key的秘钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,能够放心地告诉任何人。

第2步:登录GitHub,打开“Account settings”,“SSH Keys”页面:

而后,点“Add SSH Key”,填上任意Title,在Key文本框里粘贴id_rsa.pub文件的内容

有https协议和git也就是ssh协议,https协议在每次push时都须要数据账号和密码,略麻烦,能够稍微控制push的次数。

添加远程仓库

本地的learngit仓库下运行命令:

$ git remote add origin git@github.com:mh335776191/learngit.git
添加后,远程库的名字就是origin,这是Git默认的叫法,也能够改为别的,可是origin这个名字一看就知道是远程库。
originorigin

把本地库的内容推送到远程,用git push命令,其实是把当前分支master推送到远程。

因为远程库是空的,咱们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在之后的推送或者拉取时就能够简化命令。

从如今起,只要本地做了提交,就能够经过命令:


要克隆一个仓库,首先必须知道仓库的地址,而后使用命令克隆。$ git push origin mastergit clone


分支

Git鼓励大量使用分支:

查看分支:git branch

建立分支:git branch <name>

切换分支:git checkout <name>

建立+切换分支:git checkout -b <name>

合并某分支到当前分支:git merge <name>

删除分支:git branch -d <name>

解决冲突

当Git没法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。

git log --graph命令能够看到分支合并图。

分支策略

在实际开发中,咱们应该按照几个基本原则进行分支管理:

首先,master分支应该是很是稳定的,也就是仅用来发布新版本,平时不能在上面干活;

那在哪干活呢?干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,好比1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;

你和你的小伙伴们每一个人都在dev分支上干活,每一个人都有本身的分支,时不时地往dev分支上合并就能够了。

因此,团队合做的分支看起来就像这样:

git-br-policy

Git分支十分强大,在团队开发中应该充分应用。

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

隐藏/恢复现场

修复bug时,咱们会经过建立新的bug分支进行修复,而后合并,最后删除;

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

删除分支

若是要丢弃一个没有被合并过的分支,能够经过git branch -D <name>强行删除。

多人协做

多人协做的工做模式一般是这样:

  1. 首先,能够试图用git push origin branch-name推送本身的修改;

  2. 若是推送失败,则由于远程分支比你的本地更新,须要先用git pull试图合并;

  3. 若是合并有冲突,则解决冲突,并在本地提交;

  4. 没有冲突或者解决掉冲突后,再用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,若是有冲突,要先处理冲突。

标签管理

发布一个版本时,咱们一般先在版本库中打一个标签,这样,就惟一肯定了打标签时刻的版本。未来不管何时,取某个标签的版本,就是把那个打标签的时刻的历史版本取出来。因此,标签也是版本库的一个快照。

Git的标签虽然是版本库的快照,但其实它就是指向某个commit的指针(跟分支很像对不对?可是分支能够移动,标签不能移动),因此,建立和删除标签都是瞬间完成的。

  • 命令git tag <name>用于新建一个标签,默认为HEAD,也能够指定一个commit id;

  • git tag -a <tagname> -m "blablabla..."能够指定标签信息;

  • git tag -s <tagname> -m "blablabla..."能够用PGP签名标签;

  • 命令git tag能够查看全部标签。

删除标签

  • 命令git push origin <tagname>能够推送一个本地标签;

  • 命令git push origin --tags能够推送所有未推送过的本地标签;

  • 命令git tag -d <tagname>能够删除一个本地标签;

  • 命令git push origin :refs/tags/<tagname>能够删除一个远程标签。

忽略指定文件

有些时候,你必须把某些文件放到Git工做目录中,但又不能提交它们,好比保存了数据库密码的配置文件啦,等等,每次git status都会显示“Untracked files ...”,有强迫症的童鞋内心确定不爽。

好在Git考虑到了你们的感觉,这个问题解决起来也很简单,在Git工做区的根目录下建立一个特殊的.gitignore文件,而后把要忽略的文件名填进去,Git就会自动忽略这些文件。

不须要从头写.gitignore文件,GitHub已经为咱们准备了各类配置文件,只须要组合一下就可使用了。全部配置文件能够直接在线浏览:https://github.com/github/gitignore

忽略文件的原则是:

  1. 忽略操做系统自动生成的文件,好比缩略图等;
  2. 忽略编译生成的中间文件、可执行文件等,也就是若是一个文件是经过另外一个文件自动生成的,那自动生成的文件就不必放进版本库,好比Java编译产生的.class文件;
  3. 忽略你本身的带有敏感信息的配置文件,好比存放口令的配置文件。

使用Windows的童鞋注意了,若是你在资源管理器里新建一个.gitignore文件,它会很是弱智地提示你必须输入文件名,可是在文本编辑器里“保存”或者“另存为”就能够把文件保存为.gitignore了。

  • 忽略某些文件时,须要编写.gitignore

  • .gitignore文件自己要放到版本库里,而且能够对.gitignore作版本管理!

配置别名

有没有常常敲错命令?好比git statusstatus这个单词真心很差记。

若是敲git st就表示git status那就简单多了,固然这种偷懒的办法咱们是极力同意的。

咱们只须要敲一行命令,告诉Git,之后st就表示status

$ git config --global alias.st status

好了,如今敲git st看看效果。

固然还有别的命令能够简写,不少人都用co表示checkoutci表示commitbr表示branch

$ git config --global alias.co checkout
$ git config --global alias.ci commit
$ git config --global alias.br branch

之后提交就能够简写成:

$ git ci -m "bala bala bala..."

--global参数是全局参数,也就是这些命令在这台电脑的全部Git仓库下都有用。

配置Git的时候,加上--global是针对当前用户起做用的,若是不加,那只针对当前的仓库起做用。

配置文件放哪了?每一个仓库的Git配置文件都放在.git/config文件中:

$ cat .git/config 
[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
    ignorecase = true
    precomposeunicode = true
[remote "origin"]
    url = git@github.com:michaelliao/learngit.git
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
    remote = origin
    merge = refs/heads/master
[alias]
    last = log -1

别名就在[alias]后面,要删除别名,直接把对应的行删掉便可。

而当前用户的Git配置文件放在用户主目录下的一个隐藏文件.gitconfig

配置别名也能够直接修改这个文件,若是改错了,能够删掉文件从新经过命令配置。

相关文章
相关标签/搜索