git 基础
中央仓库
分布式VCS
分布式 VCS (Distributed VCS / DVCS)和中央式的区别在于,分布式 VCS 除了中央仓库之外,还有本地仓库:团队中每一个成员的机器上都有一份本地仓库。
git 简单命令
git 练手仓库:github 仓库
1 | git 简单指令汇总 |
- 把远程仓库取到本地
1 | git clone https://github.com/dongyeforever/ihappy.git |
查看本地目录,这个 .git
目录,就是你的本地仓库(Local Repository),你的所有版本信息都会存在这里。而 .git
所在的这个根目录,称为 Git 的工作目录(Working Directory)
1 | ➜ ihappy git:(main) l |
- 查看提交记录
1 | git log |
1 | commit 03dcf7490765baf0394d518a3c6b642e9c5f88b2 (HEAD -> main, origin/main, origin/HEAD) |
- 查看工作目录当前状态
1 | git status |
添加到本地仓库
文件添加前红色,添加后变成绿色。文件的状态从 “untracked”(未跟踪)变成了 “staged”(已暂存)。所谓的 staging area,是
.git
目录下一个叫做index
的文件。你通过add
指令暂存的内容,都会被写进这个文件里。
1 | git add test.txt |
提交到本地仓库
将暂存区里的改动给提交到本地的版本库。
1 | git commit |
提交远程仓库
多人并行开发时 git push 发生冲突,中央仓库已经被其他同事先一步
push
了的情况。先用 git pull 把远端仓库上的新内容取回到本地和本地合并,然后再把合并后的本地仓库向远端仓库推送。
1 | git push |
.gitignore 文件
忽略不想被管理的文件或目录。
1 | *.class |
如果没有添加到 .gitignore 文件已经被添加到暂存区了:
1 | git rm --cached filename |
git 配置
1 | git config --list // 查看配置 |
git 进阶
- 引用
第一行的 commit
后面括号里的 HEAD -> master, origin/master, origin/HEAD
,是几个指向这个 commit
的引用。每一个 commit
都有一个它唯一的指定方式——它的 SHA-1 校验和(03dcf7490765baf0394d518a3c6b642e9c5f88b2),你可以使用03dcf74
代替这个commit。
- HEAD
当前 commit
在哪里,HEAD
就在哪里,这是一个永远自动指向当前 commit
的引用,所以你永远可以用 HEAD
来操作当前 commit
。
- branch
branch 创建、切换和删除
1.创建一个叫做 “feature” 的 branch
1 | git branch feature |
2.切换到 “feature”分支
1 | git checkout feature |
除此之外,你还可以用 git checkout -b 名称
来把上面两步操作合并执行。
1 | git checkout -b feature |
3.删除分支
1 | git branch -d feature // 出于安全考虑,没有被合并到 master 过的 branch 在删除时会失败 |
git push
1 | // 提交 main 分支 commits |
merge 合并 commits
merge
的意思是「合并」,它做的事也是合并:指定一个 commit
,把它合并到当前的 commit
来。具体来讲,merge
做的事是:
从目标 commit
和当前 commit
(即 HEAD
所指向的 commit
)分叉的位置起,把目标 commit
的路径上的所有 commit
的内容一并应用到当前 commit
,然后自动生成一个新的 commit
。
1 | git merge feature |
git pull 等价于 git fetch + git merge
合并冲突
如果两个分支修改了同一部分内容,merge
的自动算法就搞不定了。这种情况 Git 称之为:冲突(Conflict)。
- 解决冲突
- 手动提交
1 | git add xxx |
取消 merge
1 | git merge --abort |
Pull Request 工作流
这一节介绍了 Feature Branching 这种工作流。它的概念很简单:
- 每个新功能都新建一个
branch
来写; - 写完以后,把代码分享给同事看;写的过程中,也可以分享给同事讨论。另外,借助 GitHub 等服务提供方的 Pull Request 功能,可以让代码分享变得更加方便;
- 分支确定可以合并后,把分支合并到
master
,并删除分支。
这种工作流由于功能强大,而且概念和使用方式都很简单,所以很受欢迎。再加上 GitHub 等平台提供了 Pull Request 的支持,目前这种工作流是商业项目开发中最为流行的工作流。
git 查看修改记录
- git log 查看历史记录
1 | git log --stat // 查看大致改动 |
- git show [commit-id] 查看任意一个 commit 修改
- git diff 查看未提交内容
不喜欢 merge 的分叉?用 rebase 吧
rebase
指令,它可以改变 commit
序列的基础点。
可能会出问题的 rebase:
1 | git rebase feature // 在master上直接rebase |
不会出问题的 rebase 方式:
1 | git checkout feature |
所以,为了避免和远端仓库发生冲突,一般不要从
master
向其他branch
执行rebase
操作。而如果是master
以外的branch
之间的rebase
(比如branch1
和branch2
之间),就不必这么多费一步,直接rebase
就好。
刚刚提交的代码,发现写错了怎么办?
“amend” 是「修正」的意思。在提交时,如果加上 --amend
参数,Git 不会在当前 commit
上增加 commit
,而是会把当前 commit
里的内容和暂存区(stageing area)里的内容合并起来后创建一个新的 commit
,用这个新的 commit
把当前 commit
替换掉。所以 commit --amend
做的事就是它的字面意思:对最新一条 commit
进行修正。
1 | git add test.txt |
丢弃刚写的提交(最新)
1 | git reset --hard HEAD^ |
push 后发现写错了
1.在自己 branch
上,把错误的 commit 修改或者删除,然后 push -f
强制提交上去。
1 | git push origin feature -f |
2.出错的内容已经合并到 master 上
在 revert
完成之后,把新的 commit
再 push
上去。
1 | git revert HEAD^ |
紧急情况,需要紧急打包
当你手头有一件临时工作要做,需要把工作目录暂时清理干净,那么你可以:
1 | git stash |
工作目录的改动就被清空了,所有改动都被存了起来。
打包完后,切回你的分支,然后:
1 | git stash pop |
注意:没有被 track 的文件(即从来没有被 add 过的文件不会被 stash 起来,因为 Git 会忽略它们。如果想把这些文件也一起 stash,可以加上
-u
参数,它是--include-untracked
的简写。就像这样:git stash -u
1 | git stash list |
Branch 删除了还想用,reflog
引用的 log,使用它可以查看 Git 仓库中的引用的移动记录。
1 | git reflog |
1 | 212b0ed (HEAD -> main) HEAD@{0}: checkout: moving from feature to main |
从图中可以看出,HEAD 的最后一次移动行为是「从 feature 移动到 main」。而在这之后,feature 就被删除了。所以它之前的那个 commit 就是 feature 被删除之前的位置了,也就是第二行的 34c6314。
所以现在就可以切换回 34c6314,然后重新创建 feature :1
2git checkout 34c6314
git checkout -b feature
这样,你刚删除的feature
就找回来了。
tag
上线发版打 tag
1 | git tag v1.0.0 |
cherry-pick 挑选 commit 合并进来
1 | git cherry-pick commit-id |