版本控制Git
Git学习资源
•At the command line: (where verb = config, add, commit, etc.)
§$ git help
§$ git help <verb>
•Git website: http://git-scm.com/
•廖雪峰Git教程:https://www.liaoxuefeng.com/wiki/896043488029600
•通俗易懂Git入门系列:https://www.zsythink.net/archives/tag/git/
•git-flow 的工作流程:https://www.git-tower.com/learn/git/ebook/cn/command-line/advanced-topics/git-flow
•Git从小白到高手:https://www.educoder.net/paths/41
•Git在线学习:https://learngitbranching.js.org/?locale=zh_CN&NODEMO=
什么是版本控制
•版本控制是一种记录文件内容变化,以便将来查阅特定版本修改情况的系统。 版本控制其实最重要的是可以记录文件修改历史,从而让用户能够查看历史版本,方便版本切换。
•没有版本控制工具,想要随时恢复到以前内容,只能每次修改前手动备份文件,且需要人工粗略记录每次修改了哪些内容。
•通过版本控制工具,能自动保留文件所有的修改记录,能自动备份文件所有的过程状态,在需要时,可以将文件恢复到之前的某个状态,可以对比两个状态之间的差别。
§C -> C1 -> C2 -> … Cm -> … -> Cn
§Cm <- Cn
§Cm Diff Cn
Git的特点
•设置用户名和邮箱,在Git Bash下输入命令:
§$ git config --global user.name ”xxx"
§$ git config --global user.email ”xxx”
§$ git config --global --list
•git conifg --global 用于修改用户主目录下的.gitconfig配置文件
Git常用命令及概念原理
1.git init 初始化仓库
在用户主目录下创建gitTest目录,在目录中打开Git Bash
输入命令git init ,将当前目录初始化为一个git本地仓库(repository / repo)
gitTest目录中多出的隐藏目录.git(版本库),通过.git目录中的数据(包括各类git对象)对gitTest目录中的文件和目录内容进行版本管理
2.git status 查看仓库状态
§在gitTest目录新建文件file1
§在bash中输入命令 git status
§on branch master: 当前处在master分支(branch)
§No commits yet:还没有提交(commit)
Untracked files:未跟踪(Untracked)的文件
3.git add 把要提交的变更加入到暂存区
§跟踪新文件:未跟踪文件 -> 已跟踪文件
§暂存已跟踪且提交后修改(Modified)的文件
§底层做了两件事:创建新内容文件对应的git对象,更新索引文件.git/index (暂存区)
4.git commit -m “xxx” 创建提交
§将所有加入暂存区的变更作为一个变更集合,创建提交。
§-m “XXX” 提交时必须添加说明,记录做了哪些变更
§每个commit都有一个唯一的哈希吗对应,可以把一个commit看成是项目的一个副本(snapshot) / 版本(Version)。而缓存区中存放的总是预期的下一次提交的快照。
§在整个项目的开发过程中,会创建很多commit,这就相当于在开发过程中记录了多个版本,可以回退到过去的任何一个版本
5.git log / gitk 查看提交记录
§在目录中新建文件file2,并修改file1的内容。
§git add . && git commit && git log --oneline
6.分支
§每一次提交都是基于上一次提交的基础上的,每个Commit都有其Parent。C1 <- C2 <- … <- Cn,这样的若干的提交就组成了一条开发的“逻辑线”,可以把这条逻辑线理解成一条所谓的“分支”(Branch)。
§默认情况下,git仓库会为我们创建一条名为master的分支,我们创建的所有提交默认都会在master分支上。
从本质上看,一个Branch实际上是一个指向某个Commit的指针
7.git branch创建分支
§git branch b1:创建b1分支,底层做的事情:创建一个指向当前提交对象的一个指针b1。
§-d : 删除分支,git branch -d b1
§-a : 查看所有分支
8.git checkout (分支名称):切换分支
§当前分支:某一时刻,Git仓库总处于某一个分支下,即为当前分支,会有一个特殊的指针HEAD,指向当前分支。
§git checkout b1:切换到b1分支,HEAD指针会指向b1分支,工作空间中的内容会恢复成b1分支最后一次提交时的样子。
§git checkout -b b2:如果分支b2不存在,则创建分支b2,然后再切换到分支b2。
9.头指针HEAD
§在b2分支下,修改file2的内容,并提交。查看HEAD和b2的内容。可以看到,通常情况下,HEAD指针总是通过当前分支指针,从而间接的指向了当前分支的最新提交。
§git checkout commitID:可以让HEAD直接指向某个Commit,此时工作空间的内容也会恢复成该Commit对应的快照。此时称为“分离头”(detached Head)状态
10.git merge 分支名称: 合并分支
§通常是在要开发一个新的功能模块时,或者是修复一个原有Bug时会创建对应的分支。当某个分支上的任务完成后,会将该分支中所有的更改“合并”(merge)到主分支上。
§git merge b1:将b1分支上更改的内容合并到当前分支。
§在b1中修改file1后提交,然后将b1分支合并到master分支。
git merge 命令选项
§每次执行git merge命令时,git都会先去尝试能不能使用”Fast-forward”的模式进行合并,如果能,就默认使用”Fast-forward”的模式进行合并,如果不能,就创建一个合并提交进行合并。
§git merge --no-ff:指定不使用快进模式进行合并
§git merge --ff-only:指定只有能使用快进模式时才合并
§git merge --no-edit:在创建合并提交之前不会调用编辑器,采用默认注释“Merge branch ‘BranchName’ ”
§git merge --no-commit:合并后不自动提交,可以将内容进行进一步修改后。
§注意:如果git默认编辑器是vim,可以在合并时弹出的编辑器界面输入 “:wq”,保存退出合并提交的界面。
11.git reset 版本回退 :
第一步移动 HEAD(--soft)
§仓库中有一个file.txt文件,先后经过了3次修改提交
§现使用命令 git reset --soft HEAD~ | HEAD^ 回退一次
§结论:只移动分支和HEAD指针,工作区和暂存区的内容不变。即回滚到了上一次commit之前的状态。
第二步更新索引(--mixed)
§仓库中有一个file.txt文件,先后经过了3次修改提交
§现使用命令 git reset HEAD~ | HEAD^ 回退一次
§结论:移动分支和HEAD指针,取消上次暂存的内容,工作区内容不变。即回滚到了上一次commit和add之前的状态。
第三步更新工作区(--hard)
§仓库中有一个file.txt文件,先后经过了3次修改提交
§现使用命令 git reset --hard HEAD~ | HEAD^ 回退一次
§结论:移动分支和HEAD指针,取消上次暂存的内容,使工作区和暂存区内容一致。即回滚到了上上一次commit之后的状态
总结:
§修改file1的内容提交
§使用git reset --hard HEAD^ 回退一次提交
§回退后,查看file1的内容,和commit记录。
§如果此时恢复上次提交的话, 要用 git reflog命令查看上次提交的ID,然后用 git reset --hard commitID,回到“未来”的版本。
12.git clone 克隆远程仓库
§cd ~:切换到用户主目录
§克隆远程仓库 git clone 远程仓库地址
§cd 代码目录
§git clone 默认会建立与远程仓库(默认名origin)的关联,并把远程仓库中所有的内容都复制到本地仓库,并建立本地仓库和远程仓库的关联,会创建本地仓库分支master,并与远程仓库分支master的进行关联(Trace)。
§git remote -v :查看远程仓库信息
§master:本地仓库分支;remotes/origin/master:本地仓库远程分支;origin/master:远程仓库分支
§初始时,这三个Branch指向同一个Commit
13.git push 推送更新
§本地仓库创建文件file1并提交。
本地仓库分支和本地远程仓库分支 指向的是不同的Commit
§推送本地master分支后,本地仓库工作区和版本库的内容推送到了远程仓库,三个分支指向同一个Commit。
§本地仓库创建新的分支feature1
§git push --set-upstream origin feature1:feature1
§将本地仓库的feature1分支推送到远程仓库,远程仓库中也会创建对应的feature1分支,同时本地仓库的feature1分支会和远程仓库的feature1分支建立关联。
14.git fetch 拉取更新
§在本地仓库test1的feature1分支中更新推送。
在本地仓库test2中通过git fetch拉取远程仓库中最新的内容(上次fetch后,推送到远程仓库的所有更新),但只会将数据下载到你的本地仓库,不会自动合并到对应的本地分支(本地仓库分支未修改),不会修改本地仓库的工作区、暂存区。
§git fetch命令只是把远程仓库的数据拉取到本地仓库,并不会更新本地仓库对应的分支,如果需要更新本地仓库分支,需用要git merge命令合并对应的远程仓库。
§feature 功能分支:当要开一个新的功能时,使用命令:git-flow feature start 功能名称。git-flow会基于develop分支checkout一个新的功能分支。
§feature 功能分支:当新功能开发完毕后,使用命令:git-flow feature finish 功能名称。git-flow会将该功能分支merge到develop分支,然后再删除该功能分支。
§hotfix 修复分支:当发现系统有bug需要修复时,使用命令:git-flow hotfix start Bug名称。git-flow会基于master分支checkout一个新的修复分支。§当bug修复完成后,使用命令:git-flow hotfix finish Bug名称。git-flow会将该修复分支合并到 “master” 中,同样也会合并到 “develop” 分支中。