哥带你学git

git是一个很好理解的工具,托管代码,多人协作,版本控制

但是里面的设计不得不让人惊叹

目录

版本管理以及git工作方式

版本简介

版本回退方法:

然后解释Git工作方式

工作区(Working Directory)

版本库(Repository)

git为什么这么吊炸天的?因为Git跟踪并管理的是修改,而非文件。

git撤销修改(撤销的是工作区文件的修改)

删除文件

git关联远程仓库(早该说了)

分支管理

创建与合并分支

解决冲突

分支管理策略

BUG分支

Feature分支

多人协作


版本管理以及git工作方式

版本简介

版本,我们知道每次commit都会有一种类似于快照的机制,一旦你把文件改乱了,或者误删了文件,还可以从最近的一个commit恢复,然后继续工作,而不是把几个月的工作成果全部丢失。(git log [--pretty=oneline]查看commit历史)

不同于SVN,Git使用SHA1计算出来的一个非常大十六进制的数字表示版本号,这是Git是分布式的版本控制系统(SVN是集中式),如果像svn都使用1,2,3...,肯定会产生冲突

版本回退方法:


首先,Git必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,也就是最新的提交1094adb...(注意我的提交ID和你的肯定不一样),上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100。

$ git reset --hard HEAD^
HEAD is now at e475afc 提交描述

(不同于svn,git版本回退非常快,它使用指针指向当前版本,reset只是将指针移动到对应位置)

改为指向add distributed

git-head-move

如果后悔版本后退并且已经关掉窗口,可以使用git reflog查看命令历史,找到版本号,git reset --hart 版本号(版本号不用全部输入)

git防止各种智障行为

然后解释Git工作方式

工作区(Working Directory)

就是我们从服务器拉下来的项目根目录

版本库(Repository)

工作区有一个.git目录(默认是隐藏的),里面最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。(之前一直理解错了master)

因为我们拉取项目创建Git版本库时,Git自动为我们创建了唯一一个master分支,所以,现在,git commit就是往master分支上提交更改。

对于git add命令实际上就是把要提交的所有修改放到暂存区(Stage),然后,执行git commit就可以一次性把暂存区的所有修改提交到分支(当前分支(没有创建则是git自动为我们创建的master),同样我们可以切换分支)。

git为什么这么吊炸天的?因为Git跟踪并管理的是修改,而非文件。

比如有下面一种流程:

第一次修改工作区某个文件 -> git add -> 第二次修改 -> git commit

实际上,第二次修改并没有commit,就是因为git管理的修改(如果是文件,那么第二次也会提交成功)

当你用git add命令后,在工作区的第一次修改被放入暂存区,准备提交,但是,在工作区的第二次修改并没有放入暂存区,所以,git commit只负责把暂存区的修改提交了,也就是第一次的修改被提交了,第二次的修改不会被提交。(git diff HEAD -- 文件名命令可以查看工作区和版本库里面最新版本的区别)

这就是缓存区在git的地位

git撤销修改(撤销的是工作区文件的修改)

git checkout -- 文件名     //可以丢弃工作区的修改
//命令git checkout -- readme意思就是,把readme.txt文件在工作区的修改全部撤销,这里有两种情况:  //一种是readme自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
//一种是readme已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
//总之,就是让这个文件回到最近一次git commit或git add时的状态。

命令中"--"挺重要的,不要忘记带上它

删除文件

不同于我们平常在文件管理器或者使用rm命令删除文件

如果你在该git工作区中删除一个文件,就会造成工作区和.git文件夹版本库不一致问题,这时候你有两个选择:

一是确实要从版本库中删除该文件,那就用删掉命令git rm,并且不要忘记git commit

$git rm 文件名
$git commit -m "git删除文件演示"

这样,文件就从工作区和版本库里删除了

二是你手贱误删了,如果去电脑回收站恢复,好low!!! 这时候不要忘了Git跟踪管理的是修改,而不是文件.删除也是修改的一种,所以我们可以用刚才讲的撤销修改来恢复

$git checkout -- 文件名
你就会看到你上次add或commit的文件了

好吧,其实电脑回收站更好,因为它保证恢复的一定是你删除之前的内容,git不一定

git关联远程仓库(早该说了)

要关联一个远程库,使用命令git remote add origin git地址;

关联后,使用命令git push -u origin master第一次推送master分支的所有内容;

此后,每次本地提交后,只要有必要,就可以使用命令git push origin master推送最新修改;

分支管理

创建与合并分支

之前所说的所有操作我们都是在版本库中master分支上操作,因为这是我们创建本地仓库或者拉取项目时git自动为我们创建的.

同样,我们有时候需要创建另外一个分支,在不影响master分支情况下修改另一个分支,必要时合并

一开始的时候,master分支中的每一个文件是一条时间线,Git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点:

不同于SVN需要复制一份新的文件

当我们创建git新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上:

所以,Git创建一个分支很快,因为除了增加一个dev指针,改改HEAD的指向,工作区的文件都没有任何变化!

不过,从现在开始,对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变:

假如我们在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最简单的方法,就是直接把master指向dev的当前提交,就完成了合并:

所以Git合并分支也很快!就改改指针,工作区内容也不变!

合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支:

这种适合我们不能提交只完成一半的代码,也想让Git替我们管理 以及正式版和开发版分开开发

具体命令:

首先,我们创建dev分支,然后切换到dev分支:

$ git checkout -b dev
Switched to a new branch 'dev'

git checkout命令加上-b参数表示创建并切换,相当于以下两条命令:

$ git branch dev
$ git checkout dev
Switched to branch 'dev'

然后,用git branch命令查看当前分支:

$ git branch
* dev
  master

git branch命令会列出所有分支,当前分支前面会标一个*号。

然后,我们就可以在dev分支上正常提交了
...................
等我们在dev分支完成工作之后想切回master分支:
$ git checkout master
Switched to branch 'master'

切换回master分支后,查看刚才文件,刚才添加的内容不见了!因为那个提交是在dev分支上,而master分支此刻的提交点并没有变:

git-br-on-master

现在,我们把dev分支的工作成果合并到master分支上:

$ git merge dev
Updating d46f35e..b17d20e
Fast-forward
 readme.txt | 1 +
 1 file changed, 1 insertion(+)

Fast-forward表示快进合并,即直接将master指向dev

合并完成后,就可以放心地删除dev分支了:

$ git branch -d dev
Deleted branch dev (was b17d20e).

解决冲突

了解完分支之后,我们会发现一个问题,如果我们在修改dev分支同时,master也进行了修改,那合并的时候怎么办?

凉拌是不可能的

此时合并,git会提醒我们存在冲突,必须解决冲突才能提交,所以这时候工作区文件会用<<<<<<<=======>>>>>>>标记出不同分支的内容,并没有提交到.git文件夹版本库中

打开文件解决冲突之后,add,commit文件,其中过程如下:

.

分支管理策略

前面说Fast-forward表示快进合并,这种模式会让我们删除分支后丢失分支信息

强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。
我们只需要在merger时加上--no-ff即可

$git merger --no-ff -m "分支提交说明" 分支名
因为本次合并要创建一个新的commit,所以加上-m参数,把commit描述写进去。

本次合并之后时间线:

可以看出分支信息已保留,可随时用git log查看

团队使用git的正确姿势:

按照几个基本原则进行分支管理:

首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;

那在哪干活呢?干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;

你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。

就像这样

BUG分支

分支功能很强大,现在有个问题,我们正在dev分支上工作,这时候我们需要做另外创建一个分支来修改一个临时BUG,咋办?

Git还提供了一个stash功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作:

$ git stash
Saved working directory and index state WIP on dev: f52c633 add merge

这时git status发现工作空间是之前master,dev分支并未影响,这样我们就可以正常创建新的分支了


恢复现场:
修复完成后,切换到master分支,并完成合并,最后删除issue-101分支:
$git checkout master
$git merger --n-ff -m "普通合并描述"  issue-101

这时切换回dev分支:
$git checkout dev
使用git status查看工作区间也是干净的 使用下面命令恢复:
$git stash list        //查看stash列表
stash@{0}: WIP on dev: f52c633 add merge

$git stash apply       //恢复stash,但是不删除
$git stash drop        //删除stash
$git stash pop         //恢复stash并删除

你可以多次stash,恢复的时候,先用git stash list查看,然后恢复指定的stash,用命令:
$ git stash apply stash@{0}

Feature分支

如果一个分支不想要了,也不能合并污染原分支:

1,存起来,说不定以后就用到了

2,尝试$git branch -d 分支名,提示删除失败

$git branch -D 分支名              //强制删除

多人协作

先了解推送分支

$git push 远程分支名  本地分支名

如果远程仓库有分支(git remote查看远程仓库分支情况),正常情况下git clone 之后git branch之后只会看到master分支

此时我们需要

创建远程origindev分支到本地,这个命令创建本地dev分支:

$ git checkout -b dev origin/dev

多人协作的工作模式通常是这样:

  1. 首先,可以试图用git push origin <branch-name>推送自己的修改;

  2. 如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;

  3. 如果合并有冲突,则解决冲突,并在本地提交;

  4. 没有冲突或者解决掉冲突后,再用git push origin <branch-name>推送就能成功!

如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to <branch-name> origin/<branch-name>

参考地址:address

猜你喜欢

转载自blog.csdn.net/ailaojie/article/details/86221026