一文读懂之什么是Git
进一步了解git,请参考Git官网 https://git-scm.com/
一、 git的概念
1. 概念
git是一个最主流的版本控制系统。
2. 与传统版本控制系统的区别
git和svn的区别:
(1)subversion是集中式,git是分布式,类似于银行与使用区块链技术的虚拟货币的区别。精华在于在本地也有历史版本(历史版本作用:(1) 回溯之前的提交记录 (2) 回滚)。
(2)而且按照日常开发习惯,需要频繁commit代码,防止误删等错误操作无法恢复。svn的commit必须连网,而gi可以离线工作t。
(3)传统版本控制系统,存储每个文件与初始版本的差异 (它们通常称作 基于差异(delta-based) 的版本控制;而git使用的一系列快照的形式。在分支管理时性能优异。
(4)其他。
二、 基本配置
1. git config
参数:
不加参数 仅对当前项目生效。修改项目的git config文件(也就是工作目录中的 .git\config 文件)。
--global 只对当前用户生效。修改用户目录下的配置文件,如C:\Users\用户\.gitconfig 。
--system 对系统中所有用户生效。修改git安装路径\etc\gitconfig 文件。
注意:相同的配置情况下,以上上面一层的配置会覆盖下面一层的配置。
示例:
(1) 配置个人信息
git config --global user.name "your name"
git config --global user.email "email address""
(2) 查看全部配置
git config --list
可能会出现多个同名变量,是因为来自于以上3个不同的配置文件,以最后一个为准。
(3) 查询指定配置
git config user.name
整体流程图。
其中,暂存区(stage/index),其实是一个文件,Git 的术语叫做“索引”。HEAD是一个游标,指向当前分支。
三、 本地操作
A. 工作区 <-> 暂存区 的操作
1. 提交到暂存区
git add .
添加当前目录下的所有文件到暂存区。
git add <file>...
指定工作区的文件提交到暂存区(stage/index)。文件开始被git跟踪。此操作同时会在object下新建一个对象,更新或添加的文件被记录到这个对象中,对象ID记录到暂存区的文件索引中。
git add <dir>
指定工作区的文件夹提交到暂存区,包含所有dir下的子目录和文件。
2. 撤回提交到暂存区的内容(撤销add)
(1) git reset HEAD <file>...
将指定文件从暂存区去除,工作区不变
(2) git restore --stage <file>...
将指定文件从暂存区去除,工作区不变。同reset HEAD作用一样
3. 查看在工作区和暂存区的文件状态
git status [-s]
"Untracked files" 下面的文件代表未放入暂存区,未被跟踪
"Changes to be committed" 下面的文件代表放入暂存区,但未提交到本地仓库
"Changes not staged for commit" 代表已被跟踪文件有修改,但未放入暂存区
参数:
-s --short的简写。代表查看简要信息。
示例:
$ git status -s
M README 已修改
MM Rakefile 暂存后又修改
A lib/git.rb 新添加到暂存区
M lib/simplegit.rb 已修改已暂存
?? LICENSE.txt 未跟踪
4. 查看文件在工作区、暂存区、仓库区的详细差异
git diff
详细展示文件更改的内容
git diff
当文件在工作区有改动,
文件不在暂存区,查看文件在工作区与版本库的差异;
文件在暂存区,查看文件在工作区与暂存区的差异
git diff --cached 或者 git diff --staged
查看文件在暂存区与版本库的差异
git diff HEAD -- <filename>
查看文件在工作区和版本库的差异
diff:git diff --stat
显示摘要而非所有内容
5. 删除工作区或暂存区的文件
git rm <file>
删除工作区或暂存区的文件。
参数:
--cached 将文件从暂存区删除
-f 将文件从工作区和暂存区删除
删除文件最普通操作:
本地删除文件 -> git add -> git commit
使用git rm:
本地删除文件 -> git --cached rm-> git commit 或者 git -f rm -> git commit
也可以用正则,如(星号前必须加“\”):
git rm log/\*.log 删除 log/ 目录下扩展名为“.log”的所有文件
git rm \*~ 删除所有名字以“~”结尾的文件
B. 暂存区 <-> 版本库 的操作
1. 暂存区提交到仓库区
git commit -m [message]
参数:
-m message指定提交的备注信息。
实例:
(1) git commit -m [message]
提交所有文件到仓库区
(2) git commit <file>... -m [message]
提交指定文件到仓库区
(3) git commit -a <file>... -m [message]
-a 文件commit之前自动add
注意:尽量不要使用,容易误提交不需要的文件。
(4) git commit --amend
修改commit注释。会进入默认编辑器,修改注释完毕后保存。
2. 撤销提交到仓库区的内容(撤销commit)
git reset [--soft | --mixed | --hard] [HEAD]
用于重置暂存区的文件与上一次的提交(commit)保持一致,工作区文件内容保持不变。原理是HEAD指针的移动,所以非常快速,且可以切回来切过去。
参数:
--mixed 为默认值。仓库区回退到指定版本,暂存区的内容先放到工作区,然后暂存区与仓库区保存一致。仓库区前后版本的差异也会放入工作区。
--soft 保留工作区的内容,且让之前已提交的内容回到暂存区。
--hard 撤销工作区中所有未提交的修改内容,将工作区和暂存区都回到指定的之前版本,并删除之前的所有信息提交。及其危险!
注意:谨慎使用 –hard 参数,它会删除回退点之前的所有工作区和暂存区的信息。
HEAD:
HEAD 或 HEAD~0 表示当前版本
HEAD^ 或 HEAD~1 上一个版本
HEAD^^ 或 HEAD^2 上上一个版本
以此类推...
实例:
$ git reset HEAD^ # 回退所有内容到上一个版本
$ git reset HEAD^ hello.php # 回退 hello.php 文件的版本到上一个版本
$ git reset 052e # 回退到指定版本(版本号前面一部分就可以) 此命令可以在回退后,再次切换到回退之前的版本。提交版本好可以通过git reflog查看
详情参考:https://www.jianshu.com/p/c2ec5f06cf1a
3. 放弃工作区的改动
git checkout . 或者 git checkout -- <file>
用暂存区全部或指定的文件替换工作区的文件。这个操作很危险,会清除工作区中未添加到暂存区的改动。
4. 放弃工作区和暂存区的改动
git checkout HEAD . 或者 git checkout HEAD <file>
用 HEAD 指向的分支中的全部或者部分文件替换暂存区和以及工作区中的文件。这个命令也是极具危险性的,因为不但会清除工作区中未提交的改动,也会清除暂存区中未提交的改动。
5. 查看历史提交记录
git log
显示历史提交记录(默认根据时间倒叙)。
参数:
-p 显示每个提交引入的差异,按补丁格式。
--stat 显示每次提交的文件修改统计信息。
--graph 在日志旁以 ASCII 图形显示分支与合并历史。
--pretty 使用其他格式显示历史提交信息。可用的选项包括 oneline(将每次的提交信息放一行,不包括详细修改的信息)、short、full、fuller 和 format(用来定义自己的格式)。
--oneline --pretty=oneline --abbrev-commit 合用的简写。
-n 显示最近n次的提交
常用示例:
git log -p -2 显示提交文件的改动点,只显示最近2次提交
6. 查看命令历史
git reflog
可以用来查看版本号
四、 远程操作
1. 远程获取项目到本地
git clone [url] [directory]
从远程git上copy项目到指定的本地文件夹。如不指定directory,则以url最后一个“\”后面的单词作为项目目录。
2. 查看远程仓库的信息
git remote [-v]
-v:查看远程仓库详细信息。(fatch)代表拉取权限,(push)代表推送权限。
git remote show [URL]
显示某个远程仓库的信息
3. 获取远程仓库的更新
git fetch origin
4. 指定分支合并到当前分支
git merge
将服务器上的任何更新(假设有人这时候推送到服务器了)合并到当前分支。
5. 获取远程仓库更新并合并
git pull <远程主机名> <远程分支名>:<本地分支名>
从远程获取代码并合并本地的版本。此命令就是 git fetch 和 git merge 的合并操作。
实例:
(1) git pull origin master:mybranch
将远程主机 origin(仓库服务器的默认名称) 的 master 分支拉取过来,与本地的 mybranch 分支合并。
如果远程分支是与当前分支合并,则可简写为
git pull 默认拉取origin上的master分支,与本地的当前所在分支合并
或者
git pull origin
git pull origin master
6. 推送本地仓库内容到远程仓库
git push <远程主机名> <本地分支名>:<远程分支名>
实例:
(1) git push origin master:master
将本地master分支的内容推送到名称为origin的远程仓库服务器上,并与远程的master分支合并
因为当前所在的本地分支名与远程分支名相同,且默认仓库服务器名称为origin,可以简写为
git push
或者
git push origin master
(2) git push --force origin master
本地版本与远程版本有差异又要强制推送,可以使用 --force 参数,会用本地仓库代码覆盖远程仓库代码。慎用!
(3) git push origin --delete master
删除主机上的分支。
7. 整理提交
git rebase
把本地多次提交合并,整理成直线,且提前处理冲突。目的是使得我们在查看历史提交的变化时更容易。
实例:
(1) git rebase -i origin/master
整理当前分支上的提交为一个提交
(2) git rebase -i HEAD~2
整理前两个提交为一个提交
五、 分支管理
常见开发分支管理
1. 创建分支
git branch <branchname>
2. 列出分支
git branch
3. 切换分支
git checkout [-b] <branchname>
切换到已有分支branchname。
参数:
-b:创建分支,并切换到新创建的分支下
4. 合并指定分支到当前所在分支
git merge <branchname>
5. 删除分支
git branch [-d] <branchname>
参数:
-d: 删除分支
-D:强行删除未合并的分支
其他操作:
6. 工作现场暂存
git stash
将当前工作现场暂存起来
git stash list
查看暂存列表
git stash apply
恢复暂存内容
git stash drop
删除暂存内容
git stash pop
恢复暂存内容到当前分支,并删除暂存区内容
六、 冲突
冲突形成原因:
1. 本地有修改,同时远程代码也有修改,拉取代码时出现冲突
2. 多人修改同一个分支,然后merge
3. 多人修改不同分支的同一个问题,然后merge
冲突解决:
修改文件,再次add,commit
七、 常见问题及可能的解决方案
1.
问题描述:
回滚到上一次提交时,Windows终端输入git reset --hard HEAD^,显示“more?”,多按几次回车后,报错如下,该如何解决
fatal: ambiguous argument 'HEAD ': unknown revision or path not in the working tree. Use '--' to separate paths from revisions, like this: 'git <command> [<revision>...] -- [<file>...]'
原因分析:
Windows终端换行符默认是^,所以“more?”的意思是问下一行是否需要再输入,而^ 符号就被当做换行符而被git命令忽略掉了。
解决方案:
1) 加引号:git reset --hard "HEAD^"
2) 加一个^:git reset --hard HEAD^^
3) 换成~:git reset --hard HEAD~ 或者 git reset --hard HEAD~1
~ 后面的数字表示回退几次提交,默认是一次
另外,git bash,powershell等不会出现此问题