git指南

安装git

不同环境下不同安装方法,安装完成后配置git账号:

git config --global user.name "Your Name"
git config --global user.email "email@example.com"

因为Git是分布式版本控制系统,所以,每个机器都必须自报家门:你的名字和Email地址。注意git config命令的–global参数,用了这个参数,表示你这台机器上所有的Git仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和Email地址。

创建版本库

1.初始化git仓库,把新建的文件夹变成git可管理的仓库:

git init

初始化完成后会发现根目录下多了.git文件夹,这就是GIt用来跟踪管理版本库的文件。

2.添加文件到仓库:

现有的版本控制工具都只能跟踪文本文件的改动,对于word、图片、视频等二进二进制文件,版本控制工具只能知道文件大小的变化,无法跟踪到具体的内容变化。

添加文件:

git add.      //可以添加所有文件
git add file1 file2    //同时添加两个文件

提交文件到仓库:

git commit -m "some descriotion"    //提交已添加到仓库的文件,-m为对提交文件的说明

操作版本库

1.查看仓库状态及文件变化:

git status    //查看仓库当前的状态
git diff readme.txt    //如果git status告诉你有文件被修改过,可用git diff查看当前文件相比上次提交的版本修改了什么内容,既查看工作区和版本库中最新版本的区别

2.版本切换:

每当你觉得文件修改到一定程度的时候,就可以“保存一个快照”,这个快照在Git中被称为commit。一旦你把文件改乱了,或者误删了文件,还可以从最近的一个commit恢复,查看历史commit,可用命令:

git log//查看详细的历史commit
git log --pretty=oneline//更改log的输出格式(版本号:SHA1计算出来的一个非常大的数字,用十六进制表示,因为是分布式,防止每个人提交时的id冲突)和提交说明

在Git中,用HEAD表示当前版本,上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100。HEAD^也可以用commitid,命令中的commitid也可以用它的前几位来代替:

git reset HEAD //可以将暂存区的修改(还未commit的修改)还原
git reset HEAD^//回退版本,可以将已经commit的修改还原

回滚

git reset commitId//会将提交记录回滚,代码不回滚
git reset --hard commitId//会将提交记录和代码都回滚
git checkout --  filename//会将部分代码文件回滚

 重新提交代码(--amend只能修改提交信息)

git commit -m 'initial commit'
git add forgotten_file
git commit --amend

此时用git log查看历史,发现只有之前的版本了,如果要想回到最新版本(未来):

git reset --hard 最新版本的commit id

如果你回退后不记得最新版本的commitid了,可用git reflog查看你使用过的所有命令,找到你提交最新版本的哪一行命令,即可看到最新版的commitid,这样就可以回到未来了:

git reflog  
ea34578 HEAD@{0}: reset: moving to HEAD^  
3628164 HEAD@{1}: commit: append GPL  
ea34578 HEAD@{2}: commit: add distributed  
cb926e7 HEAD@{3}: commit (initial): wrote a readme file 

3.工作区和暂存区

工作区:已经初始化过的工作文件夹
版本库:工作区中的隐藏目录.git,版本库中包括叫Stage的暂存区和git自动创建的第一个分支master,及指向master分支的指针。
一次完整的版本添加包括以下两步:
第一步是用git add把文件修改添加到暂存区暂存区用来保存文件的修改(并不是文件,因为修改一次,然后git add,再修改一次,然后git commit后,用git stauts查看发现依然有未提交的更改,所以提交的其实是第一次修改后的结果,第二次修改并没放入暂存区,所以不会被提交 );
第二步是用git commit提交更改实际上就是把暂存区的所有内容提交到当前分支
可以理解为:需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。

保存当前的不提交的修改:

(1)将当前修改放到stash

git stash

(2)拉代码

git pull 

(3)提交commit的修改

git push

(4)把stash上的修改pop出来

git stash pop

(5)解决冲突

4.撤销修改

git checkout -- a.txt//丢弃工作区中的修改,必须有--,如果没有就变成了切换分支

要撤销的修改有以下几种情况:

  • 如果你只是修改了文件而没添加到暂存区,使用撤销修改命令会将文件修改恢复原状,既丢弃工作区修改。
  • 如果已经添加到暂存区后,又作了修改,使用撤销修改就回到添加到暂存区后的状态。
  • 如果要撤销暂存区中的修改,可以使用:

git reset HEAD file//git reset命令既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用HEAD时,表示最新的版本。如果没有file则表示把暂存区的全部文件的修改回退到
工作区。

    •已经提交了不合适的修改到版本库时,想要撤销本次提交,参考[2.版本切换],不过前提是没有推送到远程库。

5.删除文件

工作区中删除一个已经提交的文件后,你有两个选择:

•确实要在版本库中删除这个文件:

git rm test.txt
git add .
git commit -m "del"

•删错文件了,撤销修改即可:

git checkout -- test.txt

6.远程仓库

只要注册一个GitHub账号,就可以免费获得Git远程仓库。这样就可以使这两个仓库进行远程同步,远程仓库既可以作为备份,又可以让其他人通过该仓库来协作。

•准备git远程仓库

由于你的本地Git仓库和GitHub仓库之间的传输是通过SSH加密的,所以,需要一点设置:

第一步:创建SSH Key。(windows)

进入ssh目录看看这个目录下有没有id_rsa和id_rsa.pub这两个文件,如果已经有了,可直接跳到下一步。如果没有,打开Shell(Windows下打开Git Bash),创建SSH Key:

cd ~/.ssh/      //进入ssh目录
lsdir         //查看目录下的文件

创建 ssh key:

ssh-keygen -t rsa -C "youremail@example.com"

你需要把邮件地址换成你自己的邮件地址,然后一路回车,使用默认值即可,由于这个Key也不是用于军事目的,所以也无需设置密码。
如果一切顺利的话,可以在用户主目录(当前用户的根目录)里找到.ssh目录,里面有id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的秘钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。

第2步:登陆GitHub,打开“Account settings”,“SSH Keys”页面:
然后,点“Add SSH Key”,填上任意Title,在Key文本框里粘贴id_rsa.pub文件的内容:点“Add Key”,你就应该看到已经添加的Key:
为什么GitHub需要SSH Key呢?因为GitHub需要识别出你推送的提交确实是你推送的,而不是别人冒充的,而Git支持SSH协议,所以,GitHub只要知道了你的公钥,就可以确认只有你自己才能推送。
当然,GitHub允许你添加多个Key。假定你有若干电脑,你一会儿在公司提交,一会儿在家里提交,只要把每台电脑的Key都添加到GitHub,就可以在每台电脑上往GitHub推送了。
最后友情提示,在GitHub上免费托管的Git仓库,任何人都可以看到喔(但只有你自己才能改)。所以,不要把敏感信息放进去。
如果你不想让别人看到Git库,有两个办法,一个是交点保护费,让GitHub把公开的仓库变成私有的,这样别人就看不见了(不可读更不可写)。另一个办法是自己动手,搭一个Git服务器,因为是你自己的Git服务器,所以别人也是看不见的。

•添加远程仓库

(1)登陆GitHub》Create a new repo》填入Repository name》Create repository》创建成功。(2)本地仓库下运行:

git remote add origin git@github.com:michaelliao/learngit.git

  将本地仓库与远程仓库关联,origin为远程仓库的名字。

(3)将本地库的master分支推送到远程仓库:

git push -u origin master

  由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。

  从现在起,只要本地作了提交,就可以通过命令:git push origin master,把本地master分支的最新修改推送至GitHub,现在,你就拥有了真正的分布式版本库!

(4)SSH警告:

  当你第一次使用Git的clone或者push命令连接GitHub时,会得到一个警告:
  这是因为Git使用SSH连接,而SSH连接在第一次验证GitHub服务器的Key时,需要你确认GitHub的Key的指纹信息是否真的来自GitHub的服务器,输入yes回车即可。
  Git会输出一个警告,告诉你已经把GitHub的Key添加到本机的一个信任列表里了:
  这个警告只会出现一次,后面的操作就不会有任何警告了。
  如果你实在担心有人冒充GitHub服务器,输入yes前可以对照GitHub的RSA Key的指纹信息是否与SSH连接给出的一致。

•从远程仓库克隆

假设我们从零开发,那么最好的方式是先创建远程库,然后,从远程库克隆。

git clone git@github.com:michaelliao/gitskills.git

•同步远端分支变化

//拉取指定的分支变化
git fetch origin master
//拉取所有的分支变化
git fetch
//拉取所有的分支变化,并将远端不存在的分支同步删除
git fetch -p

•同步远端代码变化

//先git fetch再执行合并操作
git pull origin master     //执行的是git merge    
git pull -r origin master //执行的是git rebase

7.分支管理

分支在实际中有什么用呢?假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活了。如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险。
现在有了分支,就不用怕了。你创建了一个属于你自己的分支,别人看不到,还继续在原来的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工作。

•创建与分支合并

目前的实例中只有一个分支叫主分支,即master分支,之前说的HEAD严格来说不是指向提交,而是指向master,master才是指向提交的,所以,HEAD指向的就是当前分支
当我们创建新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上
不过,从现在开始,对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变
假如我们在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最简单的方法,就是直接把master指向dev的当前提交,就完成了合并
合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支:
实战:

创建并切换分支:

git checkout -b dev //-b参数表示创建并替换,相当于`git branch dev  git checkout dev`

git branch命令查看当前分支:

* dev
  master

修改工作区后提交修改:

git add readme.txt 
git commit -m "branch test"

切换到master分支后,会发现并没有刚才的修改,这是因为刚才的提交是在dev分支上:

git checkout master

将dev分支合并到当前的master分支:

git merge dev
Updating d17efd8..fec145a
Fast-forward    //表示这次合并是快进模式,也就是直接把master指向dev的当前提交
 readme.txt |    1 +
 1 file changed, 1 insertion(+)

合并完成后,删除dev分支:

git branch -d dev

8.解决冲突

如果两个分支在同一个文件同一个地方做了修改,比如a文件在分支1中是:A and B,分支2中是 A or B,那么在合并的时候就会发生冲突,此时需要手动解决冲突后合并:•使用命令git status可以看到发生冲突的文件。

•打开冲突的文件,git会在发生冲突的位置用<<<<<<<,=======,>>>>>>>标记出不同分支的内容,修改后提交即可。

git add .
git commit -m "fix conflict"

•合并分支,git log --graph --pretty=oneline --abbrev-commit该命令可以看到分支合并图,并删除不用的分支。

9.分支管理策略

通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。
如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。

git merge --no-ff -m "merge with no-ff" dev//因为本次合并要创建一个新的commit,所以加上-m参数,把commit描述写进去。

首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
那在哪干活呢?干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;
你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了,再把本地的dev合并到本地的master,最后把本地的master推到远程master。

10.bug分支

在Git中,由于分支是如此的强大,所以,每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。
当我们正在dev版本上开发新功能时,突然收到要在1小时内解决bug的需求,而自己的新功能又只开发了一半不想提交,这时就要用到Git的stash功能先把当前的工作现场隐藏起来。

git status//...发现当前工作区有未提交或未添加到暂存区的修改
git stash//隐藏当前的修改
git status//...发现工作区是干净的
git checkout master//切换到要修复bug的分支
git checkout -b issue-1//从要修复bug的master分支创建临时bug分支并切换到bug分支
.......fixing bug
git add file//添加修改到暂存区
git commit -m "fix bug 101"//提交更改
git checkout master//切回master分支准备合并
git merge --no-ff -m "merged bug fix issue1" issue-1//合并分支并添加备注
git branch -d issue-1//删除分支
git checkout dev//回dev分支继续干活
git status//发现工作区是干净的
git stash list//查看刚才隐藏的工作现场
git stash apply/pop //恢复隐藏的工作现场,apply和pop的区别在于恢复工作现场后后者删除了stash内容
git stash list//如果上一步用了`git stash pop`,此时看不到任何stash内容。
git stash apply stash@{0}//可以多次stash,恢复的时候,先用`git stash list`查看,然后恢复指定的stash

11.Feature分支

添加一个新功能时,你肯定不希望因为一些实验性质的代码,把主分支搞乱了,所以,每添加一个新功能,最好新建一个feature分支,在上面开发,完成后,合并,最后,删除该feature分支。

git checkout -b feature  //新建并切换到feature分支
git add file  //开发完成后添加到暂存区
git commit -m "add feature"  //提交更改
git checkout dev  //切换到dev分支准备合并
git branch -D feature  //此时收到通知丢弃feature功能,用-D删除未合并的分支

12.多人协作

当从远程克隆仓库时,Git会自动把本地master分支和远程master分支对应起来,查看远程库的信息用git remote,git remote -v可显示抓取和推送的origin地址,如果没有推送权限,就看不到push的地址。

•推送分支

就是把该分支上的所有本地提交推送到远程库。推送时,要指定本地分支,这样,Git就会把该分支推送到远程库对应的远程分支上:

git push origin master

但是,并不是一定要把本地分支往远程推送,那么,哪些分支需要推送,哪些不需要呢?

master分支是主分支,因此要时刻与远程同步;
dev分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;
bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;
feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。

•抓取分支

当你使用git clone命令克隆一个仓库时,你克隆的只是仓库的master分支,此时若要在dev分支上开发,需要先创建远程origin的dev分支到本地,然后再时不时把dev分支push到远程。

git checkout -b dev origin/dev
git add file
git commit -m 'xxx'
git push origin dev

如果你和同事对项目做了同样的修改,在push时会推送失败,因为你的小伙伴的最新提交和你试图推送的提交有冲突,解决办法也很简单,Git已经提示我们,先用git pull把最新的提交从origin/dev抓下来,然后,在本地合并,解决冲突,再推送:

git pull//git pull也失败了,原因是没有指定本地dev分支与远程origin/dev分支的链接,根据提示,设置dev和origin/dev的链接:
git branch --set-upstream dev origin/dev
git pull//再pull,pull成功但是合并有冲突,参考之前的冲突解决方法解决冲突后提交再push
git commit -m "xxx"
git push origin dev

因此,多人协作的工作模式通常是这样:
首先,可以试图用git push origin branch-name推送自己的修改;
如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;
如果合并有冲突,则解决冲突,并在本地提交;
没有冲突或者解决掉冲突后,再用git push origin branch-name推送就能成功!
如果git pull提示“no tracking information”,则说明本地分支和远程分支的链接关系没有创建,用命令git branch –set-upstream branch-name origin/branch-name。
这就是多人协作的工作模式,一旦熟悉了,就非常简单。

13.标签管理

发布一个版本时,我们通常先在版本库中打一个标签(tag),这样,就唯一确定了打标签时刻的版本。将来无论什么时候,取某个标签的版本,就是把那个打标签的时刻的历史版本取出来。所以,标签也是版本库的一个快照。

•创建标签

切换到要打标签的分支
git tag v1.0 //标签名为v1.0,打在最新提交的commit处
git tag //查看所有标签
如果要打到历史提交的commit处,需要先找到历史提交的commit id

git log --pretty=oneline --abbrev-commit
git tag v0.9 6224937 //git tag tagname commitid

git show tagname//查看标签信息
git tag -a v0.1 -m “version 0.1 released” 3628164//创建带说明的标签,-a指定标签名,-m指定tag说明

•操作标签

git tag -d v1.0//删除标签
git push origin tagname//推送某个标签到远程
git push origin –tags//推送所有标签到远程
删除远程标签

git tag -d v1.0//先在本地删除标签
git push origin :refs/tags/v1.0//远程删除标签,是否真正删除可登录github查看

14.如何参与开源项目

1.fork你想参与的项目,相当于在自己的账号下克隆了该项目的仓库
2.从自己的账号下clone项目到本地,一定要从自己的账号下克隆,否则将会没有权限推送
3.修改后推送到自己的仓库,然后在github上发起pull request,对方如果认可你的修改,便会接受。

15.自定义git

除了在安装git一节中介绍的user.name和user.email,git还有很多配置
如:git config --global color.ui true可以让git显示颜色

•忽略特殊文件

有的文件涉及密码、ip等配置文件,github中不能上传隐私信息,解决方法是只需在工作区的根目录下添加名为.gitignore的文件,这个文件不需要重头写,可参考.gitignore大全
配置完忽略文件后将其提交到git就完成了。
有时候当你想添加一个文件却发现添加不了,原因是这个文件被.gitignore忽略了,如果你确实想添加该文件,可以用-f强制添加到Git:

git add -f file

或者你发现,可能是.gitignore写得有问题,需要找出来到底哪个规则写错了,可以用git check-ignore命令检查:

git check-ignore -v App.class
.gitignore:3:*.class    App.class

Git会告诉我们,.gitignore的第3行规则忽略了该文件,于是我们就可以知道应该修订哪个规则。

Git使用流程

克隆代码 git clone 远程代码
创建分支 git checkout -b branch_name
在分支中开发 无
review代码 无
第一轮测试 无
添加代码到分支的暂存区 git add somefile
提交代码到分支 git commit -m “本次提交的注释”
切换到主版本 git checkout master
获取远程最新代码 git pull origin master
合并某分支到master分支 git merge branch_name
解决合并时产生的冲突 无
第二轮测试 无
准备上线文档 无
获取远程最新代码 git pull origin master
推送master分支 git push origin master
通知上线 无
没有问题了删除本地分支 git branch -d branch_name

原文地址:https://www.cnblogs.com/zhoulixue/p/6558846.html