Git -- The stupid content tracker. Linus Torvalds
使用git已经有一段时间了,从刚开始的陌生到慢慢熟悉
掌握基本的用法之后,会让人对开发、尤其是多人合作开发有了新的理解……甚至于平时写文档的时候都想用了
脑海中出现这么个画面
毕业论文.doc
毕业论文修改版.doc
毕业论文完结版.doc
毕业论文最终版.doc
毕业论文再也不改了版.doc
…这时候要是有git在,一个文件就足够了,多次保存之后commit好即可
把平时常用的一些操作做一下整理。
开始一个项目
一般开始项目有2种情况:复制一个现成的git项目或者创建新项目
复制:
1 | $ git clone [source] [destination] |
[source]里面是项目的位置,可以是本地/服务器上的某个目录,也可以是远程库(例如github)中项目的地址(HTTPS或者SSH地址)
[destination]是拷到本地存放的位置,不加就是默认当前目录下
事实上……这个命令就是复制粘贴,尤其是如果是从本地clone到本地的时候。当然,只有git项目可以clone,对一个普通的文件夹调用clone命令还是不行的
创建:
1 | $ git init [name] |
[name]是项目的名字,不加就是把当前目录初始化成git库
初始化之后,目录下面会多出一个隐藏的.git文件夹,里面保存了git库需要的各种信息文件
示例
就拿一开始的论文脑洞来举例吧,我这里是装好git之后,配好运行环境,然后就可以在cmd里面操作git了
命令行到桌面,然后:
1 | C:\Users\lenovo\Desktop>git init test |
clone一下试试
1 | C:\Users\lenovo\Desktop>git clone test lunwen |
然后就可以开始工作啦,接下来的操作都会在这个名字叫做lunwen的目录(库)下面完成
开始工作
1 | $ git status |
这条命令是显示当前库中(其实就是当前目录中)需要被跟踪的文件的状态。
文件的状态有三种,一开始新文件的状态是“Untracked”或者“Changes not staged for commit”,表示是刚创建的新文件还没有被git所追踪,或者是库中原本已有的文件发生了修改还没有被git所追踪,添加跟踪需要用到下面的这条add指令:
1 | $ git add [file] |
-A 是默认把当前目录下所有需要追踪的文件都添加追踪,或者手动输入文件名进行各个文件的单独追踪
1 | $ git reset [file] |
什么参数都不带表示把刚刚add上去的文件取消追踪,或者手动输入文件名进行各个文件的单独取消
1 | $ git diff |
对库中原本已有的修改文件进行新旧版本对比,显示文件的区别
1 | $ git diff --staged |
跟上一条指令类似,区别是这个是对已add进库中的文件进行新旧版本对比
1 | $ git commit -m "[descriptive message]" |
当把所有文件都add进来之后,文件的状态变成了“Changes to be committed”,表示所有修改都已经被追踪,等待提交
然后就需要上面这条命令,descriptive message是对本次提交的描述,如果不加-m和描述,git会打开一个编辑器要求输入描述
示例
现在库里面是空的,新建个文本文档lunwen.txt,里面写上test1,然后查看一下状态:
lunwen.txt
1 | test1 |
1 | C:\Users\lenovo\Desktop\lunwen>git status |
显示新的文件还没有被追踪过,先提交一下第一个版本:
1 | C:\Users\lenovo\Desktop\lunwen>git add -A |
提交完成,接下来对lunwen.txt稍微做点修改,然后再创建个新的文件test.txt:
lunwen.txt
1 | test2 |
test.txt
1 | test2 |
1 | C:\Users\lenovo\Desktop\lunwen>git status |
status里面清楚地显示了库中文件的改变情况即:lunwen.txt是已被追踪但是修改了的,test.txt是还没有被追踪的,接下来试一下diff这个命令:
1 | C:\Users\lenovo\Desktop\lunwen>git diff |
diff显示的只有lunwen.txt这个文件的变化,因为这个文件本来就在库里面,也是一直都被追踪着的。a/显示的是旧版本,b/显示的是新版本
diff –staged显示的则是所有被add过的文件的差异,test.txt由于是新创建的,所有没有旧版本
删除文件
1 | $ git rm [file] |
删除文件以及所有信息
1 | $ git rm --cached [file] |
删除文件的追踪信息,但是文件仍然保留
1 | $ git mv [file-original] [file-renamed] |
重命名文件
版本保存和恢复
1 | $ git log |
显示所有commit的记录
重点来了,git保存了库中所有文件完整的演变过程,以每一次commit作为一个保存点,如果发生问题,可以直接回滚到之前的任何一个版本,而需要的指令则是上面用过的这一条:
1 | $ git reset |
reset的作用是使目录会退到上一次的状态,在前面用来取消掉add,其实它的完整用法是这样的:
1 | $ git reset [--hard|soft|mixed|merge|keep] [<commit>或HEAD] |
reset这个命令比较复杂,可以戳这个了解更详细的实例
先整体明确一下整个git的结构:
首先是当前正在操作的内容,就是现在正在修改/编辑的文件,这一块叫做“Working Directory”
通过add之后,追踪的内容被保存到了“Git Index”里面,这一块可以看成是当前目录和版本库之间的暂存区
最后再用commit写上标注,把index里面更新的内容修改到“GIT Directory”即版本库里面
好,那么回到reset
commit字段用于选择哪一个版本,如果不加,则默认为HEAD,代表离当前最近的一个版本,也就是上一次最近的commit
简单地说一下常用的几个:
–hard 是强制将当前所做的所有修改都清除掉,HEAD、index和working directory全部恢复到目标commit
–mixed 是不加参数时的默认选择,将HEAD和index都恢复到目标commit,但是保留目录下面修改了的文件。即此时只要add一下,再commit一下就能把当前修改的版本保存为下一个版本
–soft 程度更弱,只将HEAD指向commit,index和当前的工作文件都保持不变,因此自目标commit以来的所有改变都会显示为“Changes to be committed”。此时只要commit一下,就能将当前修改的版本保存为下一个版本
版本暂存
这个功能用来遇到突发状况需要对最后一次的commit进行操作,然后又不想提交当前修改的时候用
1 | $ git stash |
将当前工作文件保存进栈,然后把工作区恢复到上一次的commit
然后这样的操作还可以多次进行,每次的暂存就都会被压进栈
1 | $ git stash list |
显示栈中保存的所有暂存信息
1 | $ git stash pop |
弹出栈顶的保存信息,就是把栈顶的保存信息恢复到工作区
1 | $ git stash drop |
不恢复,直接删除栈顶的保存信息
1 | $ git stash clean |
清除栈中的所有信息
远程操作
刚刚的都是针对本地库的操作,如果不需要上传到他地方,这些内容就足够了,而git的一大强大之处就是能方便多人协作,因此远程功能是少不了的
1 | $ git remote [-v] |
不带选项时,remote命令会列出所有远程主机的名字
-v 则会列出远程主机的地址
1 | $ git remote add <name><url> |
用于添加一台主机
1 | $ git remote rm <name> |
用于删除一台主机
1 | $ git remote <old-name><new-name> |
重命名一台主机
示例
一开始我创建的lunwen库是从test库clone过来的,所以查看lunwen库的远程主机情况就是这样的:
1 | C:\Users\lenovo\Desktop\lunwen>git remote |
默认clone过来的主机名是origin
分支控制
这个也是git中相当重要的一个内容
一个库中可以有多个分支,可以用来更方便地管理整个版本信息
1 | $ git branch [-a|r] |
不加参数时,默认列出本地库中所有的分支信息,并在当前分支前面加*号
-r 是列出远程库
-a 列出本地和远程库
1 | $ git branch [branch-name] |
创建一个新的分支
1 | $ git checkout [branch-name] |
切换到某个分支上,如果分支不存在,则会首先创建新分支再切换过去
切换到分支上时,当前工作目录下面的所有文件都会直接变掉(第一次用的时候觉得这个很神奇)
1 | $ git merge [branch] |
将目标分支合并到当前分支里面来
1 | $ git branch -m [oldname] [newname] |
分支重命名
1 | $ git branch -d [branch-name] |
删除某一个特定的分支
1 | $ git fetch <name> |
从某一台远程主机上获取所有的更新
远程分支操作
如果 fork 了一个别人的项目,然后对方更新了库,想要保持自己的库跟对方一直,则需要先把源库 fetch 下来,跟自己的 merge 之后,再 push 回自己的库上。
1 | $ git remote add upstream xxx.git |
添加 upstream 的远程库信息。
1 | $ git fetch upstream |
fetch upstream 源的新版本到本地
1 | $ git merge upstream/master |
将 upstream 库的 master 分支跟当前分支合并。
之后再 push 回去就行了。