Git教程学习

Git学习笔记

Git的安装

Linux

sudo apt-get install git

Ubuntu

apt-get install git -y

windows

网址安装

Git 工作流程

Git 的一般工作流程如下:

  • 克隆 Git 资源作为工作目录。
  • 在克隆的资源上添加或修改文件。
  • 如果其他人修改了,你可以更新资源。
  • 在提交前查看修改。
  • 提交修改。
  • 在修改完成后,如果发现错误,可以撤回提交并再次修改并提交。

下图展示了 Git 的工作流程:

img

工作区、暂存区和版本库

  • 工作区:就是你在电脑里能看到的目录。
  • 暂存区:英文叫 stage, 或 index。一般存放在 “.git目录下” 下的 index 文件(.git/index)中,所以我们把暂存区有时也叫作索引(index)。
  • 版本库:工作区有一个隐藏目录 .git,这个不算工作区,而是 Git 的版本库。

如下图所示:

img

Git 向仓库中添加文件流程, 如下图所示:

img

Git的使用

创建版本库

用 git init 在目录中创建新的 Git 仓库。 你可以在任何时候、任何目录中这么做,完全是本地化的。

在目录中执行 git init,就可以创建一个 Git 仓库了。比如我们创建 gitlearn 项目:

$ mkdir gitlearn
$ cd gitlearn
$ git init
Initialized empty Git repository in /root/gitlesson/gitlearn/.git/
# 在 /root/gitlesson/gitlearn/.git/ 目录初始化空 Git 仓库完毕。

添加到暂存区

当我们初始化项目后, 在工作区里进行增加, 修改, 删除 文件操作.

然后可以通过 git add 将文件添加到暂存区,作为下次提交的(部分或全部)内容。

语法

git add <文件/文件夹>

例如, 我们添加以下两个文件:

touch 是 linux 的基础命令, 可用来创建文件

git status 命令用于查看项目的当前状态。git status 加 -s 参数表示查看的是简要信息

$ touch README
$ touch hello.php
$ ls
README        hello.php
$ git status -s
?? README
?? hello.php
$ 

此时执行git status显示文件名为红色

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UbumlTLf-1654441908551)(C:\Users\83989\AppData\Roaming\Typora\typora-user-images\image-20220604001845526.png)]

接下来我们执行 git add 命令添加到暂存区中:

$ git add README hello.php 

现在我们再执行 git status,就可以看到这两个文件已经加上去了。

此时文件名为绿色

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KzK8lSnW-1654441908552)(C:\Users\83989\AppData\Roaming\Typora\typora-user-images\image-20220604001930147.png)]

$ git status -s
A  README
A  hello.php

在项目中,添加所有文件很普遍,我们可以使用 git add . 命令来添加当前项目的所有文件。

现在我们在 README 中添加以下内容:

# w3cschool Git 测试

再执行一下 git status:

$ git status -s
AM README
A  hello.php

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dJ8QqRL6-1654441908553)(C:\Users\83989\AppData\Roaming\Typora\typora-user-images\image-20220604002102507.png)]

“AM” 状态的意思是,这个文件在我们将它添加到缓存之后又有改动。改动后我们在执行 git add 命令将其添加到缓存中(暂存区):

$ git add .
$ git status -s
A  README
A  hello.php

当你要将你的修改包含在即将提交的快照里的时候,需要执行 git add 文件

三个git add命令

git add . :他会监控工作区的状态树,使用它会把工作时的所有变化提交到暂存区,包括文件内容修改(modified)以及新文件(new),但不包括被删除的文件。

git add -u :他仅监控已经被add的文件(即tracked file),他会将被修改的文件提交到暂存区。add -u 不会提交新文件(untracked file)。(git add --update的缩写)

git add -A :是上面两个功能的合集, 也就是说包括删除的文件也会被提交(git add --all的缩写)

查看改动

执行 git diff 来查看执行 git status 的结果的详细信息。

git diff 用来查看已经add了之后,对文件进行了修改,使用该指令可以看到修改的内容

若没有修改,使用git diff指令就显示不了任何内容

git diff 命令显示已写入缓存与已修改但尚未写入缓存的改动的区别。

git diff 有两个主要的应用场景。

  • 尚未缓存的改动:git diff

  • 查看已缓存的改动: git diff --cached

  • 查看已缓存的与未缓存的所有改动:git diff HEAD

  • 显示摘要而非整个 diff:git diff --stat

在 hello.php 文件中输入以下内容:

git diff执行效果
<?php
echo 'W3Cschool Git微课';
$ git status -s
A  README
AM hello.php
$ git diff
diff --git a/hello.php b/hello.php
index e69de29..6d3063e 100644
--- a/hello.php
+++ b/hello.php
@@ -0,0 +1,2 @@
+<?php
+echo 'W3Cschool Git微课';

git status 显示你上次提交更新后的更改或者写入缓存的改动, 而 git diff 一行一行地显示这些改动具体是什么。

git diff --cached 的执行效果
$ git add hello.php 
$ git status -s
A  README
A  hello.php
$ git diff --cached

diff --git a/README b/README

new file mode 100644

index 0000000..e69de29

diff --git a/hello.php b/hello.php

new file mode 100644

index 0000000..6d3063e

--- /dev/null

+++ b/hello.php

@@ -0,0 +1,2 @@

+<?php

+echo 'W3Cschool Git微课'; 

git diff --cached 用于查看已缓存的改动

向仓库提交代码

使用 git add 命令将想要快照的内容写入缓存区, 而执行 git commit 将缓存区内容添加到仓库中。

Git 为你的每一个提交都记录你的名字与电子邮箱地址,所以第一步需要配置用户名和邮箱地址。

$ git config --global user.name 'david'
$ git config --global user.email 839894616@qq.com

接下来我们写入缓存,并提交对 hello.php 的所有改动。在首个例子中,我们使用 -m 选项以在命令行中提供提交注释。

$ git commit -m '初始化项目'
[master (root-commit) ca66690] 初始化项目
 2 files changed, 2 insertions(+)
 create mode 100644 README
 create mode 100644 hello.php

现在我们已经记录了快照。如果我们再执行 git status:

$ git status
# On branch master
nothing to commit (working directory clean)

以上输出说明我们在最近一次提交之后,没有做任何改动,是一个"working directory clean:干净的工作目录"。

如果你没有设置 -m 选项,Git 会尝试为你打开一个编辑器以填写提交信息。 如果 Git 在你对它的配置中找不到相关信息,默认(Linux)会打开 vim。

如果你觉得 git add 提交缓存的流程太过繁琐,Git 也允许你用 -a 选项跳过这一步。命令格式如下:

git commit -a

我们先修改 hello.php 文件为以下内容:

<?php
echo 'W3Cschool Git微课';

echo '使用微课学习很简单';

再执行以下命令:

$ git commit -am '修改hello 新增微课介绍'

[master ee802b9] 修改hello 新增微课介绍

 1 file changed, 1 insertion(+)

取消已缓存的内容

HEAD指向的版本就是当前版本

git reset HEAD 命令用于取消已缓存的内容。

我们先改动文件 README 文件,内容如下:

# W3Cschool Git 微课

hello.php 文件修改为:

<?php
echo 'W3Cschool Git微课';
echo '使用微课学习很简单';
echo '每个知识点既学既练,真正科学的学习方式';

现在两个文件修改后,都提交到了缓存区,我们现在要取消其中一个的缓存,操作如下:

$ git status -s
 M README
 M hello.php
$ git add .
$ git status -s
M  README
M  hello.pp
$ git reset HEAD -- hello.php 
Unstaged changes after reset:
M    hello.php
$ git status -s
M  README
 M hello.php

现在你执行 git commit,只会将 README 文件的改动提交,而 hello.php 是没有的。

$ git commit -m '修改README'
[master 88abf2f] 修改README
 1 file changed, 1 insertion(+)
$ git status -s
 M hello.php

可以看到 hello.php 文件的修改并没有提交。

这时我们可以使用以下命令将 hello.php 的修改提交:

$ git commit -am '修改 hello 文件'
[master 10e6a9f] 修改 hello 文件
 1 file changed, 1 insertion(+)
$ git status
On branch master
nothing to commit, working directory clean

简而言之,执行 git reset HEAD 以取消之前 git add 添加。

删除文件

git rm 从版本库中删除文件

语法如下:

git rm <file>

如果删除之前修改过并且已经放到暂存区域的话,则必须要用强制删除选项 -f

git rm -f <file>

如果把文件从暂存区域移除,但仍然希望保留在当前工作目录中,换句话说,仅是从跟踪清单中删除,使用 --cached 选项即可

git rm --cached <file>

例如:

$ echo "# 这是一个Git微课的一个测试文件" > gittest.md
$ git add .
$ git commit -m "添加测试文件"
[master c0ca7bb] 添加测试文件
 1 file changed, 1 insertion(+)
 create mode 100644 gittest.md$ git rm gittest.md 
rm 'gittest.md'
$ ls
hello.php  README

上面创建一个文件 gittest.md 并为其写上内容 # 这是一个Git微课的一个测试文件, 然后将其添加到仓库中, 最后使用 git rm gittest.md 将其从版本库中和工作区中删除

递归删除

我们可以使用 -r 参数进行递归删除, 即如果后面跟的是一个目录做为参数,则会递归删除整个目录中的所有子目录和文件:

git rm –r test 

以上命令会删除 test 目录下的所有文件和子目录。

还原文件

发现删错了后需要还原

$ git checkout -- <file>

git checkout – 其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。

当我们需要删除暂存区或分支上的文件, 但本地又需要使用, 只是不希望这个文件被版本控制, 可以使用:

$ git rm --cached README 
rm 'README'
$ ls
hello.php  README

移动 重命名

git mv 命令用于移动或重命名一个文件、目录、软连接。

例如:

$ git add README 

然后对其重名:

$ git mv README  README.md
$ ls
README.md

远程仓库

添加远程仓库

我们使用 gitHub 创建一个在线仓库, 然后将其与本地仓库关联.

img

我们在 Repository name 填写 gitlearn 其他保持默认设置,点击“Create repository”按钮,就成功地创建了一个新的Git仓库:

img

现在,这个仓库还是空的, GitHub 告诉我们,可以从这个仓库克隆出新的仓库,也可以把一个已有的本地仓库与之关联,然后,把本地仓库的内容推送到 GitHub 仓库。

我们将本地已有仓库与之关联:

git remote add origin https://github.com/lucoo01/gitlearn.git

注意: 以上的 lucoo01 为 GitHub 账户名, 要替换成自己的

然后,我们把本地库的所有内容推送到远程库上:

git push -u origin master
Username for 'https://github.com': 425389019@qq.com
Password for 'https://425389019@qq.com@github.com': 
Counting objects: 15, done.
Compressing objects: 100% (9/9), done.
Writing objects: 100% (15/15), 1.25 KiB | 0 bytes/s, done.
Total 15 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), done.
To https://github.com/lucoo01/gitlearn.git
 * [new branch]      master -> master
Branch master set up to track remote branch master from origin.

由于远程库是空的,我们第一次推送master分支时,加上了-u参数

由于我们使用的是 https 协议所以需要输入 GitHub 账户名和密码

报错解决链接:(67条消息) github使用AccessToken登录配置教程_smileNicky的博客-CSDN博客_github的access token

登陆时使用github的SSH进行登录

SSH登录之后可以使用HTTPS正常登录

# 移除原来的远程链接
git remote remove origin
# 查看git的远程链接
git remote -v
# 重新新增git远程链接
git remote add origin https://<your token>@github.com/<your account>/<your repository>.git
# 下拉master分支
git push origin master -u

Git 不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。

git push -u origin master 如果当前分支与多个主机存在追踪关系,
使用 -u 参数指定一个默认主机,这样后面就可以不加任何参数使用 git push

克隆操作

使用 git clone 拷贝一个 Git 仓库到本地,让自己能够查看该项目,或者进行修改。

如果你需要与他人合作一个项目,或者想要复制一个项目,看看代码,你就可以克隆那个项目。 执行命令:

 git clone [url]

[url] 为你想要复制的项目地址。

例如,我们在 GitHub 创建一个新的 w3cschool

img

这次我们填上了 Description 并勾选了 初始化仓库的 README 文件.

创建完毕后可以看到仓库中有一个 README.md 文件:

img

现在,将以上项目克隆到本地:

git clone https://github.com/lucoo01/w3cschool.git
Cloning into 'w3cschool'...
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.

克隆完成后,在当前目录下会生成一个 w3cschool 目录:

$ cd w3cschool
$ ls README.md

当然你也可以克隆别人的项目与之协同开发

默认情况下,Git 会按照你提供的 URL 所指示的项目的名称创建你的本地项目目录。 通常就是该 URL 最后一个 / 之后的项目名称。如果你想要一个不一样的名字, 你可以在该命令后加上你想要的名称。

例如: git clone https://github.com/lucoo01/woodcalculator.git simpleapp

更新数据

git fetch:从远程获取最新版本到本地,不会自动 merge(合并)

$ git checkout issue12
$ git fetch origin issue12
$ git log -p issue12..origin/issue12
$ git merge origin/issue12

解析:
(1).切换到issue12分支
(2).从远程的origin的issue12主分支下载最新的版本到origin/issue12分支上
(3).比较本地的issue12分支和origin/issue12分支的差别 ( git log 常用 -p 选项展开显示每次提交的内容差异 )

(4).将origin/issue12分支合并到issue12

git pull:相当于是从远程获取最新版本并merge到本地

$ git checkout issue13
$ git pull origin issue13

上述 git pull 命令, 相当于 git fetch 和 git merge

Git分支

分支原理

Git 每次提交的版本, Git 都将其串成一条时间线, 这条时间线就是一个分支, 当你执行 git init 的时候,缺省情况下 Git 就会为你创建 “master” 分支。HEAD严格来说不是指向提交,而是指向mastermaster才是指向提交的,所以,HEAD指向的就是当前分支。

如图所示:

img

每次提交,master分支都会向前移动一步,这样,随着你不断提交,master分支的线也越来越长.

当我们创建新的分支,如dev时,Git 新建了一个指针叫dev,指向与master相同的提交,再把HEAD指向dev,现在表示当前分支在dev

如图所示:

img

从现在开始, 对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变.

如图所示:

img

我们在dev上完成相应的开发后, 我们将其合并到 master 分支上, 切换回 master 分支.

如图所示:

img

合并完成后, 也可以删除 dev 分支, 原理是将 dev 指针删除

如图所示:

img

分支基础命令

几乎每一种版本控制系统都以某种形式支持分支。使用分支意味着你可以从开发主线上分离开来,然后在不影响主线的同时继续工作。

有人把 Git 的分支模型称为"必杀技特性",而正是因为它,将 Git 从版本控制系统家族里区分出来。

创建分支命令:

git branch 分支名

切换分支命令:

git checkout 分支名

当你切换分支的时候,Git 会用该分支的最后提交的快照替换你的工作目录的内容, 所以多个分支不需要多个目录。

合并分支命令:

git merge 

你可以多次合并到统一分支, 也可以选择在合并之后直接删除被并入的分支。

列出分支

列出分支基本命令:

git branch

没有参数时,git branch 会列出你在本地的分支。

$ git branch
* master

此例的意思就是,我们有一个叫做 “master” 的分支,并且该分支是当前分支。

当你执行 git init 的时候,缺省情况下 Git 就会为你创建 “master” 分支。

创建新分支

如果我们要手动创建一个分支。执行 git branch 分支名 即可。

$ git branch dev
$ git branch
* master
  dev

现在我们可以看到,有了一个新分支 dev。

当你以此方式在上次提交更新之后创建了新分支,如果后来又有更新提交, 然后又切换到了 “dev” 分支,Git 将还原你的工作目录到你创建分支时候的样子

接下来我们将演示如何切换分支,我们用 git checkout 分支名 切换到我们要修改的分支。

$ git checkout dev
Switched to branch 'dev'$ echo '# 随时随地学编程,妈妈再也不用担心我找不到工作啦' > test.md
$ git add .
$ git commit -m "新增test.md文件"
[dev 37f4d35] 新增test.md文件
 1 file changed, 1 insertion(+)
 create mode 100644 test.md$ ls
hello.php  README  test.md
$ git checkout master
Switched to branch 'master'
$ ls
hello.php  README

以上使用 echo 输出字符串 ‘# 随时随地学编程,妈妈再也不用担心我找不到工作啦’ 并使用 > 重定向到 test.md文件中

当我们切换到"master"分支的时候,我们添加的新文件test.md不见了。切换回"master"分支的时候,新文件test.md再次出现。

$ git checkout dev
Switched to branch 'dev'
$ ls
hello.php  README  test.md

我们也可以使用 git checkout -b 分支名 命令来创建新分支并立即切换到该分支下,从而在该分支中操作。

合并分支

一旦某分支有了独立内容,你终究会希望将它合并回到你的主分支。 你可以使用以下命令将任何分支合并到当前分支中去:

git merge 分支名

我们创建并切换到 dev3 分支中, 在 dev3 中新增文件 loen.md

$ git checkout -b dev3
Switched to a new branch 'dev3'
$ touch loen.md
$ git add .
$ git commit -m "新增loen.md"
[dev3 7f03049] 新增loen.md
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 loen.md

切回 master 分支并执行合并操作

$ git checkout master
Switched to branch 'master'
$ ls
hello.php  README
$ git merge dev3
Updating 9400478..7f03049
Fast-forward
 loen.md | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 loen.md
$ ls
hello.php  loen.md  README

我们发现合并后 master 中新增了 loen.md 文件

删除分支

删除分支命令(name 为分支名):

git branch -d name

例如我们要删除"dev"分支:

$ git branch
* master
  newtest
  dev
$ git branch -d dev
Deleted branch dev(was 1037bce).
$ git branch
* master
  newtest

Git 鼓励大量使用分支:
查看分支:git branch
创建分支:git branch
切换分支:git checkout
创建+切换分支:git checkout -b
合并某分支到当前分支:git merge
删除分支:git branch -d

解决冲突

冲突是关于分支合并的,两个分支对同一个文件的同一行进行了修改,合并两个分支时会产生冲突

我们先创造一个冲突出来, 比如, 在两个分支中修改了同一个文件的同一行代码,在合并的时候就会发生冲突.

假设我们版本库中有一个 test.php 文件,内容为:

<?php
	echo "Loen is a Girl<br>";
	echo "Loen is Beautiful<br>";
	echo "actually, Loen is a Boy<br>";
        echo "hei,hei,hei";

我们新建一个 dev1 的分支

$ git checkout -b dev1
Switched to a new branch 'dev1'

修改 test.php 最后一行为:

echo "ji,ji,ji";

在 dev1 中提交修改:

$ git add .
$ git commit -m "change hei to ji"
[dev1 72bf7f9] change hei to ji
 1 file changed, 1 insertion(+), 1 deletion(-)

现在我们切回 master 分支:

$ git checkout master
Switched to branch 'master'

在 master 分支中将 test.php 最后一行改为:

echo "ha,ha,ha"

然后提交修改:

$ git add .
$ git commit -m "change hei to ha"
[master 9b1e006] change hei to ha
 1 file changed, 1 insertion(+), 1 deletion(-)

现在 master 分支与 dev1 分支各自都有新的提交:

img

我们试着合并 dev1

$ git merge dev1
Auto-merging test.php
CONFLICT (content): Merge conflict in test.php
Automatic merge failed; fix conflicts and then commit the result.

提示我们 test.php 有合并冲突,必须手动解决冲突

使用 git status 也可以告诉我们存在冲突文件和文件名:

$ git status
# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
#   (use "git push" to publish your local commits)
#
# You have unmerged paths.
#   (fix conflicts and run "git commit")
#
# Unmerged paths:
#   (use "git add <file>..." to mark resolution)
#
#	both modified:      test.php
#
no changes added to commit (use "git add" and/or "git commit -a")

我们现在直接看 test.php 的文件内容

<?php
	echo "Loen is a Girl<br>";
	echo "Loen is Beautiful<br>";
	echo "actually, Loen is a Boy<br>";
<<<<<<< HEAD
	echo "ha, ha, ha";
=======
	echo "ji,ji,ji";
>>>>>>> dev1

Git 用 <<<<<<<,=======,>>>>>>> 标记出不同分支的内容,我们最后一行修改如下后保存:

echo "ha, ha, ha and ji, ji, ji";

然后提交:

$ git add .
$ git commit -m "conflict fixed"
[master 8ae5258] conflict fixed

现在 master 分支与 dev1 分支变成如图:

img

我们使用带参数的 git log 也可以看到合并的情况:

$ git log --graph --pretty=oneline --abbrev-commit
*   8ae5258 conflict fixed
|\  
| * 72bf7f9 change hei to ji
* | 9b1e006 change hei to ha
|/  
* a9c230a Loen is a boy
* ab1ca2b Loen's feature
* e871a66 Loen's sex
* 38255de rm test.txt
* f3476aa init test.txt
* 15492c1 create test.php

分支管理策略

通常 Git 在合并分支的时候会用 Fast forward 模式, 这样删除分支后, 也会丢掉分支信息.

我们在合并分支时可以使用 **–no-ff **参数,强制禁用 Fastforward 模式, 这样 Git 在合并时会生成一个新的 commit(提交), 然后我们就可以在历史分支上看出分支信息.

我们来操作下看看效果, 我们创建一个 dev2 的分支

$ git checkout -b dev2
Switched to a new branch 'dev2'

修改 test.php 文件, 然后提交修改:

$ git add .
$ git commit -m "add Line Loen can fly"
[dev2 523fc69] add Line Loen can fly
 1 file changed, 2 insertions(+), 1 deletion(-)

切回 master 分支, 然后使用 git merge --no-ff 合并分支:

$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 3 commits.
  (use "git push" to publish your local commits)
$ git merge --no-ff -m "merge with no-ff" dev2
Merge made by the 'recursive' strategy.
 test.php | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

因为我们禁用 Fast forward 模式, 所以本次合并会创建一个新的 commit(提交), 我们用 -m 给这次 commit 加上描述

然后我们用 git log 查看下分支历史

$ git log --graph --pretty=oneline --abbrev-commit
*   73dcd5d merge with no-ff
|\  
| * 523fc69 add Line Loen can fly
|/  
*   8ae5258 conflict fixed
...

禁用 Fast forward 合并示意图(有生成一个新commit):

img

分支策略

在实际开发中,我们应该按照几个基本原则进行分支管理:

首先,master 分支应该是非常稳定的,也就是仅用来发布新版本,平时不要直接在上面开发;

你可以和你团队成员在 dev 上开发, 每个人都有自己的分支, 然后时不时往 dev 分支上合并, 也就是说 dev 分支时不稳定的, 等到要发布版本的时候, 再将 dev 往 master 上合并就可以了, 图示如下:

img

多人协作

当我们从远程仓库克隆时,实际上 Git 自动把本地的master分支和远程的master分支对应起来了(远程仓库默认名字是 origin)

可以用 git remote 查看远程库的信息

$ git remote
origin

加参数 -v 可以显示更详细的信息:

git remote -v
origin	https://github.com/lucoo01/gitlearn.git (fetch)
origin	https://github.com/lucoo01/gitlearn.git (push)

上面显示了可以抓取和推送的origin的地址。如果没有推送权限,就看不到push的地址。

推送分支

我们想将本地分支推送到远程库,可以使用 git push 命令,在推送时,要指定本地分支, 这样,Git 就会把该分支推送到远程库对应的远程分支上:

$ git push origin master

如果要推送其他分支, 比如 dev2 :

$ git push origin dev2
最新提交

在实际项目开发中,往往是多人协作开发的, 大家通常会往远程的 master 或者 dev 分支上推送各自的修改.

假设你在 dev 分支上对 入口文件(比如:index.php) 进行修改, 而你的队友恰巧也改了这个文件,并且在你前面推送到远程 dev 分支上.

这时你直接向 dev 推送修改,就会失败, Git 会提示我们先用git pull把最新的提交从origin/dev抓下来,然后,在本地合并,解决冲突(如果有冲突的话),再推送:

$ git pull

如果你没有指定关联 dev 分支与远程 origin/dev 分支的链接, git pull 会失败,这时要先设置下devorigin/dev的链接:

$ git branch --set-upstream dev origin/dev
Branch dev set up to track remote branch dev from origin.

然后再 git pull 就可以了

如果 pull 下来,提示有冲突可以参照之前的课程解决冲突,提交,再 push 就可以了

多人协作的工作模式通常是这样:

  1. 首先,用 git pull 看有没有人在远程提交代码有的话将其合并到本地;
  2. 如果合并有冲突,则解决冲突,并在本地提交;
  3. 没有冲突或者解决掉冲突后,再用 git push origin 分支名 推送就能成功!

回退与撤销

撤销修改

命令git checkout -- 文件意思就是,把 该文件 在工作区的修改全部撤销

语法:

$ git checkout -- <file>

如果 文件 修改后还没有被放到暂存区,现在,撤销修改就是用版本库的版本覆盖当前的文件。

如果 文件 已经添加到暂存区后,又作了修改,现在,撤销修改就是将暂存区中的文件版本覆盖当前的文件。

总之,就是让这个文件回到最近一次git commitgit add时的状态。

git checkout – file 命令中的 – 很重要,没有 --,就变成了 “切换到另一个分支” 的命令

历史记录

在实际工作中,我们脑子里怎么可能记得一个几千行的文件每次都改了什么内容,不然要版本控制系统干什么。

Git 可以使用 git log 命令告诉我们历史记录

git log命令显示从最近到最远的提交日志

如果嫌 git log 输出信息太多,看得眼花缭乱,可以加上--pretty=oneline参数:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5P0WwRt4-1654441908563)(C:\Users\83989\AppData\Roaming\Typora\typora-user-images\image-20220511211204736.png)]

看到的一大串类似a9c230a...909a43的是commit id(版本号),是一个SHA1计算出来的一个非常大的数字,用十六进制表示

版本回退

要把当前版本回退到上一个版本,可以使用git reset命令.

使用 git reset 回退到上一个版本:

git reset --hard HEAD^

在 Git 中,用 HEAD 表示当前版本,上一个版本就是 HEAD^,上上一个版本就是 HEAD^,当然往上100个版本写100个比较容易数不过来,所以写成HEAD~100

Git 的版本回退速度非常快,因为Git在内部有个指向当前版本的HEAD指针,当你回退版本的时候,Git仅仅是把HEAD从指向 Loen is a boy:

img

改为指向 Loen’s feature

img

然后把工作区的文件更新了。所以你让HEAD指向哪个版本号,就把当前版本定位在哪。

如果回退失误,想要改回原来的 Loen is a boy 版本, 就必须找到 Loen is a boy 的 coommit id .

Git 提供了一个命令git reflog用来记录你的每一次命令:

$ git reflog
ab1ca2b HEAD@{0}: reset: moving to HEAD^
a9c230a HEAD@{1}: commit: Loen is a boy
ab1ca2b HEAD@{2}: commit: Loen's feature
e871a66 HEAD@{3}: commit: Loen's sex
38255de HEAD@{4}: commit: rm test.txt
f3476aa HEAD@{5}: commit: init test.txt
15492c1 HEAD@{6}: commit (initial): create test.php

我们可以看到 Loen is a boy 的 commit id 为 a9c230a

$ git reset --hard a9c230a
HEAD is now at a9c230a Loen is a boy
$ git log --pretty=oneline
a9c230a8be2d3cacdb0909a43 Loen is a boy
ab1ca2bc153c7a94daaa6a546 Loen's feature
e871a660e7c4f6d03d67e69e0 Loen's sex
38255deef96d7eeb3d58edf0d rm test.txt
f3476aac14d3d297ded5f89d5 init test.txt
15492c1f537b1abedfb5db8ec create test.php

git reset --hard 后也可以指定 commit id 切到指定版本

git reflog: 显示整个本地仓储的 commit, 包括所有 branch 的 commit, 甚至包括已经撤销的 commit, 只要 HEAD 发生了变化, 就会在 reflog 里面看得到.

标签管理

创建标签

创建标签,只需切换到要打标签的分支上:

$ git branch
* dev
  master
  newtest
$ git checkout master
Switched to branch 'master'

使用 git tag 标签名 就可以创建一个新标签:

$ git tag v1.0

我们可以使用 git tag 查看所有的标签:

$ git tag
v1.0

标签是默认打在最新提交的 commit id 上的.

创建带有说明的标签

我们也可以创建带有说明的标签:

git tag -a v0.9 -m "This is v0.9 ; Loen's Feature" ab1ca2b

以上-a指定标签名,-m指定说明文字

查看标签信息 ( git show 标签名 )

我们可以使用 git show 查看标签信息:

git show v0.9
tag v0.9
Tagger: Loen <425389019@qq.com>
Date:   Tue Feb 6 18:01:36 2018 +0800
This is v0.9 ; Loen's Feature
commit ab1ca2bc150e666cd600accd33c7a94daaa6a546
Author: Loen <425389019@qq.com>
Date:   Sat Feb 3 16:14:40 2018 +0800
    Loen's feature
diff --git a/test.php b/test.php
index 8bb314e..7a01fcc 100644
--- a/test.php
+++ b/test.php
@@ -1,2 +1,3 @@
 <?php
-       echo "Loen is a Girl";
+       echo "Loen is a Girl<br>";
+       echo "Loen is Beautiful<br>";

我们可以看到 v0.9 确实指向 Loen’s feature 这个版本上,而且还看到了刚添加的标签说明

标签操作

可以使用 git tag -d 标签名 删除打错的标签:

git tag -d v0.8
Deleted tag 'v0.8' (was e871a66)

到目前为止,我们打的标签都只是存储在本地

如果要推送某个标签到远程,使用命令 git push origin 标签名

$ git push origin v1.0
Total 0 (delta 0), reused 0 (delta 0)
To https://github.com/lucoo01/gitlearn.git
 * [new tag]         v1.0 -> v1.0

也可以,一次性推送全部尚未推送到远程的本地标签:

$ git push origin --tags
Counting objects: 1, done.
Writing objects: 100% (1/1), 169 bytes | 0 bytes/s, done.
Total 1 (delta 0), reused 0 (delta 0)
To https://github.com/lucoo01/gitlearn.git
 * [new tag]         v0.9 -> v0.9

如果标签已经推送到远程,要删除远程标签就麻烦一点,先从本地删除:

$ git tag -d v0.9
Deleted tag 'v0.9' (was a4ec879)

然后,从远程删除。删除命令也是push,但是格式如下:

$ git push origin :refs/tags/v0.9
To https://github.com/lucoo01/gitlearn.git
 - [deleted]         v0.9

Git配置

Git 提供了一个叫做 git config 的工具,专门用来配置或读取相应的工作环境变量。

这些环境变量,决定了 Git 在各个环节的具体工作方式和行为。这些变量可以存放在以下三个不同的地方:

  • /etc/gitconfig 文件:系统中对所有用户都普遍适用的配置。若使用 git config 时用 --system 选项,读写的就是这个文件。
  • ~/.gitconfig 文件:用户目录下的配置文件只适用于该用户。若使用 git config 时用 --global 选项,读写的就是这个文件。
  • 当前项目的 Git 目录中的配置文件(也就是工作目录中的 .git/config 文件):这里的配置仅仅针对当前项目有效。每一个级别的配置都会覆盖上层的相同配置,所以 .git/config 里的配置会覆盖 /etc/gitconfig 中的同名变量。

在 Windows 系统上,Git 会找寻用户主目录下的 .gitconfig 文件。主目录即 $HOME 变量指定的目录,一般都是 C:\Documents and Settings$USER。

此外,Git 还会尝试找寻 /etc/gitconfig 文件,只不过看当初 Git 装在什么目录,就以此作为根目录来定位。

配置用户信息

配置个人的用户名称和电子邮件地址:

$ git config --global user.name "loen"
$ git config --global user.email loen@w3cschool.cn

如果用了 --global 选项,那么更改的配置文件就是位于你用户主目录下的那个,以后你所有的项目都会默认使用这里配置的用户信息。

如果要在某个特定的项目中使用其他名字或者邮件,只要去掉 --global 选项重新配置即可,新的设定保存在当前项目的 .git/config 文件里。

查看配置信息

要检查已有的配置信息,可以使用 git config --list 命令:

$ git config --list
http.postbuffer=2M
user.name=loen
user.email=loen@w3cschool.cn

有时候会看到重复的变量名,那就说明它们来自不同的配置文件(比如 /etc/gitconfig 和 ~/.gitconfig),不过最终 Git 实际采用的是最后一个。

这些配置我们也可以在 ~/.gitconfig 或 /etc/gitconfig 看到,如下所示:

vim ~/.gitconfig 

显示内容如下所示:

[http]
    postBuffer = 2M
[user]
    name = loen
    email = loen@w3cschool.cn

忽略特殊文件

有时你必须把某些文件放入 Git 工作目录中, 又不能将其提交, 比如:存储了数据库密码的配置文件.

我们只需在 Git 工作区的根目录下创建一个名为 .gitignore 的文件, 写入过滤规则就行了.

.gitignore 文件不需要从头写,GitHub 已经为我们准备了各种配置文件,只需根据需要组合一下就可以使用了。所有配置文件可以直接在线浏览:https://github.com/github/gitignore

忽略文件的原则是:

  1. 忽略操作系统自动生成的文件,比如缩略图等;
  2. 忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如 Java 编译产生的 .class 文件;
  3. 忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。

例如, 这是 java 项目的 .gitignore 文件

# Compiled class file
*.class

# Log file
*.log

# BlueJ files
*.ctxt

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.ear
*.zip
*.tar.gz
*.rar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值