git常用命令
创建分支
查看分支,包括远程的
git branch -a
如果远程已经有了某个分支,使用git branch -a却查看不到,使用下命令刷新远程分支
git fetch -p
如果没有分支,需要新建分支 比如:从已有的分支创建新的分支(如从master分支),创建一个dev分支
git checkout -b dev
然后提交该分支到远程仓库
git push origin dev
切换分支,切换到dev上
git checkout dev
提交代码
在dev上正常提交
1. 添加修改的代码
git add .
或者逐个添加
git add xx.txt
2.提交到本地版本
git commit -m "描述"
3.推送远端前更新本地dev代码
git pull origin dev
4.推送到远端
git push origin dev
合并代码
dev工作完成,可以切换到master分支
git checkout master
把dev分支的内容合并到master上
git merge dev
(合并指定分支到当前分支)
删除dev分支
git branch -d dev
如果一个分支还没有被合并就要作废,需要使用
git branch -D dev
删除远程分支
git push origin --delete dev
删除文件
情况一:一是确实要从版本库中删除该文件,那就用命令git rm
删掉,并且git commit
git rm src/main/java/com/yunlu/app/web/UserAppController.java
情况二:删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本,参考撤销修改
$ git checkout -- src/main/java/com/yunlu/app/web/UserAppController.java
如果有删除的文件需要执行命令来删除被管理的目录
$ git rm -r --cached target(文件目录)
修改提交版本到另一个分支
把另一个本地分支的commit修改应用到当前分支。
git cherry-pick <commit id>
查看文件修改信息
git blame src/main/java/com/yunlu/app/web/CourseWebController.java
版本回退
$ git log --pretty=oneline
在Git中,用HEAD
表示当前版本,也就是最新的提交744.....
(注意我的提交ID和你的肯定不一样),上一个版本就是HEAD^
,上上一个版本就是HEAD^^
,当然往上100个版本写100个^
比较容易数不过来,所以写成HEAD~100
$ git reset --hard HEAD^
或者使用版本号
$ git reset --hard 744aaf0
版本号没必要写全,前几位就可以了,Git会自动去找。当然也不能只写前一两位,因为Git可能会找到多个版本号,就无法确定是哪一个了。
如果不记得版本号了使用git reflog
查看
撤销修改
情况一:如果是提交到暂缓去前发现了错误,只保留在工作区
$ git checkout -- src/main/java/com/yunlu/app/web/UserAppController.java
注意--左右有空格
或者使用git checkout . 撤销所有修改
命令git checkout -- XX
意思就是,把XX
文件在工作区的修改全部撤销,这里有两种情况:
一种是XX
自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
一种是XX
已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
总之,就是让这个文件回到最近一次git commit
或git add
时的状态。
情况2:已经提交到暂缓区,但是还没有commit
$ git reset HEAD src/main/java/com/yunlu/app/web/UserAppController.java
使文件重新恢复工作区
再使用
$ git checkout -- src/main/java/com/yunlu/app/web/UserAppController.java
撤销工作区修改
git reset
命令既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用HEAD
时,表示最新的版本
情况三:commit过了,从暂缓区提交到了版本库怎么办,参考版本回退
bug分支
情况:当前正在dev
上进行的工作还没有提交,但是需要在另一个分支修改bug,而且dev分支还不能提交,因为还没做完
Git提供了一个stash(stæʃ)
功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作
1. $ git stash 储存现场
现在,用git status
查看工作区,就是干净的(除非有没有被Git管理的文件),因此可以放心地创建分支来修复bug。
首先确定要在哪个分支上修复bug,假定需要在master
分支上修复,就从master
创建临时分支
2. $ git checkout master 切换分支
3. $ git checkout -b issue-101 创建issue-101
分支
4. $ git add readme.txt 修改添加到暂缓区
5. $ git commit -m "fix bug 101" 提交
6. $ git checkout master 切换分支
7. $ git merge --no-ff -m "merged bug fix 101" issue-101 合并代码
8. $ git branch -d issue-101 删除bug分支
9. $ git checkout dev 回到之前分支
此时使用git status发现工作区是干净的
刚才的工作现场存到哪去了?
10. 用git stash list
命令看看:
工作现场还在,Git把stash内容存在某个地方了,但是需要恢复一下,有两个办法:
一是用git stash apply
恢复,但是恢复后,stash内容并不删除,你需要用git stash drop
来删除;
另一种方式是用git stash pop
,恢复的同时把stash内容也删了:
再用git stash list
查看,就看不到任何stash内容了:
你可以多次stash,恢复的时候,先用git stash list
查看,然后恢复指定的stash,用命令:
$ git stash apply stash@{0}
忽略特殊文件
在Git工作区的根目录下创建一个特殊的.gitignore
文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件。
但是有时候在项目开发过程中,突然心血来潮想把某些目录或文件加入忽略规则,按照上述方法定义后发现并未生效,
原因是.gitignore只能忽略那些原来没有被track的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore是
无效的。那么解决方法就是先把本地缓存删除(改变成未track状态),然后再提交:
配置别名
有没有经常敲错命令?比如git status
?status
这个单词真心不好记。
如果敲git st
就表示git status
那就简单多了
$ git config --global alias.st status
当然还有别的命令可以简写,很多人都用co
表示checkout
,ci
表示commit
,br
表示branch
:
$ git config --global alias.co checkout $ git config --global alias.ci commit $ git config --global alias.br branch
甚至还有人丧心病狂地把lg
配置成了:
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
配置Git的时候,加上--global
是针对当前用户起作用的,如果不加,那只针对当前的仓库起作用。
配置文件放哪了?每个仓库的Git配置文件都放在.git/config
文件中:
要删除别名,直接把对应的行删掉即可
而当前用户的Git配置文件放在用户主目录下的一个隐藏文件.gitconfig
中:
搭建git服务器
在Ubuntu上搭建git
第一步,安装git
:
$ sudo apt-get install git
第二步,创建一个
git
用户,用来运行git
服务:
$ sudo adduser git
第三步,创建证书登录:
收集所有需要登录的用户的公钥,就是他们自己的id_rsa.pub
文件,把所有公钥导入到/home/git/.ssh/authorized_keys
文件里,一行一个。
第四步,初始化Git仓库:
先选定一个目录作为Git仓库,假定是/srv/sample.git(sample.git 是一个文件夹)
,在/srv
目录下输入命令
$ sudo git init --bare sample.git
Git就会创建一个裸仓库,裸仓库没有工作区,因为服务器上的Git仓库纯粹是为了共享,所以不让用户直接登录到服务器上去改工作区,并且服务器上的Git仓库通常都以.git
结尾。然后,把owner改为git
:
$ sudo chown -R git:git sample.git
第五步,禁用shell登录:
出于安全考虑,第二步创建的git用户不允许登录shell,这可以通过编辑/etc/passwd
文件完成。找到类似下面的一行:
git:x:1001:1001:,,,:/home/git:/bin/bash
改为:
git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell
这样,git
用户可以正常通过ssh使用git,但无法登录shell,因为我们为git
用户指定的git-shell
每次一登录就自动退出。
第六步,克隆远程仓库:
现在,可以通过git clone
命令克隆远程仓库了,在各自的电脑上运行:
$ git clone git@server:/srv/sample.git
Cloning into 'sample'...
warning: You appear to have cloned an empty repository.
剩下的推送就简单了。
管理公钥
如果团队很小,把每个人的公钥收集起来放到服务器的/home/git/.ssh/authorized_keys
文件里就是可行的。如果团队有几百号人,就没法这么玩了,这时,可以用Gitosis来管理公钥。
这里我们不介绍怎么玩Gitosis了,几百号人的团队基本都在500强了,相信找个高水平的Linux管理员问题不大。
管理权限
有很多不但视源代码如生命,而且视员工为窃贼的公司,会在版本控制系统里设置一套完善的权限控制,每个人是否有读写权限会精确到每个分支甚至每个目录下。因为Git是为Linux源代码托管而开发的,所以Git也继承了开源社区的精神,不支持权限控制。不过,因为Git支持钩子(hook),所以,可以在服务器端编写一系列脚本来控制提交等操作,达到权限控制的目的。Gitolite就是这个工具。
这里我们也不介绍Gitolite了,不要把有限的生命浪费到权限斗争中