Git 基础
获取 Git 仓库
链接: http://git-scm.com/book/zh/v2/Git-基础-获取-Git-仓库
通常有两种获取 Git 项目仓库的方式:
- 将尚未进行版本控制的本地目录转换为 Git 仓库;
- 从其它服务器 克隆 一个已存在的 Git 仓库。
两种方式都会在你的本地机器上得到一个工作就绪的 Git 仓库。
- 将尚未进行版本控制的本地目录转换为 Git 仓库
进入该目录,运行
git init
命令。该命令将创建一个名为.git
的子目录,这个子目录含有你初始化的 Git 仓库中所有的必须文件,这些文件是 Git 仓库的骨干。
- 使用
git add file_name
告诉 Git ,把文件添加到仓库。【可以多次使用】- 使用
git commit -m "illumination for file"
,告诉 Git 把文件提交到仓库。克隆现有的仓库
克隆仓库的命令是
git clone <url>
。 比如,要克隆 Git 的链接库libgit2
,可以用下面的命令:$ git clone https://github.com/libgit2/libgit2
这会在当前目录下创建一个名为 “libgit2” 的目录,并在这个目录下初始化一个
.git
文件夹, 从远程仓库拉取下所有数据放入.git
文件夹,然后从中读取最新版本的文件的拷贝。 如果你进入到这个新建的libgit2
文件夹,你会发现所有的项目文件已经在里面了,准备就绪等待后续的开发和使用。如果你想在克隆远程仓库的时候,自定义本地仓库的名字,你可以通过额外的参数指定新的目录名:
$ git clone https://github.com/libgit2/libgit2 mylibgit
这会执行与上一条命令相同的操作,但目标目录名变为了
mylibgit
。所有版本控制系统只能跟踪文本文件(如 txt文件 、网页)而不能跟踪二进制文件(如图片、视频)内容的变化,对于文本文件编码的选择推荐使用 utf-8 。【windows系统要避免使用自带的记事本编辑文本文件】
记录每次更新到仓库
工作区和暂存区
工作区: 即电脑里面能看到的目录。
工作区有一个隐藏目录
.git
,这个不算工作区,而是Git的版本库。Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master
,以及指向master
的一个指针叫HEAD
。
git add
命令实际上就是把要提交的所有修改放到暂存区(Stage),然后,执行git commit
就可以一次性把暂存区的所有修改提交到分支。工作目录下的每一个文件不外乎两种状态:已跟踪或未跟踪;已跟踪的文件是指那些被纳入了版本控制的文件,在上一次快照中有它们的记录,在工作一段时间后, 它们的状态可能是未修改,已修改或已放入暂存区。
跟踪新文件
使用命令
git add
开始跟踪一个文件;git add
命令使用文件或目录的路径作为参数;如果参数是目录的路径,该命令将递归地跟踪该目录下的所有文件。假设现在新创建了一个文件a,运行
git status
:可以看出文件处在
Untrackedd files
下面,意味着该文件处于未跟踪状态即:Git 在之前的快照(提交)中没有这些文件;Git 不会自动将之纳入跟踪范围,除非你明明白白地告诉它“我需要跟踪该文件”。跟踪该文件,运行
git add a
只要在
Changes to be committed
这行下面的,就说明是已暂存状态。 如果此时提交,那么该文件在你运行git add
时的版本将被留存在后续的历史记录中。暂存已修改文件
使用
git add
命令来暂存已更新文件。这是个多功能命令:可以用它开始跟踪新文件,或者把已跟踪的文件放到暂存区,还能用于合并时把有冲突的文件标记为已解决状态等。 将这个命令理解为“精确地将内容添加到下一次提交中”而不是“将一个文件添加到项目中”要更加合适。
假设现在对前面创建的文件 a 的内容做出了修改,运行
git status
:文件
a
出现在Changes not staged for commit
这行下面,说明已跟踪文件的内容发生了变化,但还没有放到暂存区。 要暂存这次更新,需要运行git add
命令。查看状态
使用
git status
查看状态,可以使用git status -s
命令得到一个格式紧凑的输出。输出左侧有两列,第一列指明了暂存区的状态,第二列指明了工作区的状态。新添加的未跟踪文件前面有
??
标记,新添加到暂存区中的文件前面有A
标记,修改过的文件前面有M
标记。$ git status -s M README MM Rakefile A lib/git.rb M lib/simplegit.rb ?? LICENSE.txt
例如,上面的状态报告显示:
README
文件在工作区已修改但尚未暂存,而lib/simplegit.rb
文件已修改且已暂存。Rakefile
文件已修,暂存后又作了修改,因此该文件的修改中既有已暂存的部分,又有未暂存的部分。忽略文件
我们可以创建一个名为
.gitignore
的文件,列出要忽略的文件的模式。不需要从头写.gitignore文件,GitHub已经为我们准备了各种配置文件,只需要组合一下就可以使用了。所有配置文件可以直接在线浏览:https://github.com/github/gitignore
注意事项:
- 配置文件的完整文件名就是".gitignore",注意最前面有个“.”;
- 配置文件是按行从上到下进行规则匹配的,如果前面的规则匹配的范围更大,则后面的规则将不会生效;
- 该文件只能作用于
Untracked Files
,也就是那些从来没有被 Git 记录过的文件(自添加以后,从未 add 及 commit 过的文件);- 如果文件曾经被 Git 记录过,那么
.gitignore
就对它们完全无效;# 注释 build #忽视所有build文件夹,或文件名是build的文件 build/ #忽略所有build文件夹 /a/ #仅忽视/下的a文件夹,如:/t/a就不会被忽略【/指的是.gitignore所在的目录】 # *匹配零个或多个字符 *t #忽视所有文件(夹)名最后一个字符是t的文件(夹) # ?匹配单个字符; # []匹配括号内的任一字符; # !表示不忽略(跟踪)匹配到的文件或目录;
参考:
https://www.liaoxuefeng.com/wiki/896043488029600/900004590234208
查看已经暂存和未暂存的修改
git diff --staged <file>
:对比已暂存文件与最后一次提交的文件差异。
git diff <file>
:
- 如果暂存区存在该文件的未提交版本则对比工作区和暂存区的指定文件差异。
- 如果暂存区不存在该文件的未提交版本则对比工作区文件和提交历史版本的指定文件差异
对比暂存区和指定 commit-id 之间的差异
git diff --staged [<commit-id>] [<path>...]
对比两个 commit-id 之间的差异
git diff [<commit-id>] [commit-id]
对比工作区和指定 commit-id 的差异
git diff commit-id [<path>...]
提交更新
命令:
git commit
运行
git commit
命令会启动所配置的文本编辑器来输入提交说明;另外,你也可以在commit
命令后添加-m
选项,将提交信息与命令放在同一行。跳过使用暂存区域
Git 提供了一个跳过使用暂存区域的方式, 只要在提交的时候,给
git commit
加上-a
选项,Git 就会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过git add
步骤。移除文件
想把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录中。 换句话说,你想让文件保留在磁盘,但是并不想让 Git 继续跟踪。
使用命令
git rm --cached <file>
,然后提交更新。从仓库和当前目录中移除文件。
- 如果暂存区没有该文件:使用命令
git rm <file>
,然后提交更新。- 如果暂存区有该文件:必须使用强制删除选项
-f
(译注:即 force 的首字母)。 这是一种安全特性,用于防止误删尚未添加到快照的数据,这样的数据不能被 Git 恢复。移动文件
1
查看提交记录
命令:
git log
常用选项:
git log -x
: 只显示最新 x 条日志
git log --pretty=oneline
git log --graph
git log --stat
: 显示每次提交的文件修改统计信息
撤销操作
修改提交上次提交的描述信息:
git commit --amend -m 'xxx'
如:
如果上次提交忘记暂存某些要提交的文件
git commit -m 'xxxx'
git add <要补充的文件>
git commit --amend
可以看出提交后发现
second.txt
并未添加到暂存区,如不想再加一条提交记录可以按山后面方式操作。cobr@cobr-pc MINGW64 ~/Desktop/211 (master) $ git add second.txt cobr@cobr-pc MINGW64 ~/Desktop/211 (master) $ git commit --amend [master 1c199a3] modify first.txt and create second.txt Date: Wed Jan 19 19:46:17 2022 +0800 2 files changed, 1 insertion(+) create mode 100644 second.txt cobr@cobr-pc MINGW64 ~/Desktop/211 (master) $ git status On branch master nothing to commit, working tree clean cobr@cobr-pc MINGW64 ~/Desktop/211 (master) $ git log --pretty=oneline 1c199a3e0c37d280fec58a2980ce2492852d5eb5 (HEAD -> master) modify first.txt and create second.txt b27d54e880ad810c2bbc4c09f6bb04697188ed37 create and modify first.txt
撤销对文件的修改
丢弃暂存区的文件
git restore --staged <file>
:丢弃暂存区中指定文件,不会对工作区文件做出修改将工作区文件恢复与最近一次
commit
add
中的文件一致
git restore <file>
将工作区文件恢复成与指定 commit-id 一致。
git restore -s commid-id <file>
远程仓库的使用【超简介版,有些应该错了】
克隆现有的远程仓库
git clone
命令假设我们从零开发,那么最好的方式是先创建远程库,然后,从远程库克隆。
- 在 GitHub 上创建一个新仓库
- 下一步是用命令
git clone
克隆一个本地库:git clone git@github.com:co-br/testForGit.git
备注: 实际上,Git支持多种协议,默认的
git://
使用ssh,但也可以使用https
等其他协议。使用https
除了速度慢以外,还有个最大的麻烦是每次推送都必须输入口令。
要使用
ssh
方式先配置ssh
密钥
git clone git@github.com:co-br/test.git local
: 把项目放到本地的local文件夹内查看远程仓库:进入项目文件夹内运行
git remote -v
命令会显示需要读写远程仓库使用的 Git 保存的简写与其对应的 URL。下面表示,当前只有一台远程主机,叫做origin,以及它的网址。
git clone -o remote git@github.com:co-br/test.git
: 给远程服务器简写命名,如果没加-o
参数 ,git默认远程服务器的简写是 origin 。
git fetch
的使用
- 将某个远程主机点的全部分支取回本地:
git fetch <远程主机名>
- 取回特定分支的更新:
git fetch <远程主机名> <分支名>
所取回的更新,在本地主机上要用 "远程主机名/分支名" 的形式读取。比如
origin
主机的master
,就要用origin/master
读取。要特别注意的一点是当抓取到新的远程跟踪分支时,本地不会自动生成一份可编辑的副本(拷贝); 换一句话说,这种情况下,不会有一个新的origin/master
分支——只有一个不可以修改的origin/master
指针。
- 可以通过
git merge origin/master
命令将远程分支合并到当前分支。- 可以在
fetch
之后通过git switch -c <本地分支名> <远程分支[如:origin/master]>
创建一个跟踪分支。- 可以直接在
fetch
时创建一个合并该远程分支的本地分支(未设置跟踪关系):git fetch <remote> <远程分支名如:master>:<新建的本地分支名>
。
git pull
的使用作用: 取回远程主机某个分支的更新,再与本地的指定分支合并;等价于
git fetch
+git merge
格式:
git pull <远程主机名> <远程分支名>:<本地分支名>
- 如果远程分支是与当前分支合并则可省略本地分支名
- 如果当前分支是一个跟踪分支则可省略:
<远程分支名>:<本地分支名>
git push
的使用作用:将本地分支的更新,推送到远程主机
格式:
$ git push <远程主机名> <本地分支名>:<远程分支名>
- 如果省略远程分支名,则表示将本地分支推送与之存在"追踪关系"的远程分支(通常两者同名),如果该远程分支不存在,则会被新建。
- 如果省略本地分支名,则表示删除指定的远程分支,如:
git push origin :master
==git push origin --delete master
其他
- 添加远程主机(要先
git init
) :git remote add <主机名> <网址>
如:git remote add origin git@gitee.com:cobr/DALTestCode.git
- 删除远程主机:
git remote rm <主机名>
- 远程主机改名:
git remote rename <原主机名> <新主机名>
Git 分支
HEAD
严格来说不是指向提交,而是指向master
,master
才是指向提交的,所以,HEAD
指向的就是当前分支。概念辨析
- 远程分支(remote branch):远程仓库的本地分支
- 跟踪分支(tracking branch):本地分支,比如master分支,用户可写(跟踪分支是与远程分支有直接关系的本地分支;它跟踪的分支叫做“上游分支”。如果在一个跟踪分支上输入
git pull
,Git 能自动地识别去哪个服务器上抓取、合并到哪个分支。)- 远程跟踪分支(remote tracking branch):远程跟踪分支是本地仓库对远程仓库中的某个远程分支的状态的记录,它们以
“(远程仓库名)/(分支名)”
形式命名, 用户只读。
git branch
常用方法:
- 查看本地分支:
git branch
,分支名前面有*
号的代表当前正处于哪个分支。- 查看本地分支+上次提交的信息:
git branch -v
- 查看本地分支+上次提交的信息+本地和远程分支的跟踪关系:
git branch -vv
- 查看所有本地分支和远程分支:
git branch -a
- 只查看远程分支:
git branch -f
- 删除本地分支:
git branch -d branchName
- 创建本地分支:
git branch <name>
- 设置/修改本地分支的上游分支:
git branch --set-upstream-to=origin/remoteBranchName localBranchName
- 撤销当前本地分支的跟踪关系:
git branch --unset-upstream
其他
切换分支:
git switch <name>
创建+切换分支:
git switch -c <name>
合并某分支到当前分支:
git merge <name>
遇到冲突时的分支合并
有时运行
git merge <name>
命令后可能会发生冲突,这时Git会暂停下来等待解决合并产生的冲突,可以再合并冲突产生后使用git status
命令查看那些因包含合并冲突而处于未合并(unmerged)状态的文件。任何因包含合并冲突而有待解决的文件,都会以未合并状态标识出来。 Git 会在有冲突的文件中加入标准的冲突解决标记,这样你可以打开这些包含冲突的文件然后手动解决冲突。 出现冲突的文件会包含一些特殊区段,看起来像下面这个样子:
cobr@cobr-pc MINGW64 ~/Desktop/211 (dev|MERGING) $ cat second.txt <<<<<<< HEAD ======= first modify second modify third >>>>>>> master
Git用
<<<<<<<
,=======
,>>>>>>>
标记出不同分支的内容【如当前分支 second.txt 文件内容为空,master 分支 second.txt文件内容为上述三行】,我们修改如下后保存:first modify second modify third
上述的冲突解决方案仅保留了其中一个分支的修改,并且
<<<<<<<
,=======
, 和>>>>>>>
这些行被完全删除了。 在你解决了所有文件里的冲突之后,对每个文件使用git add
命令来将其标记为冲突已解决。 一旦暂存这些原本有冲突的文件,Git 就会将它们标记为冲突已解决,然后使用git commit
命令完成合并 。