欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Git教程&Github教程

程序员文章站 2022-05-21 19:58:06
...

目录

前言

Git教程

Git安装(Windows环境)

理论基础

实战教程

初始化Git

查看当前状态

回到过去

版本对比

修改最后一次提交、删除文件和重命名文件

创建和切换分支

合并和删除分支

Github教程

创建仓库

分支

分支的含义

创建一个分支

提交修改

发起Pull request操作


前言

作为一个程序员!怎么能Github也不认识呢!没错,在写这篇博客前我对Github的了解就是一个Copy代码的仓库,根本没想过在里面搞一个自己的仓库,现在我来了,因为我再也不想用文件夹去做版本控制了,这不符合我一个极客的身份!!!

Git教程

Git安装(Windows环境)

下载地址:Git官方下载地址

> git config --global user.name "FishC_Service"
> git config --global user.email "aaa@qq.com"
#检查信息是否写入成功
git config --list #如果正常显示信息则成功

理论基础

保存机制:当版本中有文件发生变动,Git会将整个文件复制保存。

执行 git log --oneline --decorate --graph --all 命令:

三棵树的概念:工作区域(本机存放项目代码的地方),暂存区域(临时存放你的改动,保存即将提交的文件信息列表),Git仓库(安全存放数据,包含所有版本的数据,其中HEAD指向最新放入仓库的版本)

工作流程:在工作目录中添加修改文件---将需要进行版本管理的文件放入暂存区域---将暂存区域的文件提交Git仓库

Git教程&Github教程

实战教程

初始化Git

#初始状态在C盘中,更改路径
C:\Users\lenovo>F:
F:\>
F:\>cd MyProject
F:\MyProject>
#初始化Git项目,成功后创建有一个.git隐藏文件
F:\MyProject>git init
Initialized empty Git repository in F:/MyProject/.git/
#在文件夹MyProject中添加一个文本文件README,md格式指Markdown格式(建议使用Notepad++编辑)
#然后输入以下命令将文件加入暂存区
F:\MyProject>git add README.md
#将文件提交到git仓库(-m表示添加本次提交的说明,强制要求写的)
F:\MyProject>git commit -m "add a readme file"
[master (root-commit) 9e08cf4] add a readme file
 1 file changed, 1 insertion(+)
 create mode 100644 README.md

小贴士:如何将Github上别人的代码据为己有

F:\>Clone>git clone 目标

查看当前状态

On branch master: 我们位于一个叫做“master”的分支里,这是默认的分支
nothing to commit, working directory clean : 说明你的工作目录目前是“干净的”,没有需要提交的文件(意思就是自上次提交后,工作目录中的内容压根儿就没改动过)。

在工作目录中添加LICENSE文件,使用NotePad++添加MIT协议(意味着别人只要在软件包含上边的版权声明,就可以对你的程序为所欲为了(包括“使用、复制、修改、合并、出版发行、散布、再授权和/或贩售软件及软件的副本”)。)

Copyright (C) <year> <copyright holders>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

输入git status,提示如下:

F:\MyProject>git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)

        LICENSE(红色)

nothing added to commit but untracked files present (use "git add" to track)

Untracked表示存在未跟踪文件(红色标识),指的是新添加且未被添加至暂存区域的文件。圆括号是git给的建议。

使用 git add <file> 命令将待提交的文件添加到暂存区域。

F:\MyProject>git add LICENSE

F:\MyProject>git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        new file:   LICENSE(绿色)

use "git reset HEAD <file>..." to unstage 的意思是“如果你反悔了,你可以使用 git reset HEAD 命令恢复暂存区域”。如果后面接文件名,表示恢复该文件;如果不接文件名,则表示上一次添加的文件。

F:\MyProject>git reset HEAD

F:\MyProject>git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)

        LICENSE(红色)

nothing added to commit but untracked files present (use "git add" to track)

再次添加到暂存区域,然后执行 git commit -m "add a license file" 命令:

F:\MyProject>git add LICENSE

F:\MyProject>git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        new file:   LICENSE


F:\MyProject>git commit -m "add a license file"
[master 9fdf9f4] add a license file
 1 file changed, 7 insertions(+)
 create mode 100644 LICENSE

F:\MyProject>git status
On branch master
nothing to commit, working tree clean

修改文件

打开 LICENSE 文件,将 Copyright (C) <year> <copyright holders> 改为 Copyright (C) 2016 FishC,保存……

执行 git status 命令:

F:\MyProject>git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   LICENSE(红色)

no changes added to commit (use "git add" and/or "git commit -a")

由于你对工作目录的文件进行了修改,导致这个文件和暂存区域的对应文件不匹配了,所以 Git 又给你提出两条建议:

  1. 使用 git add 命令将工作目录的新版本覆盖暂存区域的旧版本,然后准备提交
  2. 使用 git checkout 命令将暂存区域的旧版本覆盖工作目录的新版本(危险操作:相当于丢弃工作目录的修改)

一种特殊情况,先对新版本进行提交,然后再次修改LICENSE文件内容

F:\MyProject>git add LICENSE

F:\MyProject>git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   LICENSE(绿色)
F:\MyProject>git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   LICENSE(绿色)

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   LICENSE(红色)

这次情况是:被绿的 LICENSE 说明文件存放在暂存区域(待提交),同时红色的 LICENSE 说明文件还在工作目录等待添加到暂存区域。

这种情况你应该意识到这里存在两个不同版本的 LICENSE 文件,这时如果你直接执行 commit 命令,那么提交的是暂存区域的版本(FishC),如果你希望提交工作目录的新版本(FishC.com),那么你需要先执行 add 命令覆盖暂存区域,然后再提交……

当然有一步到位的操作

F:\MyProject>git commit -am "change the license file"
# -a的意思就是add操作

小贴士:如何查看历史操作记录和仓库提交的版本

git log

回到过去

有关退回的命令有两个:reset和checkout

Git教程&Github教程

先执行git log命令,将此时Git仓库可视化

Git教程&Github教程

三棵树的可视化

Git教程&Github教程

回滚快照

注释:快照即提交的版本,每个版本就是一个快照

执行:git reset HEAD~

注释:HEAD 表示最新提交的快照,而 HEAD~ 表示 HEAD 的上一个快照,HEAD~~表示上上个快照,如果表示上10个快照,则可以用HEAD ~10

此时我们的快照回滚到了暂存区域,第一次执行reset命令后的仓库和三棵树可视化如下所示

Git教程&Github教程

Git教程&Github教程

git reset HEAD~ 命令其实是 git reset --mixed HEAD~ 的缩写, --mixed 选项是默认的。

  • 默认
  • git reset HEAD~ 命令其实影响了两棵树:首先是移动 HEAD 的指向,将其指向上一个快照(HEAD~);然后再将该位置的快照回滚到暂存区域。
  • --soft选项
  • git reset --soft HEAD~ 命令就相当于只移动 HEAD 的指向,但并不会将快照回滚到暂存区域。相当于撤消了上一次的提交(commit)。一不小心提交了,后悔了,那么你就执行 git reset --soft HEAD~ 命令即可(此时执行 git log 命令,也不会再看到已经撤消了的那个提交)。
  • --hard选项
  • reset 不仅移动 HEAD 的指向,将快照回滚动到暂存区域,它还将暂存区域的文件还原到工作目录。

回滚指定快照

reset 不仅可以回滚指定快照,还可以回滚个别文件。

命令格式为: git reset 快照 文件名/路径

这样,它就会将忽略移动 HEAD 的指向这一步(因为你只是回滚快照的部分内容,并不是整个快照,所以 HEAD 的指向不应该发生改变),直接将指定快照的指定文件回滚到暂存区域。

不仅可以往回滚,还可以往前滚!

这里需要强调的是:reset 不仅是一个“复古”的命令,它不仅可以回到过去,还可以去到“未来”。

唯一的一个前提条件是:你需要知道指定快照的 ID 号。

那如果不小心把命令窗口关了不记得ID号怎么办?

git reflog #Git记录的每一次操作的版本ID号

版本对比

准备工作:创建MyProject2新文件夹,初始化Git;创建game.py文件,写入内容;创建README.md文件,写入内容;执行 git add README.md game.py 命令将文件添加到暂存区域,接着执行 git commit -m "猜数字游戏" 提交项目的第一个快照;修改game.py和README文件内容;

比较暂存区域和工作目录

直接执行 git diff 命令是比较暂存区域与工作目录的文件内容:

这里可能出现一个问题,直接执行的结果出现中文乱码。在cmd界面的冒号:后面输入q退出,使用Notepad++打开README文件,点击编码→转为UTF-8编码。(旧版本中选择UTF-8(无BOM),新版中的UTF-8默认为无BOM)重新执行git diff发现还是不行!怎么肥四??在本菜查遍各网站论坛之后,终于找到了解决方法
执行以下三条命令(别问我明明是四条为啥说三条...)
git config --global i18n.commitencoding utf-8
git config --global i18n.logoutputencoding utf-8

export LESSCHARSET=utf-8 ## linux bash配置环境变量
set LESSCHARSET=utf-8 #windows配置环境变量
git diff

Git教程&Github教程

现在来解释一下上面每一行的含义:

  • 第一行:diff --git a/README.md b/README.md
  • 表示对比的是存放在暂存区域的 README.md 和工作目录的 README.md
  • 第二行:index 7966837..472a180 100644
  • 表示对应文件的 ID 分别是 7966837 和 472a180,左边暂存区域,后边当前目录。最后的 100644 是指定文件的类型和权限
  • 第三行:--- a/README.md
  • --- 表示该文件是旧文件(存放在暂存区域)
  • 第四行:+++ b/README.md
  • +++ 表示该文件是新文件(存放在工作区域)
  • 第五行:@@ -1 +1,2 @@
  • 以 @@ 开头和结束,中间的“-”表示旧文件,“+”表示新文件,后边的数字表示“开始行号,显示行数”
  • 第六、七行:

Git教程&Github教程

  • 这是将两个文件合并显示的结果,前边有个 + 的绿色的那一行说明是新文件独有的,浅灰色的则是两个文件所共有的内容。所以,+1,2 表示新文件在合并显示中从第 1 行开始,显示 2 行。那为啥 -1 后边没有显示的行数?因为在合并显示的结果中,旧文件已经完全包含在新文件中了(也就是旧文件没有自己“独有的”内容)。
  • 第八行:\ No newline at end of file
  • 这是 Git 出于善意的提醒:文件不是以换行符结束。为什么会有这样多此一举的提醒呢?仔细推敲下你就会明白了:diff 将两个文件合并打印,到达最后一个字符的时候,无论文件中是否存在换行符,diff 都需要打印一个换行符!为啥?为了好看呗!!所以如果你的文件最后一个字符不是以换行符结尾,但 diff 又自行添加了一个换行符,所以它觉得有义务提醒你它这么做了!

最后的(:)是什么?
意思是窗口太小,没办法显示全部,正在等待命令(Vim编程知识)

移动命令
j、k:向下移动一行/向上移动一行
f、b:向下翻页/向上翻页
d、u:向下翻半页/向上翻半页
跳转命令
g、G:跳转到第一行/跳转到最后一行
先输入数字(如3),再输入g,表示跳转到该行(如第3行)
搜索命令
输入斜杠(/)或问号(?),后面接搜索关键字
区别:斜杠(/)表示从当前位置向下搜索,问号(?)表示从当前位置向上搜索。
接着输入 n 表示顺着当前的搜索方向快速跳转到下个匹配的位置,大写的 N 则是与当前搜索方向相反。
退出和帮助
在点点(:)后边输入 q,表示退出 diff;输入 h 表示进入帮助界面,你会看到很多命令和功能,输入 q 可以退出帮助界面。

比较历史快照

我们执行 git commit -am "添加功能:玩家只有三次机会" 命令,添加并提交工作目录中的所有文件。执行 git log 命令,可以看到现在 Git 仓库中已经有两个快照了:

Git教程&Github教程

执行 git diff 6e26975 ed3708c 命令,即可比较 Git 仓库中两个快照的差异:

Git教程&Github教程

比较当前工作目录和Git仓库中的快照

准备工作:稍微改动README.md内容,可视化Git仓库及三棵树

Git教程&Github教程

Git教程&Github教程

比较之前版本的快照与当前工作目录内容
输入 git diff ed3708c 命令即可

比较当前版本快照与当前工作目录内容
输入 git diff HEAD 命令即可

比较Git仓库与暂存区域

准备工作:执行 git add README.md 命令,将第三版的 README.md 文件添加到暂存区域。可视化三棵树

Git教程&Github教程

比较最新提交的快照和暂存区域的文件,只需要执行 git diff --cached 命令;当然也可以指定其他快照,就是需要多写上一个 ID 值,即git diff --cached ID号。

小总结

Git教程&Github教程

修改最后一次提交、删除文件和重命名文件

Situation One:版本刚一提交(commit)到仓库,突然想起漏掉两个文件还没有添加(add)
Situation Two:版本刚一提交(commit)到仓库,突然想起版本说明写得不够全面,无法彰显你本次修改的重大意义……

由于使用reset命令过于繁琐,需要提交一个新的版本,这里可以使用带 --amend 选项的 commit 命令,(即git commit --amend)Git 会“更正”最近的一次提交。由于这里没有-m说明,会进入以下页面:

Git教程&Github教程

这个界面其实只是让你编辑提交说明而已。如果不需要修改,可以连续按下两个大写Z来退出,或者按下(:)再输入q!退出,Git会保留旧的提交说明。如果需要提交说明又不想用这么繁琐的方式,输入git commit --ammend -m “新的提交说明” 即可。

删除文件

问题1:不小心删除工作目录中的文件怎么办?先查看状态

Git教程&Github教程

提醒使用 checkout 命令可以将暂存区域的文件恢复到工作目录。

Git教程&Github教程

问题2:如何彻底删除文件(假设你下载了一个图片到工作目录,又提交到了仓库)

Git教程&Github教程

执行 git rm 图片名,此时工作目录中的图片被删除,但Git status中依旧存在记录

Git教程&Github教程

意思是说它在仓库的快照中发现有个叫 yellow 的东西,但似乎在暂存区域和当前目录不见了!此时可以执行 git reset --soft HEAD~ 命令将快照回滚到上一个位置,然后重新提交,就可以了。

Git教程&Github教程

注意:rm 命令删除的只是工作目录和暂存区域的文件(即取消跟踪,在下次提交时不纳入版本管理)

问题3:我在工作目录中增加一个 test.py 文件,然后执行 git add test.py 命令将其添加到暂存区域,此时我修改 test.py 文件的内容,那么暂存区域和工作目录就是两个不同的 test.py 文件了,此时如果我执行 git rm test.py 命令,Git 会下意识地阻止我,这是怎么办?

Git教程&Github教程

 

因为两个不同内容的同名文件,谁知道你是不是搞清楚了都要删掉?还是提醒一下好,别等一下出错了又要赖机器……
根据提示,执行 git rm -f test.py 命令就可以把两个都删除。

问题4:我只想删除暂存区域的文件,保留工作目录的,应该怎么操作?

执行 git rm --cached 文件名 命令。

重命名文件:git ren 旧文件名 新文件名

小贴士:如何让Git 识别某些格式的文件,然后自主不跟踪它们?

比如工作目录中有三个文件1.temp、2.temp 和 3.temp,我们不希望后缀名为 temp 的文件被追踪,可是每次执行git status都会出现:

Git教程&Github教程

解决办法:在工作目录创建一个名为 .gitignore 的文件。windows需要在命令行窗口创建(.)开头的文件。执行 echo *.temp > .gitignore 命令,创建一个 .gitignore 文件,并让 Git 忽略所有 .temp 后缀的文件(gitignore文件夹也可以忽略):Git教程&Github教程

创建和切换分支

来到之前创建的MyProject2,对应的仓库和三棵树如下

Git教程&Github教程Git教程&Github教程

执行git status发现README.md还没有提交,对应三棵树如下

Git教程&Github教程

创建分支:git branch feature

注释:查看分支状况,如果希望以“精简版”的方式显示,可以加上一个 --oneline 选项(即 git log --decorate --oneline),这样就只用一行来显示一个快照记录。

Git教程&Github教程

可以看到最新的快照后边多了一个 (HEAD -> master, feature),它的意思是:目前有两个分支,一个是主分支(master),一个是刚才我们创建的新分支(feature),然后 HEAD 指针仍然指向默认的 master 分支。

Git教程&Github教程

切换分支 git checkout feature

Git教程&Github教程

现在我们进行一次提交,暂存区(上文)还有一个README文件没有提交

Git教程&Github教程Git教程&Github教程

切换HEAD指针回master分支 git checkout master,会发现上一次修改已经没有了

Git教程&Github教程

现在对 README.md 文件进行修改(随便改改),然后执行 git commit -m "再次修改说明文件":

Git教程&Github教程

Git教程&Github教程

执行 git log --oneline --decorate --graph --all 命令(--graph 选项表示让 Git 绘制分支图,--all 表示显示所有分支)

Git教程&Github教程

合并和删除分支

合并分支:git merge feature,将 feature 分支合并到 HEAD 所在的分支(master)上,但并不成功,因为合并README文件有冲突

Git教程&Github教程

然后 Git 会在有冲突的文件中加入一些标记,不信你打开 README.md 文件看看:

Git教程&Github教程

以“=======”为界,上到“<<<<<<< HEAD”的内容表示当前分支,下到“>>>>>>> feature”表示待合并的 feature 分支,之间的内容就是冲突的地方。现在我们将 README.md 统一修改(去掉 <<<<<<< HEAD 等内容)
保存文件,然后提交快照:

Git教程&Github教程

执行git log --decorate --all --graph --oneline 命令,可以看到此时的分支已经自动合并了:

Git教程&Github教程

当然,不存在矛盾的话就无需修改,执行 git checkout -b feature2 命令(相当于 git branch feature2 和 git checkout feature2 两个命令的合体),在工作目录中随便创建一个feature2.txt文件并提交快照(可以看到,feature2 分支比 master 分支快了一步。现在我们切换回 master 分支,并将 feature2 分支合并进来:)

Git教程&Github教程

Git教程&Github教程

Git教程&Github教程

删除分支:git branch -d feature

Git教程&Github教程

Git教程&Github教程

注释:注意:如果试图删除未合并的分支,Git 会提示你“该分支未完全合并,如果你确定要删除,请使用 git branch -D 分支名 命令。

小贴士

cheakout命令功能:从快照或暂存区域中拷贝文件到工作目录;切换分支

比如执行 git checkout HEAD~ README.md 命令会将上一个快照中的 README.md 文件复制到工作目录和暂存区域中:

Git教程&Github教程

如果命令中没有指定具体的快照 ID,则将从暂存区域恢复指定文件到工作目录(git checkout README.md):

Git教程&Github教程

 

checkout和reset的区别(reset老老实实做撤销,checkout老老实实做切换分支,不要互相搞混!!!)

恢复文件:它们的区别是 reset 命令只将指定文件恢复到暂存区域(--mixed),而 checkout 命令是同时覆盖暂存区域和工作目录。

恢复快照:reset 命令是用来“回到过去”的,根据选项的不同,reset 命令将移动 HEAD 指针(--soft) -> 覆盖暂存区域(--mixed,默认)-> 覆盖工作目录(--hard)。

对于 reset --hard 命令来说,checkout 命令更安全。因为 checkout 命令在切换分支前会先检查一下当前的工作状态,如果不是“clean”的话,Git 不会允许你这样做;而 reset --hard 命令则是直接覆盖所有数据。另一个区别是如何更新 HEAD 指向,reset 命令会移动 HEAD 所在分支的指向,而 checkout 命令只会移动 HEAD 自身来指向另一个分支。例如(图1为原始状态):

Git教程&Github教程

Git教程&Github教程

Git教程&Github教程


Github教程

创建仓库

仓库是用来组织项目的,可以存放项目所需要的任何内容。我们推荐你在项目中包含一个 README 文件,或者建立一个可以查看项目信息的文件。在 GitHub 上,一旦你创建一个新的仓库,就可以很容易地创建一个 README 文件和 license 文件(用于声明版权)。

Git教程&Github教程

Git教程&Github教程

分支

分支的含义

Git教程&Github教程

创建一个分支

Git教程&Github教程

提交修改

针对readme-edit分支中的文件进行修改,这些修改只影响了 readme-edits 分支的 README 文件,而 master 的 README 文件并没有被改变,所以现在两个分支的内容已经不同了。

Git教程&Github教程

发起Pull request操作

现在你拥有一个非 master 分支的修改,你可以发起一个 pull request。
Pull Requests 是 GitHub 实现合作的核心。当你发起一个 pull request 的时候,表示你希望别人将你修改的内容进行审查然后合并到他们的分支中去。
Pull Requests 会显示每个分支的不同之处,添加(绿色)和删减(红色)的地方都会显示出来。
只要执行一次提交,就可以开启一个 pull request 和讨论,不需要你将所有的代码都完成。
通过使用 GitHub 的 @ 通知系统,你可以获得指定小伙伴或团队(无论他们身在何处)对 pull requset 的反馈消息。
你也可以在自己的仓库中开启 pull requests 并将它们合并进来。这是你在进行大项目开发前先熟悉 GitHub 流程的好方法。
Git教程&Github教程

比较对象和查看内容

Git教程&Github教程

合并修改(给你的合并操作加一些说明)

Git教程&Github教程

Git教程&Github教程

Git教程&Github教程

Git教程&Github教程