Git 的实战教学 | 从 0 到 1
![Git的实战教学 | 从0到1](https://static001.geekbang.org/infoq/34/346320186a1881852bb592c5e2f87d42.jpeg)
“接上上文 Git 的基础操作“: https://xie.infoq.cn/article/0385f0718b67da57cb8017c69
"八月更文第二天",本月第二篇,加油
git 实战教学
1.背景:
今天在我使用 git 作为提交的时候,一不小心提交了 79 个文件,但是我改的文件事 2 个,以至于多个 commit 的,都被我直接提交了远程仓库----(好多日志的文件,老大估计又得发飙),还好是我自己的分支,可以回退版本,但是远程的代码怎么办呢;今天问题:
问题 1:
当我修改了多个文件,但是我只想提交其中的一个文件进行 commit ,然后进行 push?标准的流程是怎么样的;(如何避免日志的提交)开始新建仓库,直接在目录中拉取代码:
git init 目录初始化仓库
![](https://static001.geekbang.org/infoq/27/2785662d4cc7736ccd8278032a01ec2f.png)
git clone 拿到具体的链接地址,开始使用
实例: git clone https://gitee.com/lucasweb/testdemo1.git testdemo01
表示克隆---》原地址---》现在的目录名进入具体的源码目录,记住是要进入 git 管理的目录;开始新建一个分支(切换分支,因为拉取代码的都是 master 分支)
![](https://static001.geekbang.org/infoq/8e/8e476572857dc817dc77ed56a05e1079.png)
上述可以找到具体的 git 中有许多的分支,我们开始自己新建一个;
开始利用 idea 直接将 git 管理的数据打开:
C:\Users\web\Desktop\testgit\testdemo01
这是地址, 桌面的地址 web/deskTop\
![](https://static001.geekbang.org/infoq/43/431ec5a92698976deeaee11141a8cac4.png)
打开是这样的表示,默认是 master 分支,但是我们还具体的还没开始,我们创建了几个包名,供我们开始测试
我们先是写一个素材,放入 master 的分支中:\
![](https://static001.geekbang.org/infoq/3f/3fbebcfe87eaf9426e8d36e52e9cfb6a.png)
红色的代表:没有被 Git 管理的文件;
绿色的代表已经被 Git 管理的文件
,我们来看看,绿色的文件直接提交,master2 文件提交到 master2 远程分支上\
![](https://static001.geekbang.org/infoq/22/2213ef18626dd575449ebb15397e1268.png)
![](https://static001.geekbang.org/infoq/22/2213ef18626dd575449ebb15397e1268.png)
需要远程 push 的\
![](https://static001.geekbang.org/infoq/31/3153a9d9ae8430c4ce7e0b028f3ea0ee.png)
提交之后,我们看看远程\
![](https://static001.geekbang.org/infoq/8f/8f9cf1a42afb7df3dbdf7db7640372ad.png)
明明我选择的是一个,但是他提交的就是两个,也就是说,push 会把之前没有 push 的从 commit 的,直接提交过去;
![](https://static001.geekbang.org/infoq/8e/8e476572857dc817dc77ed56a05e1079.png)
为了解决疑惑,我有开始了提交了两个 commit,看一下我这次 push:\
![](https://static001.geekbang.org/infoq/73/736e7e622c28cc2e2509511238e48490.png)
![](https://static001.geekbang.org/infoq/1e/1e352c65d8f9b185610009c7283170de.png)
只提交了一个 commit;
但是;\
![](https://static001.geekbang.org/infoq/e3/e34ec27b9b8223cf848a4891442c2424.png)
显示直接全部提交;
事实证明,push 一次会把之前所有的 commi 都提交的;
怎么避免每次都提交一个 commit,也就是我可以失效 commit(撤销提交的 commit)来使用
已经蒙了????
2.新建分支切换去合并代码
由于之前是在 master 开发,有很大的风险,然后我们就开始在新的分支上开发然后合并或者是 review 导 master 上面
git checkout -b lucas 新建一个分支并且跳过去;
或者是 IDEA,右下角\
![](https://static001.geekbang.org/infoq/6a/6a49e3b6da15ad5281cfc0c9722e11f4.png)
开始切换成功;\
![](https://static001.geekbang.org/infoq/b0/b00b1e54cbe36f6b70e3636574359c25.png)
,因为自己新建的分支---,可以将 master 的代码直接合并到新建的 lucas 上面;
合并 master 代码:
(我们分支 A 需要 master 的最新的代码,可以直接 Git merge 分支名);\
![](https://static001.geekbang.org/infoq/22/222e6c91de95b58bb29f9098d3c8e162.png)
![](https://static001.geekbang.org/infoq/fe/febe713d6ea854f7ae282ec43b734e31.png)
本地开发 lucas\
问题 2:
当我本地的数据要更新 master 的代码,如何算是标准的 merge 到合并到自己的分支(如果是多余的文件,或者说是已经删除的代码信息呢);
![](https://static001.geekbang.org/infoq/64/64f9ff6fa60ecdbcba5a921a9e347f3d.png)
然后 master 改造完毕;
我们直接跳回去 lucas,看已经 commit 的代码能否保存(但是没有 push)\
![](https://static001.geekbang.org/infoq/57/57ca3e2de32054553c58a2e056275150.png)
master 中 commit 的所有集合都合并过来了,包括新增和修改;\
![](https://static001.geekbang.org/infoq/51/51a72c3ebb9902210cd0c5e8f5e83891.png)
虽然说已经是可以的数据,但是,突然发现 master 本地提交的代码有问题,我想撤销之前提交的 commit;
git reset --soft HEAD~n
可以将之前已经提交的 commit 撤销回来,(保存本地代码不变,add 也不变)
问题 3:
如果说我提交了一个 commit ,而且已经 push 了,但是我发现数据是错的,我要重新退回本地---重新修改;(也就是撤销远程仓库的代码已经 push 的代码);
本地开发 lucas;
但是我们开始了我们的创作之旅,首先是分支,在 lucas 上,我们创建了两个 commit,一个 push 之后,数据直接将全部提交了,但是,注意,我提交的文件多了,错误了(“和上午一样一下子日志也给提交了”),但是现在,lucas 上的提交记录
![](https://static001.geekbang.org/infoq/44/44ed90a752b6b8060dcef0be6c0d143f.png)
上述的图片中有很多的干货:git reflog 显示所有的提交;
我们能看到左侧是 commitId(版本号),可以直接回退版本;提交了两次,还有一次是合并到 lucas
现在是 lucas 的提交记录
怎么样撤回远程仓库的代码已经 push 的代码两次 commit 的代码;\
![](https://static001.geekbang.org/infoq/d6/d643faa01f5c9952b5b4d439254027da.png)
reset;revert 我们先来测试 git reset 是干嘛的;
![](https://static001.geekbang.org/infoq/62/621147eb750cf75021979e217520a7f8.png)
git reset
由于近期的护网行动,我们公司使用的是一个外网的地址,我提交的文件还有错误,所以这里我就开始讲版本回退,重新提交 commit ,然后是将数据直接变成--
强制 push
git push --force
就可以成功\
![](https://static001.geekbang.org/infoq/42/42906d7e0d3559f4cc7db0ce3544eeae.png)
修改仓库地址
因为提交的时候要修改仓库地址,外网的地址和内网的地址是不一样的,所以我们直接使用,\
![](https://static001.geekbang.org/infoq/a7/a7d3506f32f28c328f055e52ceb6bf69.png)
git remote 查看仓库信息 显示 出的结果“orgin”
git remote set-url orgin 新的地址
首先搜索一下:(百度需要你的信息)\
![](https://static001.geekbang.org/infoq/46/4601b04c418a829429b04d4c96adb267.png)
我们测试的是 soft
![](https://static001.geekbang.org/infoq/46/4601b04c418a829429b04d4c96adb267.png)
版本穿越:
本地代码会找回来,;
@#请求版本号;
git reflog
git log
![](https://static001.geekbang.org/infoq/fb/fb7da0d8679d40f4ec92f970adede206.png)
git rest --hard 版本号
目前已经删除的最近的 commit 的显示;-然后我们穿越回去;\
![](https://static001.geekbang.org/infoq/46/4601b04c418a829429b04d4c96adb267.png)
![](https://static001.geekbang.org/infoq/76/76a9868da05d0b2f9236bace7eec0d99.png)
通过版本穿越:我们找到之前删除文件--本地数据中;\
![](https://static001.geekbang.org/infoq/33/3372a96a26c80e270e28836ca7ff509a.png)
比如说我们本地代码已经退回来了,现在从最初的版本号(肯定比现在的 commit 低),我们重新提交代码,看看会发生什么事情》
会因为版本号低而变化吗;\
![](https://static001.geekbang.org/infoq/8e/8e96be6190fae18fed4afd6065600d4b.png)
![](https://static001.geekbang.org/infoq/e6/e6919d32db17820b8e12e9c01e37cad9.png)
果然:人家拒绝了;\
![](https://static001.geekbang.org/infoq/4c/4cb9aa0d82f5f67228e85ef143138f82.png)
然而不行的:
我直接是将本地开始的数据变成强制提交
git push --force
![](https://static001.geekbang.org/infoq/76/76a9868da05d0b2f9236bace7eec0d99.png)
![](https://static001.geekbang.org/infoq/95/95e8b88e355272ba83ed19e47cb99c47.png)
![](https://static001.geekbang.org/infoq/77/77b59481ad542843186af33ec5f0da45.png)
所以,对于开发
提交异常的 commit,如何解决:
第一种方法
本地分支拿到所有的版本号:
git reflog 左侧的就是
开始版本穿越:
git reset --hard 版本号(要提交之前最近的版本号)
穿越完成之后,本地代码显示提交之前的,开始进行开发
开发完毕直接将文件 commit file,由于版本号的低肯定会 push 失败;
我们强制 push 就可以成功;
git push --force
然后就会成功的;
第二种方法:
但是也可以直接重新拉取 master 代码,从新开发,要是开发量比较细就可以的;\
![](https://static001.geekbang.org/infoq/77/77b59481ad542843186af33ec5f0da45.png)
revert:表示当前一个提交是作废的,我们直接可以将再次提交作废;\
![](https://static001.geekbang.org/infoq/7a/7a937a1559008f61b88d53d85ba69d36.png)
会使得本地的提交 commit 失效,然后我们呢直接将数据 push 到远端,就可以将之前的数据改变了;\
![](https://static001.geekbang.org/infoq/60/60906e48c2c7d71c8e98b01f91495c64.png)
问题 4:
标准的如果,我现在在开发,领导让我改一个 bug,但是我又想保存我现在的已经写好的代码,又不想丢掉对吧;(暂存代码)git stash 暂存起来
git stash pop 捞出来\
![](https://static001.geekbang.org/infoq/4b/4b722b852d9cc75c6ae278251591b675.png)
实例:
我们开始写一点数据参数;然后给它放到暂存区域;
1.新增需求的我,正在加急的写代码中;\
![](https://static001.geekbang.org/infoq/2a/2a0281e5de7f17c027d678e55a1b0335.png)
但是这时候一个满脸清纯的程序媛走过来说,可能帮我调个 bug 吗,(乐于助人,怎么能拒绝呢),哈哈,但我已经写了一上午的代码,还没能开始调试,我又不想提交,怎么办呢,(又不能直接拒绝,结束单身的机会,怎么能不把握好),幸好,卢卡我知道;
IDEA 有代码输入行,就是类似于 cmd
git stash //将代码放入暂存区域\
![](https://static001.geekbang.org/infoq/8b/8b218b22277672e34de9a024170223c3.png)
然后发现我的工作空间里面现在,没有了我之前的代码了,不会丢了吧(不用担心,是被保存起来了);
然后我们切换分支,给他解决一下问题;
然后我们来本地 lucas 的代码中看看
关于已经提交的 commit 的,我们直接是将期变化成撤销;
https://www.baidu.com/index.php?tn=monline_3_dg
--soft 不删除工作空间的改动代码 ,撤销 commit,不撤销 git add file
关于参数:
–mixed
意思是:不删除工作空间改动代码,撤销 commit,并且撤销 git add . 操作
这个为默认参数,git reset --mixed HEAD^ 和 git reset HEAD^ 效果是一样的。
–soft
不删除工作空间改动代码,撤销 commit,不撤销 git add .
–hard
删除工作空间改动代码,撤销 commit,撤销 git add .
注意完成这个操作后,就恢复到了上一次的 commit 状态。
git reset --mixed HEAD~1 或者是 n
顺便说一下,如果 commit 注释写错了,只是想改一下注释,只需要:
git commit --amend
1
此时会进入默认 vim 编辑器,修改注释完毕后保存就好了。\
![](https://static001.geekbang.org/infoq/9f/9f43d1c5fa7ca43660db55cb2a72f732.png)
问题 5:
如果说 master 的版本特殊号是 1.0.0,但是我使用的本地分支 lucas 版本是 3.0.0,
但是每次我要从 master 拉取最新的代码,肯定会遇到的问题就是冲突;
有什么好的方法呢;
首先是我将 lucas 的文件版本号改变成 3.0.0.,如图所示;\
![](https://static001.geekbang.org/infoq/bc/bc7f3e1648164bb35431aeca857bc722.png)
但是 master 的已经有了新的文件,所有我需要更新;
第一种方式:
我们开始保存本地,然后直接切换分支开始进行
但是出现问题弹框了;\
![](https://static001.geekbang.org/infoq/cb/cb2708c8df15e0901eb4bdc9912bde08.png)
就是我们之前的版本号差异造成的,force checkout 会导致新增的版本号直接丢失的,
所以,我们将数据直接试一下 smart checkout\
![](https://static001.geekbang.org/infoq/46/4601b04c418a829429b04d4c96adb267.png)
类似于:
git stash 暂存改变
![](https://static001.geekbang.org/infoq/9f/9f43d1c5fa7ca43660db55cb2a72f732.png)
git stash pop 显示\
![](https://static001.geekbang.org/infoq/c3/c3854e9f123124aa06d6a7b767e8cdb7.png)
一般会出现三个展示的代码框;\
![](https://static001.geekbang.org/infoq/5c/5ce4bfd51e3a438085b329ea0f98da8d.png)
然后我们选择保存就可以,一般就是选择自己本地的呗,哈哈第二种方法:
![](https://static001.geekbang.org/infoq/da/da85c933460e3a4bfd8633738947b519.png)
暂存本地所有的 stash 哈哈;
git -->repository-->stash changes
给一个 message 标识--->然后切换分支 master 开始拉去最新的数据;
然后开始合并,到 lucas,记住这里肯定会出现 conflicts ,(合并之后,我们将之前修改的代码还原,也就是暂存区域中取出);\
![](https://static001.geekbang.org/infoq/21/216eca6f7d7cabf79112b31189415f0a.png)
这是已经将 master 的新增代码合并到 lucas 的开发分支上;
我们将数据直接变成-----开始还原暂存区的;\
![](https://static001.geekbang.org/infoq/25/2525c784d6fe12b82c4be2dd906f19c1.png)
view :\
![](https://static001.geekbang.org/infoq/d9/d99fb9c366d63ba783c40b626f080d1f.png)
直接回复之前的 stash;
没有冲突,庆幸一点;\
![](https://static001.geekbang.org/infoq/15/15bcddbcd2b11dbdfb7ea2a63afc7e51.png)
lucas 的开始作妖了:
将本地的代码继续改变,然后保存看能否发生冲突;\
![](https://static001.geekbang.org/infoq/c9/c96679feff56a8cc23bb0a34e4d2e265.png)
![](https://static001.geekbang.org/infoq/f4/f4bf81aacf05a4c014f4a79e1998d70d.png)
![](https://static001.geekbang.org/infoq/15/150b9620ee3f37298b9c8118db942ca7.png)
切换分支到 master 然后开始拉去 master 最新的代码
(因为 lucas 的代码我没有提交,合并的 master 的来源,所有直接切换就可以)\
![](https://static001.geekbang.org/infoq/1b/1b66ffcea20f9748cbb38317cbe97377.png)
这是新改变好的数据--lucas,然后我们还原看一下;\
![](https://static001.geekbang.org/infoq/18/184fd67272416bf7cf630f63f7927e16.png)
![](https://static001.geekbang.org/infoq/a0/a03debc521ea47f8ce2f0cb1f36ce8ad.png)
![](https://static001.geekbang.org/infoq/55/55bd0058229cb7abaaca57bf8fea6c4f.png)
还原失败了;\
![](https://static001.geekbang.org/infoq/38/3847f063242d67785529db5dc56333fc.png)
Please move or remove them before you merge.
开始疯狂的尝试;\
细心的我准备了很多干活命令行;\
![](https://static001.geekbang.org/infoq/54/5420a1035749809ac1772c7e1bd7f176.png)
master 分支\
![](https://static001.geekbang.org/infoq/ba/ba1410ee41fb74bd1c7f95ca57f8accc.png)
版本号是 1.0.0,
目前有两个分支,一个 master 分支,一个 lucas 的分支,master 已经有了新的代码,我自己目前使用的是 lucas 的分支,第一版本号(常量)已经改了为 3.0.0(master 的版本号为 1.0.0),而且我对 lucas 的分支已经有了整改(暂存起来 Git stash)没有提交 commit, 现在需要保存之后跳转到 master 分支上去拉取代码合并到 lucas 的分支上,合并之后,lucas 的分支上已经有了最新的 master 分支的代码,但是,想要恢复之前暂存区里的代码(git stash pop)恢复一直是失败,提示是\
![](https://static001.geekbang.org/infoq/b4/b49e266bd254d887949588959853e86f.png)
只能丢掉代码了吗;我之前写的好多;
git reset --hard 版本号;
切换到之前的版本再合并哈哈
合并之前必须先要提交本地的 commit 的整改;
master 分支有数据之后我们保存本地的修改 commit 开始数据整理;
然后合并的时候;;\
![](https://static001.geekbang.org/infoq/3b/3b3f6fad9a95e0a8064b6f00823e2eab.png)
workspace.xml 的文件----怎么忽略这些文件不被 git 管理;
IDEA git 忽略文件的几种方式\
![](https://static001.geekbang.org/infoq/95/9570cf5c5d94b33f4fe08f456f8bdefc.png)
![](https://static001.geekbang.org/infoq/c9/c944a4d764262d60e7d7618a7e826d90.png)
![](https://static001.geekbang.org/infoq/a0/a0b4661c8e5b30f58ecd198cee2640ff.png)
不合适,idea 取消 git 标记管理;\
![](https://static001.geekbang.org/infoq/64/64f4a4313dffe35228c4033f19d2b9dd.png)
![](https://static001.geekbang.org/infoq/42/4220b42f08f235a2481f0f17e612b900.png)
然后关闭 IDEA 重启;git log\
![](https://static001.geekbang.org/infoq/19/19c894ad7e1ff0c573ae630e703023f1.png)
如何本地修改代码之后,本地提交 commit,然后提交的本地 commit,但是提交了多余的文件,(本地提交了 commit)---我们撤回本地 commit 怎么做呢;
git log 查看具体的提交记录;
git reset --soft commitId 版本号;
(取消你本地的提的 commit,但是本地的代码不会变动,需要你重新修改后提交)\
![](https://static001.geekbang.org/infoq/86/86a8790365bec3a1d82ffb3a2724da10.png)
本地提交的记录也会消失,
总结:
本地修改了代码,但是现在需要我们开发新需求所以,切换分支,但是为了避免我们写的代码失效(我们本地提交一个 commit,然后拥有了一个 commit 的 ID,)
然后我们再去干别的事情;
等到切回我们的分支的时候,我们将之前本地提交 的 commit 还原回来;接着开发,先备份一下,因为还原的时候,(本地代码不会发生改变,也就是会保存之前已经存在的;)
具体操作:
比如我们现在提交了三次本地 commit;分别是 1,2,3;
类似于这样的;\
![](https://static001.geekbang.org/infoq/a0/a00ca2127e1900cceca0f9a624c4148e.png)
![](https://static001.geekbang.org/infoq/75/7563286da0cac27d25452b61a19ab279.png)
然后我们要撤销 3 的 commit 提交,回退到 2;
git log
git reset --soft 2 的 commidId ;
本地代码没有改变,但是本地的 commit 已经撤销了;
如何解决已经提交到远程的 commit,已经 push 远程的呢;\
![](https://static001.geekbang.org/infoq/00/002da73c49196571743bef89652c7559.png)
一次 push,将本地所有的 commit 都提交到远程的分支了;\
如何撤回呢;
git log 查看具体的提交记录
git reset --hard 记录 id
切换版本到提交前的一个版本,
特殊的,这里的-- hard ,会直接将回退到之前的版本(本地的代码也会修改,--soft 的本地不会被修改);
然后\
![](https://static001.geekbang.org/infoq/9b/9b3f15e4e6bb2ba3e7fd586b51c9c554.png)
将数据版本直接回退了,然后我们重新提交,看一下远程的记录;\
![](https://static001.geekbang.org/infoq/d6/d6d5611e11406c1dd4436903698a5127.png)
版本比较低的原因,肯定提交不成功;
所有强制提交;
git push --force\
![](https://static001.geekbang.org/infoq/a6/a682e474095a8f33e65816c23f294e7f.png)
终于圆满结束了;
git 实操:
如果说已经被变化的数据,和已经改变好了的数据你没有及时的拉取,
但是当你 push 到远程的时候已经就会 push 不成功:\
![](https://static001.geekbang.org/infoq/4a/4ae332ee3f1abe97bb248b0eedff25f4.png)
Your local changes to the following files would be overwritten by merge:
你本地的分支需要覆盖,因为之前有变动,版本号已经低了;(你现在提交的版本号很低)
解决方式:
先提交好你的文件,或者说是 commit 你的文件;\
![](https://static001.geekbang.org/infoq/82/8215f03dd8d2876dea974ed6301f2c27.png)
git stash 暂存已经修改;
然后就会回到之前的一个版本号,git pull 文件
然后在 git stash pop 还原文件,会有冲突解决就好了;
哈哈
然后准备提交 git push
但是一般提交会有两个的;\
![](https://static001.geekbang.org/infoq/7e/7ef1bdf888411514309c6219f7160948.png)
卢卡寄语
这篇 Git 的实战,根据上文 Git 的基础来,适合新手小白进行开发时候的一些问题, 希望我们都在研发的道路上越走越远,加油
“接上上文 Git 的基础操作“: https://xie.infoq.cn/article/0385f0718b67da57cb8017c69
版权声明: 本文为 InfoQ 作者【卢卡多多】的原创文章。
原文链接:【http://xie.infoq.cn/article/f88295ff749137113ca9b47b8】。文章转载请联系作者。
评论