.git
文件夹说明
-rw-r--r-- HEAD # 当前的头部commit/指向
-rw-r--r-- config # 本地仓库的配置
drwxr-xr-x hooks # hooks模版
-rw-r--r-- index # 暂存区的索引[被追踪的文件信息](添加到暂存区会持久化)
drwxr-xr-x logs # HEAD 的记录[分支记录以及HEAD移动记录]
drwxr-xr-x objects # 文件对象[commit对象文件,tree对象文件,bob普通文件]
drwxr-xr-x refs # 分支的头部和tags(对应的commitID)
commit 对象表示了此次提交的一次快照/版本,而暂存区是当前的修改版本,等到提交时将当前的状态建立一个 commit 保存归档。
例如一个 commit 对象关联的对象:
commit 对象包含一个 tree 对象(指针),表示了当前文件树形组织的快照版本
commit 对象之间通过 parent 指针联系
暂存区,上次提交+后续添加到暂存的文件修改的文件状态
说明:
commit 之间,相同的文件对象是共享的;
每次修改添加到暂存区后,只会影响 bob 文件对象【tree 对象等到提交才会生成】
.git/index
文件# git sha-1 hash
echo "Hello" | git hash-object --stdin
# 查看暂存区的内容[由git追踪的文件]
git ls-files --stage
# 查看git对象的类型
git cat-file -t ID
# 查看git对象的内容
git cat-file -p ID
git diff commitID1 commitID2 [-- file1 ...]
比较两个提交的[部分]文件差异,可以使用分支名代替 ID
git diff
[-- file1 ...]
比较工作区和暂存区的文件差异
git diff --cached [-- file1 ...]
比较暂存区和HEAD/最近提交的文件差异
git diff HEAD -- [-- file1 ...]
比较工作区和HEAD/最近提交的文件差异
分离头指针,即 HEAD 指向了非分支的头部提交,如果新建提交不属于任何分支,不会被 git 管理后续会被清理。
但是,基于该提交进行试验产生新提交是可行的
如果新提交需要保留,应该基于新提交建立新分支/tag
对于基于分离头指针的提交 为 unreachable object
会在默认策略下被清理【分支/tag/index/reflog 不能到达的对象】并且默认 2weeks 不变(不修改)[缓解竞争条件]的话会被清理
将对应的提交变为unreachable
后(注意 ref/reflog 等都不能索引到它),执行 git gc --prune=now
修改最新 commit 的 message
git commit --amend
使用变基rebase
修改、合并提交
变基,改变当前分支base 提交位置,使用 rebase
命令将提交到某一分支上的所有修改都移至另一分支上,就好像重新播放
一样。用于合并分支【会将分支的提交整理成线性】
git rebase 目标分支 [源分支] (会先切换到源分支[默认为当前分支],并将当前分支指向目标分支的位置,应用源分支上的每个提交)
(1) 修改本分支上的旧 commit 的提交信息
对自己进行变基,重新修改 base 提交后续的提交
git rebase -i commitID
commitID 应该选取为需要修改的前一个提交 ID,通过交互式命令操作后续提交的状态,从而修改后续的所有提交
(2) 合并分支上的几个 commit
git rebase -i commitID
同样可以操作不同的 commit
首先需要知道工作区、暂存区和最近提交 commit 三者之间的关系
注意理解:分支 branch 是指向最新提交的指针(main),通过它可以追溯到整个历史记录
git reset 命令的介绍:
# git reset [--soft | --mixed | --hard] <commit>
# --mixed 是默认值,同 git reset <commit>
# 修改当前分支,将分支指向 <commit> 位置,同时重置暂存区内容与 <commit> 相同,但是不修改工作区(还是原来最新的工作区内容)
# 可以用于将工作区的内容重新提交,通过回退分支+重新提交达到变相修改提交的目的
# --soft
# 仅移动分支的头指针到指定的提交,不修改暂存区和工作目录
# --hard
# 强制代码回滚,参考下节
常见的恢复场景:
git reset HEAD [file1 ...]
含义:使用 git reset —mixed HEAD
,重置了当前的暂存区为最新提交状态。保持最新工作区状态。
类似命令:git restore --staged <file>
必须加文件路径,是一个局部(指定文件)恢复操作,并且不会修改分支指针的状态
git checkout -- '*'
git reset —hard commitID
说明:由于丢弃的提交处于游离部分/不属于分支或 tag 关联的提交,可能会被清理,想切换分支请使用 checkout
命令。
git revert commitID [commitID ...]
,用于撤销某次特定提交,效果:反向应用某个提交的更改,生成一个新的提交,从而撤销目标提交的影响。它不会删除原始的提交记录。(git reset
功能主要是回滚,通过移动分支的头指针实现,可能丢失提交记录。)
可以使用的选项:
git revert commitID --no-commit
# 不直接生成一个新的提交,而是将反向更改放入工作目录和暂存区,下次手动提交
git revert merge-commitID -m 1
# 用于撤销一次合并提交。因为合并提交有多个父节点,Git 需要知道要保留哪个父节点的更改。(即:基于该父提交反向应用其他分支的更改)
# 通常保留主分支的更改,-m 1 (git show merge-commitID)
与分支合并(merge/rebase)不同,在只需要复制其他分支某一个 commit,使用 cherry-pick
命令,即可复制一个特定的提交到当前分支并生成一次新的提交,避免了相同的工作或分支的合并操作。
git cherry-pick commitID
在当前分支应用特定的提交
https://git-scm.com/book/zh/v2/Git-工具-贮藏与清理
场景:当正在自己分支上开发,并修改和暂存了部分文件,临时需要切换到其它分支工作,但是此时不想提交自己未完成的工作。需要临时保存自己的工作状态,使用 git stash
来保存。
git stash
将工作区和暂存区中尚未提交的修改存入栈中
git stash list
查看栈中所有元素
git stash pop --index
将栈顶存储的修改恢复到当前分支,同时删除栈顶元素
默认会将先前暂存区的存储的内容撤销到工作区(暂存区修改的内容被清空),使用 --index
恢复暂存区的内容/恢复得和原来一样。
git stash apply --index
将栈顶存储的修改恢复到当前分支,但不删除栈顶元素
git stash drop
删除栈顶存储的贮藏https://learngitbranching.js.org/?locale=zh_CN
.gitignore
配置添加忽略文件列表到 .gitignore
,让 git 忽略这些文件/不管理
有时一些文件最好不要用 Git 跟踪。这通常在名为 .gitignore
的特殊文件中完成。你可以在 github.com/github/gitignore 找到有用的 .gitignore
文件模板。或者:https://www.toptal.com/developers/gitignore
简单示例:
*.class
doc/ # 忽略doc文件夹
doc/*.txt # 非递归
doc/**/*.pdf # 递归,忽略doc/下所有pdf
# 不忽略.gitignore和App.class:
!.gitignore
!App.class
push -f
强制推送分支,发生冲突会强制覆盖远程分支的内容。会导致原来分支内容全部丢失/或部分丢失。
因此,对团队的集成分支严禁使用 push -f
命令
团队的集成分支,是不能修改历史提交的,只能通过增加 commit
提交来改进
如果使用 rebase 修改历史,会导致其他成员与集成分支的冲突。
总的原则是,只对尚未推送或分享给别人的本地修改执行变基操作清理历史, 从不对已推送至别处的提交执行变基操作.
可视化 Git 命令
https://ndpsoftware.com/git-cheatsheet.html#loc=workspace;
本文链接: 理解Git和实战
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
发布日期: 2022-10-17
最新构建: 2024-12-26
欢迎任何与文章内容相关并保持尊重的评论😊 !