Skip to content
Published at:

Git

Config

bash
# user level
$ git config --global user.name “ShiBinBin”
$ git config --global user.email “15519900807@qq.com”

# check
$ cat ~/.gitconfig

Getting a Git Repository

bash
# new repo
$ mkdir $project_name
$ git init

# clone repo
$ git clone $url
# clone a specific branch or tag
$ git clone --depth 1 --branch <name|tag_name> <repo_url>

init、status、add、commit、push、pull

bash
$ git init                          # 初始化一个新的Git仓库
$ git status                        # 查看工作区状态
$ git add .                         # 添加所有修改的文件到暂存区
$ git add ${file}                   # 添加指定文件到暂存区
$ git commit -m "msg"               # 提交
$ git commit -a -m "msg"            # 添加并提交(跳过git add的步骤)

# 第一次推送需要设置上游分支
$ git push                          # 推送到远程仓库(如果没有设置上游分支,会提示错误)
$ git push -u origin master         # 推送到远程仓库的master分支,并设置上游分支
$ git push origin master            # 推送到远程仓库的master分支
$ git push origin ${branch_name}    # 推送到远程仓库的指定分支
$ git pull                          # 从远程仓库拉取最新的代码
$ git pull origin master            # 从远程仓库的master分支拉取最新的代码
$ git pull origin ${branch_name}    # 从远程仓库的指定分支拉取最新的代码

branch

bash
$ git branch                        # 查看所有分支
$ git branch -a                     # 查看所有分支(包括远程分支)
$ git branch ${branch_name}         # 创建新分支
$ git checkout ${branch_name}       # 切换分支
$ git checkout -b ${branch_name}    # 创建并切换分支
$ git branch -d ${branch_name}      # 删除分支
$ git branch -D ${branch_name}      # 强制删除分支

checkout

bash
$ git checkout ${branch_name}       # 切换分支
$ git checkout -b ${branch_name}    # 创建并切换分支
$ git checkout ${commit_hash}       # 切换到指定的commit
$ git checkout -- ${file}           # 恢复文件到上次提交的状态

Reset

bash
$ git reset --soft HEAD~1           # 软重置:保留工作区和暂存区的修改
$ git reset --mixed HEAD~1          # 混合重置:保留工作区的修改,但清空暂存区
$ git reset --hard HEAD~1           # 硬重置:丢弃工作区和暂存区的修改

Remote

bash
$ git remote -v                     # 查看远程仓库
$ git remote add origin $url        # 添加远程仓库
$ git remote remove origin          # 删除远程仓库
$ git remote rename origin upstream # 重命名远程仓库

Tag

Git 可以给历史中的某一个提交打上标签,以示重要。 比较有代表性的是会使用这个功能来标记发布结点(v1.0)。 两种主要类型的标签:轻量标签(lightweight)与附注标签(annotated)

bash
$ git tag                           # 查看所有标签
$ git tag -l "v1.0.*"               # 查看符合模式的标签
$ git tag -a v1.0 -m "msg"          # 创建带注释的标签
$ git tag v1.0                      # 创建轻量标签
$ git show v1.0                     # 查看标签信息
$ git tag -a v1.0 9fbc3d0           # 给指定的commit打标签
$ git push origin v1.0              # 推送标签到远程
$ git push origin --tags            # 推送所有标签到远程
$ git push origin :refs/tags/v1.0   # 删除远程的标签
$ git tag -d v1.0                   # 删除本地标签
$ git tag -a v1.0 -f -m "msg"       # 强制更新标签
$ git push origin --delete tag v1.0 # 删除远程标签

Stash

贮藏(stash)会处理工作目录的脏的状态——即跟踪文件的修改与暂存的改动——然后将未完成的修改保存到一 个栈上, 而你可以在任何时候重新应用这些改动(甚至在不同的分支上

bash
$ git stash push -m "msg"   # 保存当前工作区
$ git stash push -p patch   # 保存当前工作区的patch
$ git stash list            # 查看stash列表
$ git stash show            # 查看stash内容
$ git stash apply           # 恢复stash栈顶 (不删除stash)
$ git stash apply stash@{0} # 恢复stash (不删除stash)
$ git stash pop             # 恢复并删除stash栈顶
$ git stash pop stash@{0}   # 恢复并删除stash
$ git stash drop stash@{0}  # 删除stash

Submodule

子模块是一个外部项目仓库,可以被引入到主项目中,作为主项目的一个子目录。子模块可以被其他项目引用,也可以被多个项目引用。

bash
$ git clone --recurse-submodules $url       # 克隆项目时,自动初始化子模块
$ git submodule add $url $path              # 添加子模块
$ git submodule init                        # 初始化子模块
$ git submodule update                      # 更新子模块
$ git submodule update --init --recursive   # 更新子模块

Patch

生成Patch:

两种方式:diffformat-patch

bash
# diff
$ git diff Test.java > test.patch   # 只想 patch Test.java 文件
$ git diff > test.patch             # 把所有的修改文件打成 patch

# format-patch
$ git format-patch HEAD^        # 生成最近的1次commit的patch
$ git format-patch HEAD^^       # 生成最近的2次commit的patch
$ git format-patch HEAD^^^      # 生成最近的3次commit的patch
$ git format-patch HEAD^^^^     # 生成最近的4次commit的patch
$ git format-patch <r1>..<r2>   # 生成两个commit间的修改的patch(生成的patch不包含r1. <r1>和<r2>都是具体的commit号)
$ git format-patch -1 <r1>      # 生成单个commit的patch
$ git format-patch <r1>         # 生成某commit以来的修改patch(不包含该commit)
$ git format-patch --root <r1>  # 生成从根到r1提交的所有patch

打Patch:

applyam区别:

  • apply是将patch应用到当前分支,但是不会提交,需要手动提交
  • am是将patch应用到当前分支,并且会自动提交
bash
# apply
$ git apply --stat 0001-limit-log-function.patch    # 查看patch的情况
$ git apply --check 0001-limit-log-function.patch   # 检查patch是否能够打上,如果没有任何输出,则说明无冲突,可以打上
$ git apply xxx.patch                               # 将xxx.patch的patch打上

# am
$ git am 0001-limit-log-function.patch           # 将名字为0001-limit-log-function.patch的patch打上
$ git am --signoff 0001-limit-log-function.patch # 添加-s或者--signoff,还可以把自己的名字添加为signed off by信息,作用是注明打patch的人是谁,因为有时打patch的人并不是patch的作者
$ git am ~/patch-set/*.patch                     # 将路径~/patch-set/*.patch 按照先后顺序打上
$ git am --abort                                 # 当git am失败时,用以将已经在am过程中打上的patch废弃掉(比如有三个patch,打到第三个patch时有冲突,那么这条命令会把打上的前两个patch丢弃掉,返回没有打patch的状态)
$ git am --resolved                              # 当git am失败,解决完冲突后,这条命令会接着打patch

WorkTree

bash
# 基于已有分支或commit来checkout
# 语法:git worktree add  <path> [<commit-ish>]
git worktree add ../${project_name}_${branch} ${branch}

# 基于已有分支或commit来创建新分支
# 语法:git worktree add [(-b | -B) <new-branch>] <path> [<commit-ish>]
git worktree add -b ${new_branch} ../${project_name}_${branch} ${branch}

# 查看列表
git worktree list

# worktree目录移动
git worktree move ${worktree_path} ${new-path}

# worktree 移除(有更改加-f)
git worktree remove [-f] ${worktree_path}

# worktree prune: 手动删除了worktree,清理无效记录
git worktree prune

# 其它
# git worktree repair [<path>...]
# git worktree lock [--reason <string>] <worktree>
# git worktree unlock <worktree>

Other

修改提交信息

bash
$ git commit --amend -m "msg"       # 修改最后一次提交的信息
$ git push origin master --force    # 强制推送
$ git rebase -i HEAD~3              # 合并最近的3次提交

应用已经存在(其它分支)的commit

bash
$ git cherry-pick <commitHash>      # 应用一个commit
$ git cherry-pick <HashA> <HashB>   # 应用多个commit
$ git cherry-pick A..B              # 应用A 到 B 的所有提交(包含A)
$ git cherry-pick A^..B             # 应用A 到 B 的所有提交(不包含A)
$ git cherry-pick <branch_name>     # 应用分支最新的提交

# 合并之后冲突
$ git cherry-pick --continue        # 继续:需要先解决冲突,add到暂存区,在来执行这个continue命令
$ git cherry-pick --abort           # 终止:回到之前的样子
$ git cherry-pick --quit            # 退出:退出 cherry-pick,但是不回到操作前的样子

常见问题

解决已经提交到Git的文件添加到.gitignore

正常使用流程:出现了需要屏蔽的问题,把它们添加到.gitignore,然后git add添加到git跟踪,在commit;如果已经把某些文件提交到了 Git 仓库,然后再把它们加入到 .gitignore 文件中,Git 仍然会继续跟踪这些文件。如果你希望这些被忽略的文件也从 Git 仓库中删除,可以使用下面的命令:

bash
$ git rm --cached .         # 删除所有,后面在添加
$ git rm --cached ${file}   # 删除指定文件
$ git add .                 # 重新添加
$ git commit -m "msg"       # 提交
$ git push origin master    # 推送

References