总目录:https://blog.csdn.net/qq_41106844/article/details/105553392
Python-后端 - 子目录:https://blog.csdn.net/qq_41106844/article/details/105553324
![20155953-3f7e24335e7f4f9c.png](https://i-blog.csdnimg.cn/blog_migrate/5e298259accec5f370a72dbdb36c5b1e.png)
参考:https://morvanzhou.github.io/tutorials/others/git/1-1-why/
为什么需要git
当你正在变成码农的路上,或者已经是码农的时候,就需要git了。
他会将同一个文件的不同历史版本变成一个文件。
下载路径:https://git-scm.com/downloads
一路默认参数下一步安装即可。
创建/修改版本库
创建版本库
首先找到 git bash,打开它。
![20155953-ed8b45deed37836f.png](https://i-blog.csdnimg.cn/blog_migrate/bcb523230b5ec5a97aff80bdc06f6b3e.png)
然后添加用户标识,我们添加两个标识,分别是user.name和user.email
![20155953-515b7d1c35a15b7d.png](https://i-blog.csdnimg.cn/blog_migrate/260259737e1bc5912a899afe863d0932.png)
![20155953-c1ca6e3fa62d29db.png](https://i-blog.csdnimg.cn/blog_migrate/d4834ddc9a505d4db8b5ac7e6184f752.png)
在git bash中,它遵循shell的命令。
我们新建一个文件夹用来当版本库。
![20155953-1731ba22a2b97813.png](https://i-blog.csdnimg.cn/blog_migrate/7b29ed3b361770ee9c380d2ec7b3c3f3.png)
我们可以看到他生成了一个.git的隐藏文件夹,我们看看他里面都是什么
![20155953-c7f542d883d1a8e3.png](https://i-blog.csdnimg.cn/blog_migrate/2b7c829202f6de10e54c557f35e96816.png)
这里面的数据不要随意修改。
添加文件管理
之后我们就要往版本库里面添加文件了
![20155953-dc2512bbb310d7c0.png](https://i-blog.csdnimg.cn/blog_migrate/055b9b00b1b2f53254cf1c7f2ba3bd83.png)
我们直接在版本库内新建一个文件。
![20155953-64af8091bae60f17.png](https://i-blog.csdnimg.cn/blog_migrate/1f1e5cd8565b9b9f307b6802737cfb28.png)
但是查看发现,这个文件并没有被纳入版本库。
我们看到提示中让我们使用一个命令 git add。
![20155953-247bcc59fbd87bba.png](https://i-blog.csdnimg.cn/blog_migrate/68b40101a4a2be326bac76691c51d139.png)
提交改变
这样,这个文件才算被纳入版本库。
提交改变
这样,文件才算真正提交上去了。
![20155953-d98262dce4ab0a15.png](https://i-blog.csdnimg.cn/blog_migrate/191dc5930388afd38b092883a1d37076.png)
流程图:
![20155953-c6fefd0306adbbfa.png](https://i-blog.csdnimg.cn/blog_migrate/bd39fd83bf504de5c2c7b468559e8e7a.png)
记录修改
查看当前的log
并对cs.py作出修改。
![20155953-1a544a12500cc1eb.png](https://i-blog.csdnimg.cn/blog_migrate/dcd9ad2ffffbbbb2da56e19c77316604.png)
这时查看状态,cs.py的状态变成了未纳入。
![20155953-241230d90bd8b023.png](https://i-blog.csdnimg.cn/blog_migrate/d011cd1089380d4b1a9e6136c9559b57.png)
纳入版本库
![20155953-fa97f76c8815a93c.png](https://i-blog.csdnimg.cn/blog_migrate/d7f65f6eba2860090a6aa9dc49569c5d.png)
提交,再次查看log
![20155953-658ccc85b09b3aac.png](https://i-blog.csdnimg.cn/blog_migrate/403e328ff8b2f082aa46c3e0bbc0d94b.png)
log从1个变成了2个。
如果我们想要查看一下刚才进行的修改是什么,可以通过git diff 前提是没有进行add操作将修改后的文件纳入版本库。
![20155953-65181206a7c8fb4d.png](https://i-blog.csdnimg.cn/blog_migrate/37c613d4486128e2f431a419ea4f9109.png)
如果已经进行了add操作,那么不要着急,我们还有一个cached参数。
![20155953-fdce85568bfc6e68.png](https://i-blog.csdnimg.cn/blog_migrate/c0c253b52a2723e55cd576c6e09adc8e.png)
这样就OK了。
我么先别提交,我们在修改一下cs.py。之后使用一个新的参数查看一下。
![20155953-d545b312336925b1.png](https://i-blog.csdnimg.cn/blog_migrate/e59ef0509e1150b0ed00254a4829d69c.png)
![20155953-2ef45436b1ad6420.png](https://i-blog.csdnimg.cn/blog_migrate/d2ed62661d1db1020efafc8aaff15b05.png)
回到从前
回到 add 之前
有时我们添加 add 了修改, 但是又后悔, 并想补充一些内容再 add. 这时, 我们有一种方式可以回到 add 之前.
![20155953-7c18bad997ce9b2f.png](https://i-blog.csdnimg.cn/blog_migrate/938c60cba809a641d1aecace9702f8f7.png)
![20155953-3aebe7dc6a34c494.png](https://i-blog.csdnimg.cn/blog_migrate/e06a7cb0dac6f66340ecbfc765ec81b9.png)
我们添加add后,查看状态是绿色的M,就是已添加(staged),使用reset,删除掉这次添加,就变成了红色的M,就是未添加(unstaged)。
回到 commit 之前
每个 commit 都有自己的 id 数字号, HEAD 是一个指针, 指引当前的状态是在哪个 commit. 最近的一次 commit 在最右边, 我们如果要回到过去, 就是让 HEAD 回到过去并 reset 此时的 HEAD 到过去的位置.
不管我们做了什么add操作,这一步直接回到上一个commit。
![20155953-c5ba4321ef005d88.png](https://i-blog.csdnimg.cn/blog_migrate/fcb3519707e7454a02f76cae2b6ebc2b.png)
让我们回到change1,同样也可以使用id号返回。
![20155953-bc86ea87ba10a94e.png](https://i-blog.csdnimg.cn/blog_migrate/8106c387177a6716bc07eebe7309e405.png)
查看log。
![20155953-be17dfdda286b8dd.png](https://i-blog.csdnimg.cn/blog_migrate/2ab473c92b3a5a122284663aa184dcff.png)
那么怎么回到change2呢。
![20155953-aae77dbcf8450256.png](https://i-blog.csdnimg.cn/blog_migrate/5bdc303917e047f984c4ba0663798a78.png)
首先查看最近我们做了哪些操作,然后找到 moving to HEAD 的id号,回到这个id。
改写文件
我们首先拷贝一个cs1.py,然后追加到change2中。
![20155953-2f1f7b6451e76388.png](https://i-blog.csdnimg.cn/blog_migrate/f5dea5fa72c112eb889e2d6a656488e1.png)
我们先看一下我们的log。
![20155953-cced5128fbd54b3d.png](https://i-blog.csdnimg.cn/blog_migrate/766967f59821efcd8725797aba25bec9.png)
我们指定cs.py回到 3ad86f5 的这个log。
![20155953-2233a1aa905d488d.png](https://i-blog.csdnimg.cn/blog_migrate/bf875dbace9c01b76864ecfee2304cba.png)
之后将cs.py提交上去。
![20155953-7a98f8755c662244.png](https://i-blog.csdnimg.cn/blog_migrate/2aebaa512a4c963ee3b8b1a679729a88.png)
分支管理
创建分支
使用branch创建一个分支,使用checkout来切换分支。
![20155953-4593a4179d3427b1.png](https://i-blog.csdnimg.cn/blog_migrate/9fa25bba96d2cc0f7cc5e2c5b5536cdd.png)
使用checkout -b 参数可以直接创建+切换。
![20155953-9ad49695015c42bf.png](https://i-blog.csdnimg.cn/blog_migrate/80119e5a15d8b9f5a8dc22364be0cedf.png)
dev01 分支中的 cs.py 和 cs1.py 和 master 中的文件是一模一样的. 因为当前的指针 HEAD 在 dev01 分支上, 所以现在对文件夹中的文件进行修改将不会影响到 master 分支.
我们在 cs.py 上加入一些东西, 然后再 commit(-am代表add+commit)
![20155953-4437074f898bc044.png](https://i-blog.csdnimg.cn/blog_migrate/8d48e7118c17a89ec9773de04c41dee6.png)
将 dev01 的修改推送到 master
我们先切换回master,之后使用merge合并他们。
![20155953-2c6f0c5687c7662a.png](https://i-blog.csdnimg.cn/blog_migrate/afb7c58a66b8ee602f65c1efc75e453f.png)
之后就可以我们合并了他。
![20155953-a5bacbacc2c8d6f8.png](https://i-blog.csdnimg.cn/blog_migrate/adee51d06fe9f9036fec6c705acae32e.png)
要注意的是, 如果直接 git merge dev, git 会采用默认的 Fast forward 格式进行 merge, 这样 merge 的这次操作不会有 commit 信息. log 中也不会有分支的图案. 我们可以采取 --no-ff 这种方式保留 merge 的 commit 信息.
![20155953-37b470565838a702.png](https://i-blog.csdnimg.cn/blog_migrate/88c73fad5ee7f1be57c1f5af03cf3220.png)
分支冲突
merge(合并分支冲突)
情况是这样, 想象不仅有人在做开发版 dev 的更新, 还有人在修改 master 中的一些 bug. 当我们再 merge dev 的时候, 冲突就来了. 因为 git 不知道应该怎么处理 merge 时, 在 master 和 dev 的不同修改.
当创建了一个分支后, 我们同时对两个分支都进行了修改:
master 中的 cs.py 加上 # edited in master.
dev 中的 cs.py 加上 # edited in dev.
![20155953-be37403e1743a963.png](https://i-blog.csdnimg.cn/blog_migrate/0974936faa09bb07cc688015e3312b2e.png)
![20155953-c8f089d9dc162b0e.png](https://i-blog.csdnimg.cn/blog_migrate/65d3bba310ae6f830a315436154a7ba6.png)
![20155953-0bbc7d0d9c7710f5.png](https://i-blog.csdnimg.cn/blog_migrate/ade72dc93c3095494a6cc0bd3bde034d.png)
当我们想要 merge dev 到 master 的时候,git 发现的我们的 cs.py 在 master 和 dev 上的版本是不同的, 所以提示 merge 有冲突. 具体的冲突, git 已经帮我们标记出来, 我们打开 cs.py 就能看到:
![20155953-52ec089671e60588.png](https://i-blog.csdnimg.cn/blog_migrate/08c8fc649e5f396d3e2b18b388ebea50.png)
我们随便修改一下cs.py,让里面的内容在当前HEAD统一。
![20155953-b1e7e4154b58d0d7.png](https://i-blog.csdnimg.cn/blog_migrate/ffbe4e259f7de2c5881820622485b510.png)
然后进行提交
![20155953-4ceca30772907099.png](https://i-blog.csdnimg.cn/blog_migrate/eaacfd5f5161bc7aa4be1b0af59e6e8b.png)
冲突就会解决掉:
![20155953-6f20e1b603984533.png](https://i-blog.csdnimg.cn/blog_migrate/91a1168c9488dab40cbe9271d3607be7.png)
![20155953-76960da2d5820eb1.png](https://i-blog.csdnimg.cn/blog_migrate/223db45ddfcd4e2b8b88b000e5d1cb6a.png)
rebase(重新划分分支冲突)
假设共享的分支是branch B,我而在branch A上工作,一天有我发现branch B已经有一些小更新,我也想试试我的程序和这些小更新兼不兼容,我也我想合并,就这时可以用rebase来补充我的分支branch B的内容。补充完以后,和后面那张图的merge不同,我还是继续在C3上工作,不过此时C3的本质却不一样了,因为吸收了那些小更新。我们所以用C3'来代替。
![20155953-934c11c5bef9b385.png](https://i-blog.csdnimg.cn/blog_migrate/e96450c19c0d04c3320a9e6d407fc40f.png)
![20155953-cb3d158596387492.png](https://i-blog.csdnimg.cn/blog_migrate/2f01a274d353d4bdb2f7b2c495c8172c.png)
![20155953-14fd6a93c10a8cf0.png](https://i-blog.csdnimg.cn/blog_migrate/cead3686bd0856ab6f34eaaf426c2c7d.png)
![20155953-606f617f3ff1e967.png](https://i-blog.csdnimg.cn/blog_migrate/e461003e8f47fffa3f1122e770c72cd1.png)
可以抛光rebase改变了C3的属性,C3已经不是从C1衍生而来的了。这一点和merge不一样。merge在合并的时候创造了一个新的C5 commit。这一点不同,使得在共享分支中使用rebase变得危险。如果是共享分支的历史被改写。别人之前共享内容的commit就被你的rebase修改掉了。
![20155953-28928c64b43cbf04.png](https://i-blog.csdnimg.cn/blog_migrate/60a2361f84fc3be4ddb69aefaa4684f6.png)
只能在你自己的分支中使用rebase,而别人共享的部分是不能用 。如果你不小心弄错了了。没事,我们还能用reflog恢复原来的样子。为了验证在共享分支上使用rebase的危险性,我们在下面的示例中也验证一下。
我们先将master和dev中的cs1.py修改为不同内容。
然后进行合并:
![20155953-36a59e51bb83dc6a.png](https://i-blog.csdnimg.cn/blog_migrate/525dc6736dd4fc42ff47641c4954a07f.png)
![20155953-9628d857e486852d.png](https://i-blog.csdnimg.cn/blog_migrate/9f6eea5fd844b346f421b75ff98a13ba.png)
这时HEAD并没有指向master或者dev,甚至停在了rebase模式上
然后手动合并,再次rebase,这时必须使用 --continue 参数。查看log。
![20155953-c5206186ddfee2d4.png](https://i-blog.csdnimg.cn/blog_migrate/0379517819212816d05d6cf53e0b02ed.png)
这个例子也说明了使用rebase要万分小心,千万不要在共享的branch中rebase,不然就像上面那样,现在master的历史已经被rebase改变了。其中master别人提交的change就被你无情地修改掉了,所以千万不要在共享分支中使用rebase。
临时修改
假如我们正在进行任务a,突然有一个紧急任务b介入,需要先停下手里的工作来完成任务b,但是不能将任务a和任务b同时commit,所以就有了暂存,也就是临时修改。
我们来dev这个分支来做。
![20155953-7653337bc899e69b.png](https://i-blog.csdnimg.cn/blog_migrate/b111e5e47dcd379f9e5f0b023e46ca75.png)
我们修改了一下cs.py文件,然后先不add,用stash来暂存他。之后查看他的状态,发现是另外一种情况。
然后我们来做任务b
介入其他任务
创建并进入taskb
![20155953-7df9fc731bafb264.png](https://i-blog.csdnimg.cn/blog_migrate/62613988a3a39bd99e873992c0e6ad70.png)
完成taskb任务并且提交。
![20155953-21315b16f07aeda6.png](https://i-blog.csdnimg.cn/blog_migrate/e02c4b16c38d89c6011c33051c132ec3.png)
回到master进行合并,如果有冲突则先修改文件进行合并。
![20155953-656e2162c36576da.png](https://i-blog.csdnimg.cn/blog_migrate/71023726d042b672ce9a522d076e5a11.png)
查看log
![20155953-8157d876245154f7.png](https://i-blog.csdnimg.cn/blog_migrate/243d37732cf69d6a0a4c175841391c77.png)
恢复工作
先切换回dev分支,之后查看一下stash的缓存。
![20155953-961cf9fafe166f66.png](https://i-blog.csdnimg.cn/blog_migrate/6cfeab21f17e964c0708ca33da3520fc.png)
通过pop提取他,继续工作。
![20155953-4f94cd298bb06ad5.png](https://i-blog.csdnimg.cn/blog_migrate/9d14121be71b3967cca3a8a797d71999.png)