Git从原理到实践
背景
如果有一个软件,不但能自动帮我记录每次文件的改动,还可以让同事协作编辑,这样就不用自己管理一堆类似的文件了,也不需要把文件传来传去。如果想查看某次改动,只需要在软件里瞄一眼就可以,岂不是很方便?
这个软件用起来就应该像这个样子,能记录每次文件的改动:
版本 | 用户 | 说明 | 日期 |
---|---|---|---|
1 | 张三 | 删除了软件服务条款5 | 7/12 10:38 |
2 | 张三 | 增加了License人数限制 | 7/12 18:09 |
3 | 李四 | 财务部门调整了合同金额 | 7/13 9:51 |
4 | 张三 | 延长了免费升级周期 | 7/14 15:17 |
那么它就是Git
到了 2002 年,Linux 系统已经发展了十年了,代码库之大让 Linus 很难继续通过手工方式管理了,社区的弟兄们也对这种方式表达了强烈不满,于是 Linus 选择了一个商业的版本控制系统 BitKeeper,BitKeeper 的东家 BitMover 公司出于人道主义精神,授权 Linux 社区免费使用这个版本控制系统。
安定团结的大好局面在 2005 年就被打破了,原因是 Linux 社区牛人聚集,不免沾染了一些梁山好汉的江湖习气。开发 Samba 的 Andrew 试图破解 BitKeeper 的协议(这么干的其实也不只他一个),被 BitMover 公司发现了(监控工作做得不错!),于是 BitMover 公司怒了,要收回 Linux 社区的免费使用权。
Linus 可以向 BitMover 公司道个歉,保证以后严格管教弟兄们,嗯,这是不可能的。实际情况是这样的:
Linus 花了两周时间自己用 C 写了一个分布式版本控制系统,这就是 Git!一个月之内,Linux 系统的源码已经由 Git 管理了!牛是怎么定义的呢?大家可以体会一下。
常用命令
git init
初始化仓库
git add <file>
添加文件到缓冲区,git add .
添加所有文件到缓冲区(Stage)
git commit
提交代码到本地版本库,此时会生成版本的提交hash
git status
查看状态,可以查看当前所处的分支,当前的修改内容和提交到版本库里的内容
git diff
可以让你看到你更改的内容
git log
查看commit的版本,参数--pretty=oneline
会只显示版本和commit
git rest --hard hash or head^
会进行版本号的回退可以选用版本的hash值或者HEAD^代表回退上一版本,
git reflog
记录你的版本操作,
git checkout -- file
可以丢弃工作区的修改。把 readme.txt 文件在工作区的修改全部撤销,这里有两种情况:
- 一种是 readme.txt 自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
- 一种是 readme.txt 已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
git checkout file
不加横杠就是创建分支
git reset HEAD file
撤销存储在缓冲区里的内容,HEAD 代表最新版本,也可以使用hash。 unstage是撤销缓存区中的内容
将你本地删除的文件在git上也删除,然后再提交,现在,文件就从版本库中被删除了。
1 | git rm test.txt |
git checkout -- test.txt
是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
远程库需要把一个已有的本地仓库与之关联,然后,把本地仓库的内容推送到 GitHub 仓库。
1 | git remote add origin git@github.com:michaelliao/learngit.git |
git push -u origin main
把本地库的所有内容推送到远程库上,-u
参数,Git 不但会把本地的 master 分支内容推送的远程新的 master 分支,还会把本地的 master 分支和远程的 master 分支关联起来
创建分支就是创建了一个指针,他可以独立于master进行提交和更改
1 | git checkout -b dev #创建并切换分支 |
git merge dev
可以将你对分支的提交的修改提交到master上,这里的dev是把dev合并到当前分支,当你同时修改一个文件时才会冲突,修改两个文件不会冲突。然后再提交到缓冲区,在提交版本
git branch -d dev
删除分支
git branch
查看分支
当出现如下修改时不能自动的合并分支
需要我们去手动解决冲突后再提交。git status 也可以告诉我们冲突的文件:
可以看到合并的过程
1 | git log --graph --pretty=oneline --abbrev-commit |
git merge --no-ff -m "merge with no-ff" dev
会以提交的方式合并分支
git stash
可以保存缓冲区的内容而不用提交
git stash list
可以查看工作现场的列表
git stash apply
恢复保存起来的现场
git stash drop
删除保存起来的现场
git stash apply stash@{0}
恢复指定现场
git branch -D feature-vulcan
强制删除分支
远端合并解决方案
分支策略
在实际开发中,我们应该按照几个基本原则进行分支管理:
首先,master 分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
那在哪干活呢?干活都在 dev 分支上,也就是说,dev 分支是不稳定的,到某个时候,比如 1.0 版本发布时,再把 dev 分支合并到 master 上,在 master 分支发布 1.0 版本;
你和你的小伙伴们每个人都在 dev 分支上干活,每个人都有自己的分支,时不时地往 dev 分支上合并就可以了。
所以,团队合作的分支看起来就像这样:
如果版本库领先自己一个版本应该如何操作和更改
应该git rebase
如何pull和push
git和pull 和是在和远程库操作,只是在拉取相应的分支并合并,与其他分支之间没有关系
git rebase 原理
git rebase
是一个强大的 Git 命令,用于将一个分支的提交历史重新应用到另一个分支之上。
基本工作流程
假设我们有两个分支,main
和 feature
,并且 feature
分支是从 main
分支分出来的,现在我们想要把 feature
分支的更改重新基于 main
最新的提交之上。我们可以使用 git rebase main
来实现这个目标。
内部指令解析
假设初始状态:
main
分支:A - B - C
feature
分支:A - B - C - D - E
执行 git rebase main
:
确定共同祖先提交:
1
git merge-base main feature
假设共同祖先提交是
A
。创建补丁并保存到临时文件:
1
git format-patch A..feature -o /tmp/patches
这会在临时目录中创建从
A
到feature
的补丁文件。切换到
main
分支并重置feature
分支:1
2git checkout feature
git reset --hard main现在
feature
分支的 HEAD 和main
分支的 HEAD 是一致的。应用补丁:
1
git am /tmp/patches/*.patch
这一步会逐个应用补丁,并创建新的提交。应用过程中,如果有冲突,Git 会暂停并允许用户手动解决冲突。
其他常见操作
处理冲突
如果在应用补丁的过程中遇到冲突,Git 会暂停并提示用户解决冲突。用户解决冲突后,需要执行以下命令继续:
1 | git add <resolved-files> |
如果用户希望放弃变基,可以执行:
1 | git rebase --abort |
git rebase 和git pull 的替换
可以使用 git pull
、git push
和 git merge
来实现类似 git rebase
的效果。虽然这并不是完全相同的操作,但通过一些步骤,你可以手动完成类似的变基过程。
以下是一个示例,展示如何使用这些命令来实现 git rebase
的效果:
场景设置
假设有两个分支:
main
分支feature
分支
我们希望将 feature
分支的更改重新基于 main
分支的最新提交之上。
步骤
1. 更新 main
分支
首先,确保 main
分支是最新的:
1 | git checkout main |
这将把 main
分支拉到最新状态。
2. 更新 feature
分支
接下来,切换到 feature
分支并拉取最新的更改:
1 | git checkout feature |
这将确保 feature
分支也是最新的。
3. 创建临时分支
创建一个临时分支来保存 feature
分支的更改:
1 | git checkout -b feature-temp |
4. 将 feature
分支重置到 main
分支
切换回 feature
分支并将其重置到 main
分支的最新提交:
1 | git checkout feature |
现在 feature
分支的 HEAD 与 main
分支的 HEAD 相同。
5. 合并临时分支的更改
将临时分支的更改合并到 feature
分支:
1 | git merge feature-temp |
在这个过程中,如果有冲突,解决冲突并继续合并。
6. 推送更改
如果合并成功,将 feature
分支的更改推送到远程仓库:
1 | git push origin feature --force |
总结
通过这样述步骤,可以实现类似 git rebase
的效果总结步骤如下:
- 更新
main
分支和feature
分支。 - 创建一个临时分支保存
feature
分支的更改。 - 将
feature
分支重置到main
分支。 - 合并临时分支的更改到
feature
分支。 - 推送更改到远程仓库。
hexo常用命令
https://www.jianshu.com/p/c14e70f5885d
参考
https://doc.yonyoucloud.com/doc/wiki/project/git-tutorial/index.html