Git 笔记系列(三)—— Git常用命令-一览
时间 更新备注
2018-02-28 新建文章
2018-06-08 整理补充
2019-01-18 更新链接

目录

命令

  • workspace: 本地的工作目录。(记作A)
  • index:缓存区域,临时保存本地改动。(记作B)
  • local repository: 本地仓库,只想最后一次提交HEAD。(记作C)
  • remote repository:远程仓库。(记作D)
    以下所有的命令的功能说明,都采用上述的标记的A、B、C、D的方式来阐述。

Git 命令图解

初始化

1
2
3
4
git init //创建
git clone /path/to/repository //检出
git config --global user.email "[email protected]" //配置email
git config --global user.name "Name" //配置用户名

操作

1
2
3
4
5
6
7
8
9
10
11
git add <file> // 文件添加,A → B
git add . // 所有文件添加,A → B
git commit -m "代码提交信息" //文件提交,B → C
git commit --amend //与上次commit合并, *B → C
git push origin master //推送至master分支, C → D
git pull //更新本地仓库至最新改动, D → A
git fetch //抓取远程仓库更新, D → C
git log //查看提交记录
git status //查看修改状态
git diff //查看详细修改内容
git show //显示某次提交的内容
撤销操作
1
2
3
4
5
6
git reset <file>//某个文件索引会回滚到最后一次提交, C → B
git reset//索引会回滚到最后一次提交, C → B
git reset --hard // 索引会回滚到最后一次提交, C → B → A
git checkout // 从index复制到workspace, B → A
git checkout -- files // 文件从index复制到workspace,用来丢弃本地修改, B → A
git checkout HEAD -- files // 文件从local repository复制到workspace, C → A

分支

1
2
3
4
5
6
git checkout -b branch_name //创建名叫“branch_name”的分支,并切换过去
git checkout master //切换回主分支
git branch -d branch_name // 删除名叫“branch_name”的分支
git push origin branch_name //推送分支到远端仓库
git merge branch_name // 合并分支branch_name到当前分支(如master)
git rebase //衍合,线性化的自动, D → A
冲突处理
1
2
3
4
git diff //对比workspace与index
git diff HEAD //对于workspace与最后一次commit
git diff <source_branch> <target_branch> //对比差异
git add <filename> //修改完冲突,需要add以标记合并成功

git reset

详细见Git 笔记系列(五)—— Git常用命令-Reset

重置命令(git reset)是Git最常用的命令之一,也是最危险,最容易误用的命令。来看看git reset命令的用法。

用法一:git reset [-q] [<commit>] [--] <paths>...

用法二:git reset [--soft | --mixed | --hard | --merge | --keep] [-q] [<commit>]

上面列出了两个用法,其中<commit>都是可选项,可以使用引用或者提交ID,如果省略 <commit>则相当于使用了HEAD的指向作为提交ID
上面列出的两种用法的区别在于,第一种用法在命令中包含路径<paths>。为了避免路径和引用(或者提交ID)同名而冲突,可以在<paths>前用两个连续的短线(减号)作为分隔。

第一种用法(包含了路径<paths>的用法)不会重置引用,更不会改变工作区,而是用指定提交状态(<commit>)下的文件(<paths>)替换掉暂存区中的文件。例如命令git reset HEAD <paths>相当于取消之前执行的git add <paths>命令时改变的暂存区。

第二种用法(不使用路径的用法)则会重置引用。根据不同的选项,可以对暂存区或者工作区进行重置。参照下面的版本库模型图,来看一看不同的参数对第二种重置语法的影响。

git reflog

如果没有记下重置前master分支指向的提交ID,想要重置回原来的提交真的是一件麻烦的事情(去对象库中一个一个地找)。幸好Git提供了一个挽救机制,通过.git/logs目录下日志文件记录了分支的变更。默认非裸版本库(带有工作区)都提供分支日志功能,这是因为带有工作区的版本库都有如下设置:

1
2
$ git config core.logallrefupdates
true

查看一下master分支的日志文件.git/logs/refs/heads/master中的内容。下面命令显示了该文件的最后几行。为了排版的需要,还将输出中的40位的SHA1提交ID缩短形式。

1
2
3
4
5
6
$ tail -5 .git/logs/refs/heads/master
dca47ab a0c641e Jiang Xin <[email protected]> 1290999606 +0800 commit (amend): who does commit?
a0c641e e695606 Jiang Xin <[email protected]> 1291022581 +0800 commit: which version checked in?
e695606 4902dc3 Jiang Xin <[email protected]> 1291435985 +0800 commit: does master follow this new commit?
4902dc3 e695606 Jiang Xin <[email protected]> 1291436302 +0800 HEAD^: updating HEAD
e695606 9e8a761 Jiang Xin <[email protected]> 1291436382 +0800 9e8a761: updating HEAD

可以看出这个文件记录了master分支指向的变迁,最新的改变追加到文件的末尾因此最后出现。最后一行可以看出因为执行了git reset –hard命令,指向的提交IDe695606改变为9e8a761
Git提供了一个git reflog命令,对这个文件进行操作。使用show子命令可以显示此文件的内容。

1
2
3
4
5
6
$ git reflog show master | head -5
9e8a761 [email protected]{0}: 9e8a761: updating HEAD
e695606 [email protected]{1}: HEAD^: updating HEAD
4902dc3 [email protected]{2}: commit: does master follow this new commit?
e695606 [email protected]{3}: commit: which version checked in?
a0c641e [email protected]{4}: commit (amend): who does commit?

使用git reflog的输出和直接查看日志文件最大的不同在于显示顺序的不同,即最新改变放在了最前面显示,而且只显示每次改变的最终的SHA1哈希值。还有个重要的区别在于使用git reflog的输出中还提供一个方便易记的表达式:<refname>@{<n>}。这个表达式的含义是引用<refname>之前第<n>次改变时的SHA1哈希值。
那么将引用master切换到两次变更之前的值,可以使用下面的命令。
重置master为两次改变之前的值。

1
$ git reset --hard [email protected]{2}

HEAD is now at 4902dc3 does master follow this new commit?

重置后工作区中文件new-commit.txt又回来了。

1
2
$ ls 
new-commit.txt welcome.txt

提交历史也回来了。

1
2
3
4
5
$ git log --oneline
4902dc3 does master follow this new commit?
e695606 which version checked in?
a0c641e who does commit?
9e8a761 initialized.

此时如果再用git reflog查看,会看到恢复master的操作也记录在日志中了。

1
2
3
4
5
6
$ git reflog show master | head -5
4902dc3 [email protected]{0}: [email protected]{2}: updating HEAD
9e8a761 [email protected]{1}: 9e8a761: updating HEAD
e695606 [email protected]{2}: HEAD^: updating HEAD
4902dc3 [email protected]{3}: commit: does master follow this new commit?
e695606 [email protected]{4}: commit: which version checked in?

git remote

  1. 添加远程库: $ git remote add origin
  2. 移除远程库: $ git remote remove (OrignName)
  3. 查看远程库: $ git remote -v(–verbose)

git grep查找

git grep -n "要查找的字符串"

  1. -W 查找函数上下文
  2. 使用 –count 参数, 只会显示在哪个文件里有几个要查找的字符串, 如下:
    git grep --count "(defun format "

    src/format.lisp:1

可以使用 $ git help grep 来查看帮助

Git 其他常用命令

Git undo撤销方法

  1. git revert <SHA>
  2. git commit --amend -m "Modify last add message"
  3. 撤销本地的修改git checkout -- <bad filename>
  4. 重置本地的修改git reset <last good SHA>

Git的各种Undo技巧

Git Merge

使用XcodeFileMerge合并代码

1
2
3
4
5
# Tell system when Xcode utilities live:
sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer

# Set "opendiff" as the default mergetool globally:
git config --global merge.tool opendiff
  1. 代码冲突! [rejected] master -> master (non-fast-forward)的原因以及解决办法:
1
2
3
4
5
 ! [rejected]        master ->  master (non-fast-forward)  
error: failed to push some refs to '[email protected]:archermind/LEDTorch.apk-for-Android.git'
To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes before pushing again. See the 'Note about
fast-forwards' section of 'git push --help' for details.

操作命令:

  • 正确的做法是,在push之前git fetch origin,将github上的新代码拉下来,然后在本地merge,如果没有冲突就可以push了,如果有冲突的话要在本地解决冲突后,再push。具体做法就是:
1
2
git fetch origin
git merge origin (master)
  • 这两步其实可以简化为
1
git pull origin master

git-fetch - Download objects and refs from another repository
git-merge - Join two or more development histories together

Git log

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
Table 3. 限制 git log 输出的选项
选项 说明
-(n)

仅显示最近的 n 条提交

--since, --after

仅显示指定时间之后的提交。

--until, --before

仅显示指定时间之前的提交。

--author

仅显示指定作者相关的提交。

--committer

仅显示指定提交者相关的提交。

--grep

仅显示含指定关键字的提交

-S

仅显示添加或移除了某个关键字的提交

来看一个实际的例子,如果要查看 Git 仓库中,2008 年 10 月期间,Junio Hamano 提交的但未合并的测试文件,可以用下面的查询命令:

$ git log --pretty="%h - %s" --author=gitster --since="2008-10-01" \
--before="2008-11-01" --no-merges -- t/
5610e3b - Fix testcase failure when extended attributes are in use
acd3b9e - Enhance hold_lock_file_for_{update,append}() API
f563754 - demonstrate breakage of detached checkout with symbolic link HEAD
d1a43f2 - reset --hard/read-tree --reset -u: remove unmerged new paths
51a94af - Fix "checkout --track -b newbranch" on detached HEAD
b0ad11e - pull: allow "git pull origin $something:$current_branch" into an unborn branch
在近 40000 条提交中,上面的输出仅列出了符合条件的 6 条记录。
  1. 显示每次提交的diff:
1
git log -p
  1. 按成员的提交历史
1
git shortlog
  1. 在提交的历史改动中查找关键字,-p代表显示log提交的改动
1
git log -S"searchKeyWord" -p

5, 搜索提交的注释

1
git log --grep=“keyWord”
  1. 搜索某个用户的提交
1
git log --author=“authorName”

Git diff

通过使用不同的参数调用git diff命令,可以对工作区、暂存区、HEAD中的内容两两比较。下面的这个图,展示了不同的git diff命令的作用范围。


diff: 分支点之间的变化
分支点的继承
当add了change后, git diff是不会显示已经add后的change的,可以制定stage的diff

1
git diff --staged

Git 比较不同版本文件差异的常用命令格式:

1
2
3
4
5
6
7
8
9
10
11
12

git diff 查看尚未暂存的文件更新了哪些部分

git diff filename 查看尚未暂存的某个文件更新了哪些

git diff –cached 查看已经暂存起来的文件和上次提交的版本之间的差异

git diff –cached filename 查看已经暂存起来的某个文件和上次提交的版本之间的差异

git diff ffd98b291e0caa6c33575c1ef465eae661ce40c9 b8e7b00c02b95b320f14b625663fdecf2d63e74c 查看某两个版本之间的差异

git diff ffd98b291e0caa6c33575c1ef465eae661ce40c9:filename b8e7b00c02b95b320f14b625663fdecf2d63e74c:filename 查看某两个版本的某个文件之间的差异

Git config

Git的配置

  1. 列出Git全局配置列表
1
git config --global --list
  1. 列出Git本地仓库配置列表
1
git config --local --list
  1. 设置用户名,邮箱密码等
1
2
$ git config --global user.name "John Doe"
$ git config --global user.email [email protected]
  1. 设置编辑器
1
$ git config --global core.editor emacs

设置git命令 别名

1
2
3
4
5
6
7
$ git config --global alias.st status
$ git config --global alias.co checkout
$ git config --global alias.ct commit
$ git config --global alias.df diff
$ git config --global alias.br branch
#git lg to view commit log like network graph
$
Git命令的别名

有些Git的命令很长,如果经常输入就很繁琐,通过设置Git的别名,可以简化输入,提交效率,这里推荐一个Git的别名库,方便使用各种Git命令。

git-extras/Commands.md at master · tj/git-extrasGIT utilities – repo summary, repl, changelog population, author commit percentages and more

Cheatsheet · robbyrussell/oh-my-zsh Wiki

Alias Command
_g_ git
_ga_ git add
gau git add -u
gaa git add –all
gapa git add –patch
_gb_ git branch
gba git branch -a
gbd git branch -d
gbl git blame -b -w
gbnm git branch –no-merged
gbr git branch –remote
gbs git bisect
gbsb git bisect bad
gbsg git bisect good
gbsr git bisect reset
gbss git bisect start
_gc_ git commit -v
gc! git commit -v –amend
gca git commit -v -a
gca! git commit -v -a –amend
gcan! git commit -v -a –no-edit –amend
gcans! git commit -v -a -s –no-edit –amend
gcam git commit -a -m
gcsm git commit -s -m
gcb git checkout -b
gcf git config –list
gcl git clone –recursive
gclean git clean -fd
gpristine git reset –hard && git clean -dfx
gcm git checkout master
gcd git checkout develop
gcmsg git commit -m
gco git checkout
gcount git shortlog -sn
gcp git cherry-pick
gcpa git cherry-pick –abort
gcpc git cherry-pick –continue
gcs git commit -S
_gd_ git diff
gdca git diff –cached
gdct git describe –tags git rev-list --tags --max-count=1
gdt git diff-tree –no-commit-id –name-only -r
gdw git diff –word-diff
_gf_ git fetch
gfa git fetch –all –prune
gfo git fetch origin
_gg_ git gui citool
gga git gui citool –amend
ggpnp git pull origin $(current_branch) && git push origin $(current_branch)
ggpull git pull origin $(current_branch)
ggl git pull origin $(current_branch)
ggpur git pull –rebase origin $(current_branch)
glum git pull upstream master
ggpush git push origin $(current_branch)
ggp git push origin $(current_branch)
ggfl git push –force-with-lease origin <your_argument>/$(current_branch)
ggsup git branch –set-upstream-to=origin/$(current_branch)
gpsup git push –set-upstream origin $(current_branch)
gignore git update-index –assume-unchanged
gignored git ls-files -v grep “^:lower:
git-svn-dcommit-push git svn dcommit && git push github master:svntrunk
_gk_ gitk –all –branches
_gl_ git pull
glg git log –stat –max-count = 10
glgg git log –graph –max-count = 10
glgga git log –graph –decorate –all
glo git log –oneline –decorate –color
glog git log –oneline –decorate –color –graph
glp _git_log_prettily (git log –pretty=$1)
_gm_ git merge
gma git merge –abort
gmt git mergetool –no-prompt
_gp_ git push
gpoat git push origin –all && git push origin –tags
_gr_ git remote
grb git rebase
grba git rebase –abort
grbc git rebase –continue
grbd git rebase develop
grbm git rebase master
grbs git rebase –skip
grbi git rebase -i
grh git reset HEAD
grhh git reset HEAD –hard
grmv git remote rename
grrm git remote remove
grset git remote set-url
grt cd $(git rev-parse –show-toplevel echo “.”)
grup git remote update
grv git remote -v
gsd git svn dcommit
gsps git show –pretty = short –show-signature
gsr git svn rebase
gss git status -s
gst git status
gsta git stash save
gstaa git stash apply
gstd git stash drop
gstl git stash list
gstp git stash pop
gsts git stash show –text
gsu git submodule update
gts git tag -s
gunignore git update-index –no-assume-unchanged
gunwip git log -n 1 grep -q -c “–wip–” && git reset HEAD~1
gup git pull –rebase
gvt git verify-tag
gwch git whatchanged -p –abbrev-commit –pretty = medium
gwip git add -A; git ls-files –deleted -z xargs -r0 git rm; git commit -m “–wip–”

同一台电脑可以有2个git账号(不同网站的)

1.同一台电脑可以有2个git账号(不同网站的)

这种情况下,需要几点注意

1.remote pull push的时候有问题,因为要设置邮箱问题了 pull的时候识别的是邮箱,2个github账号,2个邮箱,我们自然不能使用global的user.email了

1.取消global

1
2
git config --global --unset user.name
git config --global --unset user.email

2.设置每个项目repo的自己的user.email

1
2
git config  user.email "[email protected]"
git config user.name "suzie"

之后push pull就木有问题了

备注
生成ssh key

ssh-keygen -m rsa -C "your mail (当前目录) 然后可以命名默认id_rsa或者id_rsa_second 把对应的pub放到公共服务器上。

其他

1
2
3
4
gitk //开灯图形化git
git config color.ui true //彩色的 git 输出
git config format.pretty oneline //显示历史记录时,每个提交的信息只显示一行
git add -i //交互式添加文件到暂存区

Githug

Githug is designed to give you a practical way of learning git. It has a series of levels, each requiring you to use git commands to arrive at a correct answer.

Gazler/githug: Git your game on!

常见命令菜单

Git Cheat Sheet Part1

看了前面那么多命令,是不是有点多了?ㄟ( ▔, ▔ )ㄏ平时开发用的到那么多命令吗?Don`t worry,常用的命令只需看下面几张图即可:

Git Cheat Sheet

Git Cheet Sheet Part2


参考

  1. git reset soft,hard,mixed之区别深解
  2. Git - git-reset Documentation
文章作者: MichaelMao
文章链接: http://frizzlefur.com/2018/02/28/Git 笔记系列(三)—— Git常用命令-一览/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 MMao
我要吐槽下