目录
git原理:
本地包含三个部分:工作区、缓存区、版本库。工作区就是我们操作的文件,修改后的文件add到缓存取,也就是将修改保存到缓存区,缓存区确认无误的话可以commi到版本库,成为一个新的版本。
不过这个版本是保存在本地的,怎么协同工作呢?
还需要一个远程仓库,可以将本地仓库的内容push到远程仓库,也可以从远程仓库获取,fetch和clone命令拉取到本地仓库,pull命令直接拉取到工作区。
所有的版本控制系统,其实只能跟踪文本文件的改动,比如TXT文件,网页,所有的程序代码等等,而图片、视频这些二进制文件,虽然也能由版本控制系统管理,但没法跟踪文件的变化,只能把二进制文件每次改动串起来,也就是只知道图片从100KB改成了120KB,但到底改了啥,版本控制系统不知道,也没法知道。
本地仓库
版本追踪
git add 添加修改
git add . 添加全部修改
git commit 提交所有的修改文件,会进入vim编辑器添加修改信息。
git commit -m "commit comments" 不进入vim直接添加修改信息
git status 查看状态
回退版本
git log 命令可以查看提交日志,其中HEAD指向的就是当前版本(最新版本),如果这个版本是有问题的且不小心提上去了的,就可以回退到之前的版本。
git reset --hard HEAD^
上一个版本就是HEAD^
,上上一个版本就是HEAD^^
,当然往上n个版本写成HEAD~n。
其实这只是一个特殊情况,通用的方法是: git reset --hard commit_id 即根据某个版本的版本号(版本号很长,不用写完,一般五六位就够了)来回退到该版本。(所以说这里说回退是不严谨的,其实HEAD只一个指针,它指向主分支,主分支指向当前版本,只要知道版本号,就可以指向任何版本,即恢复到任何版本)
那怎么获取版本号呢?
git reflog 可以查看所有分支的所有操作记录(包括已经被删除的 commit 记录和 reset 的操作),里边可以看到版本号。
git reset HEAD filename
可以把暂存区的修改(add 但没commit)撤销掉(unstage),重新放回工作区。
git checkout -- filename 将工作区文件回到最近一次git commit
或git add
时的状态,比如误修改甚至误删等。git checkout . 全部撤回。
本地工作区文件删除后回复的操作:
当然,也可以真的是删除这个文件,这时只要把这个改动add并commit就行了。
远程仓库
先添加配置信息(--global是全局配置,即一台设备只需要配置一次即可)
#配置用户名和邮箱
git config --global user.name "your username"
git config --global user.email "your email"
添加秘钥SSH
cd ~/.ssh
进入SSH文件夹,然后ls查看有没有公钥和私钥文件。
如果没有则需要生成:
ssh-keygen -t rsa -C "******@***.com"
添加邮箱然后一路回车。然后ls看一下公钥和私钥都已经生成了。
然后在github中把公钥(id_rsa.pub)里的内容粘贴进去就可以了。
只要把每台电脑的Key都添加到GitHub,就可以在每台电脑上往GitHub推送。
添加远程仓库
在github上创建一个仓库,复制仓库的SSH链接,这个链接很重要,它是远程和本地的桥梁。
然后在本地与这个远程仓库关联:这里的origin是本地给这个远程仓库起的名字,可以自己定义。
git remote add origin git@github.com:Forestliwei/PythonWeb.git
可以通过下面的命令查看所有关联的仓库
git show-ref
从远程仓库克隆:
git clone git@github.com:Forestliwei/PythonWeb.git
从远程仓库克隆时,实际上Git自动把本地的
master
分支和远程的master
分支对应起来了,并且,远程仓库的默认名称是origin
。要查看远程仓库的信息:git remote -v
然后就是推送本地版库本到远程仓库。
git push -u origin master
只有第一次推送的时候才加 -u , 它将本地和远程的主分支联系起来。以后push就可以不用加-u了
git push origin master
git push <远程主机名> <本地分支名>:<远程分支名>
本地分支名和远程分支名相同的话可以省略冒号。
小结
要关联一个远程库,使用命令
git remote add origin git@server-name:path/repo-name.git
;从远程克隆到本地 git clone git@github.com:Forestliwei/PythonWeb.git
关联后,使用命令
git push -u origin master
第一次推送master分支的所有内容;此后,每次本地提交后,只要有必要,就可以使用命令
git push origin master
推送最新修改;
分支管理
查看分支
git brnach 查看本地分支; git brnach -a 查看所有分支(本地和远程分支);其中带星号的是当前分支。
删除分支
git branch -d branchname 删除brnachname分支。如果一个新分支还没有被合并,如果删除,将丢失掉修改,因此会提醒删除失败,如果非要强行删除,需要使用大写的-D
参数。
删除远程分支:git push origin --delete [branchname]
创建/切换分支
git branch branchname 创建本地分支
git checkout 'branchname' 切换到branchname分支;git checkout -b 'branchname' 创建一个分支并切换到该分支(HEAD指向该分支);
合并分支
git merge branchname 讲branchname分支合并到当前分支。所以要将一个分支合并到另外一个分支的话就需要先切换到要合并到的分支。
分支合并冲突:在两个分支上都对同一个文件进行修改并且还都进行了提交的话,merge的 时候就会产生冲突。也就是说,为了避免冲突,分支应该只是来维护特定的代码,这样维护好之后才能merge。
合并分支时,如果可能,Git会用Fast forward
模式(快速合并),但这种模式下,删除分支后,会丢掉分支信息。如果强制禁用Fast forward
模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。
可以使用 --no-ff 修饰来限制其以普通模式merge,由于普通模式下像commit一样需要提交merge信息,所以要快速添加merge信息还要再加上-m "merge mesg":
git merge --no-ff -m "merge me.txt" dev
bug分支与feature分支:当发现一个BUG需要另辟一个bug分支来处理;当开发一个新功能时需要另辟一个feature分支来处理。
Git提供了一个stash
功能,用来保存现场,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作。git stash命令的作用就是将目前还不想提交的但是已经修改的内容进行保存至堆栈中,后续可以在某个分支上恢复出堆栈中的内容。这也就是说,stash中的内容不仅仅可以恢复到原先开发的分支,也可以恢复到其他任意指定的分支上。git stash作用的范围包括工作区和暂存区中的内容,也就是说没有提交(commit)的内容都会保存至堆栈中。
推送分支
一般的分支管理:
-
master
分支是主分支,因此要时刻与远程同步; -
dev
分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步; -
bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;
-
feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。
push主分支:
git push origin master
或push开发分支
git push origin dev
如果push冲突了,则是因为远程的版本比本地的新(有人先于我们push),则需要先pull一次,在在本地合并,然后再push。
抓取分支
git pull
如果有人已经向origin/dev
分支推送了他的提交,而碰巧你也对同样的文件作了修改,并试图推送,就会产生冲突。
分支链接
如果没有指定本地分支和远程分支的连接的话无法push,建立本地分支和远程分支的关联:
git branch --set-upstream-to=origin/dev dev
小结
多人协作的工作模式通常是这样:
-
首先,可以试图用
git push origin <branch-name>
推送自己的修改; -
如果推送失败,则因为远程分支比你的本地更新,需要先用
git pull
试图合并; -
如果合并有冲突,则解决冲突,并在本地提交;
-
没有冲突或者解决掉冲突后,再用
git push origin <branch-name>
推送就能成功!
如果git pull
提示no tracking information
,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to <branch-name> origin/<branch-name>
。
标签管理
每个版本都有一个commitID,这个ID是一个大长串,不方便交流。而tag跟某个commitID绑在一起,是一个让人容易记住的有意义的名字。
创建标签
git tag tagname commitID
这就将commitID绑上了一个标签:tagname。这里commitID省略不写是默认将标签打到当前分支的最新commi。git tag命令查看当前分支的tag,git shou tagname显示tagname的详细信息。
如果这个commitID既出现在master分支,又出现在dev分支,那么在这两个分支上都可以看到这个标签。标签都只存储在本地,不会自动推送到远程,如果要推送某个标签到远程,使用命令
git push origin <tagname>;或者一次推送全部尚未推送到远程的本地标签 git push origin --tags
删除标签
删除本地标签 :git tag -d tagname
删除远程标签:先删除本地标签,再删除远程标签:git push origin :refs/tags/tagname
其他
0.国内的Git托管服务gitee,免费版也提供私有库功能,只是有5人的成员上限。【用过的都说好,关键是速度快...】
1.对于一些在git工作目录中的一些不想被追踪的文件,在Git工作区的根目录下创建一个特殊的.gitignore
文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件。
2.搭建git服务器
参考资料:这里。