Git
19 May 2015

Git中你不知道的秘密

注: 下面的一些命令和参数需要git 1.7.2以上的版本.


日志内显示branches, tags

$ git log --oneline --decorate
7466000 (HEAD, mislav/master, mislav) fix test that fails if current dir is not "hub"
494a414 fix cherry-pick of a commit URL
4277848 (origin/master, origin/HEAD, master) whoops
d270fae bugfix: git init -g
9307af3 test deps
8ccc17e http://github.com/defunkt/hub/contributors
64bb19c bugfix: variable name
546726a dont need you
3a8d7af (tag: v1.3.1) v1.3.1
197f429 (tag: v1.3.0) v1.3.0
a1e1a50 not important
3c6af16 magic `cherry-pick` supports GitHub commit URLs and "user@sha" notation

比较版本变化时, 只高亮行内改动, 而非整行

$ git diff --word-diff
# Returns a Boolean.
def command?(name)
  `type -t [-#{command}`-]{+#{name}`+}
  $?.success?
end

这个选项也适用于其他可以接受diff标记的git命令(比如: git log -p 和 git show).


简短的状态信息

$ git status -sb

## thibaudgg...thibaudgg/master [ahead 1, behind 2]
 M ext/fsevent/fsevent_watch.c
?? Makefile
?? SCEvents/
?? bin/fsevent_watch

默认, 长状态输出对于新手是OK的, 但是一旦你对git渐渐熟练了起来, 那冗长的状态信息就没显得必要了. 由于我经常查看状态信息, 所以我想把它变得尽量的简洁.


推送分支并自动设置追踪

$ git push -u origin master

# pushes the "master" branch to "origin" remote and sets up tracking

“追踪”本质上来说就是在本地与远程分支之间的一个链接. 当一个本地分支追踪了某个分支时, 可以直接使用 git pull 和 git push, 而不用添加任何额外的参数, git会自动解析追踪的分支.

然而, git pul 会默认推送所有远程的同名分支. 为了限制这个行为, 从而只推送当前分支, 需要添加下面的配置:

$ git config --global push.default tracking

这样就防止了计划之外的分支推送.


简单的从其他分支追踪远程分支

$ git checkout -t origin/feature

# creates and checks out "feature" branch that tracks "origin/feature"

一旦你的同事共享了他正在工作的分支, 如果你需要在上面做修改, 就需要创建一个本地分支. 上面的命令就完成了你需要的操作, 并且设置了追踪分支, 以便于你可以在完成修改后进行 git push.


检出分支, 衍合与合并分支

# on branch "master":
$ git checkout feature && git rebase @{-1} && git checkout @{-2} && git merge @{-1}

# rebases "feature" to "master" and merges it in to master

”@{-n}” 语法表示 “当前分支之前的第 n 个检出的分支”. 当检出了 “feature”, “@{-1}” 就指向了 “master”. 在执行了 rebase 之后, 就需要通过 “@{-2}” 来检出 master, 这是因为 rebase 的内部操作已经使 “@{-1}” 指向了 “feature”.

更新: Björn Steinbrink 指出这个操作可以只用2个命令来完成:

$ git rebase HEAD feature && git rebase HEAD @{-2}

使用衍合(rebase)取代合并(merge)进行pull操作

$ git pull --rebase

# e.g. if on branch "master": performs a `git fetch origin`,
# then `git rebase origin/master`

因为 git 中的分支的合并会添加一个合并的提交记录, 这其实是有它存在的意义的, 举个例子, 可以用来展现某功能是何时合并到发布分支. 然而, 在日常的工作中, 当组员们经常会同步某分支时, 这些不必要的合并记录会污染时间线. 衍合保证了所有的提交总是重新做一遍, 从而保证历史是线性的.

可以配置特定的分支, 而不需要总是添加 –rebase 标识:

# make `git pull` on master always use rebase
$ git config branch.master.rebase true

也可以通过全局配置的属性来为新的追踪分支配置此功能:

# setup rebase for every tracking branch
$ git config --global branch.autosetuprebase always

查找某变更是否是发布的一部分

$ git name-rev --name-only 50f3754

"tags/v2.3.8~6"

通常大家只知道某次提交的 SHA-1 而不清楚具体存在于项目历史的哪个位置. 如果你有这样的情况, 你或许想了解这次变更是否属于某次发布的一部分. 其实可以通过 git show 来看提交信息, 时间和全部的变更比对, 但是这并没有给我们带来具体的帮助, 因为比较项目历史内的提交时间对于它们最后实际应用 的顺序是意义不大的.

name-rev 命令则可以展示某次提交相比于项目内标签的位置. 上面的例子源自于 Ruby on Rails 项目. 命令展示了这次提交被定位在了 “v2.3.8” 被打标签的前6个提交. 现在就可以确定这次变更是 Rails 2.3.8 的一部分了.

这个命令还有很多用处. 设想你在一次讨论中有一些被提及的提交:

这个 bug 在 e6cadd422b72ba9818cc2f3b22243a6aa754c9f8 被引入, 而在 50f3754525c61e3ea84a407eb571617f2f39d6fe 被修复.

可以将这些信息拷贝到剪贴板并作为 git name-rev 的参数, 命令会识别提交的 SHA 并添加标签信息到上面:

$ pbpaste | git name-rev --stdin

"This bug was introduced in e6cadd422b72ba9818cc2f3b22243a6aa754c9f8 (tags/v2.3.6~215)
but fixed in 50f3754525c61e3ea84a407eb571617f2f39d6fe (tags/v2.3.8~6), if I recall
correctly."

可以参考: git help describe


查找某变更在哪个分支内

$ git branch --contains 50f3754

这个命令过滤了分支的列表, 只展现指定的提交是其祖先的分支. 如果需要也包含远程追踪分支, 则可以添加 “-a” 标识.


查看分支内的哪些变更也存于上游

# while on "feature" branch:
$ git cherry -v master

+ 497034f2 Listener.new now accepts a hash of options
- 2d0333ff cache the absolute images path for growl messages
+ e4406858 rename Listener#run to #start

cherry 命令对于查看哪些提交已经从开发分支被挑选到稳定分支. 命令比较了当前分支(“feature”)与上游分支(“master”)的变更, 并通过 “-“ 符号显示两者都有的变更. 上游分支缺失的变更则通过 “+” 符号标记.


展现提交信息匹配某个正则表达式的最后一次提交

$ git show :/fix
# shows the last commit which has the word "fix" in its message

$ git show :/^Merge
# shows the last merge commit

读取一组远程仓库

$ git config remotes.default 'origin mislav staging'
$ git remote update

# fetches remotes "origin", "mislav", and "staging"

可以通过 remote update 命令定义一个远程仓库的默认列表. 这个列表可能包括: 同事, 开源项目的受信任的社区成员, 等等. 也可以定义命名组, 例如:

$ git config remotes.mygroup 'remote1 remote2 ...'
$ git fetch mygroup

编写提交注解

$ git notes add
# opens the editor to add a note to the last commit

Git notes 是针对已存的提交的注解. 它们不修改历史, 因此可以为已存的提交进行随意添加. 这些注解只存储在你的仓库内, 但是可以共享出去. (这里)[http://lists-archives.org/git/709977-git-notes-notes.html]还有一些有趣的注解的用例.


安装 “hub”

Git + Hub = GitHub. 如果你正在使用GitHub上的仓库, 你绝对需要安装 hub, 如果你参与了开源项目, 这会帮助你减少大量的按键次数.


参考

07 Feb 2014 ▸ Every line of code is always documented 10 Dec 2013 ▸ Speeding up Travis CI builds 28 Jul 2013 ▸ SSLError and Rubyist, sitting in a tree



Tags:
0 comments