Git学习笔记精华

Git 作为一个代码版本管理的软件,越来越多被使用,以下是在工作使用过程中总结出来的精华,同时在网上参考学习一下网上的博文,下面就直接上内容,力争简短,完整,实用....


.创建一个版本库非常简单,首先,选择一个合适的地方,创建一个空目录:
$ mkdir learngit
$ cd learngit
$ pwd
/Users/michaelName/learngit
 

.pwd 命令用于显示当前目录;
$ pwd 
/d/mygit


.如果你使用Window系统,为了避免遇到各种莫名其妙的问题,请确认目录名(包含父目录)不含中文;


.通过git init命令把这个目录变成Git可以管理的仓库:
$ git init

成功会显示提示:Initialized empty Git respository in /Users/michaelName/learngit/.git


.千万不要使用Window自带的记事本编辑任何文本文件,Microsoft开发记事本团队自作聪明地在每个文件的开头添加了
0xefbbbf (十六进制)的字符,你会遇到很多不可思议的问题;


.把一个文件放到Git仓库只需两步,
第一步,用 git add 告诉Git,把文件(假设为readme.txt)添加到本地git缓存工作区,还没到仓库,
$ git add readme.txt
可多次使用 add 命令来添加多个文件本地的git缓存工作区;

第二步,用命令 git commit 告诉Git,把第一步中本地的缓存文件区中的文件实际提交到远程仓库中,
$ git commit -m "提交文件的相关说明内容"
参数 -m 后面输入的是本次提交的解释说明内容,可以输入任意内容,当然最好是与本次提交文件相关说明;
commit命令一次可提交多个文件;


.git status 命令可以让我们时刻掌握仓库当前的状态,查看是否修改状态和是否提交状态;


.git diff 查看文件(假设文件为readme.txt)具体修改了什么内容,命令如下:
$ git diff readme.txt


.提交修改和提交一个文件到Git仓库是一样的,分两步:
$ git add readme.txt
$ git commit -m "本次修改的内容说明描述"
在commit提交之前可以用 git status 查看被提交的修改是否包含了readme.txt文件,以便放心提交,
同时提交之后也可以用  git status 查看提交后的修改状态;

.文件修改到一定程度的时候,就可以“保存一个快照”,这个快照在Git中被称为commit,一般你把文件改乱了,或者误删了文件,还可以从最近的一个commit恢复,然后继续工作;


.git log 命令可以告诉我们从最近到最远的提交历史日志记录,运行如下命令
$ git log
即可列出当前文件的历史修改记录,包含版本号 [commit id],提交作者[Author],提交时间[Date],修改内容信息;


.git log 命令加上 --pretty=oneline参数,即可一行内仅仅看到版本号[commit id]和修改的内容信息,漂亮,命令如下:
$ git log --pretty=oneline


.在Git中,用 HEAD 表示当前版本,上一个版本就是 HEAD^,上上一个版本就是 HEAD^^,往上(之前)第N(N >= 3)个版本写成 HEAD~N,例如往上(之前)的第50个版本,写出 HEAD~50;


.回退(假设文件为readme.txt)到上一个版本或某个版本,Git必须知道当前版本是哪个版本;


.git reset 命令可回退(假设文件为readme.txt)到上一个版本或以前的某个版本,命令如下:
$ git reset --hard HEAD^
即可回退到上一个版本,--hard参数带有强制作用,即强制恢复到上一个版本,可以用 cat readme.txt查看操作后的版本内容;


.当 git reset 回退到某个版本后,在想往前或往后到某个版本,给出指定目标版本号[commit id](假设为123456)即可,如下:
$ git reset --hard 123456
命令运行完后当前版本即为123456;单个文件的回退见下面;

.版本号没必要写全,写前几位(能唯一区别)就可以了,Git会自动去找。当然也不能只写前一两位,因为Git可能会找到多个版本号,就无法确定是那个一个了;


.命令 git reflog 用来记录你的每一次命令,通过这个可以找到需要的某个版本号[commit id];


.工作区(Working Directory)就是我们能在电脑里能看到的目录;


.版本库(Repository),就是工作区有一个隐藏目录 .git,这个不算工作区,而是Git的版本库;
Git的版本库里存了很多东西,其中最重要的就是称为 stage(或者叫index)的暂存区
还有Git为我们自动创建的第一个分支 master,以及指向 master 的一个指针叫 HEAD;


.暂存区,即Git的版本库里存了很多东西,其中最重要的就是称为 stage(或者叫index)的暂存区;
命令 git add 文件名,把文件添加进去,实际上就是把文件修改添加到暂存区;
命令 git commit 提交更改,实际上就是把暂存区的所有内容提交到远程仓库的当前分支;


.Git管理的是修改,而不是文件;修改的定义是任何有变动的操作,比如:增加/删除/修改某行或某个字符
或创建/删除一个文件等;
所有修改只有 git add 操作之后才放到暂存区;
只有放到暂存区里的所有修改才被 git commit 命令提交;


.git checkout -- yourFileName 命令可以丢弃工作区中该文件(假设文件名为myFile.txt)的所有修改,命令如下:
$ git checkout -- myFile.txt
(包括文件修改后已放或未放到暂存区两种情况)命令运行后就让该文件回到最近一次 git commit或
git add时的状态;
注意 -- 必须有,没有则变成“切换到另一个分支”命令了,注意--后面至少有一个空格,文件如果有路径的还加路径;


.命令 git reset HEAD yourFileName 可以把该文件在暂存区的修改撤销掉(unstage),重新放回工作区;
$ git reset HEAD readme.txt
git reset 命令即可回退版本,也可以把暂存区的修改回退到工作区,即用远程仓库的当前版本覆盖本地文件和暂存区;


.撤销场景例子
场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令 git checkout -- file;

场景2:当你不但乱改了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,
第一步用命令 git reset HEAD file,就回到了场景1,第二步按场景1操作;

场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本回退一节,不过前提是没有推送到远程仓库;

.一般情况下,你通常直接在文件管理器中把没用的文件(假设文件名为myFile.txt)删了,或者可用rm命令删了,命令如下:
git rm myFile.txt
命令运行完,可用 git status 查看哪些文件被删除了;


.确定要从版本库中完整删除文件(假设文件名为myFile.txt),用命令 git rm 删掉,并且用 git commit 两步完成删除一个文件,命令如下:
git rm myFile.txt 
git commit -m "remove and delete myFile.txt file"
运行命令后文件就从版本库中被删除了,可用 git status 查看哪些文件被删除了;
上面仅仅是本地的删除,如果所做的删除同步到远程仓库中,则需要push到远程仓库,命令如下:
git push


.如果是本地删错了文件(假设文件名为myFile.txt),因为版本库里还有,故可用 git checkout命令把误删的文件恢复到最新版本,如下:
git checkout -- myFile.txt
命令运行后,无论工作区是修改还是删除,都用版本库里的版本替换工作区的版本,完成“一键还原”


.远程仓库,可用找一台电脑充当服务器的角色,24小时开机,别人都从这个“服务器”仓库克隆一份到自己的电脑上,
完全可用自己搭建一台运行Git的服务器,但已有个叫GitHub的网站,提供Git仓库托管服务的,
所以只有注册一个 GitHub账号,就可以免费获得Git远程仓库了;


.本地Git仓库和远程的GitHub仓库之间的传输是通过SSH加密的,所以有点设置:
第一步,创建SSH Key。在用户主目录下,看看有没有 .ssh 目录,如果有,再看看这个目录下有没有 id_rsa 和 id_rsa.pub这两个文件,
如果已经有了,可直接跳到下一步。如果没有,打开Shell(windows下打开Git Bash),创建SSH Key:
ssh-keygen -t rsa -C "youremail@example.com"
然后一路回车,使用默认值即可,如果顺利, .ssh目录应有 id_rsa,这是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心告诉他人,
这两个就是SSH Key的密钥对;

第二步,登录GitHub,打开“Account settings”,“SSH Keys”页面:
然后,点“Add SSH Key”,填上任意Title,在Key文本框里粘贴 id_rsa.pub文件的内容,点“Add Key”,你就应该看到已经添加的Key,
GitHub只要知道了你的公钥,就可以确认只有你自己才能推送;
GitHub允许你添加多个Key,所以在公司/家里的电脑KEY添加到GitHub上,两个地方电脑都可以向GitHub推送东西了;
GitHub网址:https://gitgub.com 或 http://www.github.com


.添加远程库(先有本地库,后有远程库的时候,如果关联远程库)
情景,你已经在本地创建了一个Git仓库后,又想在GitHub创建一个Git仓库,并且让这两个仓库进行关联并远程同步,
这样GitHub上的仓库即可以作为备份,又可以让其他人通过该仓库来协作,真是一举多得;

实现步骤:
首先,登录GitHub,然后在右上角找到“Create a new repo”按钮,创建一个新的仓库;
在Repository name填入与本地库一样的文件夹(假设为mygit),其它保持默认设置,点击“Create repository”按钮,
即可创建了一个新的Git仓库;在GitHub上的这个仓库还是空的,GitHub告诉我们,可以从这个仓库克隆出新的仓库,
也可以把一个已有的本地仓库与之关联,然后把本地仓库的内容推送到GitHub上的仓库。

其次,进行关联,在本地的(假设为mygit)仓库下运行命令:
$ git remote add origin git@github.com:自己的git账户/自己的github上的仓库名.git
添加后,远程库的名字就是origin,这是Git默认的叫法,也可以改成别的,但是origin这个名字一看就知道是远程库;
这之后完成本地仓库和远程仓库的关联;

再次,把本地仓库的所有内容推送到远程仓库上,
git push -u origin master
远程库是空的,第一次推送master分支时,加上 -u 参数,Git不但会把本地的master分支内容推送到远程新的master分支,
还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令;

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


.SSH警告,当你第一次使用Git的clone或者push命令连接GitHub时,会得到一个警告,此因为Git使用SSH连接,而SSH连接在第一次验证GitHub服务器的Key时,需要你确认GitHub的Key的指纹信息是否真的来自GitHub的服务器,输入yes回车即可;


.从远程库克隆(最好的方式是先创建远程库,然后从远程库克隆到本地库)
首先,(假设你已有Github账号)登录GitHub,创建一个新的仓库[步骤前面的步骤],名字叫firstgit,
页面中勾选 Initialize this repository with a README,这样GitHub会自动为我们创建一个README.md文件,
创建完毕后,可以看到README.md文件,现在,远程库已经准备好了;

其次,是用命令 git clone 克隆一个本地仓库,命令如下:
git clone git@github.com:自己的Github账号/firstgit.git
命令运行后即可从远程仓库克隆一份到本地仓库了;

可用 cd firstgit 进入目录,然后用命令 ls 查看当前目录下有哪些文件了;

.注意支持协议问题,GitHub给出的地址不止一个,还可以用 https://github.com/自己的GitHub账号/firstgit.git此类地址,实际上,Git支持多种协议,默认的git://使用ssh,但也可以使用https等其它协议;使用https除了速度慢以为,还有个最大的麻烦是每次推送都必须输入口令,但是在某些只开放http端口的公司内部就无法使用ssh协议而只能用https;


.分支在实际中有什么用?
分支的创建,其解决了自己某个功能代码开发到半,想提交就提交,减少代码丢失的风险,直到开发完毕后,再一次性合并到原来的分支上;
这期间别人看不到自己的分支,也不影响别人继续在原来的分支上正常的工作;Git分支无论创建,切换和删除分支,Git在一秒之内就完成;


.在Git里,有一个主时间线,叫主分支,即master分支;


.创建分支[假设为 dev],然后切换到当前分支 [dev],命令如下:
git checkout -b dev

git checkout命令加上 -b 参数表示创建并切换,相当于以下两条命令:
git branch dev
git checkout dev


.查看列出所有分支命令:
git branch
该命令会列出本地所有分支,当前分支前面会标一个绿色的 * 号,跟其它有所区别;
如果该命令在加上 -a 参数会列出所有分支,包括远程服务器上的分支,命令如下:
git branch -a 


.切换分支命令:
git checkout 分支名称

假设切换到master主分支,命令为: git checkout master 
回车后master即为当前分支;

.合并[merge]指定分支到当前分支命令(注意当前是哪个分支):
git merge 指定分支名称

假如当前在master分支上,要把dev分支上的工作结果合并[merge]到当前的master分支,命令如下:
git merge div 合并完成后就可以删除dev分支(Fast-forward信息,提示这次合并是“快进模式”),
该命令需要确保当前分支是哪个分支,然后在当前分支基础上merge指定的分支


.删除分支命令:
git branch -d 分支名称

如果用大写的参数 D 则强制删除,即

git branch -d 分支名称

假设分支名称为dev,则命令为
git branch -d dev 或 git branch -D dev 
运行完即可删除dev分支,也可git branch查看分支列表;


.Git用 <<<<<<<<<(HEAD),=========(中间分割线),>>>>>>>>>(另一分支名称)标记出不同分支的冲突内容,例如:
<<<<<<<<< HEAD
Creating a new branch is quick & simple.
=========
Creating a new branck is quick AND simple.
>>>>>>>>> featurel


.当文件产生冲突以后,必须首先直接修改文件解决冲突,然后保存后再提交(命令如下),才完成合并:
git add 修改的文件名
git commit -m "修改描述"

之后可以用 git log 查看合并情况,命令如下:
git log --graph --pretty=online --abbrev -commit

最后删除分支(命令如下)
git branch -d 分支名称


.git log --graph 命令以树形结构给我们展示从最近到最远的提交历史记录;
按向下箭头或回车可以不断查看,需要结束时可输入冒号然后按q键,即":q" 退出树形显示结果,返回git命令模式


.如果强制禁用 Fash forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息;


.带 --no-ff参数的合并[merge]命令,表示禁用 Fast forward,命令如下:
git merge --no-ff -m "修改描述" 分支名称
注意,本次命令创建一个新的commit,故加上 -m 参数把修改描述写进去;

合并分支时,加上 --no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出曾经做过合并,
而 fast forward合并就看不出来曾经做过合并;


.分支策略
实际开发中,我们应该按照几个基本原则进行分支管理;
首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
其次,那在哪里干活呢?干活都在[非master,假设为]dev分支上,也即是说,dev分支是不稳定的,到某个时候,
      比如1.0版本发布时,再把dev分支合并到master上,再在master分支发布1.0版本;
再次,团队每个人应该在[非master,假设为]dev分支上工作,
      每个队员应都有自己个人分支,个人工作修改结束时不时往dev分支上合并自己的结果;
团队的合并分支看起来像如下结构:

*==============*=================*=======----- master[主干分支]
 \                          /                                     /
  \*=====*=====*==========*======*=====*----------- teamA[团队A分支]
   |\         /|         /                      /             /           /
   | \*==*=|===*===*===*===*======*=====*-------------- member1[队员1的个人分支]
   |           |                              /                       /
   + \*====*======*======*===========*--------------- member2[队员2的个人分支]
   |
   |...扩展团队的更多其它个人分支


.开发中每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除;


.git stash 可把当前工作现场“储藏”起来,等以后恢复现场后继续工作,命令如下:
git stash


.修复bug需要创建临时bug分支,要创建临时bug分支需要确定当前是在哪个分支上;所以在哪里修复bug,首先切换到对应的分支上作为当前分支,然后创建临时bug分支,然后修复bug,提交并合并修改,最后删除bug分支;


.用git stash list命令可查看由git stash命令把工作现场存储在某个地方;


.可多次运行git stash命令,恢复的时候,先用git stash list查看,然后恢复指定的stash,用命令:
git stash apply stash@{0}
注意指定{n}中的序数n即可;


.Git把git stash把工作现场存储再某个地方,有两个办法恢复;
一,是用git stash apply恢复,但是恢复后,stash内容并不恢复,你需要git stash drop来删除;
二,是用git stash pop,恢复的同时吧stash内容也删除了;


.软件开发中,准备添加一个新功能时,为防止实验性代码弄乱了主分支,所以每添加一个新功能时,最好新创建一个feature分支,再上面开发,完成后,合并,最后,删除该feature分支,期间各个阶段注意当前处在哪个分支上;


.当从远程仓库克隆时,实际上Git自动把本地的master分支和远程的master分支对应起来了;


.查看远程仓库的信息,远程仓库的默认名称是origin,用git remote命令:
git remote

加上 -v 参数显示更详细的远程仓库信息,命令如下:
git remote -v
如果有push权限,应该看到push地址;

.推送分支,就是把该分支上的所有本地提交推送到远程库,推送时,要指定本地分支,这样Git就会把该分支推送到远程库对应的远程分支上;
git push origin 本地分支名称
例如把本地的master主分支推送到远程仓库,命令如下:
git push origin master

如果要把本地其它分支,假设为dev推送到远程仓库上对应的分支上,命令如下:
git push origin dev


.并不是一定要把本地所有分支往远程仓库推送,哪些分支需要推送,哪些不需要,根据工作需要而定,有些自己本地验证性代码完全没必要推送到远程库;


.git 设置本地的用户名和密码
git config --global user.name "stone.qin"
git config --global user.email "stone.qin@qq.com"


.对于删除的文件同样需要提交到远程库中,需要先rm标记,然后commit,最后push,共三步;
例如:远程库有kkk.txt文件,现在已经不用,本地已经删除,但需要关联到远程库,步骤如下:
一,git rm path/kkk.txt
二,git commit -m "remove not use file"
三,git push

-----------------------------------------------------------------------------------

.综合实例,要求如下:
在某分支上建立子分支,然后将新建立分支同步到远程仓库,在日后开发中父分支和子分支分别有更新,因开发需要父分支需要每日不断merge到该子分支,
以满足子分支的开发需要;假设有父分支fenzhi01,希望在此基础上建立子分支fenzhi02,分四步如下:

1,在父分支上建立子分支;就是切换到父分支,pull最新代码到本地,然后在此基础上建立子分支,步骤如下:
git checkout fenzhi01
git pull
git checkout -b fenzhi02

2,把新建的分支同步到远程仓库;就是切换到最新的子分支,然后push到远程库;
git checkout fenzhi02
git push origin fenzhi02
注意:这种带分支的push只push该分支,如果期间该分支中某个文件修改,这个也不提交变动的文件;

3,父分支和子分支分别更新;分别切换到父分支和子分支,然后pull最新代码到本地:
git checkout fenzhi01
git pull
git checkout fenzhi02
gipull

4,把父分支最新的更新merge到子分支上;切换到子分支,然后用merge,命令如下:
git checkout fenzhi02
git pull
git merge fenzhi01


.综合实例,要求如下(此参考开发中的实例)
当某分支代码修改或建立好了,已经push到git远程库中,要求需要发pull request,以便等候和需要别人code review,其步骤为:

1,登录Git 远程库中心,并进入到项目的Git地址首页;

2,在首页下[新窗口]打开Bamboo地址,选择自己的修改或建立的分支,记下自己分支的Bamboo地址;

3,在Bamboo自己的分支确保build已经完成后,再在Git地址首页选择自己的修改或建立分支,然后点击前面的连接;[后来已不用]

4,进入建立pull request的页面,在下面的输入框中输入上面自己分支的Bamboo地址和请求review等说明,
再选择属于的哪个发布版本(milestone,也可后面在code review页修改),
然后点击“create pull request”连接,然后完成pull request的建立;

5,再在IM工具(如lync)的群中告知,code review地址和请求别人code review,即完成了;

6,最后别人review通过,打label后即可merge到父分支(如master)上,原来的分支可删可留;

.综合实例,在某分支上,如果git某些命令出现异常或文件出现冲突,如何强制本地代码与远程库的代码同步到一致,
例如:虽然进行git pull拉取代码操作,(可能也显示正常)但实际本地的代码和远程库的代码还是不同步或不一样,
这时先进入对应的分支,然后可用如下命令强制本地代码跟远程库的代码进行同步,

git branch --set-upstream-to= origin/分支名称

命令执行后即远程库的代码会拉取下来,并(即使有冲突的也)覆盖本地的文件;
例如,本地分支为fenzhi01,因某原因部分文件出现冲突或其它问题,先希望把远程库的代码拉取下来,覆盖本地该分支
所有文件,以达到本地文件和远程库同步的问题,命令如下:

git checkout fenzhi01
git branch --set-upstream-to= origin/fenzhi01

命令执行后,远程库分支fenzhi01中的所有代码会拉取下来,不管冲突与否,都会覆盖本地该分支的对应代码文件;

.如何把远程库中的某分支复制到本地?即远程库有某分支,本地没有,现需要从远程中把某分支拿下来,然后再修改,命令如下:

$ git checkout --track origin/分支名称 或者 
$ git checkout --track remote/分支名称 

假设分支名称为fenzhi03,则具体的命令如下:

$ git checkout --track origin/fenzhi03 或者
$ git checkout --track remote/fenzhi03 


.综合实例,如何使用其它分支上的某个文件来替换当前分支上的对应文件?
例如:不同的分支fenzhi01和fenzhi02上都有文件File01.txt,现处在当前分支为fenzhi02上,
现需要用fenzhi01分支上的File01.txt来替换当前分支(fenzhi02)中File01.txt文件,命令如下:

git checkout fenzhi02
git checkout fenzhi01 -- xpath/File01.txt

命令运行完,即用分支fenzhi01上的File01.txt来替换当前分支fenzhi02中File01.txt文件,注意如有路径需加上对应路径;


.综合实例,如何恢复到某次提交修改的之前状态?
例如:在某次修改完一个或几个文件后,又同时也已经提交到远程库中,因某原因现在需要把那次的提交所做的修改全部撤销,即恢复那次提交之前的状态;

假如在某个分支有文件 File01.txt, File02.txt 已经修改,同时已经进行如下操作(即提交到远程库):

git add filepath/File01.txt
git add filepath/File02.txt
(git add filepath/File0N.txt 可更多提交修改的文件)
git commit -m "修改描述说明"
git push

现在因某原因,需要把这次提交(commit)所做的修改全部撤销,即恢复到这次提交之前的状态,步骤如下:
1,首先用 git log 列出所提交的log记录,
2,根据提交作者, comment,提交时间等信息查出本次commit的唯一ID,复制该ID(复制可全部或能识别该ID的部分内容),
3,用命令 git revert commitID 进行撤销本次修改,
4,因恢复也是一种修改,故恢复完也需要push到远程库中,所有步骤命令如下:

git log (假设查出确认的commitID为b32asdf45dh789)
git revert b32asdf45dh789
git push

相应扩展:
git revert HEAD   撤销前一次 commit
git revert HEAD^  撤销前前一次 commit


.希望以试图方式查看Git中各个分支的建立和父子分支依赖关系,可用用gitk命令;
$ gitk
回车之后即可启动Git试图;退出时,直接关闭试图窗口,再在Git命令窗口使用q命令退出即可,
$ q


.综合实例,本地删除无用分支而远程库忘记删除导致pull不成功,怎么办?
比如在本地分支fenzhi01上开发了某个功能,已经完成,代码也已经merge到master上了,
理应本地和远程库都删除对应的该分支fenzhi01,以便移除不必要的分支,同时也节省名称资源和空间,
但是现在把本地该分支已经删除了,却忘记了把远程库对应的分支删除,长时间过后,在进行pull操作,发现报错,

可尝试把远程分支进行删除,命令如下:

git branch -d -r origin/fenzhi01

命令运行之后,即提示远程库中分支fenzhi01已删除,这时再在其它分支(如:master)中进行pull,应该出现pull成功;
 

分享一下,实现懒人计划,欢迎拍砖... 同时参考的网上资料链接如下:

http://www.liaoxuefeng.com

 

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页