常用Git命令

工作中用过的命令~

编辑状态维护


  • 文件位置

    • 工作区
    • 暂存区
    • 仓库区
  • 文件状态

    • Untracked: 本地新建的尚未被仓库跟踪的文件
    • Unmodify: 仓库有并且本地没修改
    • Modified: 仓库已有,本地修改
    • Staged: 暂存,作为提交的范围
  • 状态查看

1
git status
  • 放弃对文件的修改
    重新从库里取出一份,即回到未修改状态
1
git checkout -- <file>
  • 放弃对当前目录的修改
1
git checkout -- .
  • 取消暂存状态
1
git reset HEAD <file>
  • 放弃最近提交的修改,回到指定提交的状态
    不保留后续修改
1
git reset --hard <commit>

后续修改保留,回到暂存状态

1
git reset --soft <commit>

※ reset本质上是移动头指针指向历史的某个提交,并非删除修改

也可用来强制把本地分支和远程同步

1
git reset --hard origin/<branch>
  • 将全部改动加入暂存
    包括未跟踪
1
git add --all
  • 只加入修改的内容
    不包含未跟踪
1
git add --update
  • 加入部分修改
    一个文件修改了多处,但是不想一次全部提交
    一次提交只解决一个问题更加清晰
    执行后进行交互,会询问每个修改块是否暂存
1
git add --patch <file>
  • 删除未暂存文件
    物理删除并且把改动加入暂存,会进入提交范围;不通过git直接删已跟踪的文件,不会进入暂存
1
git rm <file>
  • 删除已暂存文件
    物理删除文件,同时解除已经暂存的改动
1
git rm -f <file>
  • 递归删除
    接受正则表达式,但是要注意转义,不转义走shell模式,只会删除当前目录下,转义后作为一个pattern被git接受,可以递归
1
git rm \*.log
  • 清除新增文件和目录,即未跟踪部分
    选项f代表强制,选项d代表目录
1
git clean -fd

选项n并不真正清空,可以告知要删哪些内容,起到确认作用,推荐先执行一遍

1
git clean -nfd
  • 脱离仓库
    不物理删除文件,但是放弃管理这个文件,即相当于删除远程仓库文件,恢复成未跟踪状态
    比如.gitignore遗漏的文件,已被仓库管理
1
git rm --cached <file>
  • 改名
    相当于rmadd的综合体
1
git mv <old-file> <new-file>

分支管理


  • 切换到已有分支
1
git checkout <branch>
  • 以当前分支为基准新建分支并进入
1
git checkout -b <branch>
  • 创建同名跟踪分支
1
git checkout --track <remote>/<branch>
  • 创建不同名跟踪分支
1
git checkout -b <local-branch> <remote>/<remote-branch>
  • 列出本地分支
1
git branch
  • 同时显示最后一次提交
1
git branch -v
  • 列出包含指定提交的分支
    可用于验证cherry-pick结果
1
git branch --contains <commit>
  • 列出远程分支
1
git branch --remotes
  • 以当前分支为基准,本地新建分支
1
git branch <branch>
  • 以指定提交为基准,创建分支
1
git branch <branch> <commit>
  • 本地删除分支
    如果分支没合并过,会有提示
1
git branch -d <branch>

强制删除

1
git branch -D <branch>

※ 删除分支其实只是删除了一个指针

  • 跟踪指定的远程分支
1
git branch --set-upstream <local-branch> <remote>:<remote-branch>
  • 删除远程分支
1
git push <remote> --delete <remote-branch>

另一种语法,语义相当于把本地空白推送到远程

1
git push <remote>  :<branch>

提交


  • 跳过暂存,提交所有已跟踪的文件
    即新增文件不会被提交
1
git commit -a
  • 撤销提交
    撤销上次
1
git revert HEAD

撤销指定的提交

1
git revert <commit>

※ revert撤销不会修改已有历史,而是生成新的提交反作用抵消

  • 写错了提交信息,修改最近一次提交的message
1
git commit --amend
  • 少提交了文件
    表面上是修改,实际上是用新提交替换,只适合改本地,不适合改远程仓库的提交
1
2
git add <file>
git commit --amend --no-edit
  • 合并一段线性提交
    指定最老的提交,在此提交之后的就是本次操作范围,执行后进入编辑模式
  • pick:原样保留这个提交
  • reword: 保留但是需要修改提交信息,即修改历史提交信息
  • edit: 编辑提交
  • squash: 合并这个提交
  • fixup: 合并同时丢弃提交信息
  • drop: 丢弃
1
git rebase -i <commit>
  • 合并过程中可能有冲突中间状态
    • abort: 放弃本次的合并操作
    • continue: 解决冲突后继续合并
    • skip: 无视冲突继续合并
1
2
3
git rebase --abort
git rebase --continue
git rebase --skip

其他变更操作也可以在这个模式里完成

  • 改变提交顺序,直接文本编辑调整里面提交的顺序即可
  • 拆分提交,选择edit,会回到暂存状态,结合reset命令可以重新进行提交

※ 注意修改会导致新的提交,如果修改了中间一个提交,那么后续所有提交哈希值都会变化,即后续其实是新的提交,头指针指向新的,旧的被丢弃

  • 从所有提交中删除文件
    比如以前错误的加了某个文件,现在要在历史里也彻底清除这个文件
1
git filter-branch --tree-filter 'rm -f xxx.txt' HEAD
  • 将子目录设为根目录
    改变目录后,跟这个目录无关的提交会被排除
1
git filter-branch --subdirectory-filter <folder> HEAD
  • 全局修改邮件地址
1
2
3
4
5
6
7
8
9
git filter-branch --commit-filter '
if [ "$GIT_AUTHOR_EMAIL" = "aaa@example.com" ];
then
GIT_AUTHOR_NAME="AAA";
GIT_AUTHOR_EMAIL="bbb@example.com";
git commit-tree "$@";
else
git commit-tree "$@";
fi' HEAD

分支合并


  • 以当前分支为基础,合并指定分支
1
git merge <branch>
  • 合并进来,但是不自动提交
    默认行为是直接生成一个新提交代表合并后的结果
    可以先合并过来,后期自己手动进行提交
1
git merge --no-commit <branch>
  • 局部合并
    不合并整个分支,而是合并单独挑出的几个提交
1
git cherry-pick <commit>
  • 查找公共祖先
1
git merge-base <branch1> <branch2>
  • 改动融合到主分支之后
    先找两个分支的公共祖先,然后将特性分支在主分支之后重演
1
git rebase <base-branch> <feature-branch>
  • 指定主干分支,将特性分支与参照分支公共祖先之后的部分接上
    即比较两个分支,取出特性分支的独有部分,接到主干分支后面
1
git rebase --onto <base-branch> <reference-branch> <feature-branch>

配置及管理


  • 初始化
    在普通目录中新建.git,为托管做准备
1
git init
  • 添加远程仓库信息
    比如本地新建项目时,添加远程仓库信息
1
git remote add <remote> <address>
  • 删除远程仓库信息
1
git remote rm <remote>
  • 列出所有远程仓库名称
1
git remote
  • 查看远程仓库地址
1
git remote --verbose
  • 列出综合后生效的配置信息,可加三类限制查看各级的配置
    针对全局的设置在/etc/gitconfig,使用--system
    针对用户的设置在~/.gitconfig,使用--global
    针对项目的设置在.git/config,使用--local
1
git config --list
  • 显示单个配置项
    比如显示用户名
1
git config --get user.name
  • 设置信息,通常要设置用户名称user.name和邮箱user.email
1
git config --global user.name <name>
  • 重置配置项,比如取消代理
1
git config --global unset http.proxy
  • 记住密码
1
git config --global credential.helper store

临时记住,默认15分钟

1
git config --global credential.helper cache
  • 支持长文件路径
1
git config --global core.longpaths true

标记


  • 给提交打上标签
    给哈希吗关联一个别名
1
git tag <tag> <commit>
  • 删除标签
1
git tag -d <tag>
  • 显示已有标签
1
git tag
  • 显示对应提交内容
    标签就视为提交的别名,直接show
1
git show <tag>

本地远程数据同步


  • 默认推送
    推送到默认远程仓库,与当前分支名相同的分支
1
git push
  • 推送与远程分支名不同的分支
1
git push <remote> <local-branch>:<remote-branch>
  • 强行推送
    适合本地已经和远程不兼容,以本地为准的情况
1
git push -f
  • 强行推送前检查
    强行推送会强制覆盖,有可能丢失远程新加的内容
    更安全的方式是检查,远程如果有新更新会拒绝
1
git push --force-with-lease
  • 更新本地的远程内容
    取回远程分支的最新内容,不和本地合并
    远程内容在本地以remote/branch的形式存在
1
git fetch <remote> <remote-branch>
  • 拉取远程最新内容,并与当前合并
    相当于fetchmerge结合
1
git pull <remote> <remote-branch>
  • 拉取远程最新内容,指定以衍和方式进行合并
    相当于fetchrebase结合
1
git pull --rebase origin develop

检查


  • 检查空白字符
    默认配置检查末尾空格和空格后Tab字符
1
git diff --check

查找提交记录


  • 当前分支提交记录
1
git log
  • 显示修改行数统计
1
git log --stat
  • 显示指定作者
1
git log --author=<author>
  • 显示时间范围
    多种时间表达式
  • n.days/weeks
  • “yyyy-MM-dd”
1
git log --since <datetime>
  • 图形化展示
1
git log --oneline --decorate --graph --all
1
git log --graph --abbrev-commit --date=relative --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset'
  • 只看关于某个目录或文件的提交
1
git log -- <file>
  • 查看提交信息中包含指定内容的提交
1
git log --grep <content>
  • 查看改动中包含指定内容的提交
1
git log -S<content>
  • 展示具体内容修改
1
git log -p
  • 只显示纯提交,忽略合并
1
git log --no-merges
  • 限制显示数量
    最近n条
1
git log -<n>
  • 以单词形式显示内容修改
    适用于查看纯文本修改
1
git log -p --word-diff
  • 查看在基准分支上新增的提交
    即把原来分支上已有的提交排除掉
1
git log <feature-branch> --not <main-branch>

或者用上三角表示排除

1
git log ^<main-branch> <feature-branch>

或者使用双点操作符

1
git log <main-branch>..<feature-branch>
  • 分支提交记录差异,左右箭头指示在哪个分支
1
git log --left-right <branch1>...<branch2>
  • 单行显示每个提交
    单行显示并且使用短哈希码,相当于--pretty=oneline--abbrev-commit的组合
1
git log --oneline
  • 查看每行代码的修改历史
1
git blame <file>

限制行数范围

1
git blame -L <from>,<to> <file>

同时检测原始出处,是否复制重命名而来

1
git blame -C <file>

差异比较


  • 当前最新和暂存之间比较
    即尚未暂存的改动
1
git diff <file>
  • 当前最新和上次提交之间比较
1
git diff HEAD <file>
  • 暂存和上次提交之间比较
1
git diff --cached <file>
  • 只显示相对路径文件名和总改动行数
1
git diff <branch1> <branch2> --stat
  • 以公共祖先为基准的比较
    特性分支原来从主干分支而来,后来主干有了新修改,那么直接和主干比较不合适
    应该以当时的主干节点为基准,即公共祖先
1
git diff <main-branch1>...<feature-branch2>

分支比较,显示具体增删行数和绝对路径文件名

1
git diff <branch1> <branch2> --numstat

提交之间比较

1
git diff <commit> <commit> -- <file>

分支比较 特定文件

1
git diff <branch1> <branch2> -- <file>

※ 分支名就是指针,本质和提交等价

特定类型文件,只显示修改的文件, include

1
git diff <branch1> <branch2> --diff-filter=M

小写表示不显示修改的文件, exclude

1
git diff <branch1> <branch2> --diff-filter=m

查看上次提交

1
git show

查看单次提交的改动

1
git show <commit>

Shortlog


按作者统计提交列表
s不显示具体提交信息只显示提交数量,n按数量排序

1
git shortlog -sn

Clone


下载后进入指定分支,默认是master分支

1
git clone <repo> -b <branch>

只下载指定分支最新的commit, 可以避免项目过大时全部下载慢

1
git clone <repo> --b <branch> --single--branch --depth=1

指定远程名字,默认是origin

1
git clone -o hostname <remote>

下载到指定目录
默认会在当前目录下新建项目名目录

1
git clone <repo> <folder>

储藏


工作到一半,需要切换分支,但又不想提交这个未完成部分

1
git stash

储藏是堆栈结构,可以储藏多份,查看列表
stash@{n}区分多次储藏

1
git stash list

重新应用储藏内容

1
git stash apply <stash>

删除储藏内容

1
git stash drop <stash>

应用最近一次储藏并删除

1
git stash pop

应用储藏后撤销

1
git stash show -p <stash> | git apply -R

以应用储藏内容后的结果创建新分支

1
git stash <stash> branch <branch>

引用日志


查看HEAD的移动历史,仅本地保存
通过可以找出已经不在历史中的游离的提交,比如本地不小心reset后退,可以通过reflog查找先前的提交,再恢复回去
引用作为一道安全屏障前提是本地要有提交,并且没超过90天的过期期限

1
git reflog

查看引用日志详细信息

1
git log -g

子模块


将一个仓库作为子模块,放在指定文件夹下
执行后会产生.gitmodules文件记录子模块地址
而文件夹作为一个特殊的链接,指向了子模块项目的一个提交

1
git submodule add <repo> <folder>

连同子模块下载,不加参数的话子模块将是空的

1
git clone --recurse-submodules <repo>

更新主项目时只更新了子模块指针,但是子模块代码没有同时更新

1
git submodule update

忽略文件


.gitignore模板
https://github.com/github/gitignore

检查哪一行配置造成了文件忽略

1
git check-ignore <file>

文件入库,但是忽略本地修改
比如库里有标准配置,每个开发有自己配置,不提交

1
2
git update-index --assume-unchanged <file>
git update-index --no-assume-unchanged <file>

显示被忽略文件列表

1
git ls-files -v | grep ^[a-z]

强制加入被忽略文件

1
git add -f <file>

git是不跟踪文件夹的,如果文件夹为空,无法提交到远端
解决方式是在文件夹下建立.gitkeep文件

图形工具


提交历史

1
gitk

解决冲突

1
git mergetool

kdiff3配置

1
2
3
git config --global --add diff.guitool kdiff3
git config --global --add difftool.kdiff3.path "C:/Program Files/KDiff3/kdiff3.exe"
git config --global --add difftool.kdiff3.trustExitCode false

一次打开所有差异文件

1
git difftool --dir-diff <commit> <commit>

元数据查看


  • 元数据文件类型
1
git cat-file -t <file>
  • 元数据文件内容
1
git cat-file -p <file>

SSH配置


生成key

1
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

启动SSH代理

1
eval $(ssh-agent -s)

把生成的key加入

1
ssh-add ~/.ssh/id_rsa

复制生成的公钥key,粘贴进git网站配置

1
clip < ~/.ssh/id_rsa.pub

测试连接

1
ssh -T git@github.com