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 stash
、git 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 checkout
、git 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 状态树的完美线性
原理: 首先找到这两个分支(当前分支
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 --amend
、git 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 的区别
- reset 是移动 HEAD 指向的分支
- checkout 是移动 HEAD
checkout
reset
git checkout filename
命令
git checkout readme.txt
意思就是,把 readme.txt 文件在工作区的修改全部撤销,这里有两种情况:-
一种是
readme.txt
自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态; -
一种是
readme.txt
已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
总之,就是让这个文件回到最近一次
git commit
或 git add
时的状态。rm / git rm 删除之后怎么恢复
使用 rm 删除文件
这个删除恢复的前提是在你把文件添加到暂存区里了,想要恢复可以使用
git checkout -- <fileName>
使用 git rm 删除文件
如果用 git rm 删除文件,就相当于不仅删除了文件,而且还添加到了暂存区,需要先使用
git reset HEAD <fileName>
,
然后在使用git checkout -- <fileName>
就可以恢复了重命名文件的两种方式
第一种
mv a.txt b.txt
先使用mv
命令将 a 文件重命名 b 文件git add b.txt
使用git add
将 b 文件添加到暂存区git rm a.txt
使用git rm
将 a 文件从暂存区删除
第二种
git mv a.txt b.txt
直接使用git mv old-file-name new-file-name
进行重命名
如果是从
Index
重命名成index
的时候, 个人推荐使用第二种, 因为假如是 mac 电脑是不区分大小的, 但是 linux 系统是区分的, 所以你在本地改了, push 上去远程还是没有改.pull 和 fetch 的区别
- fetch 等同于拉取最新的代码到一个
FETCH_HEAD
- pull = fetch + merge FETCH_HEAD
- pull --rebase = fetch + rebase FETCH_HEAD
- fetch 是安全的命令,因为
git fetch
将下载远程内容,并且不会改变本地存储库的状态 - pull 是不安全的命令,因为
git pull
将下载远程内容,并立即尝试更改本地状态以匹配该内容, 可能会导致本地存储仓库处于冲突状态。