Git learn manual
Git learn manual
--Alex
目录
一、 基本使用应用... 2
1.1创建版本库与本地初步使用应用... 2
1.2 Gitlab状态使用应用... 3
1.3 版本退回使用应用... 3
1.3 工作区与暂缓区应用... 3
1.4 管理与撤销修改应用... 4
1.5 删除应用... 5
1.6 远程仓库应用... 5
二、 场景应用... 10
2.1删除远程仓库但不删除本地资源应用... 10
2.2本地仓库更换绑定的远程仓库应用... 10
2.3分支管理-创建于合并应用... 11
2.4分支管理-解决冲突应用... 14
2.4分支管理-bug分支应用... 15
附件... 16
一、基本使用应用
1 |
|
1.1创建版本库与本地初步使用应用
1. 首先,选择一个合适的地方,创建一个空目录
2. 第二步,通过git init命令把这个目录变成Git可以管理的仓库
1 |
git init |
a.Git就把仓库建好,这是一个空的仓库(empty Git repository),当前目录下多了一个.git的目录,这个目录是Git来跟踪管理版本库的,不要手动修改这个目录里面的文件,不然改乱了,就把Git仓库给破坏了。
b.如果没有看到.git目录,那是这个目录默认是隐藏的,用ls -ah命令就可以看见。
c. Git命令必须在Git仓库目录内执行(git init除外),在仓库目录外执行是没有意义的
3.第三步,用命令git add告诉Git,把文件添加到仓库:
1 |
git add . |
2 |
git add test.c // 添加单独文件 |
4.第四步,用命令git commit告诉Git,把文件提交到仓库
1 |
git commit -m “wrote a readme file” |
解释一下:
a.git commit命令,-m后面输入的是本次提交的说明,可以输入任意内容,当然最好是有意义的,这样你就能从历史记录里方便地找到改动记录
b. Git添加文件需要add,commit一共两步呢?因为commit可以一次提交很多文件,所以可以多次add不同的文件
5.小结
1 |
初始化一个Git仓库,使用git init命令。
添加文件到Git仓库,分两步: 使用命令git add <file>,注意,可反复多次使用,添加多个文件; 使用命令git commit -m <message>,完成。 |
1.2 Gitlab状态使用应用
1 |
git status命令可以让我们时刻掌握仓库当前的状态 |
2 |
git diff查看difference,显示的格式正是Unix通用的diff格式 |
1.3 版本退回使用应用
1 |
git log 查看历史记录 |
2 |
git log --pretty=oneline // log 单行显示 |
3 |
git reset --hard HEAD^ git reset --hard HEAD~1 |
|
首先,Git必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,也就是最新的提交1094adb...上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100。 |
4 |
cat readme.txt // 显示内容 |
5 |
git reset --hard 1094a(版本号) |
6 |
小结: HEAD指向的版本就是当前版本 因此,Git允许我们在版本之间穿梭,使用命令git reset --hard commit_id。 回退前,用git log可以查看提交历史,以便确定要回退到哪个版本。 要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本。 |
1.3 工作区与暂缓区应用
1 |
工作区(Working Directory) |
2 |
版本库(Repository)
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。 |
|
|
3 |
我们创建Git版本库时,Git自动为我们创建了唯一一个master分支,所以,现在,git commit就是往master分支上提交更改。
可以理解:需要提交的文件修改通放到暂存区,然后,一次性提交暂存区的所有修改。 |
1.4 管理与撤销修改应用
1 |
git add命令实际上就是把要提交的所有修改放到暂存区(Stage), 然后执行git commit就可以一次性把暂存区的所有修改提交到分支
每次修改,如果不用git add到暂存区,那就不会加入到commit中 |
2 |
Git跟踪并管理的是修改,而非文件 |
3 |
git checkout – file //可以丢弃工作区的修改: |
|
把file文件在工作区的修改全部撤销,这里有两种情况:
一种是file自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
一种是file已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
总之,就是让这个文件回到最近一次git commit或git add时的状态。
git checkout -- file命令中的--很重要,没有--,就变成了“切换到另一个分支”的命令 |
4 |
git reset HEAD <file>可以把暂存区的修改撤销掉(unstage),重新放回工作区 |
|
git reset命令既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用HEAD时,表示最新的版本 |
5 |
小结时:
场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file。
场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD <file>,就回到了场景1,第二步按场景1操作。
场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本回退一节,不过前提是没有推送到远程库 |
1.5 删除应用
1.克隆远程仓库到本地库
1 |
git clone http://10.0.3.24/chucheng.cao/gitlab_test |
2.对删除文件操作
1 |
git rm test.txt (删除文件) |
2 |
git rm test (删除文件夹) |
3.提交修改
1 |
git commit -m "Delete some files." |
4.修改提交远程仓库
1 |
git push origin master |
1.6 远程仓库应用
1 |
使用ssh-keygen生成免登录秘钥 1.打开bash shell
|
2 |
2.在bash中使用命令生成秘钥,引号内改成自己的邮箱地址 ssh-keygen –t rsa –C figo.qiu@vidar.ai
|
3 |
3.复制公钥到git服务器中 以记事本方式打开id_rsa.pub,这个文件在上一步ssh-keygen时有提示过 复制文本全部内容
|
4 |
|
5 |
登陆http://git.vidar.ai,将复制的公钥内容拷贝到框中,点击添加秘钥
|
6 |
6.配置TortoiseGit的用户信息
|
7 |
7.更改默认的ssh客户端
|
第一点:
把本地库的内容推送到远程,用git push命令,实际上是把当前分支master推送到远程
1 |
git push -u origin master |
2 |
git push origin master //只要本地作了提交,就可以通过命令 |
3 |
建议先用git remote -v查看远程库信息
|
由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。
如果有多个人协作开发,那么每个人各自从远程克隆一份就可以了。
你也许还注意到,GitHub给出的地址不止一个,还可以用https://github.com/michaelliao/gitskills.git这样的地址。实际上,Git支持多种协议,默认的git://使用ssh,但也可以使用https等其他协议。
使用https除了速度慢以外,还有个最大的麻烦是每次推送都必须输入口令,但是在某些只开放http端口的公司内部就无法使用ssh协议而只能用https。
小结:
要关联一个远程库,使用命令git remote add origin ;
关联一个远程库时必须给远程库指定一个名字,origin是默认习惯命名;
关联后,使用命令git push -u origin master第一次推送master分支的所有内容;
此后,每次本地提交后,只要有必要,就可以使用命令git push origin master推送最新修改;
分布式版本系统的最大好处之一是在本地工作完全不需要考虑远程库的存在。
要克隆一个仓库,首先必须知道仓库的地址,然后使用git clone命令克隆。
Git支持多种协议,包括https,但ssh协议速度最快。
二、场景应用
2.1删除远程仓库但不删除本地资源应用
1. 把xxx.iml加到`.gitignore`里面忽略掉,然后提交使.gitignore生效:
1 |
git rm –r – cached readme.md // -r是递归的意思 当最后面是文件夹的时候有用 |
2 |
git add readme.md //.gitignore 文件中已经忽略readme.md 可以不用执行此句 |
3 |
git commit –m “ignore readme.md” |
4 |
Git push |
2.2本地仓库更换绑定的远程仓库应用
方式一:通过命令直接修改远程地址
1 |
进入git_test根目录 |
2 |
git remote 查看所有远程仓库, git remote xxx 查看指定远程仓库地址 |
3 |
git remote set-url origin http://192.168.100.235:9797/john/git_test.git |
方式二:通过命令先删除再添加远程仓库
1 |
进入git_test根目录 |
2 |
git remote 查看所有远程仓库, git remote xxx 查看指定远程仓库地址 |
3 |
git remote rm origin |
4 |
git remote add origin http://192.168.100.235:9797/john/git_test.git |
方式三:直接修改配置文件
1 |
进入git_test/.git |
2 |
vim config |
3 |
修改 [remote “origin”]下面的url即可 |
方式四:通过第三方git客户端修改
1 |
以SourceTree为例,点击 仓库 -> 仓库配置 -> 远程仓库 即可管理此项目中配置的所有远程仓库, 而且这个界面最下方还可以点击编辑配置文件,同样可以完成方法三。 |
2.3分支管理-创建于合并应用
原理介绍:
0 |
每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。 只有一条时间线,在Git里,这个分支叫主分支,即master分支。HEAD严格来说不是指向提交,而是指向master,master才是指向提交的,所以,HEAD指向的就是当前分支。每次提交,master分支都会向前移动一步,这样,随着你不断提交,master分支的线也越来越长。
|
1 |
创建新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上 Git创建分支,除了增加一个dev指针,改变HEAD的指向,工作区的文件都没有任何变化!
|
2 |
对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变
|
3 |
我们在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最简单的方法,就是直接把master指向dev的当前提交,就完成了合并
Git合并分支,就改改指针,工作区内容也不变! |
4 |
合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支 |
5 |
切换回master分支后,再查看一个readme.txt文件,刚才添加的内容不见了!因为那个提交是在dev分支上,而master分支此刻的提交点并没有变:
|
第一点,创建分支
1 |
git checkout -b dev //加上-b参数表示创建并切换 |
2 |
git branch命令查看列出所有分支,当前分支前面会标一个*号。 |
3 |
git checkout master //dev分支的工作完成,我们就可以切换回master分支 |
4 |
git merge dev 把dev分支的工作成果合并到master分支上 |
|
git merge命令用于合并指定分支到当前分支。合并后,再查看readme.txt的内容,就可以看到,和dev分支的最新提交是完全一样的。
注意到上面的Fast-forward信息,Git告诉我们,这次合并是“快进模式”,也就是直接把master指向dev的当前提交,所以合并速度非常快。
当然,也不是每次合并都能Fast-forward,我们后面会讲其他方式的合并。 |
5 |
git branch -d dev //合并完成后,就可以放心地删除dev分支了 |
第二点,创建分支
1 |
我们注意到切换分支使用git checkout <branch>,而前面讲过的撤销修改则是git checkout -- <file>,同一个命令,有两种作用,确实有点令人迷惑。
实际上,切换分支这个动作,用switch更科学。因此,最新版本的Git提供了新的git switch命令来切换分支: |
2 |
git switch -c dev //创建并切换到新的dev分支,可以使用 |
3 |
git switch master //直接切换到已有的master分支 |
第三点,
1 |
Git鼓励大量使用分支:
查看分支:git branch
创建分支:git branch <name>
切换分支:git checkout <name>或者git switch <name>
创建+切换分支:git checkout -b <name>或者git switch -c <name>
合并某分支到当前分支:git merge <name>
删除分支:git branch -d <name> |
2.4分支管理-解决冲突应用
1 |
Git无法执行“快速合并”,只能试图把各自的修改合并起来,但这种合并就可能会有冲突
|
2 |
git merge feature1 |
3 |
git log --graph --pretty=oneline --abbrev-commit 看到分支的合并情况 |
4 |
git log –graph 命令可以看到分支合并图 |
通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息
1 |
git merge --no-ff -m "merge with no-ff" dev |
2 |
不使用Fast forward模式,merge后就像这样 |
分支策略:
在实际开发中,我们应该按照几个基本原则进行分支管理:
首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
其次,干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;
最后,每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。所以,团队合作的分支看起来就像这样:
合并分支时,加上--no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。
2.4分支管理-bug分支应用
每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。
1 |
当新接收bug任务时,很自然地,你想创建一个分支issue-101来修复它,但是当前正在dev上进行的工作还没有提交。并不是你不想提交,而是工作只进行到一半,还没法提交,预计完成还需1天时间。但是必须在两个小时内修复该bug,怎么办? Git还提供了一个stash功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作:
git stash |
2 |
git stash list命令看看:
Git把stash内容存在某个地方了,但是需要恢复一下,有两个办法: 一是用git stash apply恢复,但是恢复后,stash内容并不删除,你需要用git stash drop来删除; 另一种方式是用git stash pop,恢复的同时把stash内容也删了: |
3 |
修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;
当手头工作没有完成时,先把工作现场git stash一下,然后去修复bug,修复后,再git stash pop,回到工作现场;
在master分支上修复的bug,想要合并到当前dev分支,可以用git cherry-pick <commit>命令,把bug提交的修改“复制”到当前分支,避免重复劳动。 |
附件
1 |
初始化一个Git仓库,使用 |
2 |
添加文件到Git仓库,分两步:
|
3 |
git问题记录:fatal: pathspec ‘xxxx’ did not match any files
使用git pull 到本地后文件改了名字,git add 出现: fatal: pathspec ‘xxxxxx’ did not match any files 报错,导致无法git push
git add . 先把更新本地仓库 git add xxxx 再提交单个文件 git commit -m “xxxx” 添加注释 正常git push origin master 就可以了
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
git pull --rebase origin master git pull origin master
解决:远程与本地版本库不一致问题 |
20 |
我们用 git log --graph --pretty=oneline --abbrev-commit
准备合并 git merge --no-ff -m "merge with no-ff" dev
|