Git命令

init

创建一个空的Git仓库或重新初始化已有仓库
该命令创建一个空的Git存储库 - 本质上是一个 .git 目录,其中包含 objects、refs/heads、refs/tags 和模板文件的子目录。将创建一个没有任何提交的初始分支,还将创建一个引用master分支 HEAD 的初始 HEAD 文件。
如果设置了 $GIT_DIR 环境变量,则会指定一个路径,而不是 ./.git 作为版本库的基础。
如果通过 $GIT_OBJECT_DIRECTORY 环境变量指定了对象存储目录,那么 sha1 目录就会在其下创建;否则,就会使用默认的 $GIT_DIR/objects 目录。
在现有版本库中运行 git init 是安全的。它不会覆盖已有的内容。重新运行 git init 的主要原因是为了拾取新添加的模板(或者如果给定了 --separate-git-dir 则是为了将仓库移到另一个地方)。
--bare创建裸仓库。如果未设置 GIT_DIR 环境,则将其设置为当前工作目录。
--object-format=<format>指定存储库的对象格式(哈希算法)。有效值为 sha1 和(如果启用)sha256。sha1 是默认值。
--template=<template-directory>指定要使用模板的目录,默认模板目录:/usr/share/git-core/templates。模板目录中名称不以点开头的文件和目录将在创建后复制到 $GIT_DIR 中。默认模板目录包括一些目录结构、建议的 “排除模式” 和示例钩子文件;默认情况下,所有示例钩子都是禁用的。要启用其中一个示例钩子,可移除其 .sample 后缀,重命名该示例钩子。
[-b <branch-name> | --initial-branch=<branch-name>]在新创建的仓库中为初始分支指定名称。如果没有指定,则使用默认名称:master。

git init /* 初始化目录的版本控制,当前目录创建一个名为.git的子目录 */
git init demo /* 指定目录完成创建 */

add

该命令使用工作树中的当前内容更新索引,为下一次提交做好准备。它通常会将现有路径的当前内容作为一个整体添加到索引中,但也可以通过一些选项,在添加内容时只应用对工作树文件所做的部分修改,或删除工作树中已不存在的路径。
[--interactive | -i]以交互方式将工作树中修改过的内容添加到索引中。可以提供可选的路径参数,将操作限制在工作树的子集。详情请参阅 “交互模式”。
[--patch | -p]交互地在索引和工作树之间选择补丁块并将它们添加到索引中。这让用户有机会在将修改后的内容添加到索引之前查看差异。这实际上是运行 add --interactive 命令,但绕过了初始命令菜单,直接跳转到 patch 子命令。
[--update | -u]只更新索引中已匹配 <pathspec> 的条目。这将删除和修改索引条目以匹配工作树,但不会添加新文件。如果使用 -u 选项时没有给出 <pathspec>,则会更新整个工作树中的所有跟踪文件(旧版本的 Git 将更新限制在当前目录及其子目录)。
[-A |--all |all | --no-ignore-removal]
不仅在工作树中有与 匹配的文件的地方更新索引,而且在索引中已有条目的地方也更新索引。这将添加、修改和删除索引条目,以匹配工作树。如果在使用 -A 选项时没有 ,则会更新整个工作树中的所有文件(旧版本的 Git 将更新限制在当前目录及其子目录)。
[--]–此选项可用于分离命令行选项和文件列表(当文件名可能被误认为命令行选项时非常有用)。

git add hello.c /* 将仓库中hello.c添加至暂存区 */
git add . /* 添加当前目录及其子目录下所有文件到暂存区 */
git add -u /* 所有修改,删除的文件加入暂存区 */
git add -A /* 本地修改,删除,新增文件都加入暂存区 */

status

显示索引文件和当前 HEAD 提交之间存在差异的路径、工作树和索引文件之间存在差异的路径,以及工作树中未被 Git 跟踪(也未被 gitignore忽略)的路径。
[-s | --short]以简短的形式给出输出。
--show-stash显示当前藏匿的条目数量。
[-v | --verbose]除了显示被修改的文件名外,还显示要已暂存将要提交的文本更改(即类似于 git diff --cached 的输出)。如果-v被指定了两次,那么还显示工作树中尚未暂存的更改(即类似 git diff 的输出)。

git status /* 检查当前文件状态 */
git status -s  /* 简洁的方式查看文件状态 */

diff

显示工作树和索引或树之间的变化,索引和树之间的变化,两个树之间的变化,合并产生的变化,两个blob对象之间的变化,或者磁盘上两个文件之间的变化。
git diff [<options>] [--] [<path>…​]该表单用于查看相对于索引(下一次提交的暂存区域)所做的更改。换句话说,这些差异就是你可以告诉 Git 进一步添加到索引中但尚未添加的内容。您可以使用 git-add 来暂存这些改动。
git diff [<options>] --cached [--merge-base] [<commit>] [--] [<path>…​]此表单用于查看相对于命名的 <commit> 下次提交的暂存更改。通常情况下,您希望与最新提交进行比较,因此如果您没有给出 <commit>,它就会默认为 HEAD。如果 HEAD 不存在(例如未出生的分支),也没有给出 <commit>,则会显示所有已暂存的变更。--staged--cached 的同义词。
如果给出 --merge-base,则不使用 <commit>,而使用 <commit> 和 HEAD 的合并基数。 git diff --cached --merge-base A 等同于 git diff --cached $(git merge-base A HEAD)
git diff [<options>] [--merge-base] <commit> [--] [<path>…​]这个表格是用来查看你的工作树中相对于命名为的修改。 您可以使用 HEAD 来与最新的提交进行比较,或者使用分支名称来与不同分支的顶端进行比较。
如果给出 --merge-base,则不使用 <commit>,而使用 <commit> 和 HEAD 的合并基数。 git diff --cached --merge-base A 等同于 git diff --cached $(git merge-base A HEAD)
git diff [<options>] <commit>..<commit> [--] [<path>…​]这与早先用于查看两个任意 之间的更改的形式(不带 …)是同义的。如果省略一侧的 ,其效果与使用 HEAD 相同。
git diff [<options>] <blob> <blob>这种形式是为了查看两个blob对象的原始内容之间的差异。
-p | -u | --patch生成补丁。 这是默认设置。
-s | --no-patch抑制差异(diff)工具的所有输出。 对于默认显示补丁的 git show 等命令,可以压制其输出,或在别名中取消命令行中的 --patch、--stat 等选项的效果。
U<n> | --unified=<n>生成带有 <n> 行上下文的差异,而不是通常的 3 行。暗含 --patch 选项。
--output=<file>输出到一个特定的文件,而不是标准输出。
--stat[=<width>[,<name-width>[,<count>]]]生成差异统计(diffstat)。默认情况下,文件名部分将使用尽可能多的空间,其余空间用于图表部分。最大宽度默认为终端宽度,如果未连接终端,则为 80 列,可以用 <width>改写。文件名部分的宽度可以通过在逗号后添加宽度 <name-width> 或设置 diff.statNameWidth=<width> 来限制。图形部分的宽度可以通过使用 --stat-graph-width=<width> 或设置 diff.statGraphWidth=<width> 来限制。使用 --stat--stat-graph-width 会影响所有生成统计图的命令,而设置 diff.statNameWidth 或 diff.statGraphWidth 不会影响 git format-patch。通过给出第三个参数 <count>,可以将输出限制在前 <count> 行,如果行数更多,则在后面加上...
这些参数也可以通过 --stat-width=<width>, --stat-name-width=<name-width>--stat-count=<count> 单独设置。
--numstat--stat 类似,但会以十进制形式显示添加和删除的行数,并且路径名不带缩写,使其对机器更友好。对于二进制文件,会输出两个"-",而不是 0 0。
ignore-space-at-eol忽略行尾空格的变化。
ignore-space-change忽略空格数量的变化。这会忽略行尾的空格,并认为包含一个或多个空格字符的其他序列都是等同的。
ignore-all-space比较行时忽略空格。即使一行有空格而另一行没有空格,也会忽略差异。
--ignore-cr-at-eol在进行比较时,忽略行末的回车。
--full-index在生成补丁格式输出时,在 "索引 "行显示完整的图像前和图像后 blob 对象名称,而不是显示前几个字符。
--binary除了 --full-index 之外,还输出二进制差异,可以用 git-apply 应用。意味着 --patch
-S<string>查找改变文件中指定字符串出现次数(即增加/删除)的差异。供脚本编写者使用。
当您要查找一个精确的代码块(如结构体),并想了解该代码块自首次出现以来的历史时,该功能非常有用:通过 -S 选项迭代,将原文件中的感兴趣的块显示出,并继续进行,直到获得该块的第一个版本。二进制文件也会被搜索到。
-G<regex>查找补丁文本中包含符合 <regex> 的添加/删除行的差异。
为了说明 -S<regex> --pickaxe-regex-G<regex> 之间的区别,请考虑同一文件中包含以下差异的提交:

git diff  /* 默认情况下workspace与index的差别 */
git diff --cached /* index和当前分支最新的提交(HEAD)比较 */
git diff HEAD /* workspace和当前分支最新的提交(HEAD)比较 */
git diff --stat=200 HEAD^ /* 显示与上次提交已更改文件的名称和行数,并指定文件名显示宽度 */
git diff origin/master /* 本地master分支与origin/master分支比较,一般在fetch后用 */
/* git diff可以传递Git refs以提交到diff。一些示例引用是、HEAD、标签和分支名称 */
git diff branch1 other-feature-branch /* 两个分支差异 */
git diff main new_branch ./diff_test.txt /* 跨分支比较特定文件,后跟文件路径 */
git diff -p --output=a.diff /* 生成补丁,-p是默认的,可不加;--output=file,也可用重定向">" */

show

显示各种类型(blobs, trees, tags and commits)一个或多个对象
git show [<options>] [<object>…​]

git show commit /* 显示特定提交中更改的代码 */
git show stash@{0} /* 查看一个 stash 中的内容 */
git show commit  --stat /* 显示差异文件的统计 */

log

查看历史提交记录

git log /* 查看提交记录 */
git log --stat /* 查看每次提交的文件变更 */
git log -p /* 显示每次提交所引入的差异(按补丁的格式输出 */
git log --pretty=oneline /* 精简输出来显示日志,每个提交放在一行显示*/
git log --pretty=--graph /* ASCII 图形显示分支与合并历史 */
git log --pretty=fuller /* 更完整的格式显示 */
git log --author="abc" /* 显示指定的作者的提交 */
git log --committer="abc" /* 显示指定的提交者的提交 */
git log --after="2020.01.01 00:00:00" --before="2020.01.03 00:00:00"/* 显示指定时间段的提交 */
git log <since>..<until> /* 显示在<since>和<until>之间发生的提交 */
git log -S "function" /* 显示添加或删除内容当中有function字符串的提交 */
git log --grep "socket" /* 显示提交说明中包含socket字符串的提交 */
git log --reverse /* 以相反的顺序输出要显示的提交 */
git log --format=fuller /* 以更全的方式显示log */

difftool

difftool是git版本管理工具中的一个内容差异比较器,通过参数设置可以配置调用其它可视化工具

git difftool --tool-help /* 查看支持的git diff的插件*/
git mergetool --tool-help /* 查看支持的git merge插件 */
git difftool t bc4 /* 以指定工具对比 */
git config --global merge.tool bc4 /* mergetool 的默认工具配置成 bc4 */
/* 指定了工具 bc4 的调用路径和参数 依次代表本地修改,被合并分支修改,两端未修改前版本文件,最终合并导出的文本文件 */
git config --global mergetool.bc4.cmd '\"D:\Beyond Compare 4\BComp.exe\" "$LOCAL" "$REMOTE" "$BASE" "$MERGED"'
 /* 设置为 true 表示信任软件的返回码,并依据返回码确定合并是否成功,如果设置成 false 就会在合并完成后问你是否解决完冲突*/
git config --global mergetool.bc4.trustExitCode true
git config --global mergetool.keepBackup false /* 指定在合并完成后删除调用 git mergetool 是产生 *.orig 备份文件 */
git config --global diff.tool bc4
/* $LOCAL和$REMOTE的顺序控制,即左窗格显示哪个文件,右窗格显示哪个文件 */
git config --global difftool.bc4.cmd '"D:\Beyond Compare 4\BComp.exe" "$LOCAL" "$REMOTE"'
git config --global difftool.prompt false /* 每次使用git difftool时会有二次提示,设置可以取消 */
git config --global difftool.trustExitCode true
tips:注意不是"BCompare.exe"这个东西,BCompare.exe 是主程序,BComp.exe 用在版本控制工具中更加优秀
git difftool /* 提交时查看差异修改了什么 */
git mergetool /* 合并时冲突修改 */

apply

将修补程序应用于文件或索引,此命令应用修补程序,但不创建提交,推荐使用git-amgit-format-patch生成的补丁或通过电子邮件接收的补丁创建提交。

git apply a.diff --check /* 检测补丁是否适用于当前工作区或索引并检测错误 */
git apply -p1 a.diff /* 应用该补丁, -p1表示忽略/标识的前导目录,与patch -p1 < a.diff 命令几乎相同 */
git apply --cached -p1 a.diff /* 修补程序仅应用于索引 */

cherry-pick

遴选,它可以在当前分支应用其他已经存在的 commit 修改,并对每一个合并过来的 commit 产生一个新的提交记录(commit hash)。
cherry-pick 的一些常用配置项:
-n, --no-commit 只更新工作区和暂存区。不产生新的提交
-x 在提交信息末尾追加一行(cherry picked from commit…)方便以后查到这个提交是如何产生的
-m parent-number, --mainline parent-number 如果原始分支是一个合并节点,那么 cherry-pick 默认会失败,因为不知道应该采用哪个分支的代码变动。 -m 配置项告诉 git 应该采用哪个分支分变动,parent-number 代表原始提交的父分支编号
git cherry-pick -m 1 <commit>
一般1号父分支是接受变动分支(the branch being merged into),2号父分支是作为变动来源的分支(the branch being merged from)

git cherry-pick <commit> /* 指定任何本地分支上的某个存在的提交 */
git cherry-pick <commit1> <commit2> /* 多个不连续的提交,提交之间用空格相隔 */
git cherry-pick <start-commit>..<end-commit> /* 连续的提交(左开右闭),使用`..`注意中间没有任何空格 */
git cherry-pick <branchName> /* 会将指定分支的最后一次提交应用到当前分支 */
/* 转移另一个代码库的提交 */
/* 其实 cherry-pick 的奥义就是,只要是在一个.git仓库管理下的本地代码,任何提交都可以被应用到任何可访问的本地分支,哪怕是跨代码库:*/
git remote add repo2 git@xxx.git /* 添加另一个代码库 */
git fetch repo2 /* 抓取新代码库到本地 */
git log repo2/master /* 查看新代码库master分支的提交记录 */
git cherry-pick <commitInRepo2> /* 将新的代码库的某个提交应用到当前分支(跨代码库的合并) */

merge

将两个或多个分叉历史合并在一起,最常见用于组合两个分支。

git merge debug /* 将 debug 分支合并到当前分支 */
git merge debug fixup /* 合并分支 debug 和 fixup 到当前分支之上 */
git merge --no-commit debug /* 合并分支 debug 到当前分支,但是不自动创建新提交,快进是合并不适用 */
git merge --no-ff debug /* 非快进式合并,产生合并提交  */
git merge -Xours debug /* 不用手动解决冲突,在那个分支(debug)上所有其他非冲突的改动都可以被成功地合并入,有冲突的区别,选择特定的一边(当前分支)并忽略另外一边(debug分支)*/

如果想要做类似的事情但是甚至并不想让 Git 尝试合并另外一边的修改, 有一个更严格的选项,它是 “ours”
合并 策略。 这与 “ours” recursive 合并选项不同
git merge -s ours debug /* 这本质上会做一次假的合并。 它会记录一个以两边分支作为父结点的新合并提交,但是它甚至根本不关注你正合并入的分支。 它只会简单地把当前分支的代码当作合并结果记录下来 */
git merge -s theirs debug /* 用 debug 的修改作为合并策略 */

rebase

变基是将一系列提交移动或组合到新的基础提交的过程,变基的主要原因是保持线性项目历史记录。

git rebase <base> /* 将当前分支重定向到 <base>,<base> 可以是提交 ID、分支名、标签,或者 HEAD 的相对引用,然后获取当前分支中的提交,并将它们应用于分支的头部 */
git rebase -i <base> /* 以交互方式将当前分支重设为<base>的基础。启动编辑器,输入 命令,说明如何将每个提交转移到新的分支 */
git rebase --interactive <base> /* 交互式变基 */
 git rebase --onto <newbase> <oldbase> /* 类似于切片变基,以newbase为新的基点,将以oldbase基点的下一个提交到该分支的顶端 */
git rebase master debug /* 以master分支为基点应用debug分支的提交(这样写不必在变基前签出debug分支) */
git rebase --onto=<new_base> <old_base> [<branch>]
git rebase --onto=<new_base> <old_base> /* 如果现在是在分支上,可以省略 */
git rebase <new_old_base> /* 如果new_base与old_base相同,我们可以省略--onto参数 */
(事实上,<old_base>是我们用来比较分支的东西。如果它是一个分支,那么 git 就会寻找一个共同的祖先(参见 --fork-point);如果它是当前分支上的一个提交,就会使用之后的提交;如果它是一个与当前分支没有共同祖先的提交,就会使用当前分支的所有提交。<new_base>也可以是一个提交。因此,举例来说,git rebase --onto HEAD~ HEAD 会把旧基地 HEAD 和当前 HEAD 之间的提交放在 HEAD~ 的上面,有效地删除了最后一个提交)。

git rebase branch

           Before                           After
    A---B---C---F---G (branch)        A---B---C---F---G (branch)
             \                                         \
              D---E (HEAD)                              D---E (HEAD)

git rebase --onto F D 将父级为D的HEAD的可达提交重置于F之上

          Before                           After
    A---B---C---F---G (branch)        A---B---C---F---G (branch)
             \                                     \
              D---E---H---I (HEAD)                  E---H---I (HEAD)

git rebase --onto B E 删除一些提交时不要交互式变基

          Before                       After
    A---B---C---E---F (HEAD)        A---B---F (HEAD)

git rebase --onto有3个参数
git rebase --onto 可以在精度方面更进一步。事实上,它允许您在另一个提交的基础上重设一个任意范围的提交
git rebase --onto F D H 把 E–H 的切片放在 F 的上面,忽略 HEAD 当前指向的位置

          Before                                     After
    A---B---C---F---G (branch)                A---B---C---F---G (branch)
             \                                             \
              D---E---H---I (HEAD)                          E---H (HEAD)

git rebase时产生冲突标记

<<<<<<< - ||||||| /* 变动来源的分支的修改 */
||||||| - ======= /* 基线 */
======= - >>>>>>> /* 接受变动分支的修改 */

commit

提交暂存的更改到仓库

git commit /* 默认编辑器打开,提示添加一条新的提交消息 */
git commit -m 'first commit' /* 将所有暂存的文件提交至仓库 */
git comm --allow-empty /* 创建空提交 */
git commit --amend / 使用当前暂存的修改更新之前的提交,并提供一个新的提交消息 */
git commit --amend --date="$(date -R)" /* 将commit的时间改为当前时间 */

reset

重置当前HEAD到指定的状态

git reset --hard HEAD^ /* HEAD和branch切换到上一条commit,且工作区和暂存区也重置为上一次commit状态 */
git reset --hard /* 工作区和暂存区重置为HEAD新位置,branch和HEAD也切换 */
git reset --soft HEAD^ /* HEAD切换到HEAD^,工作区不改变,暂存区不改变 */
git reset --mixed /* git reset缺省默认,重置暂存区,工作区不改变,更改引用 */
git reset HEAD filename /* 将文件filename撤出暂存区,相当于对命令git add filename的反向操作 */
git reset --merge ORIG_HEAD /* 移除当前分支中所有在最近一次合并中引入的提交,保留工作树尚未添加的更改 */

重置命令的一个用途就是修改引用(如master)的游标,重置命令的时候没有使用任何参数对所要重置的分支名进行设置,这是因为重置命名实际上所针对的是头指针HEAD,之所以没有改变HEAD的内容是因为HEAD指向了一个引用refs/heads/master,所以重置命令体现为分支“游标”的变更,HEAD本身一直指向的是refs/heads/master,并没有在重置时改变。

stash

将本地修改保存到一个新的 stash 条目,并将其回滚到 HEAD(工作树和索引中)。 部分是可选的,它给出了描述和储藏状态。

git stash push /* 保存当前工作区和暂存区未提交的改动,最新保存的永远都是stash@{0},回到干净目录,push可省略 */
git stash save message /* 保存备注的信息(已弃用)改用 git stash push */
git stash push -m message /* 代替 save */
git stash push -k /* 所有已添加到索引中的更改将保持不变 */
git stash push --staged /* 仅存储当前暂存的更改。这与基本的 git commit 类似,只是将状态提交到储藏库,而不是当前分支 */
git stash push [--] <pathspec>…​ /* 部分存储,指定缓存哪些路径文件 */
git stash list /* 列出存储的stash */
git stash pop /* 从最近存储的进度(stash@{0})进行恢复将其应用到当前并从储藏列表移除,但当前工作区要与暂存区保持一致 */
git stash pop stash@{0} /* 恢复指定索引的进度 */
git stash drop stash@{0} /* 从储藏条目列表中删除一个单一的储藏条目 */
git stash clear /* 删除所有储藏条目列表 */
git stash show -p stash@{1} /* 以补丁形式查看指定的暂存 */

worktree

一个 git 仓库可以支持多个工作树,允许你一次签出多个分支。用git worktree添加一个新的工作树与版本库相关联,同时添加额外的元数据,以区分该工作树与同一版本库中的其他工作树。工作树,连同这些元数据,被称为 “工作树”。

这个新的工作树被称为 “链接工作树”,而不是由 git-init 或 git-clone 准备的 “主工作树”。一个版本库有一个主工作树(如果它不是一个裸版本库)和零个或多个链接工作树。当你用完一个链接的工作树后,用 git worktree remove 删除它。

在其最简单的形式中,git worktree add 会自动创建一个新的分支,其名称是 的最后一个组成部分,如果你计划在一个新的主题上工作,这很方便。例如,git worktree add …/hotfix 创建了新的分支 hotfix,并在路径 …/hotfix 处检查。如果要在新的工作树中处理现有的分支,可以使用 git worktree add 。另一方面,如果你只是打算做一些实验性的修改,或者在不影响现有开发的情况下进行测试,创建一个不与任何分支相关联的废弃工作树往往很方便。例如,git worktree add -d 在与当前分支相同的提交处创建一个带有分离的 HEAD 的新工作树。

如果没有使用 git worktree remove 就删除了工作树,那么它相关的管理文件,即驻留在仓库中的文件,最终会被自动删除(见 gc.worktreePruneExpire in git-config),或者你可以在主工作树或任何链接工作树中运行 git worktree prune 来清理任何过时的管理文件。

假如我们正在dev开发分支进行工作,这个时候遇到紧急情况,我们需要在master分支工作,暂停在dev分支的工作,但在dev分支工作还没做完,我们不想产生新的提交,除了使用stash,还可以使用worktree,创建新工作树链接到当前存储库,从而实现签出多个分支

git worktree add path commit /* 在 <path> 创建一个工作树,并将 <commit-ish> 签出到其中。新的工作树被链接到当前的版本库,共享除每个工作树文件(如 HEAD、索引等)之外的一切 */

如果 <commit-ish> 是一个分支名(称其为 <branch>),并且没有找到,也没有使用 -b、-B 或 --detach,但在恰好一个远程(称其为 <remote>)中确实存在一个名称匹配的跟踪分支,则视作等同于:
git worktree add --track -b <branch> <path> <remote>/<branch>
如果 <commit-ish> 被省略,而且既没有使用 -b 也没有使用 --detach,那么为了方便起见,新的工作树将与一个以 $(basename <path>) 命名的分支(称之为 <branch>)相关联。如果 <branch> 不存在,就会自动创建一个基于 HEAD 的新分支,就像给出 -b <branch> 一样。

git worktree add -b emergency-fix ../temp master /* 创建一个名为 emergency-fix 的新分支,如果 <commit-ish> 被省略,它默认为 HEAD。默认情况下,如果一个新的分支已经存在,-b 会拒绝创建它,-B 覆盖这一保护措施,将 <new-branch> 重置为 <commit-ish>*/

git worktree remove ../temp /* 删除工作树 */
git woektree list /* 列出工作树,首先列出主工作树,在列出worktree链接的工作树 */

revert

本地分支中使用git reset很方便,但是这种“改写历史”的方法对大家一起使用的远程分支是无效的,revert是用来撤销一个指定提交的操作,revert之后就可以把你的更改推送到远程仓库

git revert <commit> /* 产生一个新提交,新的提交相当于撤销<commit>这个提交 */
git revert HEAD~3..HEAD~1 /* 将HEAD~2到HEAD~1的两次提交的改动还原,并连续创建(弹出提交消息框)HEAD~1和HEAD~2的提交 */
git revert -n HEAD~3..HEAD~1 /* 作用同上,但不创建任何包含还原改动的提交。还原只会修改工作区和索引 */

clone

git clone <repository> <directory><repository>指向的版本库创建一个克隆到<directory>目录,<directory>相当于克隆版本库的工作区,文件都会检出,版本库位于工作区下的.git目录中。它通常会自动地创建一个跟踪origin/master的master分支,git clone实际上是一个封装了其他几个命令的命令。 它创建了一个名为“linux”的新目录,切换到新的目录,然后git init来初始化一个空的Git仓库, 然后为你指定的URL添加一个(默认名称为origin的)远程仓库(git remote add),再针对远程仓库执行git fetch,最后通过git checkout将远程仓库的最新提交检出到本地的工作目录

git clone https://github.com/torvalds/linux.git /* 没有指定目录,存储库最后一级的目录名去掉后缀作为新克隆的目录名 */

remote

管理远程仓库,将一个远程连接加入到仓库中时,必须为它分配一个别名。默认情况下,这个别名是 origin
git remote add <name> <URL>
为位于 <URL> 的版本库添加名为 <name> 的远程。然后就可以使用 git fetch <name> 命令来创建和更新远程跟踪分支 <name>/<branch>

git remote /* 列出本地已添加的远程仓库 */
git remote -v /* 列出本地已添加的远程仓库并显示url(--verbose) */
git remote add <name> <url> / * 创建一个连接到远程软件仓库的新连接。添加远程仓库后、 可以在其他命令中使用 <name> 作为 <url> 的快捷方式 */
git remote add origin https://github.com/torvalds/linux.git /* 在config添加一个指向远程仓库的引用 */
git remote rm origin /* 删除名为 origin 的远程。远程的所有远程跟踪分支和配置设置都会被删除 */
git remote show /* 显示远程仓库名 */
git remote show origin /* 连接origin远程仓库检查远程仓库所有分支和本地分支关联情况,这个命令列出了当你在特定的分支上执行 git push 会自动地推送到哪一个远程分支。 它也同样地列出了哪些 远程分支不在你的本地,哪些远程分支已经从服务器上移除了, 还有当你执行 git pull 时哪些本地分支可以与它跟踪的远程分支自动合并。 */
git remote update /* 关联多个远程仓全部更新,相当于每个远程仓执行git fetch */
git remote rename origin new_name /* 将origin远程仓重命名new_name */
git remote set-url origin <NEW_URL> /* 重设origin远程仓的地址 */
git remote set-url --push origin <NEW_URL> /* 给git push设置origin远程仓的url地址 */
git show-ref /* 查看全部本地引用 */

fetch

访问远程仓库,从中获取本地版本库没有的数据。 执行完成后拥有那个远程仓库中所有分支的引用,可以随时合并或查看。本地远程分支列表不会自动更新,fetch命令可以更新,但如果远程仓库有删除的分支,那么在更新时本地远程分支列表并不会将其删除。

git fetch <remote> <branch> /* 从 仓库 抓取特定的 <branch>。不使用<branch> 来获取所有远程参考  */
git fetch origin /* 获取更新的列表和所有远程分支的内容,远程分支列表不会自动更新 */

git fetch origin操作时使用的默认引用表达式,fetch参数相当于执行了git fetch origin +refs/heads/*:refs/remotes/origin/*命令+号告诉Git即使在不能快进的情况下也要(强制)更新引用。引用表达式中使用了通配符,冒号前面的含有通配符的引用指的是远程版本库的所有分支(远程库上所有的以refs/heads/开头的引用),冒号后面的引用含义是复制到本地的远程分支目录(本地的refs/remotes/origin开头的引用)中。
注意:git fetch命令只会将数据下载到的本地仓库——它并不会自动合并或修改当前的工作,必须手动将其合并。

pull

拉取后合并

git pull /* 在一个跟踪分支上输入 git pull,Git 能自动地识别去哪个服务器上抓取、合并到哪个分支 */
git pull --rebase /* 通过变基来更新自己的本地分支,默认merge */
git pull --rebase <remote>/* 获取当前分支的远程副本,并将其重定为本地副本。使用 git rebase 代替 merge 来整合分支 */
git pull upstream master:tgmaster /* 将 upstream 远程版本的 master 分支合并到本地的 tgmaster 分支 */
git pull <remote> /* 获取当前分支的指定远程副本,并立即将其合并到本地副本中 */
  • 如果为当前分支设置了,即由配置branch..remote给出了远程版本库代号,则不带参数执行:command:git pull相当于执行了:command:git pull <remote>
  • 如果没有为当前分支设置,则不带参数执行:command:git pull相当于执行了:command:git pull origin
  • 要获取的远程版本库的URL地址由remote..url给出。
  • 如果为注册的远程版本库设置了fetch参数,即通过remote..fetch配置了一个引用表达式,则使用该引用表达式执行获取操作。
  • 接下来要确定合并的分支。如果设定了branch..merge,则对其设定的分支执行合并,否则报错退出。

push

[--no-verify] [<repository> [<refspec>…​]]
切换 pre-push 钩子。 默认是 --verify,给钩子一个机会来阻止推送。 如果使用 --no-verify,钩子会被完全绕过。

当命令行没有用 <repository> 参数指定推送位置时,会参考当前分支的 branch.*.remote配置来决定推送位置。 如果配置丢失,则默认为 origin
当命令行没有用 <refspec>... 参数或 --all、--mirror、--tags 选项指定推送内容时,命令通过查阅 remote.*.push 配置找到默认的 <refspec>,如果没有找到,则以 push.default 配置决定推送内容。
当命令行和配置都没有指定推送的内容时,将使用默认行为,这与 push.default 的 simple 值相对应:当前分支被推送到相应的上游分支,但作为一项安全措施,如果上游分支的名称与本地分支不一致,推送将被中止。

指定用哪个源对象更新哪个目标引用。<refspec> 参数的格式是一个可选的加号 +,后面是源对象 <src>,后面是冒号 : ,后面是目标引用 <dst>
+等同于--force,通常情况下,命令会拒绝更新一个不属于用来覆盖它的本地引用祖先的远程引用,这个标志禁用了这些检查。例:git push origin +master,强制推送到 master 分支。
<src> 通常是你想推送的分支的名字,但它可以是任何任意的“SHA-1 表达式”,比如 master~4HEAD
<dst> 远程仓库的哪个引用被这个推送更新。这里不能使用任意的表达式,必须命名一个实际的引用。

git push origin :experimentalorigin 仓库(例如refs/heads/experimental)中找到一个与 experimental 相匹配的引用,并将其删除。
推送一个空的 <src> 允许你从远程版本库中删除 <dst> 的引用。除非配置或钩子禁止,否则在引用规范中没有前面的 + (或 --force) ,删除总是被接受的。

git push

如果 git push [<repository>] 没有任何 <refspec> 参数被设置用 remote.<repository>.push 配置变量更新目的地 <src> 的某个引用,则:<dst> 部分可以省略 —— 这样的推送将更新 <src> 通常更新的引用,命令行上没有任何 <refspec>。 否则,缺少 :<dst> 意味着更新与 <src> 相同的引用。

  • 如果为当前分支设置了,即由配置branch..remote给出了远程版本库代号,则不带参数执行:command:git push相当于执行了:command:git push <remote>
  • 如果没有为当前分支设置,则不带参数执行:command:git push相当于执行了:command:git push origin
  • 要推送的远程版本库的URL地址由remote..pushurl给出。如果没有配置,则使用remote..url配置的URL地址。
  • 如果为注册的远程版本库设置了push参数,即通过remote..push配置了一个引用表达式,则使用该引用表达式执行推送。
  • 否则使用“:”作为引用表达式。该表达式的含义是同名分支推送,即对所有在远程版本库有同名分支的本地分支执行推送。
    这也就是为什么在一个本地新建分支中执行:command:git push推送操作不会推送也不会报错的原因,因为远程不存在同名分支,所以根本就没有对该分支执行推送,而推送的是其他分支(如果远程版本库有同名分支的话)。
git push <remote> <branch> /* 推送<branch>分支到<remote>远程仓,以及必要的提交和对象。如果远程仓库不存在,则在远程仓库中创建<branch>命名分支 */
git push <remote> --all /* 将所有本地分支推送到指定的远程分支 */
git push origin new_branch /* 将new_branch分支推送到origin服务器, 并创建new_branch分支,但不会建立跟踪*/
git push --set-upstream remote_name local_branch remote_branch /* 将本地分支local_branch的副本推送至远程仓remote_name,并设置跟踪上游分支remote_branch */
git push -u origin master /* 上条命令简写,将master 支推送到origin远程仓,本地分支master跟踪远程分支master */
git push origin --delete serverfix /* 删除一个远程分支, 从服务器上删除serverfix分支 */

branch

Git 中的分支本质上是一个指向某个特定提交的命名可变指针

git branch /* 显示本地分支列表,当前分支用星号 “*” 标识出来 */
git branch -r /* 显示远程分支(--remotes) */
git branch -a /* 显示所有分支(--all) */
git branch -v /* 查看每一个分支的最后一次提交 */
git branch -vv /* 查看所有分支,正在跟踪哪个远程分支与本地分支是否是领先、落后或是都有,需要先fetch */
git branch develop  /* 基于当前头指针(HEAD)指向的提交,创建一个develop分支 */
git branch bugfix ab1afef /* 基于提交ab1afef创建bugfix分支 */
git branch -d hotfix /* 删除分支。该分支必须完全合并到其上游分支中,如果没有使用 --track 或 --set-upstream-to 设置上游,则在合在HEAD中 */
git branch -D hotfix /* 强制删除hotfix分支,即使hotfix 支没有合并到上游分支 */
git branch -m <oldbranch> <newbranch> /* 重命名分支 */
git branch -f master HEAD~3 /* -f 选项让分支指向另一个提交,将master分支强制移动到HEAD的第3级父提交 */
git branch --merged /* 查看哪些分支已经合并到当前分支 */
git branch --no-merged /* 查看所有包含未合并工作的分支 */
git branch --no-merged master /* 尚未合并到master的分支 */
git branch (--set-upstream-to=<upstream> | -u <upstream>) [<branchname>] /* 设置 <branchname> 的跟踪信息,使 <upstream> 被视为 <branchname> 的上游分支。如果没有指定 <branchname>,则默认为当前分支 */
git branch -u origin/serverfix /* 设置或修改已有的本地分支serverfix跟踪一个刚刚拉取下来的远程分支 */
git branch [--track[=(direct|inherit)] <branchname> [<start-point>]
/* -t、--track 或 --track=direct 表示使用起点分支本身作为上游;--track=inherit 表示复制起点分支的上游配置 */
git reflog show --date=iso bugfix /* 指定bugfix分支的历次更改记录,最下面一条的时间即是分支创建时间 */
git branch --contains commit /* 列出所有包含指定提交对象的分支 */

checkout

检出命令,改变HEAD本身

git checkout /* 汇总显示工作区、暂存区与HEAD的差异 */
git checkout branch -- filename /* 暂存区和工作区中的filename文件被branch所指向的提交的filename文件直接覆盖 */
git checkout -- test.c /* 暂存区的test.c文件覆盖工作区的test.c文件 */
git checkout . /* 取消所有本地的修改(相对于暂存区),相当于将暂存区的所有文件直接覆盖工作区 */
git checkout ab1afef  test.c /* 用指定提交ab1afef中的文件覆盖暂存区和工作区中对应的文件 */
git checkout develop  /* 换到一个已存在的develop分支 */
git checkout -b hotfix /* 建立一个hotfix分支并切换 */
git checkout -b serverfix origin/serverfix /* 基于远程分支创建本地跟踪分支serverfix ,并且起点位于origin/serverfix */
git checkout -b sf origin/serverfix /* 基于远程分支创建本地跟踪分支sf,并且起点位于origin/serverfix */
git checkout --track origin/serverfix /* 基于远程分支创建本地跟踪分支serverfix ,并且起点位于origin/serverfix */
git checkout --conflict=merge hello.rb /* 重新恢复到冲突时候的文件状态 */

restore

用还原源中的某些内容还原工作树中的指定路径。如果跟踪到的路径在还原源中并不存在,它将被移除以匹配还原源。
使用 --staged --worktree 同时恢复工作树和索引,如果两个选项都未指定,默认情况下会还原工作树,指定--staged 只还原索引。指定两者则同时还原两者。
默认情况下,如果给了--staged,内容将从HEAD恢复,否则从索引恢复。使用--source来恢复不同的提交。

git restore --staged hello.c /* 恢复索引中的文件以匹配 HEAD 中的版本,工作区不变 */
git restore --source=HEAD --staged --worktree hello.c /* 同时恢复索引和工作树(这与使用 git-checkout[1]相同)*/
git restore '*.c' /* 恢复所有的C源文件,使之与索引中的版本一致 */

tag

有没有什么可以永远指向某个提交记录的标识呢,比如软件发布新的大版本,或者是修正一些重要的 Bug或是增加了某些新特性,有没有比分支更好的可以永远指向这些提交的方法呢,tag永久地将某个特定的提交命名为里程碑,然后就可以像分支一样引用了。更难得的是,它们并不会随着新的提交而移动。你也不能切换到某个标签上面进行修改提交,它就像是提交树上的一个锚点,标识了某个特定的位置。
远程版本库中的里程碑同步到本地版本库,会使用同样的名称,而不会像分支那样移动到另外的命名空间(远程分支)中,推送时,默认不会将本地创建的里程碑带入远程版本库,这样可以避免远程版本库上里程碑的泛滥。
Git 支持两种里程碑(标签):轻量里程碑(lightweight)与附注里程碑(annotated)

git tag <tagname> [<commit>] /* 创建轻量级里程碑 */
git tag -a <tagname> [<commit>] /* 创建带说明的里程碑 */
git tag -m <msg> <tagname> [<commit>] /* 直接通过-m参数提供里程碑创建说明 */
git tag /* 列出所有标签 */
git show tag /* 输出所有带标签提交的详细信息 */

创建里程碑需要输入里程碑的名字<tagname>和一个可选的提交ID<commit>。如果没有提供提交ID,则基于头指针HEAD创建里程碑。

rerere

git rerere 功能是一个隐藏的功能。 正如它的名字,重新使用记录的解决方案(reuse recorded resolution):会记住文件冲突时用户的解决方案,当再次出现同样冲突时自动解决。

git config --global rerere.enabled true /* 全局配置,冲突的解决会被记录下来以便以后再遇到时自动复用 */
git config --global rerere.enabled fasle /* 关闭重新使用记录的解决方案的配置,防止一些冲突没被发现 */
git checkout --conflict=merge file_path /* 文件恢复到未自动解决冲突时的状态 */
git rerere /* 恢复未解决冲突的状态后,又想用回之前的合并冲突策略 */
git merge --rerere-autoupdate /* 自动解决一个文件时,并没有把它标记为已解决(例如用git add),允许rerere机制用自动冲突解决的结果来更新索引 */
git rebase --no-rerere-autoupdate /* git rerere有rerere.autoupdate配置,但没有办法从命令行中取消它;不会停止自动重用已记录的决议,在用单独的git add将结果提交给索引之前,可以仔细检查rerere的工作,并抓住潜在的错误合并 */

bisect

使用二分搜索查找引入错误的提交
第一个git bisect子命令是git bisect start来开始搜索。然后必须设置边界以限制提交空间。通常的做法是给出一个 "坏"提交和至少一个 "好"提交。可以像这样在调用git bisect start时传递它们:

git bisect start [BAD [GOOD...]]
或 git bisect bad [COMMIT]
和 git bisect good [COMMIT...]
在搜索的每一步,用户都必须测试当前的提交,并分别使用上文所述的 "git bisect good" 或 "git bisect bad" 命令说它是 "好 "还是 "坏"。
"git bisect" 最终会找到第一个坏提交:git show HEAD 可以看到提交的内容
git bisect reset /* 回到我们开始二分前所在的分支 */

blame

查询文件历史版本信息
-L选项将限制行范围

git blame -L 40,60 file1.c /* 第40-60行修改的记录 */
git blame -L 40,+21 file1.c /* 从第40行开始的21行修改的记录 */

clean

从当前目录开始,通过递归删除不在版本控制之下的文件来清理工作区,clean 后,删除的文件无法找回。
通常情况下,只有 Git 未知的文件会被删除,但如果指定了 -x 选项,被忽略的文件也会被删除。例如,这对删除所有构建产品很有用。
如果给出任何可选的<路径规范>…​参数,只有那些与路径规范相匹配的路径会受到影响。
-d
通常,当没有指定 <路径规范> 时,git clean 不会递归到未追踪的目录,以避免删除太多。 指定 -d 可以让它也递归到这些目录。 如果指定了<路径规范>,-d 就不重要了;所有符合指定路径的未追踪文件(–force 下提到的嵌套的 git 目录除外)将被删除。
-f 或 --force
如果 Git 配置变量 clean.requireForce 没有设置为 false,git clean 将拒绝删除文件或目录,除非给出 -f 或 -i。 除非给出第二个 -f,否则 Git 将拒绝修改未跟踪的嵌套 git 仓库(有.git子目录的目录)。
-i
显示会做什么,并以交互方式清理文件。

git clean -f -d /* git clean -fd 移除工作目录中所有未追踪的文件以及空的子目录 */ 

~和^

~2 表示沿着commit树向上搜索两层,并获得该层的第一个commit(如果该层有多个commit的话)
^2 表示获得某个commit的第2个父commit(merge两个分支后产生的merge commit就拥有两个父commit)
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值