前言
世间无奇不有,这Git也算是由一个神奇的人在神奇的时刻开发出的神奇东西。Linux之父Linus选择BitKeeper作为Linux内核代码管理工具,却因为有人试图对BitKeeper进行反向工程,这是想搞事啊,结果BitKeeper的使用权被收回。Linus表示老子也很无奈,于2005年4月3日花了5天时间开发了Git,又用了3周完善,可能他当时也没想到,这个“小东西”会为成现在最流行的版本工具。
SVN
为了更好的理解Git,可以回忆一下SVN,如果没用过SVN,可跳过这段。
SVN有本地工作区Workspace,远程仓库Remote。工作区可以update仓库任何一个子目录,工作区每层目录都会有一个.svn的文件夹,内含版本信息。(如果是1.7及以上版本,顶层目录才会有一个.svn,这就是向Git看齐了)。
缺点,如果断网或远程仓库挂了,则无法提交更新。
优点,一个大仓库下,可以自由更新一部分。
Git
Git则是分布式版本,有工作区Workspace,暂存区Stage,本地仓库Repository,远程仓库Remote。文件修改后从前向后提交,完整的提交需要3步,看起来好像没有SVN一步到位简单。
本地仓库与远程仓库很好理解,分布式嘛,每个仓库都是独立的,需有不同仓库。理论上来,本地仓库与远程仓库是平级的,只是多人协作时,为了方便大家进行版本交换,默认某个远程仓库是中心节点。
Git为什么要设计一个暂存区呢?
在命令行下,多个文件有修改,只需提交其中几个,先把那几个文件提交暂存区,再把暂存区所有文件作为一次版本提交。
安装与查看配置
git --version
查看Git版本,如无,下载安装,一般centos7默认安装。在windows安装后推荐使用Git Bash
git config --global user.name 'cifer' git config --global user.email 'xx@gmail.com' git config --unset --global user.name git config --unset user.email
设置/去除名字与邮箱
创建一个简单的远程Git仓库
如果已经有现成的远程仓库,可跳过这段,这里为了让后面的远程仓库可以实践,也参考了廖雪峰的博客https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/00137583770360579bc4b458f044ce7afed3df579123eca000在Linux-107机上搭建一个服务。
linux用户设置
groupadd gitgroup useradd -g gitgroup gituser
在服务器上创建一个git用户组
在该用户组并加入一个gituser用户
进入/home/gituser里创建一个.ssh目录,及.ssh目录创建一个authorized_keys文件,并把客户端(此处以window机为例)的公钥写入至authorized_keys里,如有多个客户端,公钥一行一个即可
初始化特殊的空仓库
git init --bare
Git新建空仓库,注意—bare很重要,表示这是空仓库,其不再生成.git目录,而是只生成.git目录下面的版本历史记录文件,这样在服务端上不能进行git的一些操作,避免与客户端冲突
控制权限
sudo chown -R gituser:gitgroup /var/demo.git // 仓库拥有者赋值
为了安全,禁用gituser的shell功能
gituser:x:1001:1001::/home/gituser:/bin/bash
修改为
gituser:x:1001:1001::/home/gituser:/usr/bin/git-shell
据说git-shell每次登录就自动退出,看到的错误是:
fatal: Interactive git shell is not enabled.
hint: ~/git-shell-commands should exist and have read and execute access.
开始
在window客户机上也安装了git,使用git bash
git clone gituser@192.168.1.107:/var/demo.git // 克隆Linux-107机/var/demo.git至本机,中间远程需确认及输入gituser的密码,本处没有设置密码,直接为空即可,成功后本机当前目录下生有一个名为demo的仓库,新建一个demo.txt文件,并写下hello git server
git status // 查看当前提交状态
一个简单提交过程
git add demo.txt // 把demo.txt的提交到暂存区(如想把当前工作区所有文件提交到暂存区,git add -a) git commit -m 'say hello' // 把暂存区所有内容提交至本地仓库,注释为’say hello’ git pull // 从远程仓库下载最新代码,每次提交至远程仓库之前必做的一件事 git pull origin master:master // 同上,但是更推荐的用法 git push origin master:master //把当前分支master上传给远程分支master
修改当前分支的最后一次日志注释
git commit --amend -m 'say hi' // 如果最后一次提交注释写错了,可修改成’say hi’,同时也会把当前stage的内容一起提交,所以它不仅仅可以修改注释
强行推送
git push -f origin master:master // 强行推送,慎用!一般是已经push至远程成功,需求有变,需要重新reset原来某个id,这时push是会失败的,需要强行push
提交至暂存区
git add . // 提交新文件(new)和被修改(modified)文件,不包括被删除(deleted)文件 git add -u // 提交被修改(modified)和被删除(deleted)文件,不包括新文件(new) git add -A // 提交所有变化
比较变化
git diff // 工作区与暂存区比较 git diff --cached // 暂存区与HEAD比较(注:HEAD即为本地仓库指向位置,一般在最新位置,可使用cat .git/refs/heads/master查看) git diff HEAD // 工作区与HEAD比较
日志
日志记录
git log // 日志简要信息 git log --stat // 日志及统计 git log -p // 日志及修改记录 git log --oneline // 日志id省略型单行显示 git log --pretty=oneline // 日志id完整型单行显示
特定日志记录
git log branch-name // 查看某分支日志 git log --author=daluo // 查看某作者日志 git log --grep=xx // 关键词查找日志
查看某日志
git show id // 查看id的修改记录
查看某文件的当前责任者
git blame file_name // 查看某文件的修改记录
回退、撤销
git checkout -- demo.txt // 撤销工作区demo.txt未提交至暂存区的修改 git reset -- demo.txt // 工作区不变,撤销demo.txt暂存区修改 git reset // 工作区不变,撤销暂存区全部内容 git reset HEAD // 同上 git reset HEAD^ // 工作区不变,暂存区重置到上一次提交之前,更改引用,N个^即上N次提交之前 git reset --soft ad456sdssas // 工作区不变,暂存区不变,引用更改 git reset ad456sdssas // 工作区不变,暂存区更改,引用更改,与git reset —mixed ad456sdssas一样 // 工作区更改,暂存区更改,引用更改 git reset --hard ad456sdssas
发现了吧,其实就是soft,mixed,hard的区别。
查看所有日志(包括隐藏的)及重置
如果做了5次提交,重置到了第3次,那么第4,5次在普通log中就看不见啦,就算想reset回去,却不记得id是什么了。
git reflog // 可看所有日志,包括重置日志,那可以reset到第5次提交,如果id显示不全,则后面用^表示即可
当然还可以:
git reset --hard master@{n} // 重置n次修改之前
分支
查看分支
git branch // 本地分支 git branch -r // 远程分支,只能查看从远程refs/heads/命名空间复制至本地refs/remotes/origin/命名空间的分支名字 git branch -a // 所有分支,同上 git fetch origin branch-name // 复制origin命名空间的branch-name的分支至本地 git fetch origin // 复制origin所有命名空间 git fetch // 同上,简写
分支增删改
git branch <branchname> // 创建分支 git branch <branchname> <start-point> // 基于提交创建分支 git branch -d <branchname> // 删除分支,如未合并则失败 git branch -D <branchname> // 强制删除分支 git branch -m <oldname> <newname> // 重名字,如重名则失败 git branch -M <oldname> <newname> // 强制重名字
新手可能会犯一个错误,clone之后,都搞不清楚自己clone的是远程哪个分支,自己又在哪个分支。本地分支与远程分支之间有对应关系,如果不按这个关系来,合并代码可能会变得更加复杂。
切换分支
git checkout <branchname> // 切换分支,默认指向当前HEAD git checkout -b <branchname> // 创建并切换分支
拉取远程分支,事先可能需git fetch该remote-branch
git checkout -b local-branch origin/remote-branch // 拉取远程分支remote-branch,创建本地分支local-branch,并切换至本地分支local-branch
git branch local-branch git checkout local-branch git pull origin local-branch:remote-branch
在一个有公共源头的版本上,与上述相似
合并支付
git checkout master // 切换至想要被合并到分支 git merge --no-ff testbug // 把testbug分支合并到master分支,—no-ff,在合并之后,保留原testbug分支,这是推荐的方式,否则分支线会合成一条
Stashing
当项目修改一半,不想commit 代码,却需要切到别的分支改代码时用到,相当于额外的得到一个储藏空间,需要时再取出来了。
git stash // 保存至stashing git stash list // 列举stashing list,数字越小,时间越近 git stash pop // 由栈先进后出的原则,拿到最新的stash@{0},并且把它删除,然后其他的重新排序 git stash apply stash@{n} // 获取栈第n层的stash,不会移除stash{n} git stash drop stash@{n} // 移除第n层stash git stash clear // 移除所有stash
clean
git clean
有时我们需要不管是使用git checkout — filename或git reset hard都不能使未track的文件回退,使用git clean可清除untrack文件
冲突
多个协作中,在git merge及git push过程中,冲突是在所难免的。
如果git push失败,git pull也失败时,为了方便理解,可以把git pull看成
git fetch origin master // 从远程仓库拉取master分支至本地 git merge origin/master // 把远程master合并至本地master
这两个命令之当然会进行对比,如果有冲突,则需手动解决,提交代码至本地,再次合并
当然笔记只记下以上几个比较常用的,不到Git知识点的九牛一毛,如有兴趣,请多参考相关资料。
参考资料:
https://www.boatsky.com/blog/12