Git 进阶指南

在掌握了基础的 Git 使用 之后,可能会遇到一些常见的问题。以下是猫哥筛选总结的部分常见问题,分享给各位朋友,掌握了这些问题的中的要点之后,git 进阶也就完成了,它包含以下部分:

  • 如何修改 origin 仓库信息
  • 如何配置 git ssh keys
  • 如何撤销修改
  • 遇到冲突了怎么解决
  • git stash / alias / submodule 的使用问题等

问:如何修改 origin 仓库信息?

1、添加 origin 仓库信息

git remote add origin <git仓库地址>

2、查看 origin 仓库信息

# 以下三种方式均可
git config get --remote.origin.url
git remote -v
git remote show origin

3、删除 origin 仓库信息

git remote rm origin

问:如何配置 git ssh keys ?

  1. 在本地生成 ssh 私钥 / 公钥 文件
  2. 将「公钥」添加到 git 服务(github、gitlab、coding.net 等)网站后台
  3. 测试 git ssh 连接是否成功

接下来以添加 github ssh keys 为例,请注意替换 github 文件名:

# 运行以下命令,一直回车,文件名可随意指定
ssh-keygen -t rsa -b 4096 -C "kaiye@macbook" -f ~/.ssh/github

# 如果不是默认密钥 id_rsa ,则需要以下命令注册密钥文件
ssh-add ~/.ssh/github

# 将 pub 公钥的内容粘贴到线上网站的后台
cat ~/.ssh/github.pub

# 测试 git ssh 是否连接成功
ssh -T git@github.com

问:如何撤销修改?

修改包含四种情况,需单独区分。

1、新建的文件和目录,且从未提交至版本库

此类文件的状态为 Untracked files ,撤销方法如下:

git clean -fd .

其中,. 表示当前目录及所有子目录中的文件,也可以直接指定对应的文件路径,以下其他情况类似。

2、提交过版本库,但未提交至暂存区的文件(未执行 git add)

此类文件的状态为 Changes not staged for commit,撤销方法:

git checkout .

3、已提交至暂存区的文件

此类文件的状态为 Changes to be committed,撤销方法:

git reset .

执行之后文件将会回到以上的 1 或者 2 状态,可继续按以上步骤执行撤销,若 git reset 同时加上 --hard 参数,将会把修改过的文件也还原成版本库中的版本。

4、已提交至版本库(执行了 git commit)

每次提交都会生成一个 hash 版本号,通过以下命令可查阅版本号并将其回滚:

git log
git reset <版本号>

如果需要「回滚至上一次提交」,可直接使用以下命令:

git reset head~1

执行之后,再按照 1 或者 2 状态进行处理即可,如果回滚之后的代码同时需要提交至 origin 仓库(即回滚 origin 线上仓库的代码),需要使用 -f 强制提交参数,且当前用户需要具备「强制提交的权限」。

5、如果回滚了之后又不想回滚了怎么办?

如果是以上的情况 1 或者 2,只能歇屁了,因为修改没入过版本库,无法回滚。

如果是情况 4,回滚之后通过 git log 将看不到回滚之前的版本号,但可通过 git reflog 命令(所有使用过的版本号)找到回滚之前的版本号,然后 git reset <版本号>

问:遇到冲突了怎么解决?

两个分支进行合并时(通常是 git pull 时),可能会遇到冲突,同时被修改的文件会进入 Unmerged 状态,需要解决冲突。

最快的办法

大部分时候,「最快解决冲突」的办法是:使用当前 HEAD 的版本(ours),或使用合并进来的分支版本(theirs)。

# 使用当前分支 HEAD 版本,通常是冲突源文件的 <<<<<<< 标记部分,======= 的上方
git checkout --ours <文件名>

# 使用合并分支版本,通常是源冲突文件的 >>>>>>> 标记部分
git checkout --theirs <文件名>

# 标记为解决状态加入暂存区
git add <文件名>

最通用的办法

用编辑器打开冲突的源文件进行修改,可能会发生遗留,且体验不好,通常需要借助 git mergetool 命令。

在 Mac 系统下,运行 git mergetool <文件名> 可以开启配置的第三方工具进行 merge,默认的是 FileMerge 应用程序,还可以配置成 Meld 或 kdiff3,体验更佳。

最好的习惯

有三个好的习惯,可以减少代码的冲突:

  • 在开始修改代码前先 git pull 一下;
  • 将业务代码进行划分,尽量不要多个人在同一时间段修改同一文件;
  • 通过 Gitflow 工作流 也可以提升 git 流程效率,减少发生冲突的可能性。

最复杂的情况

如果你的项目周期比较长,还应该养成「定期 rebase 的习惯」,git pull --rebase 可以让分支的代码和 origin 仓库的代码保持兼容,同时还不会破坏线上代码的可靠性。

它的大概原理是,先将 origin 仓库的代码按 origin 的时间流在本地分支中提交,再将本地分支的修改记录追加到 origin 分支上。如果发生冲突,则可以即时的发现问题并解决,否则到项目上线时再解决冲突,可能会发生额外的风险。

rebase 大概的操作步骤如下:

# 将当前分支的版本追加到从远程 pull 回来的节点之后
git pull --rebase

# 若发生冲突,则按以上其他方法进行解决,解决后继续
git rebase --continue

# 直到所有冲突得以解决,待项目最后上线前再执行
git push origin

# 若多次提交修改了同一文件,可能需要直接跳过后续提交,按提示操作即可
git rebase --skip

问:如何在不提交修改的前提下,执行 pull / merge 等操作?

有些修改没有完全完成之前,可能不需要提交到版本库,圡方法是将修改的文件 copy 到 git 仓库之外的目录临时存放,pull / merge 操作完成之后,再 copy 回来。

这样的做法一个是效率不高,另外一个可能会遗漏潜在的冲突。此类需求最好是通过 git stash 命令来完成,它可以将当前工作状态(WIP,work in progress)临时存放在 stash 队列中,待操作完成后再从 stash 队列中重新应用这些修改。

以下是 git stash 常用命令:

# 查看 stash 队列中已暂存了多少 WIP
git stash list

# 恢复上一次的 WIP 状态,并从队列中移除
git stash pop

# 添加当前 WIP,注意:未提交到版本库的文件会自动忽略,只要不运行 git clean -fd . 就不会丢失
git stash

# 恢复指定编号的 WIP,同时从队列中移除
git stash pop stash@{num}

# 恢复指定编号的 WIP,但不从队列中移除
git stash apply stash@{num}

问:如何在 git log 中查看修改的文件列表?

默认的 git log 会显示较全的信息,且不包含文件列表。使用 --name-status 可以看到修改的文件列表,使用 --oneline可以将参数简化成一行。

git log --name-status --oneline

每次手动加上参数很麻烦,可以通过自定义快捷命令的方式来简化操作:

git config --global alias.ls 'log --name-status --oneline --graph'

运行以上配置后,可通过 git ls 命令来实现「自定义 git log」效果,通过该方法也可以创建 git stgit ci 等一系列命令,以便沿用 svn 命令行习惯。

更多 git log 参数,可通过 git help log 查看手册。

如果是看上一次提交的版本日志,直接运行 git show 即可。

问:git submodule update 时出错怎么解决?

例如,在执行 git submodule update 时有以下错误信息:

fatal: reference is not a tree: f869da471c5d8a185cd110bbe4842d6757b002f5
Unable to checkout 'f869da471c5d8a185cd110bbe4842d6757b002f5' in submodule path 'source/i18n-php-server'

在此例中,发生以上错误是因为 i18n-php-server 子仓库在某电脑 A 的「本地」commit 了新的版本 「f869da471c5d8a185cd110bbe4842d6757b002f5」,且该次 commit 未 push origin。但其父级仓库 i18n-www 中引用了该子仓库的版本号,且将引用记录 push origin,导致其他客户机无法 update 。

解决方法,在电脑 A 上将 i18n-php-server 版本库 push origin 后,在其他客户机上执行 git submodule update 。或者用以上提到的 git reset 方法,将子仓库的引用版本号还原成 origin 上存在的最新版本号。

其他问题

  • 设置本地分支与远程分支保持同步,在第一次 git push 的时候带上 -u 参数即可 git push origin master -u
  • 支持中文目录与文件名的显示(git 默认将非 ASCII 编码的目录与文件名以八进制编码展示) git config core.quotepath off

原文发布于微信公众号 - 猫哥学前班(imgXQB)

原文发表时间:2016-01-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏跟着阿笨一起玩NET

sql转Linq的工具

这些天写Linq挺烦人的,就上网搜搜可有什么好的sql转Linq的工具,咦,马上就看上了Linqer。

333
来自专栏java系列博客

Windows下安装并设置Redis

1303
来自专栏流柯技术学院

Eclipse安装SVN插件及使用说明

1、下载Eclipse,如果没有安装的请到这里下载安装:http://eclipse.org/downloads/ ,关于Eclipse的下载安装不再赘述。 ...

771
来自专栏用户2442861的专栏

NodeJS、NPM安装配置步骤(windows版本) 以及环境变量

http://xiaoyaojones.blog.163.com/blog/static/28370125201351501113581/ 6、npm作为一...

501

使用Puppet模块创建LAMP堆栈

在Puppet中,模块是服务器配置的构建块。模块安装和配置包,创建目录,并生成用户在模块中包含的任何其他服务器更改。Puppet模块旨在执行特定任务的所有部分,...

753
来自专栏北京马哥教育

Linux基础急速入门:用 TCPDUMP 抓包

简介 网络数据包截获分析工具。支持针对网络层、协议、主机、网络或端口的过滤。并提供and、or、not等逻辑语句帮助去除无用的信息。 tcpdump - dum...

3018
来自专栏Laoqi's Linux运维专列

负载均衡、集群、高可用解决方案

3494
来自专栏北京马哥教育

Codis集群搭建摘要

准备方案 Golang环境搭建 环境搭建很简单,下载go1.4.2.linux-amd64.tar.gz安装包,直接解压并添加到环境变量就可以。 假设解压到/u...

2855
来自专栏有趣的Python

最新Django2.0.1在线教育零基础到上线教程(十)

演示地址: http://mxonline.mtianyan.cn 教程仓库地址1: https://github.com/mtianyan/DjangoGe...

3466
来自专栏Google Dart

开始使用-初尝胜果 顶

本页介绍如何“测试驱动器”Flutter:从我们的模板创建一个新的Flutter应用程序,运行它,并学习如何使用Hot Reload进行更改。

653

扫描关注云+社区