一、Git介绍
Git是很强很实用的版本控制工,Git的优点是方便使用,轻量级。Git轻量级的原因是Git不进行文件的全量拷贝。
Git项目结构
当我们查看一个git项目下的文件时,会看到如图所示的项目结构:objects存放了所有文件,refs记录了所有的指针,HEAD保存了当前分支的最新commit指向,index代表了staged文件区。
Git轻量级探秘
GIt为什么是一个轻量级的版本控制工具?Git分支本质上是一个指针,包含了一个40bytes的SHA-1字符串和一个\n换行符,总计41个bytes。换句话说,git会为每个分支对应的每次提交分配41bytes的空间来存放一个指针,所以每次提交其实只占用41bytes,这就决定了git的轻量性。
Git VS SVN
Git与SVN的主要区别在于git具备了本地代码仓库,用户可以通过维护本地代码库的方式,创建稳定的版本再推送到远程仓库上,同时也能通过分支的方式,实现多人在一个项目上进行互相之间无干扰的开发。
事实上
Git如何工作?
三棵树
工作区(working directory/working tree) 即你能看到的代码
暂存区(staged file/indexed file) 通过git add命令加入的代码
仓库(repository) push过的改动或者push了的新增文件
各个区域之间的变动和对应操作如图所示
Git commit
如图所示是一次commit对应的git保存记录,一次commit记录包含了commit的size和一个tree的指针,commit里的tree指针指向tree,tree里包含了指向本次提交所对应的文件改动的指针,git就是通过这种存储指针的方式实现了轻量级的版本控制。
Git commits
如图所示是多次commit的记录之间是如何连接的,新进行的提交包含了一个父指针,指向上一次提交,git通过这种方式实现了commit之间的顺序连接。
二、Git指令总结
如图所示是git各个区域之间通过哪一条指令进行代码的转换
git init/git clone
git init用来讲一个项目初始化为git项目,git clone做的操作是从url指定的远程仓库里拉取代码到本地并且初始化为git项目。
git clone -o #重命名clone的仓库
git clone -b #重命名clone的分支
git branch
git branch用来执行与分支有关的操作
git branch #创建新分支 命名为
git branch -d #删除名为的分支
git branch -v #显示所有分支和其对应的最新一次commit
git branch --merged #显示所有进行过合并的分支
git branch --no-merged #显示所有未进行过合并的分支
git branch -f #重置分支
git branch -r #显示远程分支
git branch -a #显示所有分支
git branch -u origin/dev dev #创建并初始化一个分支dev
git branch --set-upstream master origin/master #默认设置本地master分支跟踪远程仓库origin/master分支
git branch --set-upstream dev origin/dev #默认设置本地dev分支跟踪远程仓库origin/dev分支
git branch --track #设置分支跟踪远程分支
git branch #基于指定commit创建新分支
git branch -m #重命名分支
git checkout
git checkout用于执行分支之间的切换和文件的回滚
git checkout #切换到分支
git checkout -b --track / #创建分支并切换到该分支 设置当前分支追踪远程分支/
git checkout -b #创建新分支并切换到该分支
git checkout -b #基于创建新分支并切换到该分支
git checkout -B #基于指定的commit创建新分支并切换到该分支
git branch #基于指定的commit创建新分支并切换到该分支
git checout -- #回滚到最新一次commit的代码
git checkout . #放弃工作区内所有的改动
git add
git add .
git add -A #添加所有文件到暂存区
git add #添加指定文件到暂存区
git commit
git commit -m "message" #提交
git commit --amend -m "message" #修改上一次commit
git commit --amend #针对指定文件进行重新提交一次
git push
git push : #推送本地分支到远程仓库中的
git push #本地分支到远程仓库repo 如果没有指定远程分支则默认推送到跟踪分支
git push -u origin dev #首次推送代码到远程分支dev
git push -all origin #推送所有分支
git push origin dev:master #标准推送 推送本地分支dev到远程仓库origin远程分支master
git push origin #推送分支到远程仓库origin 如果省略本地分支和远程分支 则默认推送当前分支到其跟踪的远程分支
git push #推送分支 如果当前项目只跟踪了一个远程仓库则可以省略远程仓库名
git push origin :dev #删除远程仓库origin中的分支dev
git fetch
git fetch #获取远程改动
git fetch --a #获取所有的远程改动
git fetch #获取远程仓库中的改动
git fetch #获取远程仓库中中的改动
git fetch --prune #删除本地仓库中存在但远程仓库中不存在的分支
git merge
git merge --commit #合并后产生一个commit
git merge --no-commit #合并后不产生一个commit
git merge --ff #使用fast-forward模式进行合并
git merge --no-ff #不使用fast-forward模式进行合并
git merge #合并指定的commit
git merge ... #合并多个分支
git pull
git pull = git fetch + git merge #git pull其实等于fetch+merge
git pull #拉取远程仓库中的分支到本地分支
git remote
git remote -v #显示对应的远程仓库url
git remote add #添加本地仓库连接的远程仓库
git remote rm #移除远程仓库连接
git remote rename #重命名
git remote set-head #设置默认的主要分支
git remote set-branches #设置远程分支
git remote set-branches -add #添加本地跟踪的远程分支
git remote show #打印远程仓库信息
git diff
git diff #显示两个分支之间的区别
git diff #显示指定文件工作区和暂存区之间的区别
git diff #显示指定分支中指定文件工作区和暂存区之间的区别
git diff --cached #显示暂存区和repo里的指定文件的区别
git diff --cached #显示暂存区和指定提交的区别
git diff #显示工作区和指定commit中文件的区别
git diff #显示两个commit的区别
git diff HEAD/HEAD^/HEAD^^/HEAD~3... #显示工作区和HEAD/HEAD^/HEAD^^/HEAD~3的区别
git diff —shortstat “@{0 day ago}" #显示你今天写了多少行代码
git reset
git reset <file> #reset指定文件如果说文件是新建的那么reset无效 如果没有指定commit那么就默认reset到HEAD
git revert
git revert <commit> #revert指定commit e.g git revert HEAD~3...HEAD 撤销多个commit
git status
显示还未提交的改动
git status -s #显示简洁版本
git status -b #显示分支和分支跟踪情况
git stash
git stash #stash所有的改动
git stash list #显示所有的stash记录
git stash apply stash@{0} #取出指定的stash
git stash drop #丢弃指定的stash
git stash pop #取出最上层的stash记录并且丢弃
git stash clear #清除所有stash记录
git stash save #save一个stash记录并且用message标记
git stash pop = git stash apply + git stash drop
git rm
git rm #从工作区中移除指定文件
git rm --cached #从暂存区中移除指定文件
git mv
git mv <file> <renamed_file> #重命名文件
git log
git log -n #只显示n条记录
git log #显示指定文件的提交记录
git log #显示指定分支的提交记录
git log #显示指定commit的提交信息
git log #显示[commit1, commit2]的提交信息 包括commit1
git log .. #显示(commit1, commit2]的提交信息 不包括commit1
git log -stat #只显示少量信息
git rebase
git rebase test #在当前分支上重演目标分支上的改动
git cherry-pick
git cherry-pick <commit> #再次提交一个commit 常用于commit的移植
git show
git show #显示指定commit的信息
git show : #显示指定commit中指定文件的内容
git config
git config —list #显示config中的所有配置
git config --global alias.co checkout #用于自定义git指令的简写版本
三、常用场景
如何进行常规的bugfix?
git branch bugfix #新建一个bugfix分支
git checkout bugfix #切换到该分支
#######fixing bugs######### #修复bug
git add . #添加改动到暂存区
git commit -m "fix bugs" #提交改动
git checkout master #切回到主要分支
git merge bugfix #merge改动
git branch -d bugfix #删除bugfix分支
如何查看跟踪的远程分支
git branch -vv #查看所有分支和其对应的远程分支
如何重新commit?
git commit -amend #使用amend option重新修订commit
如何回滚之前的改动?
git reset #reset将工作区和暂存区回滚到你指定的版本 你指定的提交之后的所有提交记录都被丢弃了
git revert #revert将撤销指定commit的改动 对除此之外的所有commit都没有影响
git revert会创建新的提交记录
如何使用cherry-pick?
使用cherry-pick重演指定分支上的提交改动 如果有冲突需要你解决
如何使用rebase?
使用git rebase命令将一个分支上的分支在另一个分支上重新演一次 如果有冲突需要解决冲突之后使用git rebase --continue继续执行rebase
四、Git进阶
如何设置/切换当前分支所跟踪的远程分支?
git checkout --track origin/dev #设置当前分支跟踪远程分支origin/dev
git checkout -b origin/ #创建新分支并且设置其跟踪远程分支origin/tracked_branch
git branch -u origin/dev or git branch --set-upstream-to origin/dev #初始化/更新当前分支的tracking分支
Git merge VS Git rebase VS Git cherry-pick
Git reset VS Git checkout VS Git revert
为什么在实际工作中使用git revert回滚比使用git reset安全?
使用git reset之后指定的版本之后的提交内的改动全部会被移除,如果A拉取了代码之后并基于拉取的代码进行开发,同时假设B使用了reset进行了代码回滚,如果A通知B他进行了回滚那么B可以在本地同时进行回滚处理,但如果A没有通知B,A回滚了代码、进行了开发并且推送了代码,那么远程仓库中将是更新的代码,但是B并不知情,也进行了代码推送,那么A进行的回滚又被推送回了代码库,这是分布式代码管理的优点也是缺点,所以推荐在本地开发中使用git reset指令进行回滚
如果使用git revert进行代码回滚,那么git会创建新的提交记录,假设A通过git resert撤销了commit,那么同时也会新建新的commit,当A进行代码推送后,代码库中代码进行了更新,同时B不回收到提示自己的commit领先于远程commit,那么B也可以通过推送代码的形式发布自己的改动,并且因为执行了revert操作,B重新推上去的本应该被撤销的代码也会被revert的commit撤销掉改动,同时可以保留历史代码
五、常用指令Option
-v #verbose
-q #quiet
-f #强制
-- #常用于分割命令和目标文件
六、Q&A