【Missing Semester】06 版本控制(Git)
本文为计算机教育中缺失的一课 The Missing Semester of Your CS Education 笔记
Git 工作流程
Git 更像是把数据看作是对小型文件系统的一系列快照。 在 Git 中,每当你提交更新或保存项目状态时,它基本上就会对当时的全部文件创建一个快照并保存这个快照的索引。 为了效率,如果文件没有修改,Git 不再重新存储该文件,而是只保留一个链接指向之前存储的文件。
- 工作区、暂存区、仓库
- 已修改、已暂存、已提交
Git 命令行接口
基本操作
创建仓库:
- 使用当前目录作为 Git 仓库,该命令执行完后会在当前目录生成一个 .git 目录。
cd ~/desktop/tmp
git init
# 已初始化空的 Git 仓库于 /Users/wangxinyuan/Desktop/tmp/.git/
ls .git
# HEAD description info refs
# config hooks objects
提交与修改:
-
添加文件到暂存区:
git add <filename>
。 -
将暂存区内容添加到仓库中:
git commit -m '提交说明'
。 -
查看仓库当前的状态,显示有变更的文件:
git status
。- 状态简览:
git status -s
。未track
的文件前为??
,暂存区的文件前有A
,修改过的文件前有M
标记。 输出中有两栏,左栏指明了暂存区的状态,右栏指明了工作区的状态。
- 状态简览:
-
显示与暂存区文件的差异:
git diff <filename>
。- 显示某个文件两个版本之间的差异:
git diff <revision> <filename>
。
- 显示某个文件两个版本之间的差异:
-
删除工作区文件:
git rm
。 -
移动或重命名工作区文件:
git mv
。 -
显示历史日志:
git log
。- 可视化历史记录:
git log --all --graph --decorate
。 - 查看历史记录的简洁的版本:
git log --oneline
。
- 可视化历史记录:
例——add、commit:
- 先使用
add
将文件添加到暂存区,再使用commit
将暂存区内容提交到仓库。
例——diff:
例——log:
分支合并
- 显示分支:
git branch
。 - 创建分支:
git branch <branchname>
。 - 切换分支:
git checkout <branchname>
。 - 创建分支并切换到该分支:
git checkout -b <branchname>
。 - 删除分支:
git branch -d <branchname>
。 - 合并分支(将
branchname
合并到当前分支):git merge <branchname>
。- 合并冲突:咕咕咕~
例——branch:
撤销
- 回退版本:
git reset <--soft | --mixed | --hard> <HEAD>
。 - 在工作空间但是不在暂存区的文件撤销更改:
git restore
。
I committed and immediately realized I need to make one small change!
-
git commit --amend
。 -
这个命令会将暂存区中的文件提交。
-
如果自上次提交以来你还未做任何修改,那么快照会保持不变,而你所修改的只是提交信息。
-
如果
git commit -m 'commitA' git add forgotten_file git commit --amend
最终你只会有一个提交——第二次提交将代替第一次提交的结果。
取消暂存的文件:
-
git reset HEAD <file>
。 -
例:
git add READ.md git add CONTRIBUTING.md git reset HEAD CONTRIBUTING.md
- 处于暂存状态的文件只有
READ.md
。
- 处于暂存状态的文件只有
-
这是个危险的命令。
I need to undo my changes to a file!
-
git checkout [saved hash] -- <file>
。 -
例:
git log # find a hash git checkout [saved hash] -- path/to/file
-
这是个危险的命令。
远端操作
- 查看当前配置有哪些远程仓库:
git remote
。 - 添加远程库:
git remote add <name> <url>
。 - 从现有 Git 仓库中拷贝项目:
git clone <git 仓库> <本地目录>
。 - 从远程获取代码库:
git fetch
。 - 下载远程代码并合并:
git pull <name> <远端分支名>:<本地分支名>
,相当于git fetch; git merge
。。 - 上传远程代码并合并:
git push <name> <本地分支名>:<远端分支名>
- 删除远程仓库:
git remote rm <name>
。
高级操作
咕咕咕~
Git 配置
-
使用配置文件
~/.gitconfig
或命令行接口git config <选项>
进行配置。 -
配置项指定 Git (如 log diff)运行时的分页器:
- 在命令行中执行:
git config --global core.pager ''
; - 或修改
~/.gitconfig
,在其中[core]
部分添加paper=
。
- 在命令行中执行:
-
图形界面工具
SourceTree
。 -
更多配置,咕咕咕~
使用 GitHub
ssh
GitHub 上的 ssh:
-
依次点击:
右上角的头像 -> Settings -> (左侧 Access) SSH and GPG keys
。总之是之前配过,咕咕咕~
电脑本地的 ssh:
-
相关文件是
~/.ssh
。 -
通过
~/.ssh/config
来配置,配置文件的格式为:# 添加 config 配置文件 # 配置文件参数 # Host : Host可以看作是一个你要识别的模式, 对识别的模式, 进行配置对应的的主机名和 ssh 文件 # HostName : 要登录主机的主机名 # User : 登录名 # IdentityFile : 指明上面 User 对应的 identityFile 路径 Host github1 HostName github.com User git IdentityFile ~/.ssh/id_rsa_name1 Host github2 HostName github.com User git IdentityFile ~/.ssh/id_rsa_name2
-
需要使用
ssh-add ~/.ssh/id_rsa_name1
将 ssh 私钥添加到 ssh-agent 高速缓存。- 可以使用
ssh-add -l
查看私钥列表。 - 可以使用
ssh-add -D
清空私钥列表。
- 可以使用
-
可以使用
ssh -T git@github.com
测试连接是否成功。
操作步骤
虽然这个步骤看起来很麻烦,但是没有但是~
-
在 GitHub 上创建一个仓库。
-
在本地的项目文件夹下打开终端,创建一个仓库,并将文件提交:
git init git add . git commit -m 'add something'
-
连接远程仓库:
git remote add origin git@github.com:略
-
push 到远程仓库:
git push origin master
- 这个时候惊喜的发现,Github 的仓库里有了两个分支:
main
和master
,于是接下来处理这个问题:- 在本地也创建一个
main
分支:git checkout main
。 - 合并:
git merge master --allow-unrelated-histories
,然后手动合并。 - 提交合并:
git add . && git commit
。 - 把本地
main
分支的东西push
到远程main
分支:git push origin main
。 - 删除本地
master
分支:git branch -D master
。 - 删除远程
master
分支:git push origin --delete master
。
- 在本地也创建一个
- 这个时候惊喜的发现,Github 的仓库里有了两个分支:
-
从根本上解决这个问题:
-
把
git init
默认创建的分支改为master
:git config --global init.defaultBranch main
-
由于远程仓库有一些本地没有的东西,不能
push
,先pull
,并且要加一些参数:git pull --no-rebase origin main --allow-unrelated-histories
-
否则可能出现报错:
提示:您有偏离的分支,需要指定如何调和它们。您可以在执行下一次 提示:pull 操作之前执行下面一条命令来抑制本消息: 提示: 提示: git config pull.rebase false # 合并 提示: git config pull.rebase true # 变基 提示: git config pull.ff only # 仅快进 提示: 提示:您可以将 "git config" 替换为 "git config --global" 以便为所有仓库设置 提示:缺省的配置项。您也可以在每次执行 pull 命令时添加 --rebase、--no-rebase, 提示:或者 --ff-only 参数覆盖缺省设置。
-
或出现报错:
fatal: 拒绝合并无关的历史
-
关于
merge
和rebase
:如果提交存在于你的仓库之外,而别人可能基于这些提交进行开发,那么不要执行变基。
-
-
最后
push
:git push origin main
-
提交规范
- feat:新功能 (feature)。
- fix:修补 bug。
- docs:文档 (documentation)。
- style: 格式 (不影响代码运行的变动)。
- refactor:重构 (即不是新增功能,也不是修改 bug 的代码变动)。
- test:增加测。
- chore:构建过程或辅助工具的变动。
参考
关于 Git:
关于 GitHub: