git基础:

获取git项目仓库

通常有两种方式获取git项目仓库:
1.将尚未进行版本控制的本地目录转换为git仓库
2.从其他服务器上克隆一个已有的git仓库

在已存在目录中初始化仓库

  1. 进入项目目录:
  1. $ cd /Users/user/my_project
  1. 执行初始化:
  1. $ git init

执行完毕后将会在项目目录中创建.git文件夹,这里包含初始化的仓库中所有必须文件,然后对已经存在对目录进行版本控制,需要开始追踪这些文件,并进行初始提交,用git add来指定需要追踪的文件,然后执行git commit。

克隆现有仓库

执行git clone命令,将把远程git仓库中的所有内容全部拉去下来,如果需要在克隆远程仓库的时候自定义本地仓库的名字,可以在命令后面加一个参数,如:

  1. $ git clone https://github.com/libgit2/libgit2 caizichen

记录每次更新到仓库

在你本地的git仓库中,所有文件都处于已跟踪或者未跟踪这两种状态。已跟踪文件是指已经被纳入版本控制的文件,他们可能是已经修改,未修改或放入暂存区的。初次克隆仓库之后,所有的文件都是已跟踪的状态。除了已跟踪的文件,其他的文件都是未跟踪状态,使用git status可以查看文件处于什么状态,未跟踪的文件将会出现在Untracked files中。

跟踪新文件

使用git add来跟踪新文件。如使README文件被跟踪,则执行:

  1. $ git add README

此时执行git status命令,会发现README文件的状态变成了Changes to be committed状态,即暂存状态。

暂存已修改文件

当你修改了一个已经被追踪的文件后,该文件会出现在Changes not staged for commit状态下,说明该文件已经发生变化,现在要暂存这次更新,需要使用git add命令,在git add后如果你又修改了该文件,那么执行git status会发现该文件同时处于Changes not staged for commit和Changes to be committed状态中,其中Changes to be committed里是你执行git add时的版本,而Changes not staged for commit中保存着最新的修改,需要重新运行git add来把最新版本暂存起来。

状态简览

git status显示的内容虽然详细,但是有些过于繁琐,如果执行git status -s或者git status —short则会得到一种更加紧凑的输出:

  1. $ git status -s
  2. M README
  3. MM Rakefile
  4. A lib/git.rb
  5. M lib/simplegit.rb
  6. ?? LICENSE.txt
  1. 其中,README文件是已经修改但未暂存,Rakefile是已经暂存,但之后又进行了修改,A标记代表新添加到暂存区但内容,lib/simplegit.rb 文件已修改且已暂存,??代表未追踪的文件。

忽略文件

一般我们希望有些文件不需要纳入git的管理,也不希望他出现在未追踪表列。这种情况下,我们可以创建一个.gitignore 的文件,列出要忽略的文件的模式。 如:

  1. $ cat .gitignore
  2. *.[oa]
  3. *~
  1. 第一行告诉 Git 忽略所有以 .o .a 结尾的文件,第二行告诉 Git 忽略所有名字以波浪符(~)结尾的文件。

文件 .gitignore 的格式规范如下:

  • 所有空行或者以 # 开头的行都会被 Git 忽略。
  • 可以使用标准的 glob 模式匹配,它会递归地应用在整个工作区中。
  • 匹配模式可以以(/)开头防止递归。
  • 匹配模式可以以(/)结尾指定目录。
  • 要忽略指定模式以外的文件或目录,可以在模式前加上叹号(!)取反。

所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。

  • 星号(*)匹配零个或多个任意字符;
  • [abc] 匹配任何一个列在方括号中的字符 (这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c);
  • 问号(?)只匹配一个任意字符;
  • 如果在方括号中使用短划线分隔两个字符, 表示所有在这两个字符范围内的都可以匹配(比如 [0-9] 表示匹配所有 0 到 9 的数字)。
  • 使用两个星号(**)表示匹配任意中间目录,比如 a/**/z 可以匹配 a/za/b/za/b/c/z 等。

例如:

  1. # 忽略所有的 .a 文件
  2. *.a
  3. # 跟踪所有的 lib.a,即便你在前面忽略了 .a 文件
  4. !lib.a
  5. # 只忽略当前目录下的 TODO 文件,而不忽略 subdir/TODO
  6. /TODO
  7. # 忽略任何目录下名为 build 的文件夹
  8. build/
  9. # 忽略 doc/notes.txt,但不忽略 doc/server/arch.txt
  10. doc/*.txt
  11. # 忽略 doc/ 目录及其所有子目录下的 .pdf 文件
  12. doc/**/*.pdf

提交更新

使用git commit将会提交所有在暂存区的内容,你可以在git commit后加入-m选项,将提交的信息和命令放在同一行,如果你认为使用暂存区过于繁琐,可以使用git commit -a来跳过使用暂存区,这样git会将所有跟踪过的文件暂存起来一并提交。

查看提交历史

如果你想查看某个项目的提交历史,可以使用git log命令,不穿入任何参数的情况下,git log会按照时间顺序列出所有的提交,最近的更新在最上面。
git log -p或git log —patch会显示每次提交所引入的差异,可以增加参数来限制日志条目的数量,如git log -p -2则会显示最近两次的提交。
如果你想看到每次提交的简略信息,则可以使用git log —stat选项,它会列出所有被修改的文件,已经增加和减少的行。

撤销操作

如果在提交之后,发现有些文件没有提交,或者提交信息写错了,可以使用

  1. $ git commit --amend

这个操作会看到上次的提交信息,并在上面进行编辑修改,保存后,则上次的提交信息会变成修改后的提交信息(这个操作会修改原来的commit id)

取消暂存的文件

如果想要将已经暂存的文件取消掉,可以使用git reset HEAD 命令,他将会把file移出暂存区。

撤销对文件对修改

如果想要撤销对文件对修改,可以使用git checkout — 命令,这样即可撤销这次对文件对修改。
上面对两个命令都可以通过git status来看到。

远程仓库使用

查看远程仓库

如果要查看当前目录下的远程仓库服务器,可以运行git remote命令。这个命令会列出指定的每一个远程仓库的名字。如果你是clone的仓库,应该会看到一个origin(git给克隆的仓库的默认名字)。

添加远程仓库

除了git clone命令会自动添加远程仓库之外,还可以运行git remote add <shortname> <url> 添加一个新的远程 Git 仓库,同时指定一个方便使用的简写,如:
$ git remote add demo http://git.koolearn-inc.com/caizichen/demo.git

从远程仓库中进行拉取

从远程仓库中获得数据,可以执行

  1. $ git fetch <remote>
  1. 这个命令会将远程仓库中你还没有的数据拉去下来。执行完毕后,你会拥有那个远程仓库中所有分支的引用,可以随时查看或者合并。git fetch只会将数据下载到你的本地仓库,但是并不会进行合并,你必须手动将其合并。

如果当前的分支设置了跟踪远程分支,那么可以用git pull命令来自动抓取并合并该远程分支到当前分支,默认情况下git clone会自动设置本地的master分支跟踪克隆的远程仓库的master分支(或者其他名字的默认分支)。运行git pull一般会从最初的克隆服务器上抓取数据并尝试合并到当前分支。

推送到远程仓库

当需要分享项目的时候,使用git push ,如果你要将master分支推送到origin服务器上,则输入git push origin master即可,需要注意的有,只有当你所克隆的服务器的写入权限,并且之前没有人推送过的情况下,这条命令才会生效。换句话说,如果你和其他人同时进行推送,他的推送先到而你的后到,那么你的推送就会被拒绝,你必须先拉取他们的工作并进行合并后才可以进行推送。

远程仓库的重命名和删除

运行git remote rename来修改一个远程仓库的简写名,例如要将origin改名为demo,则执行:git remote rename origin demo。
如果要移除一个远程仓库,则可以使用git remote rm或者git remote remove

打标签

要查看当前仓库的标签可以使用git tag命令,在一个你的新仓库中是没有标签的,需要创建标签,而git中的标签分为轻量标签和附注标签两种,在git中创建附注标签可以使用tag命令时指定-a选项,如:git tag -a v1.0 -m “version 1.0”,-m指定了一条将会储存在标签中的信息,可以通过git show命令来查看;如果要创建轻量标签,则直接输入git tag 即可,这时候使用git show是没有额外的标签信息的。

后期打标签

如果在提交之后想要补上标签,需要在命令的末尾加上校验和,如:git tag -a v1.2 9fceb02
这样就会在9fceb02那次提交上加上标签。

共享标签

默认情况下,git push不会将标签上传到远程仓库,假如需要将标签上传到远程origin仓库中,则需要执行git push origin ,如果要一次性推送很多标签,那么可以执行git push origin —tags,这将会把所有不在远程仓库到标签全部推送到远程仓库中去。

删除标签

要删除掉本地仓库中到标签,可以使用git tag -d ,这个命令不会对远程仓库作任何改动,需要同步改动还需要用git push :refs/tags/或者git push origin —delete

git别名

如果认为git对某些命令过于繁琐,则可以通过git config给他设置一个别名,例如:

  1. $ git config --global alias.co checkout
  2. $ git config --global alias.br branch
  3. $ git config --global alias.ci commit
  4. $ git config --global alias.st status

这样当你需要使用git checkout命令的时候,只需要输入git co就可以完成,下面的也是同理,这在某些时候可以节省很多时间。

git分支

新建分支

通常使用git checkout -b 来新建分支并且切换到该分支上去,这个命令等同于git branch ,git checkout 的简写。

合并分支

举个例子说明,假如当前你所选择当分支是master,而现在你想要把fix分支合回到master分支中去。可以使用git merge fix命令来达到上述目的。
此时如果已经不再需要fix分支,可以使用git branch -d fix命令来删除fix分支。
在某些情况下,如果master分支和fix分支对某个部分都做了修改,那么在merge的时候就会产生冲突,我们需要查看冲突的地方(在vs code中会有明显的标示),并且将冲突解决才可以进行合并操作。

分支管理

git branch除了创建和删除之外,在不加任何参数的情况下运行,可以查看当前项目所有的分支,当前HEAD所指向的分支在列表前面会有*标示。
如果要查看每一个分支的最后一次提交,可以运行git branch -v命令。
—merged和—no-merged这两个参数可以过滤这个列表中已经合并或者还未合并到当前分支的分支。

变基

假设某个项目的开发任务有两个不同的分支experiment和master,并且这两个分支都各自提交了更新。
Git学习随记 - 图1
这时候我们想要将分支整合进去,使用merge命令的话,git会将两个分支最新的提交(c3,c4)与两个分支最近的祖先分支c2进行三方合并,合并完毕之后形成一个新的提交c5,如图:Git学习随记 - 图2
另一种方式是通过变基来实现分支的整合,执行的命令如下:

  1. $ git checkout experiment
  2. $ git rebase master
  3. First, rewinding head to replay your work on top of it...
  4. Applying: added staged command

这个操作的原理是先找到两者最近的祖先分支c2,然后将之后的提交与c2对比,并存储下来,然后将当前分支指向目标基底c3,最后按照之前存储的修改去修改c3,然后回到master执行快进合并:

  1. $ git checkout master
  2. $ git merge experiment

**![](https://cdn.nlark.com/yuque/0/2020/png/2704205/1602761471538-3ff66b38-a925-4e5c-8bad-269bcc33cd04.png#align=left&display=inline&height=230&margin=%5Bobject%20Object%5D&originHeight=230&originWidth=800&size=0&status=done&style=none&width=800)**
此时的c4‘与之前使用merge合并得到的c5完全一样。这两种整合方法的结果没有任何区别,但是过程历史显得更加简洁。

变基的风险

变基操作的实质是丢弃一些现有的提交,然后相应地新建一些内容一样但实际上不同的提交。 如果你已经将提交推送至某个仓库,而其他人也已经从该仓库拉取提交并进行了后续工作,此时,如果你用 git rebase 命令重新整理了提交并再次推送,你的同伴因此将不得不再次将他们手头的工作与你的提交进行整合。

回滚

某些情况下,当你把提交已经push到远程仓库之后,发现提交到内容有问题,需要进行回滚操作,有两种方式:

  • 通过git reset直接删除到之前到那次commit

git log # 得到你需要回退到到那一次提交的commit id
git reset —hard
git push origin HEAD —force # 强制提交一次,之前错误的提交就从远程仓库删除

  • 通过git revert是用一次新的commit来撤销之前的某次commit

git log # 得到你需要回退的那一次提交的commit id
git revert # 撤销指定的版本,撤销也会作为一次提交进行保存