Git学习笔记整理
2022-06-24 凌晨发布902 次点击0 条评论需阅读14分钟

Git学习笔记整理


保存 Add

  • git add <fileName> 将某一个文件添加到暂存区
  • git add . 将所有文件添加到暂存区

比较 diff

  • git diff 比较工作区与暂存区的差异
  • git diff --cached 比较暂存区与仓库的差异

提交 commit

  • git commit -m xxxx 提交更新
  • git commit -a -m xxxx 跳过使用暂存区域对已跟踪的文件提交更新
  • git commit -am xxxx 跳过使用暂存区域对已跟踪的文件提交更新

储藏 Stash

保存当前工作进度,会把暂存区和工作区的改动保存起来
  • git stashgit stash push 推送 stash 到 stash 栈
  • git stash -u/--include-untracked 贮藏已修改、暂存的已跟踪文件和未跟踪文件
  • git stash push -m <message> 添加到 stash 栈,并加一个 message
  • git stash list 查看 stash 栈
  • git stash apply 应用最上层 stash
  • git stash apply <stashName> 应用指定 stash
  • git stash apply --index
  • git stash pop 移除栈顶 stash
  • git stash drop <stashName> 移除指定 stash
  • git stash clear 清空 stash 栈
  • git stash branch <branchName> 用 stash 的修改创建一个新的分支,创建成功后删除此 stash
  • git stash branch <branchName> <stashName> 指定 stashName 的修改创建一个新的分支,创建成功后删除此 stash

状态 Status

  • git status 检查状态

标签 Tag

Git 支持两种标签: 轻量标签与附注标签

轻量标签

像一个不会改变的分支 -- 它只是某个特定提交的引用

附注标签

存储在 Git 数据库中的一个完整对象,它们是可以被校验的.

命令

  • git tag 列出已有标签
  • git tag -ln 查看标签详细信息
  • git tag <tagName> 创建轻量标签
  • git tag -a(可省略) <tagName> -m <message> 创建附注标签
  • git tag -a <tagName> <hashCode> 给指定 commit 打标签
  • git show <tagName> 查看指定标签
  • git push <remoteName> --tags 将全部标签推送到远程仓库
  • git push <remoteName> --delete <tagName> 删除远程标签
  • git tag -d <tagName> 删除指定标签
  • git checkout <tagName> 检出标签 没懂
  • git push <remoteName> <tagName> 将指定标签推送到远程仓库

责怪 Blame

  • git blame <fileName> fileName 进行 blame
  • git blame -L start,end <fileName> fileName 进行 blame 限制 start,end 行
  • git blame -e <fileName> -e 显示邮箱
  • git blame -w <fileName> -w 忽略空格修改
  • git blame -M <fileName> -M 选项检测同一文件中移动或复制的行。这将报告行的原始作者,而不是移动或复制行的最后一个作者。
  • git blame -C <fileName> -C 选项检测从其他文件中移动或复制的行。这将报告行的原始作者,而不是移动或复制行的最后一个作者。

检出 Checkout

  • git checkout .git checkout <filename> 将暂存区文件替换工作区文件。
  • git checkout <commitId> 检出
  • git checkout HEAD .git checkout HEAD <file> 将 HEAD 指向的版本库文件同时替换暂存区和工作区文件。
  • git checkout -- <fileName> 将 fileName 恢复到最近一次 add/commit(--的作用就是:区分有同名的分支)

清除 clean

git checkoutgit reset命令对之前添加到 Git 跟踪索引的文件进行操作, 而git clean命令对未跟踪的文件进行操作。
  • git clean -n 提醒哪些文件会被删除
  • git clean -dn 提醒哪些文件/文件夹会被删除
  • git clean -f 删除当前目录下所有没被追踪的文件
  • git clean -df 删除当前目录下所有没被追踪的文件/文件夹
  • git clean -f <path> 删除指定目录下所有没被追踪的文件
  • git clean -x 删除所有没被最终的文件(包括.gitignore 忽略的文件)
  • git clean -di 交互式会话删除

反转 Revert

在当前提交后面, 新增一次提交, 抵消掉上一次提交导致的所有变化(适合于 push 到远程分支, 然后需要抵消掉某一次的 commit).
  • git revert HEAD revert 上次 commit
  • git revert <commitId> revert 指定 commitId commit
  • git revert --no-edit HEAD 不会出现编辑 commit message
  • git revert -n/--no-commit HEAD 不会自动 commit

重回 Reset

  • git reset --hard <commitId> 回退版本(更新工作区、暂存区、仓库)
  • git reset --mixed <commitId> 回退版本(默认选项,更新暂存区、工作区)
  • git reset --soft <commitId> 回退版本(更新仓库)
  • git reset --hard HEAD^ 回退到上一个版本
  • git reset --hard HEAD^<number> 回退 number 个版本
  • git reset <commitId> <fileName> 回退 fileName 到指定版本

移除 Rm

git 索引中删除被跟踪的文件
  • git rm <fileName> 删除文件(需要在暂存区,会删除文件)
  • git rm --force/-f <fileName> 移除之前修改过/已经放到暂存区的文件(会删除文件)
  • git rm --cached <fileName> 移除暂存区文件(保存在磁盘,并不想让 Git 继续跟踪)
  • git rm -r dirName 删除文件夹(需要在暂存区)

Commit --amend

修改最新提交的便捷方法,它可以将分阶段的更改与先前的提交结合在一起,而无需创建全新的提交。
  • git commit --amend 重新提交(漏掉了几个文件没有添加,或者提交信息写错了,第二次提交将替换第一次提交的结果)
  • git commit --amend -m <message> 快捷方式
  • git commit --amend --no-edit 允许您在不更改提交消息的情况下对提交进行修改

Rebase

变基: 当前执行 rebase 分支的所有基于原分支提交点之后的 commit 打散成一个个的 patch, 并重新生成一个新的 commit hash 值,再次基于原分支目前的最新 commit 点上进行提交, 并不根据两个分支上实际的每次提交的时间点排序,rebase 完成后, 切到基分支进行合并到另一个时也不会生成一个新的 commit 点,可以保持整个 Git 状态树的完美线性
rebaseImage
rebaseImage
原理: 首先找到这两个分支(当前分支experiment,变基操作的目标基底分支master)的最近共同祖先C2, 然后对比当前分支相对于该祖先的历次提交,提交相对应的修改并存为临时文件,然后将当然分支执行目标基底C3, 最后以此将之前另存为临时文件的修改依序应用.
简而言之: 这里就是提取C4中引入的补丁和修改,然后在C3的基础上应用一次.
git rebase -r/--rebase-merges <branchName> 让 commit 保持原样,不会修改提交信息,仍然是分支历史记录中的单个提交。

Rebase -i

交互式 rebase
// Commands:
// p, pick <commit> = 提交commit
// r, reword <commit> = 提交commit,edit提交信息
// e, edit <commit> = use commit, but stop for amending
// s, squash <commit> = 与上一个commit合并成一个commit,并且edit提交信息
// f, fixup <commit> = 与上一个commit合并成一个commit,使用上一个commit提交信息来展示
// x, exec <command> = run command (the rest of the line) using shell
// b, break = 卡在这里 (继续则需要使用'git rebase --continue' // NOTE: 没用)
// d, drop <commit> = 删除这次commit
// l, label <label> = label current HEAD with a name
// t, reset <label> = reset HEAD to a label
// m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]

Reflog

每次更新了 HEAD 的 git 命令比如 commint、amend、cherry-pick、reset、revert 等都会被记录下来(不限分支), 就像 shell 的 history 一样。 这样你可以 reset 到任何一次更新了 HEAD 的操作之后, 而不仅仅是回到当前分支下的某个 commit 之后的状态。

远程 Remote

  • git remote -v 显示需要读写远程仓库使用的 Git 保存的简写与其对应的 URL
  • git remote add <remoteName> <url> 添加远程仓库
  • git remote show <remote> 查看某个远程仓库
  • git remote rename <oldRemoteName> <newRemoteName> 远程仓库重命名
  • git remote remove <remoteName> 远程仓库移除
  • git fetch <remote> 访问远程仓库,从中拉取所有你还没有的数据
  • git push <remoteName> <branchName> 推送到远程分支

填充 Fetch

将远程分支最新内容拉取到本地,但是 fetch 之后是看不到内容的,此时会多出一个FETCH_HEAD分支, 这个分支就保存着 FETCH 后的内容
  • git fetch <remoteName> <branchName> 填充数据

推送 Push

  • git push <remoteName> <branchName> 将分支推送到远程
  • git push <remoteName> <tagName> 将标签推送到远程
  • git push <remoteName> --all 将所有分支推送到远程
  • git push <remoteName> --tags 将所有标签推送到远程
  • git push -f 强制推送远程(一般如果使用了git commit --amendgit rebase都会出现此情况)

拉取 Pull

首先运行 git fetch,它从指定的远程存储库下载内容.然后执行git merge 将远程内容引用合并到新的本地合并提交中
  • git pull <remoteName> <branchName> 将远程分支拉取下来并与本地分支合并
  • git pull --rebase <remoteName> <branchName> 将远程分支拉取下来并与本地分支变基
  • git pull --no-commit <remoteName> 与默认效果相似,但是不会创建一个 commit 记录

分支 Branch

merge: 合并分支会让两个分支的每一次提交都按照提交时间排序,并且会将两个分支的最新一次 commit 点进行合并成一个新的 commit, 最终的分支树呈现非整条线性直线的形式
  • git branch <branchName> 创建分支
  • git branch 列出所有分支(--merged 已经合并分支/--no-merged 未合并分支)
  • git branch -d <branchName> 删除指定分支
  • git checkout -b <branchName> 创建并切换到该分支(git 2.27 以前)
  • git switch -c <branchName> 创建并切换到该分支(git 2.27 以后)
  • git checkout <branchName> 切换到指定分支
  • git merge <branchName> 合并到当前分支

重命名操作 mv

  • git mv oldFileName newFileName 重命名文件

查看操作 log

  • git log 查看版本
  • git log -p -number 查看(每次/-number)提交所引入的差异
  • git log --stat 查看每次提交的简略信息

一些问题

快进(fast-forward)

试图合并两个分支时,如果顺着一个分支走下去能够到达另一个分支,那么 Git 在合并两者的时候,只会简单的将指针向前推进(指针右移), 因为这种情况下的合并操作没有需要解决的分歧--这就叫做"快进"

三棵树 Three trees

工作区

写代码的文件目录

暂存区

相当于一个存档
git add: 工作区的变更内容 -> 暂存区

仓库

存放数据的地方,HEAD 指向当前版本
git commit: 暂存区的变更内容 -> 仓库

reset 和 checkout 的区别

  1. reset 是移动 HEAD 指向的分支
  2. checkout 是移动 HEAD
originalImg
originalImg
checkout
checkoutImg
checkoutImg
reset
resetImg
resetImg

git checkout filename

命令 git checkout readme.txt 意思就是,把 readme.txt 文件在工作区的修改全部撤销,这里有两种情况:
  • 一种是 readme.txt 自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
  • 一种是 readme.txt 已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
总之,就是让这个文件回到最近一次 git commitgit add 时的状态。

rm / git rm 删除之后怎么恢复

使用 rm 删除文件

这个删除恢复的前提是在你把文件添加到暂存区里了,想要恢复可以使用git checkout -- <fileName>

使用 git rm 删除文件

如果用 git rm 删除文件,就相当于不仅删除了文件,而且还添加到了暂存区,需要先使用git reset HEAD <fileName>, 然后在使用git checkout -- <fileName>就可以恢复了

重命名文件的两种方式

第一种
  1. mv a.txt b.txt 先使用 mv 命令将 a 文件重命名 b 文件
  2. git add b.txt 使用 git add 将 b 文件添加到暂存区
  3. git rm a.txt 使用 git rm 将 a 文件从暂存区删除
第二种
  1. git mv a.txt b.txt 直接使用git mv old-file-name new-file-name 进行重命名
如果是从Index重命名成index的时候, 个人推荐使用第二种, 因为假如是 mac 电脑是不区分大小的, 但是 linux 系统是区分的, 所以你在本地改了, push 上去远程还是没有改.

pull 和 fetch 的区别

  1. fetch 等同于拉取最新的代码到一个FETCH_HEAD
  2. pull = fetch + merge FETCH_HEAD
  3. pull --rebase = fetch + rebase FETCH_HEAD
  4. fetch 是安全的命令,因为git fetch将下载远程内容,并且不会改变本地存储库的状态
  5. pull 是不安全的命令,因为git pull将下载远程内容,并立即尝试更改本地状态以匹配该内容, 可能会导致本地存储仓库处于冲突状态。