Git小结

起步

Git简介

Git是最流行的分布式版本控制系统,SVN是集中式的版本控制系统。
集中式:版本集中存放在中央服务器,工作时,先从中央服务器取得最新版本,修改完后再推送给中央服务器。
分布式:每个人的电脑上都是一个完整的版本库,工作时不需要联网。和集中式相比,分布式版本控制系统的安全性要高很多,因为每个人电脑都有完整的版本库。

版本控制系统,只能跟踪文本文件的改动,比如TXT文件,网页,代码等,图片、视频这些二进制文件,虽然也能由版本控制系统管理,但没法跟踪文件的变化

安装

此处省略几百字……

安装完成之后,需要设置用户名和邮箱

1
2
git config --global user.name "your name"
git config --global user.email "email@example.com"

--global表示这台机器所有Git仓库都使用这个用户名和邮箱,也可以对某个仓库指定不同的用户名和Email地址。

创建版本库

使用git init命令,把当前的目录变成Git可以管理的仓库

  • 使用git add <file>,将文件添加到暂存区
    git add readme.md

  • 使用git commit,将文件添加到版本库
    git commit -m 'add some files'-m后面输入的是本次提交的说明

工作区和版本库

  • 工作区(Working Directory)
    电脑里能看到的目录
  • 版本库(Repository)
    工作区有一个隐藏目录.git,是Git的版本库。

    其中stage(或者叫index)称之为暂存区。Git会为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD
    使用git add命令,实际上就是把文件修改添加到暂存区
    使用git commit命令,实际上就是把暂存区的所有内容提交到当前分支。

版本管理

使用git status查看文件当前处于什么状态,使用git diff查看工作区的修改内容

版本回退

git log命令查看从最近到最远的提交日志,加上--pretty=oneline参数,每条日志以一行显示。

1
2
3
4
5
6
7
8
9
$ git log
commit d1f725dfb4d7b59b4eaa6aafeac92599c33dd8c4 (HEAD -> master)
Author: gangxiaoya <1335334055@qq.com>
Date: Thu Apr 5 02:42:16 2018 -0700
word and add infos
$ git log --pretty=oneline
d1f725dfb4d7b59b4eaa6aafeac92599c33dd8c4 (HEAD -> master) word and add infos

类似d1f725...8c4commit-id(版本号)。版本回退,Git需要知道回退到哪个版本。在Git中,HEAD表示当前版本,HEAD^表示上一个版本,HEAD^^表示上上个版本,以此类推。当要回退之前多个版本,往上写多个^比较麻烦,可以用HEAD~4HEAD~number)来表示。另外要回退到某个具体的版本,可以用commit-id来表示。

git reset命令用来回退到某个版本

1
2
3
4
5
6
7
//回退到上一个版本
git reset --hard HEAD^
git reset --hard HEAD~1
//回退到commit-id为d1f725d的版本
git reset --hard d1f725d

当回退到之前的某个版本后,又想重新回到新版,可以用git reflog查看命令历史,找到未来某个版本的commit-id回退即可。

管理修改

Git跟踪并管理的是修改,而非文件。使用git add命令后,会把工作区的修改存入暂存区。使用git commit命令,会把暂存区的修改提交到当前分支。假设第一次使用git add后,对工作去进行了第二次修改,然后git commit,提交的是第一次修改,第二次修改不会被提交。

使用git diff HEAD可以查看当前工作区和版本库里面最新版本的区别

撤销修改

  • 撤销工作区修改
    使用git checkout -- <file>把文件在工作区的修改全部撤销。当文件还未提交到暂存区,撤销修改就回到和版本库一样。当文件已经提交到暂存区,然后又做了修改,撤销修改就回到添加到暂存区后的状态。

    1
    git checkout -- readme.md
  • 撤销暂存区修改
    使用git reset HEAD <file>把暂存区的修改撤销掉,重新放回工作区,如果想丢弃修改,再用git checkout -- <file>操作。

  • 撤销版本库修改,按版本回退操作。

远程仓库

本地仓库与远程仓库的连接,需要生成SSH key
ssh-keygen -t rsa -C "youremail@example.com"
然后在用户主目录下的.ssh目录下,里面有id_rsaid_rsa.pub两个文件,这两个就是SSH Key的秘钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,把公钥添加远程Git服务器就好了。

  • 关联远程仓库
    git remote add origin <repo>将一个本地仓库关联到远程仓库
  • 推送
    git push -u origin master将本地库推送到远程,使用git push命令,这里其实是将master分支推送到远程。第一次推送时,由于远程仓库是空的,加了-u参数,将本地master推送远程master并与之关联,后面就可以简化命令git push origin master
  • 克隆仓库
    git clone <repo>将一个远程仓库克隆到本地,repo表示一个远程仓库地址。

分支管理

Git中,每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。在只有一条时间线仓库里,这个分支叫主分支,即master分支。开发中,一般会从主分支创建一个分支出来,开发完成后,再合并到主分支。

创建与合并

  • 创建一个分支git branch <name>
  • 切换到某个分支git checkout <name>
  • 创建并切换到分支git checkout -b <name>
    git checkout -b dev表示创建一个dev分支,并且切换到该分支。相当于先git branch dev创建dev分支,然后git checkout dev切换到dev分支
  • 查看分支git branch,当前分支前面会标一个*
  • 合并分支git merge合并指定分支到当前分支
    git merge devmaster分支上执行这个命令,相当于把dev分支合并到master

    1
    2
    3
    4
    Updating 76476ff..fb48436
    Fast-forward
    readme.md | 3 ++-
    1 file changed, 2 insertions(+), 1 deletion(-)

    其中Fast-forward表示合并采用的是”快进模式“,直接把master指向dev的提交

    通常情况,Git会采用Fast-forward模式,但这种模式,删除分支后,会丢失分支信息。如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit。可以在合并时添加参数--no-ff禁用,例如git merge --no-ff -m 'merge with no ff' dev

    变基git rebase

  • 删除分支git branch -d <name>,未被合并的分支,删除需要使用git branch -D <name>

解决冲突

当从主分支切了一个分支出来,开发完成后,准备合并到主分支,如果主分支也有新的提交,这种情况可能无法进行自动合并时,就需要手动解决冲突。解决冲突后,再提交,合并完成。

可以使用git log --graph命令可以看到分支合并图

stash

当有紧急需求需要处理时,而当前分支功能的开发又未完成,可以使用stash功能,将当前的工作区暂存起来,以后恢复继续开发。

  • git stash,保存现场。
  • git stash list,查看stash列表,可以多次stash,这样会有多个stash。如

    1
    2
    stash@{0}: WIP on dev: 92f946c not use ff
    stash@{1}: WIP on dev: 92f946c not use ff
  • git stash apply,恢复最新的stash,可以恢复指定的stash,如git stash apply stash@{1}

  • git stash drop,删除最新stash。可以删除指定的stash,如git stash drop stash@{1}
  • git stash pop,恢复同时删除stash。可以恢复同时删除指定的stash,如git stash pop stash@{1}

远程仓库

查看远程仓库信息,可以使用git remote,更详细的信息可以使用git remote -v,远程仓库默认名称是origin。如下

1
2
3
4
$ git remote -v
origin git@****.git (fetch)
origin git@****.git (push)

  • 推送分支
    把本地分支推送到远程仓库git push origin <name>,如把dev分支推动到远程仓库git push origin dev
  • 抓取分支
    当一个分支,多人有提交,远程仓库比本地更新,推送到远程仓库,需要先拉取该分支的最新代码并且合并到本地,如果有冲突,解决完冲突后,再推送。可以使用git pull <remote> <name>拉取远程某个分支代码并合并,如git pull origin dev

    git fetch从远程获取最新版本到本地,不会自动merge

标签

发布一个版本时,通常会在版本库打一个标签,标签其实就是指向某个commit的指针。

  • 打标签,切换到需要打标签的分支,使用git tag <name>就可以打一个新的标签。如$ git tag v1.0.0
  • 查看所有标签,使用git tag
  • 查看标签信息,使用git show <tagname>,如

    1
    2
    3
    4
    5
    $ git show v1.0.0
    commit 607a3d2d476749cef1d20a1b66606add5a125ec9 (HEAD -> master, tag:v1.0.0, hotfix-bug)
    Author: ***
    Date: Sun Apr 8 05:24:47 2018 -0700
  • 新建的标签默认是指向HEAD,也可以指向某个commit,使用git tag <name> commit-id。如git tag v1.0.1 92f946c

  • 删除标签,使用git tag -d <name>
  • 将标签推送到远程仓库git push origin <name>,这些和分支的操作是类似。

其他

  • 线上版本回滚
    git reset --hard v1.0.0
    git reset --soft origin/master
    git commit -am 'revert to v1.0.0'

  • 删除远程分支
    可以运行带有--delete 选项的git push命令来删除一个远程分支,比如删除远程dev分支,$ git push origin --delete dev