git的一些疑难点

一 、git reset,git revert,git checkout的区别和联系

主要参考:http://www.cnblogs.com/houpeiyong/p/5890748.html

git resetgit checkoutgit revert是你的Git工具箱中最有用的一些命令。它们都用来撤销代码仓库中的某些更改,而前两个命令不仅可以作用于提交,还可以作用于特定文件。

因为它们非常相似,所以我们经常会搞混,不知道什么场景下该用哪个命令。在这篇文章中,我们会比较git resetgit checkoutgit revert最常见的用法。希望你在看完后能游刃有余地使用这些命令来管理你的仓库。

Git仓库有三个主要组成——工作目录,缓存区和提交历史。

提交层面的操作

你传给git resetgit checkout的参数决定了它们的作用域。如果你没有包含文件路径,这些操作对所有提交生效。我们这一节要探讨的就是提交层面的操作。注意,git revert没有文件层面的操作。

Reset

在提交层面上,reset将一个分支的末端指向另一个提交。这可以用来移除当前分支的一些提交。比如,下面这两条命令让hotfix分支向后回退了两个提交。

git checkout hotfix
git reset HEAD~2

hotfix分支末端的两个提交现在变成了悬挂提交。也就是说,下次Git执行垃圾回收的时候,这两个提交会被删除。换句话说,如果你想扔掉这两个提交,你可以这么做。

如果你的更改还没有共享给别人,git reset是撤销这些更改的简单方法。当你开发一个功能的时候发现『糟糕,我做了什么?我应该重新来过!』时,reset就像是go-to命令一样。

除了在当前分支上操作,你还可以通过传入这些标记来修改你的缓存区或工作目录:

  • --soft – 缓存区和工作目录都不会被改变
  • --mixed – 默认选项。缓存区和你指定的提交同步,但工作目录不受影响
  • --hard – 缓存区和工作目录都同步到你指定的提交

把这些标记想成定义git reset操作的作用域就容易理解多了。

这些标记往往和HEAD作为参数一起使用。比如,git reset --mixed HEAD 将你当前的改动从缓存区中移除,但是这些改动还留在工作目录中。另一方面,如果你想完全舍弃你没有提交的改动,你可以使用git reset --hard HEAD。这是git reset最常用的两种用法。

当你传入HEAD以外的其他提交的时候要格外小心,因为reset操作会重写当前分支的历史。正如Rebase黄金法则所说的,在公共分支上这样做可能会引起严重的后果。

Checkout

你应该已经非常熟悉提交层面的git checkout。当传入分支名时,可以切换到那个分支。

git checkout hotfix

上面这个命令做的不过是将HEAD移到一个新的分支,然后更新工作目录。因为这可能会覆盖本地的修改,Git强制你提交或者缓存工作目录中的所有更改,不然在checkout的时候这些更改都会丢失。和git reset不一样的是,git checkout没有移动这些分支。

除了分支之外,你还可以传入提交的引用来checkout到任意的提交。这和checkout到另一个分支是完全一样的:把HEAD移动到特定的提交。比如,下面这个命令会checkout到当前提交的祖父提交。

git checkout HEAD~2

这对于快速查看项目旧版本来说非常有用。但如果你当前的HEAD没有任何分支引用,那么这会造成HEAD分离。这是非常危险的,如果你接着添加新的提交,然后切换到别的分支之后就没办法回到之前添加的这些提交。因此,在为分离的HEAD添加新的提交的时候你应该创建一个新的分支。

Revert

Revert撤销一个提交的同时会创建一个新的提交。这是一个安全的方法,因为它不会重写提交历史。比如,下面的命令会找出倒数第二个提交,然后创建一个新的提交来撤销这些更改,然后把这个提交加入项目中。

git checkout hotfix
git revert HEAD~2

相比git reset,它不会改变现在的提交历史。因此,git revert可以用在公共分支上,git reset应该用在私有分支上。

你也可以把git revert当作撤销已经提交的更改,而git reset HEAD用来撤销没有提交的更改。

就像git checkout 一样,git revert 也有可能会重写文件。所以,Git会在你执行revert之前要求你提交或者缓存你工作目录中的更改。

文件层面的操作

git resetgit checkout 命令也接受文件路径作为参数。这时它的行为就大为不同了。它不会作用于整份提交,参数将它限制于特定文件。

Reset

当检测到文件路径时,git reset 将缓存区同步到你指定的那个提交。比如,下面这个命令会将倒数第二个提交中的foo.py加入到缓存区中,供下一个提交使用。

git reset HEAD~2 foo.py

和提交层面的git reset一样,通常我们使用HEAD而不是某个特定的提交。运行git reset HEAD foo.py 会将当前的foo.py从缓存区中移除出去,而不会影响工作目录中对foo.py的更改。

--soft、--mixed和--hard对文件层面的git reset毫无作用,因为缓存区中的文件一定会变化,而工作目录中的文件一定不变。

Checkout

Checkout一个文件和带文件路径git reset 非常像,除了它更改的是工作目录而不是缓存区。不像提交层面的checkout命令,它不会移动HEAD引用,也就是你不会切换到别的分支上去。

比如,下面这个命令将工作目录中的foo.py同步到了倒数第二个提交中的foo.py。

git checkout HEAD~2 foo.py

和提交层面相同的是,它可以用来检查项目的旧版本,但作用域被限制到了特定文件。

如果你缓存并且提交了checkout的文件,它具备将某个文件回撤到之前版本的效果。注意它撤销了这个文件后面所有的更改,而git revert 命令只撤销某个特定提交的更改。

git reset 一样,这个命令通常和HEAD一起使用。比如git checkout HEAD foo.py等同于舍弃foo.py没有缓存的更改。这个行为和git reset HEAD --hard很像,但只影响特定文件。

总结

你现在已经掌握了Git仓库中撤销更改的所有工具。git resetgit checkout、和 git revert命令比较容易混淆,但当你想起它们对工作目录、缓存区和提交历史的不同影响,就会容易判断现在应该用哪个命令。

下面这个表格总结了这些命令最常用的使用场景。记得经常对照这个表格,因为你使用Git时一定会经常用到。

命令 作用域 常用情景
git reset 提交层面 在私有分支上舍弃一些没有提交的更改
git reset 文件层面 将文件从缓存区中移除
git checkout 提交层面 切换分支或查看旧版本
git checkout 文件层面 舍弃工作目录中的更改
git revert 提交层面 在公共分支上回滚更改
git revert 文件层面 (然而并没有)

二、git reset --hard.--soft,--mixed三种模式的区别

其中,git reset --hard表示head和当前分支指针都指向之前某个提交,工作区,暂存区,仓库全部更新,  git status干净,常用于私有分支上的回滚(公有分支使用git revert,因为保留历史版本)

git reset --soft 表示head和当前分支指针都指向之前某个提交,只有提交的仓库发生改变,工作区和暂存区保留不变,git status显示暂存区会存在一个文件,在文件为reset之前的数据到当前commit的变化,以供下次提交,

可以利用此特点,删除两个提交之前的其他提交节点,有利于做patch。

git reset --mixed, 表示head和当前分支指针都指向之前某个提交,只有当前工作区不变,git status显示有未提交的文件。

主要参考:http://www.iteye.com/topic/1134995

三、git打补丁patch

1使用git format-patch生成所需要的patch:
当前分支所有超前master的提交:
git format-patch -M master
某次提交以后的所有patch:
git format-patch 4e16                --4e16指的是commit名
从根到指定提交的所有patch:
git format-patch                          --root 4e16
某两次提交之间的所有patch:
git format-patch 365a..4e16      --365a和4e16分别对应两次提交的名称
某次提交(含)之前的几次提交:
git format-patch –n 07fe             --n指patch数,07fe对应提交的名称
故,单次提交即为:
git format-patch -1 07fe
git format-patch生成的补丁文件默认从1开始顺序编号,并使用对应提交信息中的第一行作为文件名。如果使用了-- numbered-files选项,则文件名只有编号,不包含提交信息;如果指定了--stdout选项,可指定输出位置,如当所有patch输出到一个文件;可指定-o <dir>指定patch的存放目录;

2应用patch:
先检查patch文件:git apply --stat newpatch.patch
检查能否应用成功:git apply --check  newpatch.patch
打补丁:git am --signoff < newpatch.patch

(使用-s或--signoff选项,可以commit信息中加入Signed-off-by信息)

如果应用patch出现问题:参考git am PATCH 失败的处理方法http://blog.csdn.net/sunnylgz/article/details/7660638

参考:http://blog.csdn.net/sunnylgz/article/details/7661920

四、修改上次提交

1 git commit --amend

合并缓存区中的修改和最近的一次commitj,然后用生成的新的commit替换掉原来老的,如果缓存区没有内容,那么利用amend可以修改上一次commit的描述。

开发过程中很容易忘记stage某个文件或填写了不够准确的commit描述. --amend就是用来fix这些错误的.

不要对一个公共的commit使用amend

amend后生成的commit是一个全新的commit, 之前的老的commit会从项目历史中被删除. 如果你amend了一个被其他开发者使用的commit, 会严重影响其他开发者.

2 git commit --amend -m "xxx" 暂存区中没有要合并的文件时候,就是修改commmit描述

参考:http://www.cnblogs.com/irocker/p/git-commit--amend.html

五、cherry-pick , merge,rebase

cherry-pick:用于把其他本地分支的一个或者几个commit修改应用到当前分支。

主要用法看这个例子:http://blog.csdn.net/carolzhang8406/article/details/49761665

http://sg552.iteye.com/blog/1300713

				
时间: 2024-10-18 08:38:48

git的一些疑难点的相关文章

JS疑难点和GC原理

1. JS中的typeof是一元操作符,不是函数 在chrome的Console控制台上,输入typeof null,它会输出"object".因此,使用typeof操作符的时候,除了null,都会识别出其他数据的类型. 2. JS中的instanceof来区分Object下的Array.Json.RegEx.Date.Function.Error.Math instanceof对于非对象,返回false instanceof对于原型链上的对象,返回原型链对象 3. Object转St

常见的几个js疑难点,match,charAt,charCodeAt,map,search

        JavaScript match() 方法 定义和用法 match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配. 该方法类似 indexOf() 和 lastIndexOf(),但是它返回指定的值,而不是字符串的位置. 语法 //匹配字符串,返回指定的值 stringObject.match(searchvalue) //匹配正则,返回指定的值 stringObject.match(regexp) 使用 match() 来检索一个字符串例子: <html>

说说常见的几个js疑难点

JavaScript match() 方法 定义和用法 match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配. 该方法类似 indexOf() 和 lastIndexOf(),但是它返回指定的值,而不是字符串的位置. 语法 //匹配字符串,返回指定的值 stringObject.match(searchvalue) //匹配正则,返回指定的值 stringObject.match(regexp) 使用 match() 来检索一个字符串例子: <html> <bo

finereport---FineReport入门常见疑难点

一.入门介绍 二.入门需知 注意:开发人员可以设置DEBUG级别,有助于测试 原文地址:https://www.cnblogs.com/michellexiaoqi/p/8886205.html

小甲鱼python疑难点

1.python生成器 2.while 1: num = input('请输入一个整数(输入Q结束程序):') if num != 'Q': num = int(num) print('十进制 -> 十六进制 : %d -> 0x%x' % (num, num)) print('十进制 -> 八进制 : %d -> 0o%o' % (num, num)) print('十进制 -> 二进制 : %d -> ' % num, bin(num)) else: break 十

2018高企通过率仅36.59%!申报高新企业认定有哪些难点?

2018年广东省工程中心公示!几家欢乐几家愁,全省(含深圳)一共申报3105家企业,通过1136家,通过率仅有36.59%.这也是"高新质量年"必然的结果.为此,赛凡科技为你抽丝剖茧其中的原因,帮助即将申报的企业提升高新通过率. 企业申报高新有哪些难点?高新技术企业认定是含金量较高的资质,企业取得该资质后,对于吸引风投资金.申请银行贷款.参与政府招投标.及申请政府专项资金均有很好的加分作用,最重要的是可以享受一系列税收优惠政策.高新技术企业认定申报存在一定难度,2018年申报工作即将到

2018年高企认定通过率仅36.59%!申报高新企业认定有哪些难点?

企业申报高新有哪些难点?高新技术企业认定是含金量较高的资质,企业取得该资质后,对于吸引风投资金.申请银行贷款.参与政府招投标.及申请政府专项资金均有很好的加分作用,最重要的是可以享受一系列税收优惠政策.高新技术企业认定申报存在一定难度,2018年申报工作即将到来,小编整理了部分在辅导中发现的申报疑难点,帮助各位少走弯路:1.自主知识产权数量太少专利数量很重要,申报时知识产权要着重"数量布局 质量取胜"!如果仅仅一两项发明专利,是不足以在高企认定中获得评审专家的认可的.小编建议企业提前做

转载maven安装,配置,入门

转载:http://www.cnblogs.com/dcba1112/archive/2011/05/01/2033805.html 本书代码下载 大家可以从我的网站下载本书的代码:http://www.juvenxu.com/mvn-in-action/,也可以通过我的网站与我取得联系,欢迎大家与我交流任何关于本书的问题和关于Maven的问题. 咖啡与工具 本书相当一部分的内容是在苏州十全街边的Solo咖啡馆完成的,老板Yin亲手烘焙咖啡豆.并能做出据说是苏州最好的咖啡,这小桥流水畔的温馨小

Maven的安装、配置及使用入门

本书代码下载 大家可以从我的网站下载本书的代码:http://www.juvenxu.com/mvn-in-action/,也可以通过我的网站与我取得联系,欢迎大家与我交流任何关于本书的问题和关于Maven的问题. 咖啡与工具 本书相当一部分的内容是在苏州十全街边的Solo咖啡馆完成的,老板Yin亲手烘焙咖啡豆.并能做出据说是苏州最好的咖啡,这小桥流水畔的温馨小 屋能够帮我消除紧张和焦虑,和Yin有一句没一句的聊天也是相当的轻松.Yin还教会了我如何自己研磨咖啡豆.手冲滴率咖啡,让我能够每天在家