一步步说明git

996 阅读11分钟

前记

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!!