查看版本:git --version
创建版本库:git init
查看git 脚本目录:git --exec-path
把远程分支拉到本地:git fetch origin dev(dev为远程仓库的分支名)
全局配置:
git config --global user.name "xxx"
git config --unset --global user.name "xxx" 删除设置
git config --global user.email "xxx@qq.com"
git config --global alias.st status 只在本用户中使用
git config --system alias.st status 被所有用户使用
window下配置文件位置:C:\Users\Administrator\.gitconfig
linux下配置文件位置:/etc/gitconfig
查看版本库提交日志:
git log --pretty=fuller(全展示)|oneline(只显示提交信息)|raw(显示提交对象的parent属性) --stat 查看每次提交的文件变更统计
本地备份:
git clone demo demo1
合并解决冲突:
1、git checkout dev //切换到被合并的分支
2、git pull //拉取要合并分支的最新代码
3、git checkout dev_activity //切换到要合并的分支
4、git pull //拉取最新代码
5、git checkout -b dev_activity_temp //创建临时分支用于合并,防止合并后冲突一时间解决不了而污染分支代码
6、git merge dev //合并dev代码到 dev_activity_temp
7、用tortoiseGit 或者其他可视化工具解决冲突
8、git commit -m "合并 dev 解决冲突" //提交解决冲突到临时分支
9、git checkout dev_activity //切换到 dev_activity 分支
10、git merge dev_activity_temp //合并已经合并dev的临时分支
11、git push //将合并代码推送到远端
12、git branch -D dev_activity_temp //删除临时分支
查看g工作区状态:
git status -s(显示精简信息)
ADD之前,说明工作区当前文件与暂存区的有改动
ADD之后,说明暂存区当前文件与版本库的有改动
ADD后追加内容,工作区暂存区版本库三者都有改动
重要概念:
ADD推至暂存区(stage)
HEAD(当前工作分支)
当执行git reset HEAD时,缓存区的目录树会被重写,但工作区不受影响,可用于取消add
当执行git rm --cached <file>时会直接删除暂存区文件,工作区不受影响
当执行git checkout 或git checkout -- <file>时,暂存区的文件会替换工作区的文件,这个操作很危险,因为会清除工作区的所有改动
当执行git checkout HEAD或git checkout HEAD <file>时,会用HEAD指向的master分支的全部或部分替换工作区和暂存区的文件,这个操作也很危险!
查看改动:
git diff :比较工作区与暂存区的差异
git diff HEAD:比较工作区与HEAD(当前工作分支)的差异
git diff --staged|--cached:比较暂存区与版本库文件的差异
查砍版本库中当前提交:git ls-tree -l HEAD 其中-l显示文件的大小
文件属性(rw-r--r--),文件类型,对象ID,文件大小,文件名
查看暂存区目录内容:git ls-files -s
文件属性(rw-r--r--),对象ID,暂存区编号,文件名
如果想针对暂存区使用git ls-tree命令,可以使用:git write-tree|xargs git ls-tree -l -r -t
查看Git对象ID命令:git cat-file -t(类型)-p(内容)
显示引用的对应提交ID:git rev-parse (结合git cat-file可以进行版本追踪)
git log --oneline精简版追踪日志,1.6.3版本及以后才有
git log --graph --stat 查看分支与合并信息
重置:
master分支在版本库的引用目录(.git/refs)中体现为一个引用文件.git/refs/heads/master,其内容就是分支中最新提交的提交ID。引用refs/heads/master就像一个游标,当有新提交发生时指向新的提交。git reset可以使游标指向任意一个存在的ID。
git reset --hard HEAD^ (HEAD^代表HEAD的父提交,既游标移动到上一个提交),使用重置命令可以回退到任意版本,但重置让历史改变了,意味着无法找到丢失的提交!慎用!
用reflog挽救错误的重置:.git/logs目录记录下的日志文件记录了分支的变更,带有工作区的版本库有有以下配置git config core.logAllRefUpdates --》 true。可以查看.git\logs\refs\heads\master文件,该文件记录了master分支指向的变迁。命令模式:git reflog show master。
重置master为5次改变前的值:git reset --hard master@{5},提交历史也会回来。
reset用法:
用法一:git reset [-q] [<commit>] [--] [paths] ... -q为安静模式,没有提示信息
用法二:git reset [--soft | --mixed | --hard |--merge| --keep ] [-q] [<commit>]
其中<commit>都是可选项,可以使用引用或提交ID,如果省略了<commit>就相当于使用了HEAD的指向作为提交的ID。
用法一不会重置引用,也不会改变工作区,而是指定提交状态<commit>下的<paths>替换掉缓存区中的文件,例如命令git reset HEAD <paths> 相当于取消之前add到暂存区时改变的暂存区。
用法二会重置引用。根据不同的选项,可以对暂存区和工作区进行重置:
使用--hard 如git reset --hard <commit>会执行三个动作:
1,替换引用的指向,引用指向新的提交ID
2,替换暂存区。替换后,暂存区的内容与引用指向的目录树一致。
3,替换工作区。替换后,工作区的内容和暂存区,HEAD指向的目录树内容相同。
使用--soft会执行1操作,既只改变了引用的指向,不改变暂存区和工作区
使用--mixed或不使用参数(默认为--mixed)会执行1,2操作,既改变引用指向和暂存区,不改变工作区。
命令:git reset,仅用HEAD指向的目录树重置暂存区,工作区不会受影响,相当于取消add
命令:git reset -- filename。仅将指定文件的改动撤出暂存区
命令:git reset --soft HEAD^。工作区和暂存区不变,但是引用向前回退一次。相当于取消上一次的commit。
命令:git reset HEAD^。工作区不改变,暂存区和引用会回退一次。
命令:git reset --mixed HEAD^。同上。
命令:git reset --hard HEAD^。彻底撤销最近的一次提交。而且工作区和暂存区都会回退到上一次提交状态。自上一次提交全部消失。
检出:
HEAD的重置既检出。HEAD可以理解为头指针,是当前工作区的基础版本,这时执行git branch -v会看到当前处于master分支。当执行提交时,HEAD指向的提交将作为新提交的父提交。
git提示的大致意思
什么是分离头指针:分离头指针指的是HEAD头指针指向了一个具体的提交ID,而不是一个引用(分支)。这个时候指向master变成了指向一个提交的ID。
查看一下HEAD和master对应的提交ID,会发现他们的指向不一样:
master指向并没有改变,而HEAD指向变了
如果现在添加新文件,会有以下提示:
这是因为HEAD处于分离头指针模式
执行提交,在提交输出中会出现detached HEAD标识。
detached HEAD提示
新提建立在之前的提交之上
切换到master分支上,git checkout master。HEAD重新指向了分支,没有了断头模式(分离头指针模式)
工作区的文件消失,提交日志也消失
使用git show 查看之前的提交ID可以看到这个提交仍然存在于版本库,但这个提交不会永久存在,当reflog中含有该提交的日志过期后,该提交会被彻底清除。
分离头指针模式下的提交只能使用提交ID访问,如果master需要提交的内容,可以用git merge进行合并操作。
流程:1 确认当前分支(git branch -v)2.执行合并操作,将目标提交ID合并到当前分支。3.可查看日志,会看到合并的分支图(git log --graph --pretty=oneline)4.查看最新提交的内容(git cat-file -p HEAD)可以看到这个提交有两个父提交。
合并流程
检出操作是最常用的命令之一,同时也是个危险的命令,因为这条命令会重写工作区。
用法如下:
用法一:git checkout [-q] [<commit>] -- <paths>
用法二:git checkout [<breach>]
用法三:git checkout [-m] [-b|--orphan <new_branch>] [<start_point>]
用法一的<commit>是可选项,如果省略则从暂存区检出。与重置命令大不相同:重置的默认值是HEAD,而检出的默认值是暂存区。因此,重置一般用于重置暂存区(除非使用--hard否则不重置工作区),而检出命令主要是覆盖工作区(如果<commit>不省略,也会替换暂存区的相应文件)
用法一(包含<paths>的用法)不会改变HEAD头指针,主要是用于指定版本的文件覆盖工作区的对应文件。如果省略<commit>则会用暂存区的文件覆盖工作区的文件,否则用指定提交中的文件覆盖暂存区和工作区的文件。
用法二(不使用<paths>的用法)会改变HEAD头指针,之所以后面参数写作<branch>是因为只有HEAD切换到一个分支才可以对提交进行跟踪。否则仍然会进入分离头指针状态。在分离头指针状态下的提交不能被引用关联到,从而可能丢失。所以用法二的最主要作用就是切换到分支。如果省略<branch>则相当于对工作区进行状态检查。
用法三主要是用于创建和切换到新的分支(<new_branch>),新的分支从(<start_point>)指定的提交开始创建,新分支和我们熟悉的master分支没有什么实质的不同,都是在refs/heads命名空间下的引用。
命令:git checkout branch。检出branch分支,更新HEAD以指向branch分支,以及用branch指向的书更新暂存区和工作区。
命令:git checkout。汇总显示工作区、暂存区与HEAD的差异。
命令:git checkout HEAD。同上。
命令:git checkout -- filename。用暂存区的filename文件来覆盖工作区中的filename文件。相当于取消自上次执行git add filename以来的本地修改。这个命令很危险,因为对本地的修改会悄无声息的覆盖,毫不留情。
命令:git checkout branch -- filename。维持HEAD的指向不变,用branch所指向的提交中的filename替换暂存区和工作区中的相应文件,注意是直接覆盖!
命令:git checkout -- .或写作git checkout . 。注意最后参数为一个点,这条命令最危险!会取消所有本地的修改(相对于暂存区)。用暂存区的所有文件直接覆盖本地文件,不给用户任何确认机会!
暂存区进度保存与恢复
保存进度命令:git stash
查看保存的进度:git stash list 可以多次保存工作进度,并在恢复时进行选择。
恢复进度:git stash pop
删除多余目录命令:git clean -nd(显示会删除哪些目录)git clean -fd(真正强制删除)
命令:git stash pop [--index] [<stash>] 如果不使用任何参数,会恢复最新保存的工作进度,并将恢复的进度从存储的工作进度列表中清除。选项--index除了恢复工作区的文件之外,还尝试恢复暂存区。<stash> git stash list中的进度列表 如 0 1 2
命令:git stash apply [--index] [<stash>]除了不删除恢复的进度之外,其余和git pop一样
命令:git stash drop [<stash>]删除一个存储的进度,默认删除最新的进度
命令:git stash clear 。删除所有存储的进度
命令:git stash branch [branchname] <stash>
查看保存进度的引用信息:git reflog show refs/stash
删除与移动、恢复
删除命令:git rm 执行后会直接保存到暂存区,本地删除则不会自动保存到暂存区
恢复上一次删除的文件:git cat-file -p HEAD~1:filename > filename
可使用show命令 git show HEAD~1:filename > filename代替,效果相同
最简单可使用:git checkout HEAD~1 -- filename
HEAD~1相当于HEAD^。执行git add -A会将工作区所有改动以及新增文件添加到暂存区。
移动命令:git mv file1 file2
版本表示法
显示分支: git rev-parse --symbolic --branches
显示里程碑: git rev-parse --symbolic --tags
显示定义的所有引用:git rev-parse --symbolic --glob=refs/*
将对应的git对象表达式表示为对应的SHA1值。
显示里程碑:git describe --tags
版本范围表示法
显示该版本的所有历史提交:git rev-list --online,实际上一个提交ID就可以代表一个版本列表
取两个版本的并集 git rev-list --online a b
取反,既排除这个版本及其历史版本 git rev-list --online a^
点点表示法 表示上面如git rev-list --online a..b 相当于^a b
三点表示法含义是两个版本共同能访问到的排除出去。
某提交的历史提交,将自身除外 git rev-list --online a^@
提交本身不包括其历史提交git rev-list --oneline a^!
查看分支指向的提交ID git rev-parse brachname1 brachname2
浏览日志:git log
可接表示版本范围的参数
分支图表示:
git config --global alias.glog "log --graph"
git glog --oneline
显示每次提交的具体改动:git log -p -1
显示每次提交的变更概要:git log --stat --oneline
只显示改动了哪些文件
定制显示:--pretty
--pretty=raw 显示commit的原始数据,可以显示提交对应的树ID
--pretty=fuller -1会先作者和提交者
--pretty=oneline -1 会显示精简输出
如果想查看和分析某一个提交,也可以使用git show 或git cat-file
差异比较:git diff
比较里程碑B和里程碑A。git diff A B
比较工作区和里程碑A。git diff A
比较暂存区和里程碑A。git diff --cached A
比较工作区和暂存区。git diff
比较暂存区和HEAD。git diff --cached
比较工作区和HEAD。git diff HEAD
文件不同版本的比较。git diff <commit1> <commit2> -- <paths>
非git目录/文件的比较。git diff <path1> <path2>
文件回溯:git blame 会显示文件,在每一行显示此行最早在什么版本引入的,由谁引入的
二分查找:git bisect start
标记当前版本:git bisect bad |good
当找到坏提交后:标记git bisect bad
修复好后:git bisect reset
git修补提交信息:git commit --amend -m "修补提交"。
命令git rebase是对提交进行变基操作。可实现将指定范围内的提交“嫁接”到另一个提交上。
归一化命令:git rebase --onto <newbase> <since> <till>
变基操作过程:1.首先会执行git checkout 切换到<till> ,如果<till>指向的不是一个分支(如master),则变基操作是在detacached HEAD(分离头指针)状态下进行的。当变基结束后,要对master分支执行重置以实现变基结果在分支中提交。2,.将<since>..<till>所标识的提交范围写到一个临时的文件中,<since>..<til>是指包括<till>的所有提交排除<since>及<since>的历史提交后形成的版本范围。3.将当前分支强制重置(git reset --hard)到<newbase>。4.从保存在临时文件中的提交列表按提交顺序重新提交到重置之后的分支上。5.如遇到提交已经在分支中包含,则跳过该提交。 6.如果在提交过程中遇到冲突,则变基过程暂停,用户解决冲突后,执行git rebase --continue继续变基操作,或执行git rebase --skip跳过此提交。或执行git rebase --abort终止变基操作并切换到变基前的分支上。
场景1:有A,B,C,D,E的历史提交,现在要去掉C。
方法1:1、git rebase --onto B D^ E 。这时会进入分离头指针状态,,需要将master分支指向变基后的提交上
2、git checkout master 。切换回master分支
3、git reset --hard HEAD@{1}。使用了reflog语法HEAD@{1}相当于切换回master分支前的HEAD指向。
4、完成变基操作。
5、git reset --hard E重新布景
方法2:1、git checkout D。将HEAD指向D,这时会进如detached状态。
2、git reset --soft HEAD^^。回退两次提交操作,B、C回到暂存区。
3、git commit -C C。重新提交B、C所改动的内容,-C说明重用C的提交说明
4、git tag newbase。用里程碑是记忆提交ID最好的方法。
5、git rebase --onto newbase E^ master。执行变基操作,这个操作会直接修改master分支,无需对master进行重置操作。
6、git tag -d newbase。删除不需要的里程碑。
7、完成变基操作。
git克隆:
用法1:将<repository>指向的版本库创建一个克隆到<directory>目录,目录<directory>相当于克隆版本库的工作区,文件都会检出,版本库位于工作区下的.git目录中
用法2:克隆出的版本库不包含工作区,只有版本库的内容,这样的版本库称为裸版本库,一般约定以.git为后缀。
用法3:与用法2的区别在于版本库对上游版本库进行了注册,这样可以用git fetch命令与上游版本库进行持续同步。
git分支:
用法1:用于显示本地分支列表,当前分支会以*号显示。
用法2:基于当前HEAD指针指向的提交创建新分支。
用法3:基于提交<start-point>创建新分支。
用法4:用与删除分支,删除时要检查所删除的分支是否已经合并到其他分支中,否则拒绝删除。
用法5:强制删除分支。
用法6:重命名分支,如果已经存在该分支名则拒绝执行。
用法7:强制重命名分支。
创建分支后立刻切换分支:git checkout -b <branchname> [<start_point>]。
分支合并到master: git merge branchname,实际上合并后master分支和开发分支指向同一个提交,这是因为合并前master分支的提交就是开发分支的父提交,所以相当与本次将分支master重置到开发分支。默认情况下,Git执行"快进式合并"(fast-farward merge),会直接将Master分支指向Develop分支。
fast-farward merge
使用--no-ff参数后,会执行正常合并,在Master分支上生成一个新节点
查看本地分支哪些提交领先远程版本库:git cherry
创建发布分支:
场景:发布版本出现bug,master分支存在修改,就必须以基于发布版本的代码创建分支。因此在发布版本时需要给发布版本打上里程碑,当线上出现bug时使用命令:git checkout -b fix_v1.0 v1.0 ,修复后推送至远程共享库git push origin,其他开发者使用命令git fetch拉取该分支,拉取完后切换到该分支git checkout -b fix_v1.0 origin/fix_v1.0,该远程分支不能直接检出,而是需要基于该远程分支创建本地分支然后基于该本地分支进行开发,当开发完成后需要将代码推送至本地仓库,此时推送会遇到非快进式推送的问题。此时需要一个拉回操作,将远程服务器的改动获取到本地并和本地提交进行合并,合并之后就可以推送至远程仓库了。
合并到主线:
当开发者在fix_v1.0中将相应的bug修改完后,就需要将代码合并到主线。
流程:切换至master分支,从远程代码库同步master分支,查看分支fix_v1.0的日志,确认要拣选的提交ID,git log -3 --graph --oneline fix_v1.0。
拣选到主线git cherry-pick fix_v1.0^。
冲突解决:当挑选分支上的一个提交到master分支时,可能出现多个提交在重叠位置更新代码,通过以下命令可以看到底是哪些提交引起的冲突
git log master...fix_v1.0。并使用图形话界面解决冲突。解决冲突后执行推送命令将本地master分支同步到远程版本库。
删除本地分支:git branch -d branchname
删除远程分支:git push origin :branchname
远程版本库
多版本交互:
流程:1、克隆2个版本库裸版本git clone --bare .git user.git。 2、 查看远程版本库有哪些版本:git ls-remote --heads file:///d:/user.git
3、克隆user.git版本库git clone file:///d:/user1.git。4、进入user本地版本库cd d:/user。5、执行git branch会看到只有一个master分支。
6、执行git show-ref可以查看所有的本地引用。
查看远程仓库分支:git branch -r
注册新远程版本库:git remote add new-remote file:///d:/user2.git
显示已经注册的远程版本库:git remote -v
从新的远程版本库中获取分支:git fetch new-remote
重命名远程分支名:git remote rename newname oldname
当注册了多个远程版本库并希望获得所有版本库的更新时,使用命令:git remote update
删除远程版本库:git remote rm new-remote
git pull和git fetch 的区别:
.一、远端跟踪分支不同
1、Git fetch:Git fetch能够直接更改远端跟踪分支。
2、git pull:git pull无法直接对远程跟踪分支操作,我们必须先切回本地分支然后创建一个新的commit提交。
二、拉取不同
1、Git fetch:Git fetch会将数据拉取到度本地仓库 - 它并不会自动合专并或修改当前的工作。
2、git pull:git pull是从远程获取最新版本并merge到本地,会自动合并或修改当前的工作。
三、commitID不同
1、Git fetch:使用Git fetch更新代码,属本地的库中master的commitID不变,还是等于1。
2、git pull:使用git pull更新代码,本地的库中master的commitID发生改变,变成了2。
Git协同模型
容易带入不成熟代码,造成数据丢失
1.创建本地分支git checkout -b my/dev 2.创建远程独享分支git push origin my/dev 3.开发完成后将本地分支合并到主线上,推送到共享版本库
Git子模组协同模型:
创建子模组:git submoddule add submodule.git localpath
添加完成后在super版本库根目录上多了一个.gitmodules文件
查看子模组状态git submodule status,前面的减号含义是该子模组尚未检出
如果需要克隆子模组形式引用的外部库,需要先执行git submodule init,然后执行git submodule update完成子模组版本库的克隆。
子模组的修改和更新:在父项目中修改子模组内容后,需进入到子模组,此时子模组会进入分离头指针状态,此时执行提交后,git checkout master切换到master分支,执行git merge操作,然后执行git push推送至远程子模组。然后cd 到父项目,将子模组添加并提交,执行git push完成子模组更新。
fast-farward merge