Skip to content

Git 笔记系列(三)—— Git常用命令 一览

michaelmao edited this page Feb 14, 2019 · 1 revision

title: Git 笔记系列(三)—— Git常用命令-一览 date: 2018-02-28 20:20:10 tags: - Git

时间 更新备注
2018-02-28 新建文章
2018-06-08 整理补充

目录

命令

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

Git 命令图解

初始化

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

操作

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 //显示某次提交的内容
撤销操作
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

分支

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
冲突处理
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目录下日志文件记录了分支的变更。默认非裸版本库(带有工作区)都提供分支日志功能,这是因为带有工作区的版本库都有如下设置:

$ git config core.logallrefupdates
true

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

$ 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改变为9e8a761Git提供了一个git reflog命令,对这个文件进行操作。使用show子命令可以显示此文件的内容。

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

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

$ git reset --hard master@{2}

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

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

$ ls 
new-commit.txt  welcome.txt

提交历史也回来了。

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

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

$ git reflog show master | head -5
4902dc3 master@{0}: master@{2}: updating HEAD
9e8a761 master@{1}: 9e8a761: updating HEAD
e695606 master@{2}: HEAD^: updating HEAD
4902dc3 master@{3}: commit: does master follow this new commit?
e695606 master@{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合并代码

# 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)的原因以及解决办法:
 ! [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。具体做法就是:
git fetch origin
git merge origin (master)
  • 这两步其实可以简化为
git pull origin master

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

Git log

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:
git log -p 
  1. 按成员的提交历史
git shortlog
  1. 在提交的历史改动中查找关键字,-p代表显示log提交的改动
git log -S"searchKeyWord" -p

5, 搜索提交的注释

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

Git diff

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

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

git diff --staged

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


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

设置git命令 别名

$ 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 config --global alias.lg "log --all --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%ci) %C(bold blue)<%an>%Creset' --abbrev-commit"
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

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

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

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

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

1.取消global

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

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

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放到公共服务器上。

其他

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

常见命令菜单

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