19

10 个节省时间和改善工作流的 Git 技巧

 4 years ago
source link: https://www.infoq.cn/article/tgdOxMBqYHoVslvlZqxT
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Z7FrMzi.jpg!web

根据 手册 ,Git 被定义为傻瓜式内容追踪器,它功能丰富,但有些功能却让人望而生畏。因此,我们只是重复使用那几个被记住的命令,而没有充分使用。

技巧 1: 优化配置

Git 在全局、用户和本地级别上都是高度可配置的。

https://git-scm.com/docs/git-config

查找顺序

每个设置都可以被覆盖:

复制代码

$CWD/.git/config
▼ ▼ ▼
$HOME/.gitconfig`
▼ ▼ ▼
$HOME/.config/git/config
▼ ▼ ▼
/etc/gitconfig

修改设置

用你喜欢的编辑器或者 CLI 编辑任何配置文件:

复制代码

# 全局设置
gitconfig--global <keypath> <value>
# 本地设置
gitconfig<keypath> <value>

如果值包含空格字符,则需要用引号引起来。

显示当前设置

复制代码

# 显示当前设置及其来源
gitconfig--list --show-origin

一些有用的配置

复制代码

# 设定身份
gitconfig--global user.name"<your name>"
gitconfig--global user.email <your email>
# 首选编辑器
gitconfig--global core.editor vim
# 证书缓存
# WINDOWS
gitconfig--global credential.helper manager
# LINUX (超时时间——以秒为单位)
gitconfig--global credential.helper"cache --timeout=3600"
# MACOS
gitconfig--global credential.helper osxkeychain

https://git-scm.com/docs/gitcredentials

技巧 2:别名(alias)

创建一个别名来保存常用的 git 命令:

复制代码

# 创建别名
gitconfig--global alias.<alias-name>"<git command>"
# 使用别名
git <alias-name> <more optional arguments>

一些有用的别名

复制代码

# 撤销上次提交
gitconfig--global alias.undo"reset --soft HEAD^"
# 将暂存区更新修订到上次提交 (不改变提交信息)
gitconfig--global alias.amend"commit --amend --no-edit"
# 压缩的状态输出
gitconfig--global alias.st"status -sb"
# 用 GRAPH 为日志着色
gitconfig--global alias.lg"log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset'"
# 删除所有已合并的分支
gitconfig--global alias.rmb"!git branch --merged | grep -v '*' | xargs -n 1 git branch -d"
# 贡献排行
gitconfig--global alias.rank"shortlog -n -s --no-merges"

技巧 3:查找 Commits 和更改

通过 Commits 信息查找

复制代码

# 通过 commit 信息查找 (所有分支)
gitlog--all --grep='<search term>'
# 通过 commit 信息查找 (包含 reflog)
gitlog-g --grep='<search term>'

通过更改查找

复制代码

# 通过更新的内容查找
gitlog-S '<search term>'

通过日期查找

复制代码

# 通过日期范围查找
gitlog--after='DEC 152019' --until='JAN 102020'

技巧 4:添加 hunk

git add <filepath> 不仅能添加文件的所有变更, --path / -p 参数还可以交互式暂存区块。

复制代码

# 补丁命令
y = 暂存区块
n = 不暂存这个区块
q = 退出
a = 暂存当前文件的此区块以及所有剩余区块
d = 不暂存当前文件的此区块以及所有剩余区块
/ = 查找区块 (正则表达式)
s = 划分成更小的区块
e = 手动编辑区块
? = 打印帮助说明
g = 选择要前往的区块
j = 将区块设为未定,查看下一个未定区块
J = 将区块设为未定,查看下一个区块
k = 将区块设为未定,查看上一个未定区块
J = 将区块设为未定,查看下一个区块

https://git-scm.com/docs/git-add#Documentation/git-add.txt–i

技巧 5: 储藏(stash)更改而不提交

stash 将当前的更改临时搁置起来。在它的帮助下,可以返回当前状态的索引,并能在稍后应用已储藏的更改。

默认情况下,仅储藏当前跟踪文件中的更改,新文件将被忽略。

我们可以独立地创建和应用多个 stash。

https://git-scm.com/docs/git-stash

创建

复制代码

# 创建新的 STASH
git stash
# 创建新的 STASH (包含未追踪的更改)
git stash -u/--include-untracked
# 创建新的 STASH 并命名
git stash save"<stash name>"
# 交互式储藏
git stash -p

罗列

复制代码

# 列出所有的 STASH (为其他命令提供 "n")
git stashlist

浏览

复制代码

# 浏览 STASH 内容
git stashshow
# 浏览 STASH 差异
git stashshow-p

应用

复制代码

# 应用上一个 STASH (删除 stash)
git stash pop
# 应用上一个 STASH (保留 stash)
git stash apply
# 应用特定的 STASH (n = stash 列表序号)
git stash pop/apply stash@{n}
# 从 STASH 创建新的分支 (n = stash 列表序号)
git stash branch <newbranch name> stash@{n}
# 从 STASH 应用单个文件 (n = stash 列表序号)
git checkout stash@{n} -- <filepath>

清理

复制代码

# 删除特定的 STASH (n = stash 列表序号)
gitstash drop stash@{n}
# 删除所有的 STASH
gitstash clear

技巧 6:空运行(Dry Run)

许多 git 操作可能具有破坏性,例如, git clean -f 将删除所有未跟踪的文件,而且无法恢复。

要避免出现这种灾难性的结果,许多命令都支持 dry-run ,可以在实际产生结果前对其进行检查。不过遗憾的是,使用的选项不完全一致:

复制代码

git clean -n/--dry-run
gitadd-n/--dry-run
git rm -n/--dry-run
# GIT MERGE 模拟 DRY-RUN
gitmerge--no-commit --no-ff <branch>
git diff--cached
gitmerge--abort

请注意, git commit -n 根本不是 *dry-run!* 它实际上是 --no-verify ,作用是忽略所有 pre-commit / commit-msg githooks

技巧 7:安全强制推送

在处理旧的 commit、创建新的 head 等情况时时很容易弄乱分支。 git push --force 可以覆盖远程变更,但不应该这样做!

git push --force 是一种具有破坏性且危险的操作,因为它无条件生效,并且会破坏其他提交者已经推送的所有 commit。这对于其他人的代码仓库来说不一定是致命的,但是改变历史记录并影响其他人并不是一个好主意。

更好的选择是使用 git push --force-with-lease

git 不会无条件地覆盖上游的远程仓库,而是检查是否有本地不可用的远程更改。如果有,它会失败并显示一条“stale info”消息,并告诉我们需要先运行 git fetch

https://git-scm.com/docs/git-push#Documentation/git-push.txt—force-with-leaseltrefnamegt

技巧 8:修改 commit 信息

Commit 是不可变的,且不能更改。不过可以用一条新的 commit 信息修订现有的 commit,这会覆盖原始 commit,因此请勿在已推送的 commit 中使用它。

复制代码

gitcommit--amend-m"<new commit message>"

https://git-scm.com/docs/git-commit#Documentation/git-commit.txt—amend

技巧 9:修改历史

修改代码仓库的历史不仅限于修改上次提交信息,使用 git rebase 可以修改多个提交:

复制代码

# 提交的范围
git rebase -i/--interactive HEAD~<number of commits>
# 该 hash 之后的所有提交
git rebase -i/--interactive <commit hash>

在配置的编辑器中倒序列出所有的 commit,像这样:

复制代码

#<command><commit hash><commit message>
pick5df8fbc revamped logic
pick ca5154e README typos fixed
pick a104aff added awesome new feature

通过更改编辑器中的实际内容,可以为 git 提供一个方案,来说明如何进行 rebase:

复制代码

# p, pick = 使用提交而不更改
# r, reword = 修改提交信息
# e, edit = 编辑提交
# s, squash = 汇合提交
# f, fixup = 类似 "squash",但是会丢弃提交信息
# x, exec = 运行命令 (其余行)
# d, drop = 移除提交

保存编辑器后,git 将运行该方案以重写历史记录。

e, edit 会暂停 rebase,就可以编辑代码仓库的当前状态。完成编辑后,运行 git rebase --continue

如果过程中出现问题(例如合并冲突),我们需要重新开始,可以使用 git rebase --abort

https://git-scm.com/docs/git-rebase

技巧 10:存档跟踪文件

可以使用不同格式( ziptar )来压缩特定引用的跟踪文件:

复制代码

git archive --format<format> --output<filename> <ref>

<ref> 可以是一个分支、commit hash 或者一个标签。

https://git-scm.com/docs/git-archive

额外提醒:单破折号

有一个快捷方式可以表示刚用过的分支:一个单破折号 -

复制代码

git checkout my-branch
# 当前分支:my-branch
<dosome git operations, e.g. adding/commiting>
git checkout develop
# 当前分支:develop
git merge -
# 将 my-branch 合并到 develop

单破折号等同于 @{-1}

https://git-scm.com/docs/git-checkout#Documentation/git-checkout.txt-ltbranchgt

总结

Git 还有很多话题可谈,这里只涉及一些皮毛。在另一篇文章中,我想展示如何用 git bisect 有效查找损坏的 commit,或者如何通过 git reflog 来运用任意 git 操作的完整历史记录。

阅读英文:

10 Git Tips To Save Time And Improve Your Workflow


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK