常用命令

git init : 初始化仓库
git add 文件名 :把文件添加到暂存区
git commit -m "操作记录" : 提交到仓库,设置相关操作的记录

git status : 查看git状态,用于查看做了哪些的操作

git diff 文件名 : 在提交之前查看文件到底修改了什么,方便我们确认修改内容是否使我们想要的

git log : 查看历史记录
git log --pretty=oneline : 查看历史记录,单行显示,一般我喜欢用户这个,很清爽

版本回退:在工作区中回退,没有在git上显示,且回退之后用git log查看,改版本之后的记录都没有了
git reset --hard HEAD^ : 回退到上一个版本,上上个版本就用^^
git reset --hard HEAD~100 : 回退到前100个版本

版本恢复:如果想要回退到最新的版本,或者现在版本的之后版本
git reflog : 查看所有操作的版本号
git reset --hard 版本号 :按照指定的版本号进行恢复,当然这个命令也可以进行回退使用,只要加上对应的版本号即可

git checkout -- 文件名 :撤销修改,恢复删除(都是在没有提交的情况下)
1.撤销文件的修改,在add之前
2.如果有内容在暂存区,我们这时候再修改文件,我们想要恢复到和暂存区内的内容一样,也可以用这个
3.恢复删除了的文件

远程仓库:

1.ssh-keygen -t rsa –C “youremail@example.com” 创建私钥密钥,在用户文件夹下的.ssh文件夹中
2.登录GitHub,settings-》SSH keys->add ssh keys->填写任意title->把.ssh/id_rsa.pub的内容复制到key里面-》add key
创建仓库:
new Repository
为空的仓库与本地仓库关联:(命令在创建之后都有)
git remote add origin https://github.com/xuming2860/testgit
git push -u origin master 第一次推送master分支时,加上了 –u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令

此时本地仓库中的所有东西就上传到了github中

git push origin master : 把本地master分支的最新修改推送到github上了

git clone https://github.com/xxxxx/testgit2 :把github项目克隆到本地仓库

分支:

git checkout -b 分支名 : 创建分支
git branch :查看当前所有分支。当前分支前面会添加一个星号
git checkout mater : 切换分支到master

在分支上做的操作一开始不会在主分支中显示,需要进行合并

git merge dev :在master分支上合并dev分支的内容,合并指定分支到当前分支上
git branch -d dev : 删除分支dev

注意:我们在分支上面提交了修改之后切换到主分支上,此时主分支对文件进行修改并提交。该操作结束后再进行合并分支的内容,那么就会出现冲突。我们在修改的文件中也可看到相关的内容(主分支修改的内容以及分支修改的内容)。这个时候就需要我们自己去决定去留。

通常合并分支时,git一般使用”Fast forward”模式,在这种模式下,删除分支后,会丢掉分支信息,我们可以使用带参数 –no-ff来禁用”Fast forward”模式
1.git checkout -b dev : 创建一个dev分支。
2.修改readme.txt内容。
3.git add '';git commit -m ''; 添加到暂存区。
4.git checkout master : 切换回主分支(master)。
5.git merge --no-ff -m “注释” dev : 合并dev分支 
6.git branch -d dev : 删除dev分支
7.git log --graph --pretty=oneline --abbrev=commit
大家可以对比没有加“--no-ff”之前的git log,可以看到被删除的分支信息还在。

多人协作:
git remote :查看远程库的信息
git remote -v :查看远程库的详细信息

git push origin master :把master分支推送到远程分支origin上

那么一般情况下,那些分支要推送呢?
1.master分支是主分支,因此要时刻与远程同步。
2.一些修复bug分支不需要推送到远程去,可以先合并到主分支上,然后把主分支master推送到远程去。

分支的理解(摘取廖雪峰教程)

在版本回退里,你已经知道,每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即master分支。HEAD严格来说不是指向提交,而是指向master,master才是指向提交的,所以,HEAD指向的就是当前分支。

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

每次提交,master分支都会向前移动一步,这样,随着你不断提交,master分支的线也越来越长:

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

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

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

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

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

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

分支策略

在实际开发中,我们应该按照几个基本原则进行分支管理:

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

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

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

所以,团队合作的分支看起来就像这样:

以上就是相关操作的介绍,关于标签管理和解决冲突等知识,可以到官网查看:

案例

首先我们有这样的需求:我们有一个应用程序,后续要对这个应用程序不断的开发,更新版本,并且不定期的打补丁。这些所有的记录我都想要记录下来,以便于版本的更新与回退。

  • 如果对这个操作不满意可以回退到之前的版本,
  • 如果回退错误了,我们需要恢复成原来的样子。

下面是我的想法已经方案:

我们用文件夹和txt文件模拟应用程序,版本,补丁:

目录结构:
testgit:
-- main-master.txt 一开始1.0的应用版本
-- main-v1.1 1.1版本
----- main-v1.1.txt
----- mendbug1.1.1 对应的补丁(当然实际不止1个补丁)
---------mendbug1.1.1.txt
-- main-v1.2 1.2版本
----- main-v1.2.txt
----- mendbug1.2.1 对应的补丁
---------mendbug1.1.1.txt
-- main-v1.3 1.3版本
----- main-v1.3.txt
----- mendbug1.3.1 对应的补丁
---------mendbug1.3.1.txt

创建过程:

1.初始化仓库创建main-master.txt应用版本

git init,添加文件,git add main-test.txt,git commit -m "第一次main版本"

2.创建分支dev模拟版本更新

  • 创建分支:git checkout -b dev,
  • 创建main-v1.1文件和txt文件,
  • git add main-v1.1,
  • git commit -m "1.1版本的发布"
  • 切换到master分支:git checkout master
  • 合并dev的版本到master:git merge dev
  • 查看日志记录:git status --pretty=oneline

按照上面步骤创建1.2版本和1.3版本

3.提交到git上:

  • 在git上创建一个仓库create new repository
  • 在客户端运行git上给你的命令关联本地仓库:git remote add origin https://github.com/xxxx/testgit
  • 把本地仓库中的master分支上的东西都上传到git上:git push -u origin master

这个时候我们查看git上面就有了我们的所有文件和log:

4.创建patch分支,用于打补丁:

  • 创建分支:git checkout -b patch
  • 创建mendbug1.1.1文件夹和txt文件
  • git add mendbug1.1.1
  • git commit -m "添加补丁mengbug1.2.1"
  • 切换会dev分支:git checkout dev
  • 合并patch内容:git merge patch
  • 切换到master分支:git checkout master
  • 合并dev内容:git merge devd

重复上述步骤创建1.2.1和1.3.1版本的补丁

5.把master的内容上传到git上:

git push origin master

提交的记录和所有文件就都在git上面了。

这里要说一句,其实应该开发一个版本之后开发对应版本的补丁,我这里的执行的顺序有问题。但是该有的记录是已经有了。下面就可以根据对应操作的版本号进行版本的回退和恢复:

需求一:我们现在提交了1.3版本,但是感觉不好,想要回到1.2版本:

1.git reset --hard 865c72

这时候我们可以看一下我们的目录文件夹:

原来的main-v1.3已经没有了,我们回退到1.2版本

我们通过log看到在发布1.2版本之后之前的所有的东西都没有了。

2.提交到git上面

我们如果使用正常的命令:git push origin master,会出错:

说远端做了更改需要先pull一下, 如果pull那就又回到最新版本了,相当于没回退。 
a.思路1:我们可以新建一个分支temp,然后把回退后的代码提交到temp分支上暂存,然后删除master主分支,新建一个master分支,提交现有代码到master上。

/*1.新建分支*/
git checkout -b temp //新建分支并切换到temp分支
git push origin temp :temp //将代码push到temp分支
/*2.删除主分支*/
git push origin --delete master //删除远端主分支
git branch -d master //删除本地主分支
/*3.新建主分支*/
git checkout -b master //新建主分支并切换到主分支
git push origin master //提交主分支
/*4.删除暂存分支*/
git branch -d temp
git push origin --delete temp

注意:在github下,操作(删除或重建分支)需要在github网页上切换当前分支,如你要删除master,就要将分支切换到建的temp分支上。(可以理解为自己不能删除自己)

b.思路2:或者还有一种方法,就是强制提交:

git push -f origin master

这样git上面也就和我们仓库一样

需求二:我们想要恢复之前的样子,我们后悔了:

1.查找到最后操作的commit id:git reflog

我们可以看到我们每个操作的版本号,按照版本号恢复就可以了。这里我们恢复到第三个补丁打过之后:

方法一:$ git reset --hard HEAD^回退到上一个操作之前

方法二:$ git reset --hard 版本号

这个时候我们可以看到v1.3又回来了。

2.上传到git上:因为这个是回退仓库中没有的,所以不需要强制:

git push origin master

谢天谢地,熟悉的赶脚又回来了。大功告成。

此时我们可以注意到一个问题,我们每个操作的版本号是不是固定的,及时删除了我们的版本号也不会重新赋值改变,一开始是481b91,之后还是。所以我们可以把这个存储下来,然后恢复的时候直接拿这个数据就可以了

好了,我们的需求是实现了,但是在版本回退的时候其实还是有东西要注意的:

我们已经能够回滚远程分支的版本了,那么你也许会问了,回滚公共远程分支和回滚自己的远程分支有区别吗? 答案是,当然有区别啦。

如果你回退公共远程分支,把别人的提交给丢掉了怎么办?

假如你的远程master分支情况是这样的:A1–A2–B1

其中A、B分别代表两个人,A1、A2、B1代表各自的提交。并且所有人的本地分支都已经更新到最新版本,和远程分支一致。

这个时候你发现A2这次提交有错误,你用reset回滚远程分支master到A1,那么理想状态是你的队友一拉代码git pull,他们的master分支也回滚了,然而现实却是,你的队友会看到下面的提示:

$ git status
On branch master
Your branch is ahead of 'origin/master' by 2 commits.
(use "git push" to publish your local commits)
nothing to commit, working directory clean

也就是说,你的队友的分支并没有主动回退,而是比远程分支超前了两次提交,因为远程分支回退了嘛。

(1) 这个时候,你大吼一声:兄弟们,老子回退版本了。如果你的队友都是神之队友,比如: Tony(腾讯CTO),那么Tony会冷静的使用下面的命令来找出你回退版本后覆盖掉的他的提交,也就是B1那次提交:

git reflog

然后冷静的把自己的分支回退到那次提交,并且拉个分支:

git checkout tony_branch        //先回到自己的分支
git reflog //接着看看当前的commit id,例如:0bbbbb
git reset --hard B1 //回到被覆盖的那次提交B1
git checkout -b tony_backup //拉个分支,用于保存之前因为回退版本被覆盖掉的提交B1
git checkout tony_branch //拉完分支,迅速回到自己分支
git reset --hard 0bbbbbb //马上回到自己分支的最前端

通过上面一通敲,Tony暂时舒了一口气,还好,B1那次提交找回来了,这时tony_backup分支最新的一次提交就是B1,接着Tony要把自己的本地master分支和远程master分支保持一致:

git reset --hard origin/master

执行了上面这条命令后,Tony的master分支才真正的回滚了,也就是说你的回滚操作才能对Tony生效,这个时候Tony的本地maser是这样的:A1

接着Tony要再次合并那个被丢掉的B1提交:

git checkout master             //切换到master
git merge tony_backup //再合并一次带有B1的分支到master

好了,Tony终于长舒一口气,这个时候他的master分支是下面这样的:A1 – B1

终于把丢掉的B1给找回来了,接着他push一下,你一拉也能同步。

同理对于所有队友也要这样做,但是如果该队友没有提交被你丢掉,那么他拉完代码git pull之后,只需要强制用远程master覆盖掉本地master就可以了:

git reset --hard origin/master

(2) 然而很不幸的是,现实中,我们经常遇到的都是猪一样的队友,他们一看到下面提示:

$ git status
On branch master
Your branch is ahead of 'origin/master' by 2 commits.
(use "git push" to publish your local commits)
nothing to commit, working directory clean

就习惯性的git push一下,或者他们直接用的SourceTree这样的图形界面工具,一看到界面上显示的是推送的提示就直接点了推送按钮,卧&槽,你辛辛苦苦回滚的版本就这样轻松的被你猪一样的队友给还原了,所以,只要有一个队友push之后,远程master又变成了:A1 – A2 – B1

这就是分布式,每个人都有副本。这个时候你连揍他的心都有了,怎么办呢?你不能指望每个人队友都是git高手,下面我们用另外一种方法来回退版本。

公共远程分支版本回退的方法

使用git reset回退公共远程分支的版本后,需要其他所有人手动用远程master分支覆盖本地master分支,显然,这不是优雅的回退方法,下面我们使用另个一个命令来回退版本:

git revert HEAD                     //撤销最近一次提交
git revert HEAD~1 //撤销上上次的提交,注意:数字从0开始
git revert 0ffaacc //撤销0ffaacc这次提交

git revert 命令意思是撤销某次提交。它会产生一个新的提交,虽然代码回退了,但是版本依然是向前的,所以,当你用revert回退之后,所有人pull之后,他们的代码也自动的回退了。 
但是,要注意以下几点:

  1. revert 是撤销一次提交,所以后面的commit id是你需要回滚到的版本的前一次提交
  2. 使用revert HEAD是撤销最近的一次提交,如果你最近一次提交是用revert命令产生的,那么你再执行一次,就相当于撤销了上次的撤销操作,换句话说,你连续执行两次revert HEAD命令,就跟没执行是一样的
  3. 使用revert HEAD~1 表示撤销最近2次提交,这个数字是从0开始的,如果你之前撤销过产生了commi id,那么也会计算在内的。
  4. 如果使用 revert 撤销的不是最近一次提交,那么一定会有代码冲突,需要你合并代码,合并代码只需要把当前的代码全部去掉,保留之前版本的代码就可以了.

git revert 命令的好处就是不会丢掉别人的提交,即使你撤销后覆盖了别人的提交,他更新代码后,可以在本地用 reset 向前回滚,找到自己的代码,然后拉一下分支,再回来合并上去就可以找回被你覆盖的提交了。

revert 合并代码,解决冲突

使用revert命令,如果不是撤销的最近一次提交,那么一定会有冲突,如下所示:

<<<<<<< HEAD
全部清空
第一次提交
=======
全部清空
>>>>>>> parent of c24cde7... 全部清空

解决冲突很简单,因为我们只想回到某次提交,因此需要把当前最新的代码去掉即可,也就是HEAD标记的代码:

<<<<<<< HEAD
全部清空
第一次提交
=======

把上面部分代码去掉就可以了,然后再提交一次代码就可以解决冲突了。

简单粗暴的回滚方法

如果你们开发中,忽然发现前面很远的地方有一次错误的合并代码,把本来下一次才能发的功能的代码合并到了这一次来了,这个时候全体成员都觉得直接回滚比较快,因为他们都有备份,覆盖了无所谓,这个时候用reset的话对队友的要求比较高,用revert的话呢要大面积的解决冲突,也很麻烦呀,怎么办呢?

这个时候,可以使用简单粗暴的办法,直接从那个错误的提交的前一次拉取一份代码放到其他目录,然后将master代码全部删除,把那份新代码方进去,然后提交。

总结

远程分支回滚的三种方法:

  1. 自己的分支回滚直接用reset
  2. 公共分支回滚用revert
  3. 错的太远了直接将代码全部删掉,用正确代码替代

基于GIT的管理的更多相关文章

  1. 基于git的管理应用程序基线包和版本

    由于工作的需要,身为git的小白的我开始研究git相关的命令和操作.结合网上收集和廖雪峰的git教程,记录所学知识点. 相关的效果就不再这里显示了. 首先我们看一下git的常用命令: 常用命令 git ...

  2. 基于git的源代码管理模型——git flow

    基于git的源代码管理模型--git flow A successful Git branching model

  3. 基于Git的数据库sql文件的管理——完美解决团队sql操作协同问题

    目录 基于Git的数据库sql文件的管理--完美解决团队sql操作协同问题 1.产生背景 2.之前没用Git管理数据库出现的问题 2.1 用同一个库调试带来的问题 3.解决方案 3.1 Sql文件的创 ...

  4. Pull Request的过程、基于git做的协同开发、git常见的一些命令、git实现代码的review、git实现版本的管理、gitlab、GitHub上为开源项目贡献代码

    前言: Pull Request的流程 1.fork 首先是找到自己想要pull request的项目, 然后点击fork按钮,此时就会在你的仓库中多出来一个仓库,格式是:自己的账户名/想要pull ...

  5. 利用cocoapods创建基于git的私有库

    上一篇文章记录了我利用cocoapods创建基于SVN的私有库的全部过程,今天我再记录一下基于git创建的过程. 整体先说明一下创建一个私有的podspec包括如下那么几个步骤: 创建并设置一个私有的 ...

  6. 基于git的代码版本管理规范及流程-简版

    基于git的简单实用的版本管理规范及流程,包括:代码库的分布.人员角色的划分.代码提交合并流程.代码冲突处理.分支管理. 代码库分类 根据代码库分布的位置及作用,分为以下几类: 主库:位于服务端,所有 ...

  7. 好代码是管出来的——使用Git来管理源代码

    软件开发过程中一个重要的产出就是代码,软件的编码过程一般是由一个团队共同完成,它是一个并行活动,为了保证代码在多人开发中能够顺利完成,我们需要使用代码版本控制工具来对代码进行统一存储,并追踪每一份代码 ...

  8. 基于Git项目管理客户端SourceTree的免注册安装及远程连接方法

    作为程序员,不可避免的要在github上查询代码,而在企业项目中,为了使得项目好管理需要使用项目管理客户端,所以接下来详细讲解一下基于git的sourceTree在windows系统下的安装及与Git ...

  9. 利用cocoapods创建基于git的私有库Spec Repo

    上一篇文章记录了我利用cocoapods创建基于SVN的私有库的全部过程,今天我再记录一下基于git创建的过程. 整体先说明一下创建一个私有的podspec包括如下那么几个步骤: 创建并设置一个私有的 ...

随机推荐

  1. vue---结合elementui做异步数据分页

    使用vue+elementui来请求数据做分页: <el-col :span="24" class="toolbar pageBar"> <e ...

  2. poj3261 Milk Patterns【后缀数组】【二分】

    Farmer John has noticed that the quality of milk given by his cows varies from day to day. On furthe ...

  3. 推荐系统之余弦相似度的Spark实现

    推荐系统之余弦相似度的Spark实现 (1)原理分析    余弦相似度度量是相似度度量中最常用的度量关系,从程序分析中, 第一步是数据的输入, 其次是使用相似性度量公式 最后是对不同用户的递归计算. ...

  4. 1.4激活函数-带隐层的神经网络tf实战

    激活函数 激活函数----日常不能用线性方程所概括的东西 左图是线性方程,右图是非线性方程 当男生增加到一定程度的时候,喜欢女生的数量不可能无限制增加,更加趋于平稳 在线性基础上套了一个激活函数,使得 ...

  5. codeforces 892 - A/B/C

    题目链接:https://cn.vjudge.net/problem/CodeForces-892A Jafar has n cans of cola. Each can is described b ...

  6. RFQ 、IFB、RFP 、RFI的区别是什么

    询价类型 信息索取书 RFI 报价申请书 RFQ 建议要求书 RFP 投标邀请书 IFB 目的 获得与产品服务供应商相关信息 取得供应商对所需产品.服务或服务的承诺 要求供应商对需求提出最好解决方案建 ...

  7. 软件工程-wordcount(C语言实现)

    Github项目地址:https://github.com/xiaobaot/wordcount-wc/tree/master WC 项目要求 wc.exe 是一个常见的工具,它能统计文本文件的字符数 ...

  8. Python开发【算法】:斐波那契数列两种时间复杂度

    斐波那契数列 概述: 斐波那契数列,又称黄金分割数列,指的是这样一个数列:0.1.1.2.3.5.8.13.21.34.……在数学上,斐波纳契数列以如下被以递归的方法定义:F(0)=0,F(1)=1, ...

  9. (转)Spring实现IoC的多种方式

    原文地址:http://www.cnblogs.com/best/p/5727935.html 目录 一.使用XML配置的方式实现IOC 二.使用Spring注解配置IOC 三.自动装配 四.零配置实 ...

  10. 启动InnoDB引擎的方法

    启动InnoDB引擎的方法 http://down.chinaz.com/server/201207/2090_1.htm 启动InnoDB引擎的方法 Mysql中默认的是MyISAM数据引擎,可惜此 ...