2.1 Git 目录介绍
项目初始化
mkdir git_study # 随便创建一个目录
cd git_study # 切换到该目录下
git init # 初始化 之后会得到一个 .git 的目录
# 环境为 windows 10
# 使用 tree 查看 .git 目录结构,失败了:
tree .git
tree .git bash: tree: command not found
windows下的 git 没有 tree 命令,默认调用的是cmd的tree命令,而cmd 提供的 tree 命令比较特殊,并不是常见的 .exe 结尾文件,而是 .com 结尾的文件。去下载tree-1.5.2.2-bin.zip,解压,然后将 tree-1.5.2.2-bin\bin\tree.exe 文件复制到git Bash 的安装目录下 Git\usr\bin 下,然后就能使用tree命令了:
$ tree .git
.git
|-- HEAD # 当前指向的分支
|-- config # 配置文件
|-- description
|-- hooks
| |-- applypatch-msg.sample
| |-- commit-msg.sample
| |-- fsmonitor-watchman.sample
| |-- post-update.sample
| |-- pre-applypatch.sample
| |-- pre-commit.sample
| |-- pre-merge-commit.sample
| |-- pre-push.sample
| |-- pre-rebase.sample
| |-- pre-receive.sample
| |-- prepare-commit-msg.sample
| |-- push-to-checkout.sample
| `-- update.sample
|-- info
| `-- exclude
|-- objects
| |-- info
| `-- pack
`-- refs
|-- heads
`-- tags
2.1.1 Git Config
不同级别的 Git 配置:system > global > local (按照级别高到低的顺序)。
每个级别的配置可能重复,但是低级别的配置会覆盖高级别的配置。
2.1.2 常见 Git 配置
- 用户名配置
git config --global user.name "yourname"
git config --global user.email youremail@example.com
# 查看用户名 后面不加参数就行
git config --global user.name # 查看邮箱同理
- Instead of 配置
# eg: 将 ssh 协议转换为 http 协议
git config --global url.git@github.com:.insteadOf https://github.com/
- Git 命令别名配置
# eg:
git config --global alias.cin "commit --amend --no-edit"
2.2 Git Remote
- 查看 Remote
# 查看已添加的远程仓库
git remote -V
- 添加 Remote 仓库
git remote add repoName repoAddr # repoName 远程仓库名 repoAddr 远程仓库地址
# eg:
git remote add origin_ssh git@github.com:git/git.git # 添加 git@github.com:git/git.git(该地址为 ssh 协议,下一行的是 http 协议) ,命名为 origin_ssh ,以下同理
git remote add origin_http https://github.com/git/git.git
演示如下:
git remote add origin git@github.com:git/git.git # 添加 git@github.com:git/git.git(ssh 协议的)仓库地址,命名为 origin
默认 pull 和 push url 是同一个:
git remote set-url --add --push origin git@github.com:my_repo/git.git # 设置push url 为 git@github.com:my_repo/git.git
结果:
也可以通过cat .git/config 来查看远程仓库的配置,经过上述操作,然后可以看到以下三个远程仓库信息:
2.3 Git Add
通过git add命令将文件添加到缓冲区。
Ace@MacBook-Air-15 MINGW64 /d/git_study (main)
$ touch readme.md
Ace@MacBook-Air-15 MINGW64 /d/git_study (main)
$ vim readme.md # 写入内容: Hello, I am a readme file.
Ace@MacBook-Air-15 MINGW64 /d/git_study (main)
$ git status
On branch main
No commits yet
Untracked files: # 表示有未加入缓冲区的文件
(use "git add <file>..." to include in what will be committed)
readme.md
nothing added to commit but untracked files present (use "git add" to track)
Ace@MacBook-Air-15 MINGW64 /d/git_study (main)
$ git add . # 加入缓冲区
Ace@MacBook-Air-15 MINGW64 /d/git_study (main)
$ git status
On branch main
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: readme.md
查看.git目录结构,发现objects增加了一些内容
- 前
- 后
(增加的是文件的id)
通过文件的id查看文件内容:
2.4 Git Commit
通过git commit命令提交。
git commit -m "description" # -m 用来加注释
提交上面创建的 readme.md,提交后,object目录下多了两个文件:
2.5 object
object:
- Blob 存储文件的内容
- Tree 存储同一次提交的所有文件的目录信息,每次不同的提交都会创建不同的tree对象。
- Commit 存储提交信息,一个 Commit 可以对应唯一版本的代码,即每次提交都会有一个commit。
具体结构如下:
关联起来:
- 通过 Commit 寻找到 Tree 信息,每个 Commit 都会存储对应的 Tree ID.
- 通过 Tree 存储的信息,获取到对应的目录树信息。
- 从 tree 中获得 blob 的 ID, 通过 Blob ID 获取对应的文件内容。
最后一个是commit,通过commit中的tree的ID可以查看tree的内容,tree中有blob的ID,可以用来查看源文件的内容。
2.6 Refs
git chechout -b branchName # 创建新分支并自动切换到新分支 branchName 表示分支名
- Refs 文件存储的內容
创建myTestBranch分支之后,refs目录下多出了一个文件,且它们的内容都是一样的,即refs 的内容就是对应的 Commit ID,因此把 ref 当做指针,指向对应的 Commit 来表示当前 Ref 对应的版本。
不同种类的 ref
-
refs/heads前缀表示的是分支,除此之外还有其他种类的 ref, 比如 refs/tags 前缀表示的是标签。
-
Branch git checkout -b 可以创建一个新分支,分支一般用于开发阶段,是可以不断添加 Commit 进行迭代的。
-
Tag 标签一般表示的是一个稳定版本,指向的 Commit 一般不会变更,可通过 git tag 命令生成 tag.
创建 tag v0.0.1
2.7 追溯历史版本
-
获取当前版本代码:通过 Ref 指向的 Commit 可以获取唯一的代码版本。
-
获取历史版本代码:Commit 里面会存有 parent commit 字段,通过 commit 的串联获取历史版本代码。
先用git log查看当前版本的 commit ID,然后查看commit,找到 parent 字段:
2.8 修改历史版本
- git commit --amend 通过这个命令可以修改最近的一次 commit 信息,修改之后 commit id 会变,tree ID 和 parent 字段不变。
原来的commit对象仍然存在,但是没有 refs 指针指向它,变成了 悬空的commit
- 实例:
修改最近一个commit,commit ID 更新了:
与修改之前的commit对比,tree和parent没变:
前:
后:
- git rebase
通过 git rebase -i HEAD-3 可以实现对最近三个 commit 的修改:
- 合并 commit
- 修改具体的 commit message
- 删除某个 commit
- git filter --branch 该命令可以指定删除所有提交中的某个文件或者全局修改邮箱地址等操作
2.9 完整的 Git 视图
2.10 Git Clone & Pull & Fetch
Clone 拉取完整的仓库到本地目录,可以指定分支,深度。 Fetch 将远端某些分支最新代码拉取到本地,不会执行 merge 操作, 会修改 refs/remote 内的分支信息,如果需要和本地代码合并需要手动操作。 Pull 拉取远端某分支,并和本地代码进行合并,操作等同于 git fetch + git merge, 也可以通过 git pull --rebase 完成 git fetch + git rebase 操作。 可能存在冲突,需要解决冲突。
2.11 Git Push
Push 是将本地代码同步至远端的方式。
常用命令: 一般使用 git push origin master 命令即可完成。
冲突问题:
1.如果本地的 commit 记录和远端的 commit 历史不一致,则会产生冲突,比如 git commit --amend or git
rebase 都有可能导致这个问题。
2. 如果该分支就自己一个人使用,或者团队内确认过可以修改历史则可以通过 git push origin master -f 来完成强制推送,一般不推荐主干分支进行该操作,正常都应该解决冲突后再进行推送。
推送规则限制: 可以通过保护分支,来配置一些保护规则,防止误操作,或者一些不合规的操作出现,导致代码丢失。
写在最后
参考: git 入门教程之 git bash 竟然不支持 tree 命令 - 雪之梦技术驿站 - 博客园 (cnblogs.com)