初始化一个Git仓库,使用 git init 命令,此时会创建一个默认的master分支。
添加文件到Git仓库,分两步:
- 使用命令git add <file>,将文件添加到暂存区;
- 使用命令git commit -m <message>,把暂存区的所有内容提交到当前分支。
要随时掌握工作区的状态,使用git status命令。用git diff可以查看修改内容。
Git的commit id是一个SHA1计算出来的一个非常大的数字,用十六进制表示。
git log 查看日志 git log -1 查看最近一次的日志 git log --pretty=oneline 查看简短日志
在Git中,用HEAD表示当前版本,上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100。
回退到上一个版本,使用git reset命令:
git reset --hard HEAD^
此时git log 已经看不到最新的几个版本了。如果需要回到reset之前的最新的版本,需要跟上指定的commitID:
git reset --hard 1094a
Git的版本回退速度非常快,因为Git在内部有个指向当前版本的HEAD指针,当你回退版本的时候,Git仅仅是修改了HEAD的指向,然后顺便把工作区的文件更新了。
所以你让HEAD指向哪个版本号,你就把当前版本定位在哪。
如果找不到最新版本的commit ID了,可以使用 git reflog查看命令历史。
Git和其他版本控制系统如SVN的一个不同之处就是有暂存区的概念。
git commit只负责把暂存区的修改提交。每次修改,如果不使用git add到暂存区,就不会加入到commit中。
用git diff HEAD -- readme.txt命令可以查看工作区和版本库里面最新版本的区别
git checkout -- readme.txt 可以丢弃工作区的修改,把readme.txt文件在工作区的修改全部撤销,让这个文件回到最近一次git commit或git add时的状态。
git checkout . 丢弃工作区所有的修改
* 如果已经 git add 操作了,但是还没有git commit,使用:git reset HEAD readme.txt,可以把暂存区的修改撤销掉(unstage),重新放回工作区。然后再使用git checkout -- readme.txt 撤销修改。
* 如果已经git add 并且 git commit 了,那就使用 git reset HEAD^ 回退到上一个版本。
git reset命令既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用HEAD时,表示最新的版本。
从版本库删除文件,使用 git rm test.txt,然后再git commit 就可以了。如果不小心误删了,使用git checkout -- test.txt恢复。
Git是分布式版本控制系统,同一个Git仓库,可以分布到不同的机器上。分布式版本系统的最大好处之一是在本地工作完全不需要考虑远程库的存在,也就是有没有联网都可以正常工作,而SVN在没有联网的时候是拒绝干活的!当有网络的时候,再把本地提交推送一下就完成了同步,真是太方便了!
要克隆一个仓库,首先必须知道仓库的地址,然后使用git clone命令克隆。
Git支持多种协议,包括https,但通过ssh支持的原生git协议速度最快。
要在本地关联一个远程库,使用命令git remote add origin git@server-name:path/repo-name.git;
关联后,使用命令git push -u origin master第一次推送master分支的所有内容;
此后,每次本地提交后,只要有必要,就可以使用命令git push origin master推送最新修改;
Git的分支是与众不同的,无论创建、切换和删除分支,Git在1秒钟之内就能完成!无论你的版本库是1个文件还是1万个文件。
Git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点。
每次提交,master分支都会向前移动一步,这样,随着你不断提交,master分支的线也越来越长。
当我们创建新的分支dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上。
Git合并分支很快!就改改指针,工作区内容也不变!
查看分支:git branch 创建分支:git branch <name> 切换分支:git checkout <name> 创建+切换分支:git checkout -b <name> 合并某分支到当前分支:git merge <name> 删除分支:git branch -d <name> 如果要丢弃一个没有被合并过的分支,可以通过git branch -D <name>强行删除。
【解决冲突】
Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容。
出现冲突后,手动修改冲突的文件,然后重新git add,git commit。
git log --graph --pretty=oneline --abbrev-commit 可以看到分支的合并情况
【分支管理策略】
通常,合并分支时,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。
如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。
测试--no-ff方式合并分支,表示禁用Fast forward:git merge --no-ff -m "merge with no-ff" dev
【stash 紧急修复线上bug】
git stash 暂存当前的所有修改 git checkout master 切换到master git checkout -b debug-01 基于master创建debug分支 git add && git commit 修改后进行提交 git checkout master 切换回master git merge debug-01 将debug的修改合并到master git branch -d debug-01 删除debug分支 git checkout dev 切换回之前正在开发的dev分支 git merge master 把刚才修复的bug合并到当前的分支(视情况而定要不要merge) git stash list 查看暂存的修改
恢复暂存的内容,有两种操作:
一是用git stash apply恢复,但是恢复后,stash内容并不删除,你需要用git stash drop来删除;
另一种方式是用git stash pop,恢复的同时把stash内容也删了。
可以多次stash,恢复的时候,先用git stash list查看,然后恢复指定的stash,用命令:git stash apply stash@{0}
【推送分支到远程】
git push origin dev
并不是一定要把本地分支往远程推送,那么,哪些分支需要推送,哪些不需要呢?
master分支是主分支,因此要时刻与远程同步;
dev分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;
bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;
feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。
【从远程抓取分支】
默认新clone的项目,只能看到本地的master分支。
查看远程库信息,使用git remote -v;
要在dev分支上开发,就必须创建远程origin的dev分支到本地。
创建本地dev分支并和远程分支对应: git checkout -b dev origin/dev
用git pull把最新的提交从origin/dev抓下来:
git branch --set-upstream-to=origin/dev dev #建立本地分支和远程分支的关联
git pull
【git rebase】
rebase操作可以把本地未push的分叉提交历史整理成直线;
rebase的目的是使得我们在查看历史提交的变化时更容易,因为分叉的提交需要三方对比。
【标签】
Git的标签虽然是版本库的快照,但其实它就是指向某个commit的指针(跟分支很像对不对?但是分支可以移动,标签不能移动)
tag就是一个让人容易记住的有意义的名字,它跟某个commit绑在一起。
git tag v1.0 创建新标签 git tag 查看所有标签 给历史提交的commit id打标签:git tag v0.9 f52c633 还可以创建带有说明的标签,用-a指定标签名,-m指定说明文字: $ git tag -a v0.1 -m "version 0.1 released" 1094adb
标签不是按时间顺序列出,而是按字母排序的。可以用git show <tagname>查看标签信息:
推送某个标签到远程,使用命令 git push origin v1.0 一次性推送全部尚未推送到远程的本地标签:$ git push origin --tags git tag -d v0.1 删除本地的标签 git push origin :refs/tags/v0.9 删除远程的标签(需要先删除本地标签)
【配置git】
Git的用户设置:
git config --global user.name "Your Name" 设置用户名 git config --global user.email "email@example.com" 设置邮箱 git config user.name;git config user.email 查看用户名和邮箱 git config --global color.ui true 让Git显示颜色,会让命令输出看起来更醒目 git config --global alias.st status 配置命令别名
说明:配置Git的时候,加上--global是针对当前用户起作用的,如果不加,那只针对当前的仓库起作用。
每个仓库的Git配置文件都放在.git/config文件中;当前用户的Git配置文件放在用户主目录下的一个隐藏文件.gitconfig中。配置别名也可以直接修改这个文件,如果改错了,可以删掉文件重新通过命令配置。
在Git工作区的根目录下创建一个特殊的.gitignore文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件。
不需要从头写.gitignore文件,GitHub已经为我们准备了各种配置文件,只需要组合一下就可以使用了。所有配置文件可以直接在线浏览:https://github.com/github/gitignore
忽略文件的原则是:
忽略操作系统自动生成的文件,比如缩略图等;
忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如Java编译产生的.class文件;
忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。
试试如下配置:
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 lg的效果:
【搭建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,在/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来管理公钥。
【参考资料】https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000