常用命令

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严格来说不是指向提交,而是指向mastermaster才是指向提交的,所以,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. MUI---上传头像功能实现

    这里使用MUI上传头像的功能是结合VUE来做的,所以: changeFace:function(){ var IMAGE_UNSPECIFIED = "image/*"; //相册 ...

  2. Win10 下 RabbitMQ 的 安装 配置

    记录下本人在win10环境下安装RabbitMQ的步骤,以作备忘. 第一步:下载并安装erlang 原因:RabbitMQ服务端代码是使用并发式语言Erlang编写的,安装Rabbit MQ的前提是安 ...

  3. Codeforces Round #435 (Div. 2)

    A. Mahmoud and Ehab and the MEX 题目链接:http://codeforces.com/contest/862/problem/A 题目意思:现在一个数列中有n个数,每个 ...

  4. 解决windows系统的oracle数据库不能启动ora-00119和ora-00130的问题

    SQL>startup 报错ora-00119 ora-00130 出现上述错误应该是数据库的监听文件出了问题,修改listener.ora文件: # listener.ora Network ...

  5. mysql八:视图、触发器、事务、存储过程、函数

    一 视图 视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名],用户使用时只需使用[名称]即可获取结果集,可以将该结果集当做表来使用. 使用视图我们可以把查询过程中的 ...

  6. 25个站长必备的SEO优化工具

    搜索引擎抓取内容模拟器 可以模拟蜘蛛抓取指定网页,包括Text.Link.Keywords及Description信息等.http://www.webconfs.com/search-engine-s ...

  7. Chrome百度不显示中文字体

    chrome://flags/ 启用DirectWrite 关闭就可以了

  8. AspNetPager使用方法

    一.AspNetPager支持两种方式分页: 一种是PostBack方式分页, 一种是通过Url来实现分页以及Url重写功能 二.AspNetPager支持各种数据绑定控件GridView.DataG ...

  9. Service 的 onStartCommand(Intent, int, int) 返回值

    (1)START_NOT_STICKY If the system kills the service after onStartCommand() returns, do not recreate ...

  10. android(五)----使用WakeLock使Android应用程序保持后台唤醒

    在使用一些产品列如微信.QQ之类的,如果有新消息来时,手机屏幕即使在锁屏状态下也会亮起并提示声音,这时用户就知道有新消息来临了. 但是,一般情况下手机锁屏后,Android系统为了省电以及减少CPU消 ...