引言
- 本文为git小白的学习记录。将工作中遇到的git相关问题和常见用法逐步记录。以下为初次接触git遇到的问题:
- 如何在远程仓库中找到自己需要的分支(每一项目会有master版本、release版本、develop版本等等)
- 本地建仓是什么意思,如何在本地仓库中建立不同的分支以及如何在不同的分支上工作
- 自己开发代码后提交的流程
- 小白阅读建议:git的这堆名词对小白真的很不友好,和代码很难有个形象的对应(但是理解结构之后会觉得真香)。所以初学git的小白,不要太注重于乱七八糟的命令和名词,第一章留个印象有哪些类型的命令就行,核心是第二章的结构和对应的命令,看完第二章再拿第一章作为字典去动手实操一下就可以有个大概的理解了。
Reference
- 视频:----->理解结构原理和使用方法
- 文档:----->查指令的手册
一、Git的常用指令(完整版见码云的Git大全)
-
配置基本用户信息:在拉代码之前需要配置当前本地机器的git账户信息(Note:公司使用SSH而不是HTTPS来拉代码,所以本地的git用户信息和远端仓库生成的git指令中的用户信息必须是同一用户,才能够成功下载)
- 查询git账号信息:git config -l
- 配置基本用户信息:分别配置用户名(自定义)和邮箱
- git config --global user.name your_name
- git config --global user.email your_email
-
创建本地仓库:创建本地仓库有两种方法:①创建一个全新的空仓库、②git clone从远端仓库克隆一个仓库到本地(NOTE:怎么看仓库有没有建立成功?—>当前路径的文件夹中有个.git文件就代表这个文件夹是一个本地仓库了)
- 创建一个全新的本地仓库:git init [filename(即仓库名)] / mkdir [filename] && cd [filename] && git init
- 从远端仓库克隆一个仓库到本地:git clone [url]
-
提交流:
- 工作区–>暂存区:
- 将指定目录添加到暂存区:git add [filename] [filename] …
- 将指定目录(包括其子目录)添加到暂存区:git add [dir]
- 将当前目录的所有文件添加到暂存区:git add .
- 将同一文件n个更改的可选择添加(添加每个更改的时候都让你确认):git add -p
- 暂存区–>本地仓库:
- 将暂存区的所有文件提交到仓库:git commit -m [message]
- 将暂存区的指定文件提交到仓库:git commit [file1] [file2] … [message]
- 将工作区自上次commit后的所有更改提交到仓库:git commit -a
- 本地仓库–>远端仓库:
- 将本地仓库的指定分支提交到远端仓库的指定分支(需要同名):git push <远程主机名> <本地分支名>:<远程分支名>
- 工作区–>暂存区:
-
拉取流:
- 远端仓库–>本地仓库:
- 将远端仓库拉取到本地仓库(本地原本没有仓库,完整的拉过来):git clone [url]
- 远端仓库–>工作区:
- 将远端仓库的指定分支拉到本地和本地仓库的指定分支合并(本地原本有仓库):git pull <远程主机名> <远程分支名>:<本地分支名>
- 本地仓库–>暂存区&&工作区:
- 将HEAD指向的本地仓库master分支中的全部文件替换暂存区和工作区中的文件(会清除工作区和暂存区未提交的改动):git checkout HEAD .
- 将HEAD指向的本地仓库master分支中的指定文件替换暂存区和工作区中的文件(会清除工作区和暂存区未提交的改动):git checkout HEAD [filename]
- 远端仓库–>本地仓库:
-
撤销流(用于将暂存区/工作区回退到之前某一次commit的版本,这个commit由HEAD指针决定):
- 将缓存区回退到上一个版本(用master分支指向的目录树重写暂存区的目录树,不影响工作区):git reset HEAD
- 将缓存区中的某个文件回退到上一个版本:git reset HEAD [filename]
- 将缓存区和工作区都回到上一个版本(–hard 参数撤销工作区中所有未提交的修改内容,将暂存区与工作区都回到上一次版本,并删除之前的所有信息提交):git reset --hard HEAD
-
分支:
- 列出本地仓库所有分支:git branch
- 列出远端仓库所有分支:git branch -r
- 列出所有本地仓库分支和远端仓库分支:git branch -a
- 新建一个分支:git branch [filename] / git checkout -b [fiename]
- 切换到指定分支:git checkout [filename]
- 合并指定分支到当前分支:git merge [filename]
- 删除工作区分支:git branch -d [filename]
-
查看信息:
- 显示所有的远程仓库:git remote -v
- 查看本地有变更的文件:git status
- 显示当前分支的历史版本:git log
- 显示暂存区和工作区的差异:git diff
- 显示暂存区和工作区上一个commit的差异:git diff --cached [file]
- 显示工作区和当前分支最新commit的差异:git diff HEAD
二、 Git工作原理---->每个指令是让代码从哪到哪的
- Git的结构如下图所示:
- Git在本地可以分为三个工作区:
- 工作目录 <-----> Working Directory
- 暂存区 <-----> Stage(index)
- 资源库(本地仓库)(本地仓库,内容和远端仓库相同,分布式系统) <-----> History
- Git在远端可以分为一个工作区:
- 远端仓库 <-----> Remote Directory
- 在这个过程中的6个指令(这里只放个最通用的指令,详细指令见文末引文)
- 写完代码的提交过程:
- git add <文件名>:将变化的文件(你今天新写的代码)从工作区提交到暂存区。------>作用:告诉git,哪些代码是即将要commit到仓库区的。
- git commit -m “提交文件的简介”:将暂存区中的变化提交到本地仓库中的分支版本。
- git push <远程主机名> <本地分支名>:<远程分支名>:将本地仓库的分支版本上传到远程仓库的对应分支版本合并(eg.将本地master合并进远端master分支),即用自己写完的已经更新到本地仓库中新代码去更新远端仓库中的旧版本代码。
- 拉代码或提交过程中回滚的过程:
- git pull <远程主机名> <远程分支名>:<本地分支名>:拉取远端仓库的指定分支(就像你改论文一样会有很多版本一样,不同的分支就是存放项目不同的版本),合并进本地的指定分支,即用远端仓库中的新代码来更新本地仓库的旧版本代码。
- git checkout HEAD .:将本地仓库上一次的commit版本来重写暂存区和工作区
- git reset HEAD:将缓存区切换到本地仓库的上一次commit版本
- 写完代码的提交过程:
- Git在本地可以分为三个工作区:
如果你是git小白,看完第二章你可能模模糊糊地知道了大概的git流程是什么,但是对每个区是什么,每个分支是什么肯定觉得很抽象,接下来在第三章就用一个例子说明白git的四个区域和本地分支到底是什么样的。
三、实践:拉一个仓库下来并切换分支,看看文件结构的变化。
- cd到你存放工程文件的路径(每个工程(远端仓库)就是一个文件夹,该路径就是存这些工程文件的文件夹)
- git clone [url] 将远端仓库拷贝下来(这里有两种情况,具体什么区别暂不研究,会用就行)。一种就是github那种git clone之后工程文件就在了,另一种就是目前我工作遇到的这种,git clone后是一个只有.git文件的远端仓库同名文件夹,我们以这种来研究第二章图中git的工作流。
- 此时你可以切到.git文件夹中看看有哪些文件,需要注意其中的index和HEAD文件。其中index是指向缓存区的指针,HEAD是指向本地仓库的指针。这里有个重要的概念:在git的4个区中,我们可以看见的只有工作区和远端仓库。工作区就是git clone后自动创建的这个空文件夹,远端仓库就是Github上你能看到的整个工程。那你可能会问git clone下来的代码去哪了?代码其实是在电脑里的,存在了HEAD指向的一块内存中,我们看不见而已,这块内存就是本地仓库。缓存区同理。
- 此时已经git clone,本地仓库已经有了完整的项目工程,而工作区只有.git文件,我们应该如何把代码从本地仓库拉到工作区呢?别急,先git branch看看此时工作区有哪些分支,你会看到*master,即主分支,这是自动创建的,但我们一般不会在主分支上开发,因为这是稳定版,开发一般是在develop分支上,所以此时我们需要做的就是从本地仓库中把develop分支拉到工作区。我们再du -sh查看一下该文件夹的大小,应该就是.git文件的大小(记住这个大小与后续其他分支比较)。
- 我们可以在工作区使用git checkout develop命令将develop分支拉到工作区,此时你ll查看该文件夹就可以发现已经有完整的代码工程了。此时你再git branch一下,可以发现工作区有两个分支branch和*develop。NOTE:*在谁前面,就说明当前我们在哪个分支!这边会有点抽象,我们明明一直在同一个文件夹里,为什么切了个分支文件结构就不同了?你可以把不同的分支想象成上一层一个隐藏的路径即develop/project或者master/project,这样就好理解了。此时你再du -sh看一下文件大小,就可以很明显的看出大小的变化。到这里你应该能理解本地分支的意思了。
- 最后,切到不同的分支,我们就可以在上面进行开发、代码修改然后提交到相应的分支。