Git

10/21/2019 Git

# Git简介

Git 是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。之前对git没有很深的认识,只是了解过简单的push pull等基本命令。一直听说廖雪峰的git教程,刚好也想看看,所以就有了今天的博客:)

# 分布式&集中式

集中式版本控制系统,版本库是集中存放在中央服务器的,工作时,用的都是自己的电脑,所以要先从中央服务器取得最新的版本,然后开始工作,工作后版本变更则需要把自己变更后的版本推送给中央服务器。 分布式版本控制系统没有“中央服务器”,每个人的电脑上都是一个完整的版本库,但是在团队工作中往往会有一台服务器充当中央服务器的角色,用于团队互相查阅各个版本的变更。(可能这就是github诞生的原因8) 其实分布式的版本控制系统还有Mercurial和Bazaar等,但是目前最火的肯定还是git了。

# Git的安装

最早Git是在Linux上开发的,很长一段时间内,Git也只能在Linux和Unix系统上跑。不过,慢慢地有人把它移植到了Windows上。现在,Git可以在Linux、Unix、Mac和Windows这几大平台上正常运行了。

# Linux安装

如果是比较新的debian系,比如ubuntu18.04LTS(亲测)应该直接sudo apt install git就行了。如果是别的发行版(没试过),可以考虑官网下载源码安装(大致是解压、./configmakesudo make install就行了)

# MacOS安装

直接从AppStore安装Xcode,Xcode集成了Git,不过默认没有安装,你需要运行Xcode,选择菜单“Xcode”->“Preferences”,在弹出窗口中找到“Downloads”,选择“Command Line Tools”,点“Install”就可以完成安装了。

# Windows安装

在Windows上使用Git,可以从Git官网直接下载安装程序,(网速慢的同学请移步国内镜像),然后按默认选项安装即可。 安装完成后,在开始菜单里找到“Git”->“Git Bash”,蹦出一个类似命令行窗口的东西,就说明Git安装成功! 安装完成后,还需要最后一步设置,在命令行输入: git config --global user.name "Your Name" git config --global user.email "email@example.com"

# 创建版本库

什么是版本库呢?版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改,删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。

第一步,选择或者新建一个空目录

第二步 ,执行git init(会多一个.git目录)

然后这个文件夹就是repository,ez!

# 基本命令

git add (file):把文件添加到repository中,可以多次添加,可以添加文件夹 git commit -m (commit message):用于将添加的文件进行提交,并且需要填写提交信息。

# 时光机穿梭

git status:用于查看版本库的状态(有无文件被修改) git diff:查看修改的内容

# 版本回退

git log 命令显示从最近到最远的提交日志。 如果嫌输出信息太多,看得眼花缭乱的,可以试试加上--pretty=oneline参数: git log --pretty=oneline。 需要友情提示的是,你看到的一大串类似1094adb。。。的是commit id(版本号),和SVN不一样,Git的commit id不是1,2,3……递增的数字,而是一个SHA1计算出来的一个非常大的数字,用十六进制表示。

git reset --hard HEAD^/ commit_id / HEAD ~ n:在Git中,用HEAD表示当前版本,上一个版本就是HEAD ^ ,上上一个版本就是HEAD ^^ ,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100。 --hard删除末次提交,并清空所有基于这次commit的修改。可能会造成数据丢失。

提示:版本号没必要写全,前几位就可以了(形成独一标识),Git会自动去找。

git reflog:查看命令历史(可以用来确定未来某个版本的commit_id用git reset变更为未来版本)

# 工作区和暂存区

工作区(Working Directory):就是你在电脑里能看到的目录

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

Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。之前的git add操作就是将文件添加到暂存区,需要commit之后才会将暂存区的文件提交到分支当中。理解暂存区有利于理解很多命令大概干了哪些事。

# 管理修改

为什么Git比其他版本控制系统设计得优秀,因为Git跟踪并管理的是修改,而非文件。比如说你修改了一个文件,然后调用git add,之后你再修改文件,并且没有add而是直接commit,然后你会发现第二次更改没有被提交。所以说git提交的不是文件,而且修改之后add操作添加到暂存区的内容。

# 撤销修改

  • 情况1:修改后未执行add操作,使用git checkout --file,注意是两个-,单个的话则是切换命令分支。

  • 情况2:修改文件执行了add操作,但未执行commit,则需要多一步,第一步先执行git reset HEAD file,此刻暂存区的内容会被清除,之后再执行情景1的命令就好了。

  • 情况3:已经commit过了,则需要进行版本回退(前面有提到),前提是还没推送到远程库。

# 删除文件

在Git中,删除也是一个修改操作,一般情况下,你通常直接在文件管理器中把没用的文件删了,或者用rm命令删了rm file,这个时候,Git知道你删除了文件,因此,工作区和版本库就不一致了,git status命令会立刻告诉你哪些文件被删除了,现在你有两个选择:

  • 确实要从版本库中删除该文件,那就用命令git rm删掉,并且git commit。
  • 删错了,但是版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:git checkout -- filegit checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。

注意:从来没有被添加到版本库就被删除的文件,是无法恢复的!

# 远程仓库

Git是分布式版本控制系统,同一个Git仓库,可以分布到不同的机器上。但是远程仓库是需要服务器环境的,所以你可以考虑搭建git私服或者使用GitHub (opens new window)。这个网站就是提供Git仓库托管服务的,所以,只要注册一个GitHub账号(very ez),就可以免费获得Git远程仓库。(现在私有库都免费了,不过最多支持3人协作,但是还是,真香!)

# 添加远程库

当你有了github的免费git仓库之后,你就可以使用它来同步你本地的git仓库了。(还能分享给别人学习- -)同步到远程库具体分为以下步骤:

  • 在github创建repository
  • 本地库和远程库关联xxxx(可以使用https或者ssh协议自行选择) git remote add origin path/xxxx.git
  • git push推送本地库到远程库进行同步git push -u origin master

此命令是把当前分支master推送到远程。由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。

推送成功后,可以立刻在GitHub页面中看到远程库的内容已经和本地一模一样,从现在起,只要本地作了提交,就可以通过命令:git push origin master

# 从远程仓库克隆

git clone path/xxxx.git 然后你会得到在当前目录下多了一个本地库。和远程库一致。

# 分支管理

几乎每一种版本控制系统都以某种形式支持分支。使用分支意味着你可以从开发主线上分离开来,然后在不影响主线的同时继续工作。

Git的分支是与众不同的,无论创建、切换和删除分支,Git在1秒钟之内就能完成!无论你的版本库是1个文件还是1万个文件。

# 创建与合并分支

git checkout -b branchName 创建指定分支并切换到该分支。相当于git branch branchName git checkout branchName git branch命令会列出所有分支,当前分支前面会标一个*号。 git merge branchName命令用于合并指定分支到当前分支。 合并之后可以使用git branxh -d branchName删除指定分支 因为创建、合并和删除分支非常快,所以Git鼓励你使用分支完成某个任务,合并后再删掉分支,这和直接在master分支上工作效果是一样的,但过程更安全。

switch & checkout

最新版本的Git提供了新的git switch命令来切换分支:git switch -c branchName,效果等同于git checkout -c branchName,checkout就让他专门用来进行撤销吧,省的整混了

# 解决冲突

有的时候分支合并可能会发生冲突,比如你在a分支某个文件进行了append,然后你又在b分支对同一个文件又进行了append,此刻快去合并分支则会失败,并要求对冲突的内容进行修改。

# 分支管理策略

通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。

如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。 git merge --no-ff -m "merge with no-ff" dev,其中--no-ff表示禁用Fast forward

因为本次合并要创建一个新的commit,所以加上-m参数,把commit描述写进去。

之后可以用git log查看分支历史

在实际开发中,通常master都是正式版本的分支,个人开发一般新建一个分支,之后确认无误再将新建的分支合并到master分支中。

# Bug分支

修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;

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

在master分支上修复的bug,想要合并到当前dev分支,可以用git cherry-pick <commit>命令,把bug提交的修改“复制”到当前分支,避免重复劳动。

# Feature分支

开发一个新feature,最好新建一个分支;

如果要丢弃一个没有被合并过的分支,可以通过git branch -D <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,如果有冲突,要先处理冲突。

# Rebase

rebase操作可以把本地未push的分叉提交历史整理成直线;

rebase的目的是使得我们在查看历史提交的变化时更容易,因为分叉的提交需要三方对比。

# 标签管理

tag就是一个让人容易记住的有意义的名字,它跟某个commit绑在一起。

发布一个版本时,我们通常先在版本库中打一个标签(tag),这样,就唯一确定了打标签时刻的版本。将来无论什么时候,取某个标签的版本,就是把那个打标签的时刻的历史版本取出来。所以,标签也是版本库的一个快照。

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

# 创建标签

  • 命令git tag <tagname>用于新建一个标签,默认为HEAD,也可以指定一个commit id。

  • 命令git tag -a <tagname> -m "message"可以指定标签信息。

  • 命令git tag可以查看所有标签。

# 操作标签

  • 命令git push origin <tagname>可以推送一个本地标签。

  • 命令git push origin --tags可以推送全部未推送过的本地标签。

  • 命令git tag -d <tagname>可以删除一个本地标签。

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

# 码云

众所周知,github访问速度一般,但是除了github还有gitee!也就是码云。码云也是一个git仓库托管的平台,同样支持私有库,最高5人上限,良好的访问速度。而且git本来就是分布式版本控制系统,也就是说,你可以把本地库同步到github的同时也同步到gitee,只是远程名不能都叫origin了,得分别设置。总之,gitee的中文界面,访问速度值得你去尝试。至于有些开源项目,你仍然可以选择star on github,这并不冲突。

# 自定义功能

# 忽略配置文件

当你不想把一些文件提交到git仓库时,你可以选择提交忽略。 忽略某些文件时,需要编写.gitignore;

.gitignore文件本身要放到版本库里,并且可以对.gitignore做版本管理!

# 配置别名

有的时候你可能会忘记有些命令单词,贴心的git为你设计了别名。但是感觉git使用频率不高,感觉没必要配置,这里就简单说一下,其实就是可以通过命令配置别名达到偷懒的作用。eg:git config --global alias.st status,在输入这个命令后,以后就可以直接git st代替git status,其他类似。感觉没什么必要,就不多赘述了。

# 搭建git服务器

  1. 服务器安装git(根据发行版自行安装)
  2. 创建git用户,用于运行git服务
  3. 创建证书登录
  4. 初始化git仓库
  5. 禁用shell登录
  6. 克隆远程仓库

管理公钥:自行了解Gitosis

管理权限:自行了解Gitolite

# 最后

差不多了,对了最近好像 GitHub Mobile beta ios已经开始测试了,Android也可以预约beta了 感兴趣可以了解一下 over -.-