当前位置: 首页 > news >正文

盘点那些不知名却常用的 Git 操作

Git 非常复杂。我即使几乎每天都在用,也不敢保证对 Git 的每一个角落都了如指掌。
本文试图盘点一些不知名,但在我看来较常用的操作。如果没有你预期的操作,说明要么在我看来它很知名,要么在我看来它不太常用。

  • git log --graph --abbrev-commit --decorate --all --oneline

  • git cherry

  • git show ref:path

  • git reset [--hard|--soft|--keep]

  • git update-index --assume-unchanged

git log --graph --abbrev-commit --decorate --all --oneline

如果要看项目中的分支情况,通常的做法是打开一个 Git GUI 软件,通过 GUI 界面来查看全景。
对于有些人来说,这是装 GUI 的唯一需求。
其实这个需求可以砍掉,因为 Git 提供了在终端中输出提交记录全景的操作:

git log --graph --abbrev-commit --decorate --all --oneline

输出结果相当惊艳,你可以像看 GUI 界面一样,在终端中查看不同分支的提交信息。
git-log.png
(这里采用了一个开源项目的提交历史来示例,如果是公司的商业项目,输出会更炫目)

这个输出跟 man xxx 一样,会通过 $PAGER(通常是 less) 显示在终端上。这意味着你可以在输出中搜索特定的提交或 tag。
许多 GUI 界面并不提供这一功能,导致用户只能瞪大眼睛,一点点地挪动,才能揪出特定的提交。
就这一点上,终端版的功能要比 GUI 版本胜出许多。
终端版的另一个优点是,提供了自由组合各种选项的能力。你可以自定义输出信息和显示的提交范围。
如果嫌命令太长,可以给它一个 alias(通过 git alias 或 shell 的 alias 功能)。

git cherry

有一个常用的 Git 操作是 git cherry-pickgit cherry 顾名思义,自然跟 cherry-pick 有关。
git cherry 可以比较两个分支,筛选出存在于甲分支却不存在于乙分支的提交。显而易见,这是在为后面的 cherry-pick 做准备。

 ¥ git cherry 4.2.0 | tail
+ bb5f4b02340b3c269d7a8e11842d4a16b2b8eba1
+ 2451c0c202dd48bc610ef9731c503ea54f19af83
+ 64b4a599e8af4b31444f2a86559d4860401925f4
+ c80b4e773f746ffe11aca9010b4433f6b6ba13ad
+ b2c7de9a5a5c8ea0254001a07ae24ffc27118dbb
+ 719dd2c3af9ba801114101ccdec1cd9e2f1bbc5d
+ 518db6e648aaf646db4be3067a583bdcc37ee2a8
+ b01359efc5761a17cd3b893fd51219a005009641
+ 422c9a8e69acc5cf013340715f8d2fa7d7cabf75
+ cc0dff2f49cfbd786eca498fe2532de0455e1759

美中不足的是,git cherry 的输出是 sha1,对机器来说友好,对人来说就是天书。如果要看具体的提交信息,需要借其他命令之力。比如 git show

git show --no-patch --format='%s' cc0dff2f49cfbd786eca498fe2532de0455e1759

git show ref:path

git show 是我最喜欢的命令之一。输出提交的内容,是 git show 的拿手好戏之一。举个例子,git show @ 可以显示当前分支上最新提交。(@HEAD
的别名,能少敲三个字符呢)

不过这不算 git show 的杀手锏。git show 的绝活,是能在不检出特定提交的前提下,显示特定提交的某个文件的内容。
假设我们想看看 xxx 提交上的 db.lua,纯粹只想看一看,不涉及调试或其他复杂的操作。我们当然可以 git checkout xxx,然后想看啥就看啥。然而用 git show 的话,就能保持当前分支不变,直接显示 xxx 提交上的 db.lua 了:

git show xxx:path/to/db.lua

编辑器的 Git 插件一般支持在编辑器内直接打开 git show 的输出。如果你用的是 Vim,又装了 fugitive,
通过敲 :Gedit revision:%,可以打开当前文件的特定版本。
如果想找到哪几个提交修改了特定文件,可以先用 git log --format='%s' -- /path/to/your/file 获取涉及的提交。

git reset [--hard|--soft|--keep]

git reset 可不能算是“不知名”操作。任何 Git 入门教程,都会提到怎么用 git reset 把文件移出暂存区。但在本人的日常开发流程中,移出暂存区其实是最少用上的
git reset 操作。所以我觉得可以打个擦边球,讲讲 git reset 其他的打开方式。

移出暂存区的 git reset 操作,相当于 git reset --mixed。除了 --mixed,常用的选项还有下面三个:

  • --soft

  • --hard

  • --keep

开发中常有的情况:劈劈啪啪写了一堆代码,连续好几个提交。然后脑子里灵机一动,顿悟了更好的做法。这个做法是如此地好,以致于之前的提交记录都成了你的黑历史。你恨不得
把这些提交记录一笔勾销,但该怎么办呢?这时候就轮到 reset --soft 上场了。
reset --soft 俗称 squash,可以在保留修改的同时,把最近的几个提交历史给抹掉。比如 git reset --soft @~3 就能重置到倒数第四个提交,但保留被抹掉的三个提交的更改。
这么操作之后再提交一次,然后选一个夜深人静的时刻,push -f 到远程仓库,你的黑历史就烟消云散了。当然还是会留下些痕迹什么的,但至少别人一般发现不了……

--soft 对应的是 --hard--hard 也会抹掉最近的几个提交,但不保留修改。如果感到自己的代码实在没法看,可以直接 reset --hard 试试。不过 reset --hard 倒不失清理环境的好方法。

--keep 正好在 --soft--hard 之间。--keep 会保留未提交的更改,这一点跟 --soft 一样;同时会抹掉已经提交的更改,这一点跟 --hard 相同。
有些时候,这一特性会派上用场。

如果你在开发的时候,突然发现自己忘记切分支了,可以这么做:

git branch feature/you_need
git reset --keep comit_your_hack_starts_from
git checkout feature/you_need

这样做既消除了错误分支上的提交,又保留了工作区里未提交的内容。

提到 reset,不能不提误操作时的补救办法。

  1. 被抹掉的内容已经提交了。这种情况好办。通过 git reflog,我们可以找到被抹掉的提交,然后 cherry-pick回来,抑或 reset --hard HEAD{x} 到对应的提交上去。

  2. 被抹掉的内容原来在暂存区里。这个比较蛋疼。你需要 git fsck | grep blob 拣出每一个 dangling blob,逐个 git show xxx 看看,应该能找回被抹掉的内容。这种感觉,就像在垃圾桶里翻出丢失的手稿一样。

  3. 被抹掉的内容不在暂存区里。靠 Git 已经救不回来了。要不找下编辑器的备份文件,要不尝试能不能从文件系统缓存里把文件抠出来。如果不行,试试磁盘数据恢复程序……

说这么多,关键记住一点:reset 有风险,用时需谨慎。

git update-index --assume-unchanged

假设代码仓库里存在这么一个配置文件:每个人在开发时,会根据本地情况修改里面的值。比如某些 IDE 的项目描述文件,里面可能夹杂着项目的路径。
有什么办法,可以避免本地的修改不会提交到仓库里去呢?
个人认为 git update-index --assume-unchanged 是众多解决方法中最好的。
git update-index 可以修改 Git 对特定路径下的文件的处理方式。其中 --assume-unchanged 选项告诉 Git,指定路径下的文件不会有修改。
即使在本地修改了那些文件,也不会被 Git 记录在案。
如果我有一天需要修改这个配置文件并入库,可以用 --no-assume-unchanged 选项解开封印,让 Git 重新追踪修改。

 ¥ gs
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   check_integrity.sh

no changes added to commit (use "git add" and/or "git commit -a")
 ¥ git update-index --assume-unchanged check_integrity.sh
 ¥ gs
On branch master
nothing to commit, working tree clean
 ¥ git update-index --no-assume-unchanged check_integrity.sh
 ¥ gs
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   check_integrity.sh

相关文章:

  • Linux学习笔记1
  • C# 客户端服务器开发 异步实现
  • 打印mac地址
  • (转)EXC_BREAKPOINT僵尸错误
  • phantomjs技巧之将html页面转换为pdf文件
  • 完毕port(CompletionPort)具体解释 - 手把手教你玩转网络编程系列之三
  • 入门到进阶:最全面Vim快捷键键位图
  • github帐号及文章选题
  • 【Datastage】NULL VALUE TO A NOT NULL VALUE
  • MongoDB-3.4安装文档
  • C#开发微信门户及应用(28)--微信“摇一摇·周边”功能的使用和接口的实现
  • bug给你带来的四个好处
  • C++中怎样获取类成员的指针
  • lol盒子重点内容
  • 安卓逆向系列教程 4.6 去广告
  • IE9 : DOM Exception: INVALID_CHARACTER_ERR (5)
  • 10个最佳ES6特性 ES7与ES8的特性
  • Angularjs之国际化
  • CSS3 变换
  • ES6简单总结(搭配简单的讲解和小案例)
  • IDEA常用插件整理
  • PAT A1017 优先队列
  • Spark in action on Kubernetes - Playground搭建与架构浅析
  • supervisor 永不挂掉的进程 安装以及使用
  • V4L2视频输入框架概述
  • windows下mongoDB的环境配置
  • 前端每日实战:61# 视频演示如何用纯 CSS 创作一只咖啡壶
  • 通过获取异步加载JS文件进度实现一个canvas环形loading图
  • 智能合约Solidity教程-事件和日志(一)
  • 好程序员大数据教程Hadoop全分布安装(非HA)
  • 小白应该如何快速入门阿里云服务器,新手使用ECS的方法 ...
  • 新海诚画集[秒速5センチメートル:樱花抄·春]
  • ​3ds Max插件CG MAGIC图形板块为您提升线条效率!
  • #快捷键# 大学四年我常用的软件快捷键大全,教你成为电脑高手!!
  • (附源码)php投票系统 毕业设计 121500
  • (附源码)springboot课程在线考试系统 毕业设计 655127
  • (附源码)springboot码头作业管理系统 毕业设计 341654
  • (附源码)ssm户外用品商城 毕业设计 112346
  • (九)c52学习之旅-定时器
  • (离散数学)逻辑连接词
  • (每日持续更新)jdk api之FileFilter基础、应用、实战
  • (十) 初识 Docker file
  • (四)Controller接口控制器详解(三)
  • (原創) 如何解决make kernel时『clock skew detected』的warning? (OS) (Linux)
  • (转) SpringBoot:使用spring-boot-devtools进行热部署以及不生效的问题解决
  • (转)菜鸟学数据库(三)——存储过程
  • (最完美)小米手机6X的Usb调试模式在哪里打开的流程
  • .Net - 类的介绍
  • .NET 5.0正式发布,有什么功能特性(翻译)
  • .NET 读取 JSON格式的数据
  • .NET 服务 ServiceController
  • .NET/C# 编译期间能确定的相同字符串,在运行期间是相同的实例
  • .net访问oracle数据库性能问题
  • @JsonFormat与@DateTimeFormat注解的使用
  • @Transactional 竟也能解决分布式事务?