你需要知道的12个Git高级命令

本贴最后更新于 3246 天前,其中的信息可能已经时过境迁

众所周知,Git目前已经是分布式版本控制领域的翘楚,围绕着Git形成了完整的生态圈。学习Git,首先当然是学习Git的基本工作流。相比于SVN等传统版本控制系统来说,Git是专为分布式版本控制而生的强大工具。使用Git时常用的命令有pull、commit、push等,貌似很简单。不过,有时你会遇到合并冲突的情况,Git这时会将冲突标记出来,需要你手工来解决。有时,你会不小心将代码提交到错误的分支上,并且又推送到了远程仓库。还有些时候,你需要切换到不同的分支,但Git却不让你这么做,因为还有未保存的修改。如果需要通过另一个分支的提交来为代码打补丁该怎么做呢?本文就将介绍12个Git高级命令,合理使用这些命令可以大大提升应用Git的效率。

1. 使用rebase而非merge来拉取上游修改

分支合并会被记录为一次合并提交,这种做法是很有意义的。比如说,可以通过这种方式来标识一个新特性被合并到了发布分支中。不过,当多个团队成员工作在一个项目中并使用常规的git pull来同步分支时,提交时间线就会被不必要的合并提交所污染。更好的做法则是使用git rebase将一个feature分支变基到master分支:

$ git checkout feature
$ git rebase master

这么做会将整个feature分支移动到master分支的起点,它会合并master分支上所有新的提交。不过,相比于使用合并提交来说,变基会通过在原来的分支中为每次提交创建全新提交来重写项目历史。变基的主要好处在于你会得到一个更加整洁的项目历史。此外,这里还有关于变基的陷阱的一些讨论。

2. 在执行git rebase后解决合并冲突

正如能力越大责任就越大一样。在执行git rebase时,你可能会遇到合并冲突的情况。合并冲突表示两个提交修改了同一个文件的同一行,Git不知道该应用哪一个修改。这会导致如下所示的错误消息:

Git会为你提供3个选择来修复导致冲突的提交(fa39187):

  • 可以运行git rebase --abort来完全取消变基。这么做会取消变基修改,并将分支置回到执行git rebase之前的状态。
  • 可以运行git rebase --skip来完全忽略该提交。这样,有问题的提交所引入的变化就不会被添加到历史中。
  • 可以使用与合并冲突相同的标准步骤来解决冲突。

3. 临时性保存修改

在工作进行中时,有些东西常常会处于凌乱的状态。如果这时需要切换到不同的分支该怎么办呢?Git是不允许你这么做的,因为还有尚未保存的修改。坦率地说,你并不想将半成品提交上去,后面再来修改。这个问题的解决之道就是使用git stash命令。Stash会接收工作目录的当前状态(比如说,修改了的追踪文件与暂存区的修改等),并将其保存到未完成的修改栈中,这样后面随时可以再来修改。可以通过如下命令来暂存你的工作:

$ git stash
Saved working directory and index state WIP on feature: 3fc175f fix race condition
HEAD is now at 3fc175f fix race condition

现在,工作目录就是干净的了:

$ git status
# On branch feature
nothing to commit, working directory clean

这时就可以安全地切换分支做别的事情了。不过不必担心,暂存的提交依旧还在:

$ git stash list
stash@{0}: WIP on feature: 3fc175f fix race condition

稍后,在回到feature分支后,你就可以取回所有暂存的变更了:

$ git stash pop
On branch feature
Changes not staged for commit:
  (use "git add ..." to update what will be committed)
 modified:   index.html

Dropped refs/stash@{0} (ac2321cc3a33ba712b8e50c99a99d3c20da9d6b8)

关于暂存,还有其他一些选项可用,如下所示:

$ git stash save "describe it"   # give the stash a name
$ git stash clear                # delete a stashed commit
$ git stash save --keep-index    # stash only unstaged files

4. 克隆一个特定的远程分支

如果想要从远程仓库中克隆一个特定的分支该怎么做呢?通常你会使用git clone,不过这么做会将所有其他分支都一并克隆下来。一个便捷的方式是使用git remote add:

$ git init  
$ git remote add -t  -f origin 
$ git checkout 

5. 将cherry-pick远程提交合并到自己的分支中

更有甚者,如果只想将远程仓库的一个特定提交合并到自己的分支中该怎么做呢?可以使用git cherry-pick 来选择给定SHA值的提交,然后将其合并到当前分支中:

$ git cherry-pick 

6. 应用来自于不相关的本地仓库的补丁

如果需要将另一个不相关的本地仓库的提交补丁应用到当前仓库该怎么做呢?答案就是下面这条命令:

$ git --git-dir=/.git format-patch -k -1 --stdout  | git am -3 -k

7. 忽略追踪文件中的变更

如果你和你的同事操纵的是相同分支,那么很有可能需要频繁执行git merge或是git rebase。不过,这么做可能会重置一些与环境相关的配置文件,这样在每次合并后都需要修改。与之相反,你可以通过如下命令永久性地告诉Git不要管某个本地文件:

$ git update-index --assume-unchanged 

8. 每隔X秒运行一次git pull

通常,合并冲突出现的原因在于你正在工作的本地仓库不再反映远程仓库的当前状态。这正是我们为什么每天早晨要首先执行一次git pull的缘故。此外,你还可以在后台通过脚本(或是使用GNU Screen)每隔X秒调用一次git pull:

$ screen
$ for((i=1;i<=10000;i+=1)); do sleep X && git pull; done

9. 将子目录分隔为新的仓库

有时,你可能需要将Git仓库中某个特定的目录转换为一个全新的仓库。这可以通过git filter-branch来实现:

$ git filter-branch --prune-empty --subdirectory-filter  master
# Filter the master branch to your directory and remove empty commits
Rewrite 48dc599c80e20527ed902928085e7861e6b3cbe6 (89/89)
Ref 'refs/heads/master' was rewritten

现在,仓库会包含指定子目录中的所有文件。虽然之前的所有文件都会被删除,但他们依旧存在于Git历史中。现在可以将新的本地仓库推送到远程了。

10. 清理

有时,Git会提示“untracked working tree files”会“overwritten by checkout”。造成这种情况的原因有很多。不过通常来说,我们可以使用如下命令来保持工作树的整洁,从而防止这种情况的发生:

$ git clean -f     # remove untracked files
$ git clean -fd    # remove untracked files/directories
$ git clean -nfd   # list all files/directories that would be removed

11. 将项目文件打成tar包,并且排除.git目录

有时,你需要将项目副本提供给无法访问GitHub仓库的外部成员。最简单的方式就是使用tar或zip来打包所有的项目文件。不过,如果不小心,隐藏的.git目录就会包含到tar文件中,这会导致文件体积变大;同时,如果里面的文件与接收者自己的Git仓库弄混了,那就更加令人头疼了。轻松的做法则是自动从tar文件中排除掉.git目录:

$ tar cJf .tar.xz / --exclude-vcs

12. 查找修改者

最后,如果出现混乱的情况,你一定想要找出是谁造成的。如果生产服务器宕机,那么找到罪魁祸首是比较容易的事情:只需执行git blame。该命令会显示出文件中每一行的作者,提交hash则会找出该行的上一次修改,还能看到提交的时间戳:

$ git blame 

当然,Git命令是非常多的,除了上面介绍的12个重要命令外,相信各位InfoQ读者在日常工作过程中也有自己偏爱且好用的一些命令,不妨以评论的形式与其他读者一同分享。

 

转自: http://www.infoq.com/cn/news/2016/01/12-git-advanced-commands

  • Git

    Git 是 Linux Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。

    209 引用 • 358 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • Vanessa
    $ git --git-dir=/.git format-patch -k -1 --stdout  | git am -3 -k
    

    这个是啥意思,如果我要从改一个库提交 patch 到另外一个库,可以用这个么?要不然,每次改为 Sym 都要同步到 SymX,很是麻烦

    @88250

  • 88250

    @Vanessa 没用过高级命令,同步的话还是一行一行对着改比较好,不然容易报废~

  • zempty

    好,支持。

  • zempty

    另外,弱弱地问一句,签名档能否改为添加的方式,而不是现在固定的三个,有时是需要 3 个以上的签名档的😄

  • Vanessa

    @zempty Solo 么?

  • zempty 1

    @Vanessa 是的啊。

  • Vanessa

    @zempty 目前不可以嘢,是写死的。

  • someone

    [em01][em01]说得很好。

请输入回帖内容 ...
Vanessa
我们终此一生,就是要摆脱他人的期待,找到真正的自己。 昆明

推荐标签 标签

  • Q&A

    提问之前请先看《提问的智慧》,好的问题比好的答案更有价值。

    8447 引用 • 38484 回帖 • 155 关注
  • LaTeX

    LaTeX(音译“拉泰赫”)是一种基于 ΤΕΧ 的排版系统,由美国计算机学家莱斯利·兰伯特(Leslie Lamport)在 20 世纪 80 年代初期开发,利用这种格式,即使使用者没有排版和程序设计的知识也可以充分发挥由 TeX 所提供的强大功能,能在几天,甚至几小时内生成很多具有书籍质量的印刷品。对于生成复杂表格和数学公式,这一点表现得尤为突出。因此它非常适用于生成高印刷质量的科技和数学类文档。

    12 引用 • 54 回帖 • 49 关注
  • TGIF

    Thank God It's Friday! 感谢老天,总算到星期五啦!

    288 引用 • 4485 回帖 • 663 关注
  • 又拍云

    又拍云是国内领先的 CDN 服务提供商,国家工信部认证通过的“可信云”,乌云众测平台认证的“安全云”,为移动时代的创业者提供新一代的 CDN 加速服务。

    21 引用 • 37 回帖 • 548 关注
  • CloudFoundry

    Cloud Foundry 是 VMware 推出的业界第一个开源 PaaS 云平台,它支持多种框架、语言、运行时环境、云平台及应用服务,使开发人员能够在几秒钟内进行应用程序的部署和扩展,无需担心任何基础架构的问题。

    5 引用 • 18 回帖 • 172 关注
  • JRebel

    JRebel 是一款 Java 虚拟机插件,它使得 Java 程序员能在不进行重部署的情况下,即时看到代码的改变对一个应用程序带来的影响。

    26 引用 • 78 回帖 • 672 关注
  • CongSec

    本标签主要用于分享网络空间安全专业的学习笔记

    1 引用 • 1 回帖 • 15 关注
  • 学习

    “梦想从学习开始,事业从实践起步” —— 习近平

    171 引用 • 512 回帖
  • TensorFlow

    TensorFlow 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组,即张量(tensor)。

    20 引用 • 19 回帖 • 1 关注
  • Logseq

    Logseq 是一个隐私优先、开源的知识库工具。

    Logseq is a joyful, open-source outliner that works on top of local plain-text Markdown and Org-mode files. Use it to write, organize and share your thoughts, keep your to-do list, and build your own digital garden.

    6 引用 • 63 回帖 • 5 关注
  • 分享

    有什么新发现就分享给大家吧!

    248 引用 • 1795 回帖 • 1 关注
  • 运维

    互联网运维工作,以服务为中心,以稳定、安全、高效为三个基本点,确保公司的互联网业务能够 7×24 小时为用户提供高质量的服务。

    149 引用 • 257 回帖
  • WiFiDog

    WiFiDog 是一套开源的无线热点认证管理工具,主要功能包括:位置相关的内容递送;用户认证和授权;集中式网络监控。

    1 引用 • 7 回帖 • 592 关注
  • WebSocket

    WebSocket 是 HTML5 中定义的一种新协议,它实现了浏览器与服务器之间的全双工通信(full-duplex)。

    48 引用 • 206 回帖 • 318 关注
  • 工具

    子曰:“工欲善其事,必先利其器。”

    288 引用 • 734 回帖 • 2 关注
  • 程序员

    程序员是从事程序开发、程序维护的专业人员。

    574 引用 • 3533 回帖
  • Linux

    Linux 是一套免费使用和自由传播的类 Unix 操作系统,是一个基于 POSIX 和 Unix 的多用户、多任务、支持多线程和多 CPU 的操作系统。它能运行主要的 Unix 工具软件、应用程序和网络协议,并支持 32 位和 64 位硬件。Linux 继承了 Unix 以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。

    946 引用 • 943 回帖
  • SpaceVim

    SpaceVim 是一个社区驱动的模块化 vim/neovim 配置集合,以模块的方式组织管理插件以
    及相关配置,为不同的语言开发量身定制了相关的开发模块,该模块提供代码自动补全,
    语法检查、格式化、调试、REPL 等特性。用户仅需载入相关语言的模块即可得到一个开箱
    即用的 Vim-IDE。

    3 引用 • 31 回帖 • 104 关注
  • 数据库

    据说 99% 的性能瓶颈都在数据库。

    343 引用 • 723 回帖
  • Postman

    Postman 是一款简单好用的 HTTP API 调试工具。

    4 引用 • 3 回帖 • 7 关注
  • 链滴

    链滴是一个记录生活的地方。

    记录生活,连接点滴

    156 引用 • 3792 回帖
  • Webswing

    Webswing 是一个能将任何 Swing 应用通过纯 HTML5 运行在浏览器中的 Web 服务器,详细介绍请看 将 Java Swing 应用变成 Web 应用

    1 引用 • 15 回帖 • 637 关注
  • HHKB

    HHKB 是富士通的 Happy Hacking 系列电容键盘。电容键盘即无接点静电电容式键盘(Capacitive Keyboard)。

    5 引用 • 74 回帖 • 478 关注
  • jQuery

    jQuery 是一套跨浏览器的 JavaScript 库,强化 HTML 与 JavaScript 之间的操作。由 John Resig 在 2006 年 1 月的 BarCamp NYC 上释出第一个版本。全球约有 28% 的网站使用 jQuery,是非常受欢迎的 JavaScript 库。

    63 引用 • 134 回帖 • 724 关注
  • 快应用

    快应用 是基于手机硬件平台的新型应用形态;标准是由主流手机厂商组成的快应用联盟联合制定;快应用标准的诞生将在研发接口、能力接入、开发者服务等层面建设标准平台;以平台化的生态模式对个人开发者和企业开发者全品类开放。

    15 引用 • 127 回帖
  • Solidity

    Solidity 是一种智能合约高级语言,运行在 [以太坊] 虚拟机(EVM)之上。它的语法接近于 JavaScript,是一种面向对象的语言。

    3 引用 • 18 回帖 • 401 关注
  • 域名

    域名(Domain Name),简称域名、网域,是由一串用点分隔的名字组成的 Internet 上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时也指地理位置)。

    43 引用 • 208 回帖