前记
git是大多数公司常用的代码管理工具,在实际的工作中我们会遇到一些git上的问题,会让我们不知所措,所以这次总结下,以下都是工作中常见的场景和问题,如果想了解其他的git方面的奇技淫巧可以查阅其他的文章,如有不对欢迎指出
使用
想要用git得话,你必须是在一个版本库里面,那么怎么样才可以有一个版本库了,有两种方法,首先介绍第一种
git clone 这个是克隆一个远程的库生成一个本地库,跟随着这个远程库一起生成得有.git文件,这个就是git得版本库,这里我们用一张图看一下版本库几个概念
- 工作区:工作区就是你克隆下来的代码目录那一块,是你新增,修改代码的地方
- 暂存区:暂存区在你的版本库里面,在你使用git add 的时候,git会把你工作区的修改,放到暂存区里面去
- 本地分支:当你使用git commit 得时候,这个命令是把暂存区的代码提交到本地分支上,注意是本地的分支 介绍了上面三分名词,前两个可以理解,我们看看第三个,本地的分支
git clone -b develop github.com/yizhengfeng… 克隆远程的某一个指定分支
本地分支
跟随着版本库一起被克隆下来得还有远程分支
红色的表示远程分支,那么绿色的master是什么了,他是跟踪远程仓库中活动分支的本地分支,是git自己创建的
创建版本库
上面说了用git clone 可以生成一个版本库,第二个方法是自己本地创建一个版本库,创建命令是 git init 这个命令就是初始化一个版本库,生成一个.git文件,此时版本库创建好了我们怎么把他推上远程分支了,假如我们的git客户端是github,你创建一个私有仓库就知道了,看下面得照片
第一步:git init 初始化版本库
第二步:git add . 把所有得更改放在暂存区
第三步:git remote add origin xxxxxx 和远程库关联
第四步:git push -u origin master 把本地得master 推到远程去,刚创建时候只有一个master分支,所以这个命令就是推送你得整个版本库
!! 如果第三步不小心关联错了,可以用下面命令取消关联
git remote remove origin
常用命令
上面主要介绍了git一些概念,现在主要讲一下git的常见命令以及场景
git status:查看工作区得状态
git add : 把工作区的修改放到暂存区里面去
git commit -m '':把暂存区里面的修改,提交到本地库的分支上去
git branch:查看当前分支是哪个
git checkout : 切换分支
git log : 查看commit得记录
场景1
git 中比较重要的一个命令就是回退 当你修改了代码,并且用git add . 之后发现更改的文件有问题,你想改回来,这个时候你可以直接去修改一次,然后在git add . 一次就行,但是如果你git add . 之后并且还git commit -m ''; 此时得工作区是干净得,你想撤回之前得操作怎么办,那么就用到了git reset --hard HEAD^
HEAD:当前检出记录的符号引用,默认指向最新得提交
HEAD^:^表示得是上一个,这个命令就是表示上一次得提交
HEAD~2:~可以让你指定数字,这个命令是指定回退几次
--hard:--hard 这个要注意,一旦你加了--hard得话,你能返回到上一次的提交,但是你工作区得修改全部没了。
场景2
git中还有一个比较重要得场景是代码回滚,就是突然出现了一个bug,但是不知道这个bug是哪次提交产生的,那么就可以用git checkout 123aa
git checkout 一般用来切换分支的,但是如果一旦在当前分支用这个命令,并且指定提交的hash值的话,就会让HEAD分离(默认HEAD是和当前分支指向同一个最新提交,所以当前分支总是有一个*号),一但HEAD分离,那么HEAD指向了其他的提交,此时你当前分支代码,就是HEAD指向得代码,利用这个特性我们就可以做到代码得回滚了
场景3
我们在实际应用git的操作中,用的最多的可能是代码合并,代码合并有两种一种是 git merge Bug,表示当前分支合并bug分支,这种合并方式的好处是bug分支和当前分支是独立的,能很好追踪提交的历史,但是会让代码线比较复杂,看下面一个图
第二种合并分支的方法是 git rebase。Rebase 实际上就是在bug分支上取出一系列的提交记录,“复制”它们,然后在master分支上逐个的放下去。 Rebase 的优势就是可以创造更线性的提交历史。如果只允许使用 Rebase 的话,代码库的提交历史将会变得异常清晰。 git rebase master 表示把当前分支提交内容移动到master分支上去
这里要注意一下,此时master分支不是新的,bugFix才是,和merge不同,此时你还要把master更新
git checkout master
git rebase bugFix
或者git rebase bugFix master
场景4
比如发版的时候我们有一个release分支,一个develop分支,我们在develop上面提交一个功能,但是产品临时说也想发出去,那我们怎么办,直接把develop代码复制过来么,我们可以有更简单得方法
git checkout release
git cherry-pick C4
这个命令就是把某一个分支得提交,复制一份放到当前分支,C4是某个提交得hash值,一般都是把其他得分支提交拿过来,记住只是把C4这次提交得内容拿过来
场景5
无论是回滚还是代码的撤销,我们都需要知道提交得hash值,所以会用到git log,有时候这样会有点复杂,因为都是hash,如果commit 信息写得不好,一时还不知道是哪个,此时我们就可以使用git tag 来打一个标签,用来设置某一个提交的id,快速切换到此次的提交
git tag -a 3.0.8 -m '3.0.8提交'
-a:增加标签
3.0.8:标签名,
-m:标签得描述信息
git tags 查看所有的标签
git push origin 推送一个本地得标签
git push origin --tags 推送本地所有得标签到远程
远程操作
现在说一下git里面远程的相关操作
git fetch
这个命令是把远程仓库的远程分支代码,拉到本地库的远程分支上,具体我们看看下面的图片
执行了git fetch之后,o/master更新了(这个是本地的远程分支),但是本地的master分支还没有更新,想要更新本地master 还需要执行git merge o/master
git pull
这个命令也是下拉代码,但是他会自动帮你合并本地的远程分支代码 git pull = git fetch + git merge o/master
git push
这个命令是把本地的修改,推送到远程库的对应的分支,这个命令也是值得说明的 这里主要说明git push参数相关的内容 git push 不带任何参数时的行为与 Git 的一个名为 push.default 的配置有关。它的默认值取决于你正使用的 Git 的版本,所以在推送之前最好检查一下这个配置。
git push说明1
我们在本地master分支推送,不加任何参数直接git push 是因为git知道本地master分支关联的远程仓库分支是哪个(下面有解释)
git push说明2
那要是不知道了,比如我自己本地创建一个分支修改了代码,直接git push 会怎么样,看下图
我创建了一个test分支,修改代码,直接git push 提交,他报如下的错,因为你没有指定关联,他不知道要push到远程的哪个分支上去,所以git在bash里面建议你带参数 git push origin source:target
source:表示本地分支
target:表示远程分支
因为你现在就在test 分支上面了,所以可以直接忽略source。
git push origin test 这句话的意思就是把本地的test分支,推送到远程库的test分支,但是远程库没有test,怎么办,他会帮你在远程库创建一个远程分支test进行关联,所以这也是创建远程分支的一种方法,(另一种方法是直接在git客户端如github创建,然后去关联,下面有讲解)
疑惑
为什么我在本地master分支直接git push,他会把代码推送到远程库的master分支了,难道就是因为master o/master 名字差不多么,真正原因如下
master 和 o/master 的关联关系就是由分支的“remote tracking”属性决定的。master 被设定为跟踪 o/master —— 这意味着为 master 分支指定了推送的目的地以及拉取后合并的目标。你可能想知道 master 分支上这个属性是怎么被设定的,你并没有用任何命令指定过这个属性呀!好吧, 当你克隆仓库的时候, Git 就自动帮你把这个属性设置好了。当你克隆时, Git 会为远程仓库中的每个分支在本地仓库中创建一个远程分支(比如 o/master)。然后再创建一个跟踪远程仓库中活动分支的本地分支,默认情况下这个本地分支会被命名为 master。
自己设置关联
上面的关联是git默认设置的,那么我们可以自己设置么,答案是可以的
git checkout -b develop origin/develop
这个命令就是创建一个本地develop分支,并且关联远程库的develop分支,那么这个分支就和远程的一样,这也是我们我们常见的拉取远程分支的方法,并且这是不会合并的
git branch -u origin/develop develop
这种方法也是创建一个develop分支,并且关联远程库的develop分支,同样是拉取远程分支的一种方式,并且不会合并
git fetch origin foo
同样的git fetch和git pull 也和上面的git push 一样,拥有参数,但是不同的是 git fetch origin target:source 参数意义反过来了,远程的在前面,本地的在后面,那么上面那句代码的意思是什么了看下图
他会把远程的foo分支代码,拉到本地的远程分支上, 假如本地没有远程仓库这个分支怎么办,同样的他也会在本地创建一个远程分支。
git fetch origin bar 他会创建一个本地远程分支o/bar,此时代码显示的还是master分支,但是你是可以切换到bar上面的 git checkout bar
虽然现在只有o/bar,没有bar分支,但是当你执行git checkout bar的时候,git看到了有o/bar分支,会自动帮你创建一个看的到的本地bar分支
如果你想一开始就能看得见,就得把两个参数一起写上去 git fetch origin bar:bar 这样就是创建bar分支
git pull origin target:source
git pull 和git fetch是一样的,但是有一个不同的是,他会帮你合并!合并!合并!
git pull origin develop:develop = git fetch origin develop:develop + git merge develop
他在本地创建一个develop, 并且会帮你把develop分支和当前分支合并,如果你是在master分支操作这个命令,那么那就会帮你把develop和master合并
注意
git pull origin develop = git fetch origin develop + git merge o/develop
当命令是一个参数的时候,是创建一个o/develop 但是相同的是还是会合并,所以网上说的无论是哪种拉取只要你用的是git pull 这个pull命令,都会帮你合并 所以拉取分支不合并的方法,除了上面两种外第三种是git fetch origin develop:develop 是fetch!!