Qida's Blog

纸上得来终觉浅,绝知此事要躬行。

HTML 标签语义化

标签名 英文全拼 中文翻译
a anchor
abbr abbreviation 缩写词
acronym acronym 取首字母的缩写词
address address 地址
blockquote block quotation 区块引用于
br break 换行
caption caption 标题
center center 居中
div division 分隔
fieldset fieldset 域集
font font 字体
h1~h6 header1~header6 标题1~标题6
hr horizontal rule 水平尺
legend legend 图标
p paragraph 段落
pre preformatted 预定义格式
span span 范围
var variable 变量

HTML Formatting

标签名 英文全拼 中文翻译
b bold 粗体
i italic 斜体
s strikethrough 删除线
u underlined 下划线
strong strong 加重
em emphasized 加重
big big 变大
small small 变小
del delete 删除
ins inserted 插入
sub subscripted 下标
sup superscripted 上标

HTML Lists

标签名 英文全拼 中文翻译
ol ordered list 排序列表
ul unordered list 不排序列表
li list item 列表项目
dl definition list 定义列表
dt definition term 定义术语
dd definition description 定义描述

参考

https://www.w3schools.com/html/

上文

有时候合并操作并不会如此顺利。如果在不同的分支中都修改了同一个文件的同一部分,Git 就无法干净地把两者合到一起。这种问题只能由人来裁决,解决冲突的办法无非是从冲突中二者选其一或者由你亲自整合到一起。

你完全可以手工编辑处理冲突,或者推荐使用图形化的外部合并与比较工具(mergetool)。

mergetool 是什么?

Merge tool is a GUI that steps you through each conflict, and you get to choose how to merge. Sometimes it requires a bit of hand editing afterwards, but usually it’s enough by itself. It is much better than doing the whole thing by hand certainly.

mergetool 如何选择?

mergetool 需自行选择安装。选择很多,例如:meld, opendiff, kdiff3, tkdiff, xxdiff, tortoisemerge, gvimdiff, diffuse, ecmerge, p4merge, araxis, vimdiff, emerge …

推荐使用 meld,一款优秀的可视化 diff 和代码合并工具(merge tool),支持特性如下:

  • 跨平台,支持 Linux/Unix、 OS X、Windows,多种便捷的安装方式
  • 跨工具,支持多种版本控制系统(VCS),如 Git、SVN、Mercurial …
  • 支持双方或三方文件、目录对比
  • GUI 界面好看 :)

meld 如何使用?

安装好 meld ,还需进行如下配置:

用于 git diff

首先配置好 git :

1
$ git config --global diff.external ~/meld.sh

然后准备编写 meld.sh 包装脚本:

1
$ vim ~/meld.sh

默认情况下, git diff 会传递 7 个参数给该包装脚本:

1
path old-file old-hex old-mode new-file new-hex new-mode

但我们仅仅只需要 old-filenew-file 参数,因此需要用包装脚本来传递它们。脚本内容如下:

1
2
#!/bin/sh
meld $2 $5

如果对涉及到的参数感兴趣,可以在脚本补充一段 echo $0 $*

最后对于 Linux/Unix、OS X,还需要增加脚本的可执行权限:

1
$ chmod +x ~/meld.sh

以上配置好后,就可以调用图形化工具愉快的使用 git diff 了。

用于 git mergetool

首先配置好 git :

1
$ git config --global merge.tool meld

如果合并的时候出现如下冲突:

1
CONFLICT (content): Merge conflict in index.html Automatic merge failed; fix conflicts and then commit the result.

使用如下命令:

1
$ git mergetool

就可以调用图形化工具愉快的解决冲突了。

在解决了所有文件的所有冲突后,运行 git add 将把它们标记为已解决状态即可(一旦暂存,就表示冲突已经解决)。

参考

如果工作目录的本地代码做了修改但尚未提交,pull 拉取远程仓库的新提交时,往往会提示冲突:

1
2
3
4
$ git pull
error: Your local changes to the following files would be overwritten by merge:
/there/is/a/conflict/file
Please, commit your changes or stash them before you can merge.

如上所示,有 commitstash 两种处理方法。针对本地代码的完成情况我们需要作出选择。

代码已完成

如果确认本地代码已经完成无误,可以先将本地代码 commit 到本地仓库。再次 pull 拉取远程仓库时,如无冲突,Git 会自动产生一次“合并”提交:

1
2
3
4
5
6
7
$ git lg
* e6f4e18 - Merge branch 'master' of origin (1 minutes ago)
|\
* | abfa93b - 本地仓库的提交 (2 minutes ago)
| * 1f1c21d - 远程仓库的提交 (3 minutes ago)
|/
* 17ef24c - 基准版本 (4 minutes ago)

这是因为 pull 的默认策略是“fetch + merge”。如果本地仓库的提交一直不 push 到远程仓库,极端情况下每一次 pull 都可能会产生一次“合并”提交,这会造成祖先图谱(graph)无谓的复杂。此时推荐使用 rebase 避免本地仓库无谓的合并节点:

1
$ git pull --rebase

代码未完成

但如果本地代码仍未完成,此时推荐使用 stash 命令暂存修改,避免将未完成的功能代码 commit 到本地仓库,污染仓库。

暂存当前修改

第一步,stash 暂存当前修改:

1
2
$ git stash save "填写你的备注"
Saved working directory and index state ......
1
2
3
$ git status
On branch master
nothing to commit, working directory clean

可以看到暂存后工作目录一干二净。这是因为 stash 命令可以将“修改过的被追踪的文件(modified tracked files)”和“暂存的变更(staged changes)”暂存到临时堆栈中,并将工作目录还原干净,以便后续的操作。

Stashing takes the dirty state of your working directory – that is, your modified tracked files and staged changes – and saves it on a stack of unfinished changes that you can reapply at any time.

拉取远程仓库

第二步,继续 pull 拉取远程仓库并进行自动合并:

1
$ git pull

重新还原暂存

第三步,stash pop 重新还原暂存修改:

1
$ git stash pop

处理冲突

最后一步,如果还原后产生冲突,需要手工或使用 mergetool 进行处理。处理完毕后,使用 add 标明冲突已解决:

1
$ git add .

参考

Git-工具-储藏(Stashing)

cherry-pick 这个命令的名字是比较形象的,即“摘樱桃”,使用该命令可以将任意的 commit 合并到你想要的分支上。 例如:

1
2
3
4
5
# 切换到 master 分支
$ git checkout master

# cherry-pick 特性分支上的三个 commit
$ git cherry-pick e7ce3f8 915fe84 dc6baf3

合并完毕后,会在 master 分支上新产生三个 commit 号,但提交内容不变。

如果只是想整理当前分支,可以使用 rebase 命令。

参考

Git知识总览(四) git分支管理之rebase 以及 cherry-pick相关操作

本文介绍一个生僻但相当好用的命令 rebase(衍合)。

使用场景

衍合的两个使用场景:

  1. 生成干净历史、补丁
  2. 整理当前分支

生成干净历史

开发过程中,常常需要定期将最新的远程分支拉取(pull)到本地分支,保持本地代码最新(up to date)。如果拉取频繁,pull 默认的 merge 行为会造成祖先图谱(ancestry graph)无谓的复杂:

1
2
3
4
5
6
7
8
$ git pull origin master    // pull = fetch + merge

* ab900eb - 三方合并版本(注意这里!)
|\
| * 756ba83 - 本地分支提交的版本
* | 915fe84 - 先被推送到远程分支的版本
|/
* e7ce3f8 - 基准版本(共同祖先)

解决方案是改用 rebase 命令,其产生的祖先图谱如下,非常简洁:

1
2
3
4
5
*   dc6baf3 - 本地分支提交的版本(注意这个提交被改写了!)
|
* 915fe84 - 先被推送到远程分支的版本
|
* e7ce3f8 - 基准版本(共同祖先)

可见,这个神奇的命令功能类似 merge ,但它避免了上述无谓的合并节点,从而产生一个更为整洁的提交历史。如果视察一个衍合过的分支历史,仿佛所有的提交都是在一根时间轴上先后进行的,尽管实际上它们原本是同时并行发生的。这么做的好处是,非常便于项目管理人员按时间轴进行代码审查

命令用法

可以在 pull 时主动加上 --rebase 参数:

1
$ git pull --rebase origin master

甚至推荐将 rebase 设为 pull 命令的默认行为,从而应用于所有新建分支:

1
$ git config --global branch.autosetuprebase always

注意,对于应用上述命令前已存在的分支(例如 master),需要补充执行如下配置:

1
$ git config branch.master.rebase true

命令原理

下面进一步介绍 rebase 命令的原理:

  1. 把本地分支从上一次 pull 之后的变更暂存起来;
  2. 恢复到上一次 pull 时的情况;
  3. 合并远程分支的提交;
  4. 最后再逐一合并刚暂存下来的本地提交(相当于重放一遍)。

生成干净补丁

使用衍合的另一个目的,是想要得到一个能在远程分支上干净应用的补丁 — 比如某些项目、或些分支你不是维护者,但想帮点忙的话,最好用衍合:先在自己的一个独立分支中进行开发,当准备向主项目提交补丁的时候,根据最新的 origin/master 进行一次 git rebase 衍合操作然后再提交,这样维护者就不需要做任何整合工作(实际上是把解决分支补丁同最新主干代码之间冲突的责任,化转为由提交补丁的人来解决。),只需根据你提供的仓库地址作一次快进合并,或者直接采纳你提交的补丁。

整理当前分支

衍合的另一个用法是整理当前分支,使用 git rebase [-i | --interactive] 命令。

首先选取提交范围,e7ce3f8 为当前分支的历史提交:

1
2
3
4
5
*   dc6baf3 - commit3
|
* 915fe84 - commit2
|
* e7ce3f8 - commit1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ git rebase -i e7ce3f8

1 pick dc6baf3 本地分支提交的版本
2 pick 915fe84 先被推送到远程分支的版本
3
4 # Rebase 1ff20826..61527529 onto 1ff20826 (2 commands)
5 #
6 # Commands:
7 # p, pick = use commit
8 # r, reword = use commit, but edit the commit message
9 # e, edit = use commit, but stop for amending
10 # s, squash = use commit, but meld into previous commit
11 # f, fixup = like "squash", but discard this commit's log message
12 # x, exec = run command (the rest of the line) using shell
13 # d, drop = remove commit
14 #
15 # These lines can be re-ordered; they are executed from top to bottom.
16 #
17 # If you remove a line here THAT COMMIT WILL BE LOST.
18 #
19 # However, if you remove everything, the rebase will be aborted.
20 #
21 # Note that empty commits are commented out

可见,我们可以选取、编辑、合并、丢弃指定提交,达到整理分支的目的。

使用风险

注意,衍合必须遵守的准则:一旦本地分支中的提交(commit)已经被推送到远程仓库,就千万不要对该分支进行衍合操作。如果把衍合当成一种在推送(push)代码之前整理提交历史的手段,而且仅仅衍合那些尚未推送的本地提交,就没问题。如果衍合那些已经推送的提交,并且已经有人基于这些提交对象开展了后续开发工作的话,就会出现叫人沮丧的麻烦。

参考

快进式合并

默认情况下,当使用 git merge 合并代码时,背后实际上是进行了一次“快进式合并”:

1
2
$ git checkout master
$ git merge feature-test

什么是“快进式合并(fast-forward merge)”?如果顺着一个分支走下去可以直接到达另一个分支的话,那么 Git 在合并两者时,只会简单地把指针右移,因为这种单线的历史分支不存在任何需要解决的分歧,所以这种合并过程可以称为快进(Fast forward)。

fast-forward merge

非快进式合并

作为对比,加上 --no-ff 参数进行“非快进式合并(no-fast-forward merge)”:

1
2
$ git checkout master
$ git merge --no-ff feature-test

其祖先图谱如下:

no-fast-forward merge

可见,合并后保留有分支历史痕迹(每一次提交),能看得出来曾经做过分支合并,版本演进比较清晰。

压缩合并

但大多数时候,没有必要把特性分支的历史保留得太细,只需把整个特性分支压缩(squash)为主干上的一个提交即可。这样的祖先图谱既清晰,又能方便后人审查代码,推荐使用:

1
2
3
$ git checkout master
$ git merge --squash feature-test
$ git commit

参考

checkout 命令可以用于三种场景:

  • 切换分支
  • 创建分支
  • 撤销修改

本文只介绍第三种场景。

例子

如果我们想要撤销一个文件的本地修改,自然可以手工编辑恢复,但这样做实在是吃力不讨好。 checkout 命令可以帮助我们:

只撤销本地修改

修改文件后,使用 status 命令查看一下文件状态:

1
2
3
4
5
6
$ git status
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)

modified: /there/is/a/modified/file

Git 提示我们,对于未 add 进暂存区的文件,可以使用 git checkout -- <file> 快速撤销本地修改。

同时撤销本地和暂存区修改

那么,对于已 add 进暂存区的文件,如何撤销本地修改?还是先使用 status 命令查看一下文件状态:

1
2
3
4
5
$ git status
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)

modified: /there/is/a/modified/file

先取消暂存修改

Git 提示我们,可以使用 reset 命令取消暂存:

1
$ git reset /there/is/a/modified/file

取消暂存后,文件状态就回到了跟“例1”一样了:

1
2
3
4
5
6
$ git status
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)

modified: /there/is/a/modified/file

再撤销本地修改

这时按提示使用 checkout 即可:

1
$ git checkout -- /there/is/a/modified/file

这时工作目录就干净了:

1
2
$ git status
nothing to commit, working directory clean

可以看到,结合使用 resetcheckout 命令,可以撤销 index 和 working tree 的修改。

一步到位

那么有更便捷的、一步到位的办法吗?有,指定提交即可:

1
2
3
4
5
$ git status
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)

modified: /there/is/a/modified/file
1
$ git checkout HEAD -- /there/is/a/modified/file
1
2
$ git status
nothing to commit, working directory clean

那么 checkout 命令的全貌究竟是怎样的呢?

checkout 命令格式

checkout 命令的格式及描述如下:

1
2
3
git checkout [<tree-ish>] [--] <paths>...

Updates the named paths in the working tree from the index file (default) or from a named <tree-ish> (most often a commit, tag or branch)
  • 默认使用 index 暂存区的内容覆盖本地修改,如果不指定 <tree-ish> 参数。
  • 或者可以使用指定的提交、标记、分支版本覆盖本地修改。
  • 为了避免文件路径 <paths><tree-ish> 同名而发生冲突,在 <paths> 前用 -- 作为分隔。

checkoutreset

还记得在《git reset 命令回退版本》中介绍的 reset 命令吗?它与 checkout 命令之间有什么区别与关系?

区别

在这里介绍 reset 命令的另一种形式:

1
2
3
git reset [<tree-ish>] [--] <paths>...

This form copy entries from <tree-ish> to the index for all <paths>. (It does not affect the working tree or the current branch.)

checkout 命令的参数一模一样,区别是什么?

命令 操作目标 描述
checkout 工作目录(working tree) 用于撤销本地修改
reset 暂存区(index) 只用于覆盖暂存区

因此 git reset <paths> 等于 git add <paths> 的逆向操作。

如果企图用 reset 命令覆盖工作目录,是会报错的:

1
2
$ git reset --hard /there/is/a/modified/file
fatal: Cannot do hard reset with paths.

关系

After running git reset <paths> to update the index entry, you can use git checkout -- <paths> to check the contents out of the index to the working tree.

Alternatively, using git checkout [<tree-ish>] [--] <paths> and specifying a commit, you can copy the contents of a path out of a commit to the index and to the working tree in one go.

参考

git checkout
git reset
Git 教程 - 撤销修改

Git 相比 SVN 的其中一个卓越之处,就在于有各种“后悔药”可吃。其中一种“后悔药”叫做 reset 命令,相当好用。

三个工作区域

理解 reset 命令的前提是理解文件流转的三个工作区域:

  • 工作目录(working directory)
  • 暂存区域(staging area)
  • 本地仓库(repo)

命令

reset 命令有三种参数形式,本文只介绍最常用的一种:

1
2
3
git reset [<mode>] [<commit>]

Reset the current branch head (HEAD) to <commit>, optionally modifying index and working tree to match.

该命令用于回退本地仓库当前分支下的版本,并可以选择重置暂存区域、工作目录的修改。

mode 参数

mode 参数必须是以下五种中的一种:

--soft

HEAD Only

Git 本地仓库的版本回退速度之所以快,全因为 Git 在内部有个指向当前版本的 HEAD 指针,当你回退版本的时候,Git 仅仅是把 HEAD 指针往回移动。

--mixed

HEAD and Index

默认参数。除了回退本地仓库的版本,还会重置暂存区域(也称为 Index File 索引文件)。

这个默默无闻的 --mixed 参数其实很常见,每次运行 git status 时都会看到它的作用:

1
2
3
4
5
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)

new file: /there/is/a/new/file
modified: README.md

由于该命令实在太常用了,因此会被设为 alias 以便使用:

1
2
$ git config --global alias.unstage 'reset HEAD'
$ git unstage

--hard

HEAD, Index, and Working Directory

终极武器,将包括工作目录在内的三个工作区域全部重置或回退,工作目录将重置得一干二净,慎用。

常见的做法是回退到上一个版本,连同工作目录,就像一切从未发生过一样:

1
2
3
4
5
$ git reset --hard HEAD~1
HEAD is now at ......

$ git status
nothing to commit, working directory clean

如果“回退前的版本”已经 push 到远程仓库,则不建议这么做。

--merge

待补充。

--keep

待补充。

commit 参数

commit 参数有三种常见形式:

SHA1

使用 SHA1 值回退到指定的版本,适用于 SH1 值已知的情况:

1
$ git reset 17ef24c

更常用的参数,适用于偷懒:

  • HEAD 表示当前版本(默认参数)。
  • 上一个版本为 HEAD^ ,上上一个版本为 HEAD^^ ,以此类推。
  • 上 100 个版本,简写为 HEAD~100
  • ORIG_HEAD 表示上一个 HEAD ,一般用于撤销上一次 reset 。(”reset” copies the old head to .git/ORIG_HEAD)

HEAD@{}

Git 在 1.8.5 版本之后,加入了 HEAD@{} 功能,它通过一个链表记录 HEAD 的移动路径,链表头部的 HEAD@{0}HEAD 指针。这个功能可以用于回退到一个早已忘记的提交。

这个功能一般配合 reflog 命令使用。

例子

更多例子参见 git help reset 的 EXAMPLES 部分。

参考

Git 中 HEAD 和 ORIG_HEAD 指针分别指的是什么?

在提交了若干更新之后,又或者克隆了某个项目,想回顾下提交历史,可以使用 git log 命令查看,或者推荐使用 git 自带的图形化工具 gitk

命令方式

定制输出格式 1

git log 的默认输出格式非常不便于查阅提交历史,使用时可以带上以下三个参数:

1
2
3
4
5
6
7
$ git log --graph --oneline --decorate
* e6f4e18 (HEAD, master) Merge branch 'master' of origin
|\
* | abfa93b 本地仓库的提交
| * 1f1c21d (origin/master) 远程仓库的提交
|/
* 17ef24c 基准版本

命令的输出形象地展示了提交历史,包括本地分支比远程分支领先了多少个提交版本。

定制输出格式 2

如果对输出格式还不满意,可以使用 --pretty 参数定制输出格式:

1
2
3
4
5
6
7
$ git log -5 --pretty=format:"%h - %an, %ar : %s"

f757dcd - wuqd, 20 hours ago : commit msg 5
5ca68df - wuqd, 13 days ago : commit msg 4
486b8d4 - wuqd, 3 weeks ago : commit msg 3
e58ae38 - wuqd, 3 weeks ago : commit msg 2
4830852 - wuqd, 3 weeks ago : commit msg 1

由于该参数的选项较多,推荐设置为别名(alias)使用:

1
2
3
4
5
6
7
8
$ git config --global alias.lg log --graph --pretty=format:'%Cred%h%Creset - %s %Cgreen(%cr) %C(bold blue)<%an>'
$ git lg
* e6f4e18 - Merge branch 'master' of origin (1 minutes ago) <Cyn>
|\
* | abfa93b - 本地仓库的提交 (2 minutes ago) <Pete>
| * 1f1c21d - 远程仓库的提交 (3 minutes ago) <John>
|/
* 17ef24c - 基准版本 (4 minutes ago) <Jerry>

格式化输出,代码着色,而且附上了作者、提交时间和祖先图谱。

求差集

1
2
3
$ git log HEAD --not origin/master
$ git log HEAD ^origin/master
$ git log origin/master..HEAD

也可用于筛选出准备 push 到远程仓库的提交,例如:

1
2
3
4
$ git log --graph --oneline --decorate HEAD --not origin/master
* e6f4e18 (HEAD, master) Merge branch 'master' of origin
|
* abfa93b 本地仓库的提交

图形化方式

如果对输出格式还不满意,推荐使用 gitk 命令调用图形化工具查阅提交历史:

gitk

上半个窗口显示的是历次提交的分支祖先图谱,下半个窗口显示当前点选的提交对应的具体差异(其中右边 Patch 窗口显示当前提交的文件列表,左边 Diff 窗口显示每个文件的提交差异)。

参考

Git 基础 - 查看提交历史

要想 Git 用得爽,首先要安装与配置好。

如何选择版本?

Git 1.x

旧版本,不再维护。

Git 2.x

新版本,推荐使用。不向下兼容 1.x。

如何安装?

Windows

需要安装 Git for Windows 的客户端 msysgit。推荐使用 绿色便携版 ,优势如下:

  • 无需安装,无需写注册表,无需管理员权限;
  • 可以从任意目录运行,甚至 U 盘;

与安装版的区别:

  • 不提供右键上下文菜单(如 Git GUI HereGit Bash Here),因为该功能需要写入注册表;
  • 不修改环境变量 %path% ,因此无法在命令行工具 cmd 中直接运行 git.exegitk.exe,解决办法:
    • 推荐使用自带的 Git Bash (类 Unix Shell)或 Git Cmd 进行替代;
    • 或将 %GIT_HOME%\cmd 目录永久加入环境变量 %path% (如果只想在当前会话中临时使用,只需在 cmd 中运行 set path=%GIT_HOME%\cmd;%path% 即可),然后运行 git --help 测试配置效果;

Linux / Unix

使用包管理 apt-get 或 yum 即可。

OS X

Homebrew 是最快最便捷的安装方式:

1
$ sudo brew install git

如何配置?

Git 相关的配置文件有三个:

  1. /etc/gitconfig 包含了适用于系统所有用户和所有项目的值。
  2. ~/.gitconfig 只适用于当前登录用户的配置。
  3. Git 项目中的 .git/config 适用于特定 Git 项目的配置。

对于同一配置项,三个配置文件的优先级是 3 > 2 >1。

配置提交作者

开始使用 Git 之前,第一件重要的事情就是配置提交作者,配置后就可以愉快的开始使用 Git 了。更多配置请参考 这里

首先做如下检查:

全局配置

使用 --global 查看或修改全局配置文件 ~/.gitconfig

1
$ git config -l | grep user

如果返回为空表示未配置,需要配置如下:

1
2
$ git config --global user.name "你的姓名"
$ git config --global user.email "你的邮箱"

项目配置

如果需要单独修改项目配置文件 .git/config,去掉 --global 参数即可,或者直接打开该文件添加:

1
2
3
[user]
name = who
email = who@where.com

配置格式化与空白

格式化与空白是许多开发人员在协作时,特别是在跨平台情况下,遇到的令人头疼的细小问题。由于编辑器的不同或者Windows程序员在跨平台项目中的文件行尾加入了回车换行符,一些细微的空格变化会不经意地进入大家合作的工作或提交的补丁中。不用怕,Git 的一些配置选项会帮助你解决这些问题。

core.autocrlf

Git 在你提交时自动地把行结束符 CRLF 转换成 LF,而在签出代码时把 LF 转换成 CRLF。假如团队成员只在 Windows 上写程序,可以关闭此功能,避免 Git 自动格式化代码后干扰代码对比:

1
$ git config --global core.autocrlf false

core.whitespace

Git 预先设置了一些选项来探测和修正空白问题,配置方法待补充。

常见问题

Git 长期使用上的一点不便,解决方案仅供参考。

中文乱码显示问题

  1. 打开 GitBash(git-bash.exe)后,对窗口右键->Options->Text->Locale 改为 zh_CN,Character set 改为 GBK ;

  2. 键入exit退出关闭再打开即可。

配置工作目录

Git 默认使用程序运行目录作为工作目录,这会带来使用上的不便。解决办法是新建 .bashrc 文件:

1
$ vim ~/.bashrc

添加一行:

1
2
# 请将 /d/Repos/ 替换成你的仓库目录
cd /d/Repos/

即可自动切换到本地仓库所在目录。

配置 SSH 代理和密钥

另一个潜在的问题是运行 Git Bash 并拉取远程仓库提示错误:

1
Could not open a connection to your authentication agent.

这是因为 ssh-agent 未随 bash 一起启动。你可以每次都手工启动,或推荐编写脚本自启动。

新建 .bashrc 文件,并添加如下代码:

1
2
3
4
5
6
7
8
9
#!/bin/sh
if [ -f ~/.agent.env ]; then
. ~/.agent.env >/dev/null
kill -15 $SSH_AGENT_PID
fi

echo "Starting ssh-agent..."
eval `ssh-agent |tee ~/.agent.env`
ssh-add ~/.ssh/github_rsa

这将会自启动 ssh-agent 并添加指定私钥。 ssh-agent 是一个密钥管理器,运行 ssh-agent 以后,使用 ssh-add 将指定私钥交给 ssh-agent 保管,其它程序(例如 git)在需要身份认证的时候,可以将认证申请交给 ssh-agent 来代为完成整个认证过程。

那么以后每次运行 Git Bash 的时候,就会看到输出效果如下:

1
2
3
Starting ssh-agent...
Agent pid 8828
Identity added: ~/.ssh/github_rsa

参考