【AICon】AI 基础设施、LLM运维、大模型训练与推理,一场会议,全方位涵盖! >>> 了解详情
写点什么

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

  • 2016-01-29
  • 本文字数:3137 字

    阅读完需:约 10 分钟

众所周知,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 <remotebranchname> -f origin <remoterepourlpath>
$ git checkout <localbranchname></localbranchname></remoterepourlpath></remotebranchname>

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

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

复制代码
$ git cherry-pick <commitsha></commitsha>

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

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

复制代码
$ git --git-dir=<pathtootherlocalrepo>/.git format-patch -k -1 --stdout <otherlocalcommitsha> | git am -3 -k
</otherlocalcommitsha></pathtootherlocalrepo>

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

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

复制代码
$ git update-index --assume-unchanged <pathtolocalfile></pathtolocalfile>

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 <foldername> master
# Filter the master branch to your directory and remove empty commits
Rewrite 48dc599c80e20527ed902928085e7861e6b3cbe6 (89/89)
Ref 'refs/heads/master' was rewritten
</foldername>

现在,仓库会包含指定子目录中的所有文件。虽然之前的所有文件都会被删除,但他们依旧存在于 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 <projectname>.tar.xz <projectfolder>/ --exclude-vcs
</projectfolder></projectname>

12. 查找修改者

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

复制代码
$ git blame <filename></filename>

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

2016-01-29 02:089219
用户头像

发布了 88 篇内容, 共 258.7 次阅读, 收获喜欢 8 次。

关注

评论 3 条评论

发布
暂无评论
发现更多内容

「Linux」各目录详解

我是程序员小贱

面试 3月日更

关于融云聊天室KV 值的正确使用

融云 RongCloud

即时通讯

php 实现单链表以及链表反转等操作

一个大红包

3月日更

(28DW-S8-Day24) 重新定义流程

mtfelix

28天写作

融云 ConversationListFragment 会话列表添加头部布局

融云 RongCloud

sdk

技术实践 | 网易云信 QUIC 加速服务架构与实践

网易云信

架构 音视频

HECO火币生态链挖矿系统开发搭建技术

薇電13242772558

数字货币 区块链生态

Web 安全之 CSRF

架构精进之路

Web 安全 3月日更

融云IMKit 动态删除或添加plugin 的实现

融云 RongCloud

IM

Redis 在项目中合理使用经验总结

Java小咖秀

redis

openpyxl 对Excel的基础操作

IT蜗壳-Tango

办公自动化 3月日更 IT蜗壳教学

互联网信贷风险与大数据 催收管理

张老蔫

28天写作

区块链助飞机加油和支付过程更透明高效

CECBC

区块链

配置融云SDK的自签证书

融云 RongCloud

sdk

叫练手把手教你读JVM之GC信息

叫练

JVM JVM简介 JVM笔记

融云即时通讯SDK集成 -- 定制UI(一) ——会话界面小改动

融云 RongCloud

即时通讯

邀请领好礼!米家显示器挂灯、雷蛇烈焰神虫送给你!

滴滴云

2万字系统总结,带你实现 Linux 命令自由?

比伯

Java 编程 架构 面试 程序人生

Redis不是一直号称单线程效率也很高吗,为什么又采用多线程了?

数据库 redis 架构

融云聊天室属性 kv

融云 RongCloud

IM

融云如何更换用户信息

融云 RongCloud

即时通讯

Wireshark 数据包分析学习笔记Day12

穿过生命散发芬芳

Wireshark 数据包分析 3月日更

寻找被遗忘的勇气(十五)

Changing Lin

3月日更

干货 | 比特币就是时钟

CECBC

比特币 时间同步

Web3.0时代到来 imToken借助区块链帮更多人完成价值存储和转移

CECBC

区块链

弱网测试工具

Geek_6370d5

在融云 IMkit 会话界面基础上添加消息已读未读

融云 RongCloud

IM

唠一唠融云 VIVO push 无法跳转的解决方案

融云 RongCloud

sdk

融云即时通讯SDK集成 -- 华为推送的点击跳转处理

融云 RongCloud

即时通讯

教你如何在Centos配置Oracle客户端运行时

happlyfox

28天写作 3月日更

学习感悟

shun123456789

你需要知道的12个Git高级命令_语言 & 开发_张龙_InfoQ精选文章