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

Git的基本使用

程序员文章站 2022-07-13 16:18:36
...

Git

本文是本人学习廖雪峰的Git教程后的总结

1. Git是分布式版本控制系统

版本控制系统分为分布式和集中式两种

1.1 什么是集中式版本控制系统

集中式版本控制系统,版本库是集中存放在*服务器的,而工作的时候,都是使用自己的电脑,所以要先从*服务器取得最新的版本,然后开始工作,工作完了,再把自己的成果推送给*服务器。

集中式版本控制系统最大的毛病就是必须联网必须联网才能工作!

仅仅只是局域网还好,带宽够大,速度够快。但在互联网上,遇到网速慢的话,可能提交一个10M的文件就需要5分钟。

1.2 Git作为分布式版本控制系统

分布式版本控制系统根本没有“*服务器”,每个人的电脑上都有一个完整的版本库。这样,你工作的时候,就不需要联网了,因为版本库就在你自己的电脑上。多人协作时,需把各自的修改推送给别人,就可以看到推送者的修改了。

和集中式版本控制系统相比,分布式版本控制系统的安全性要高很多,因为每个人电脑里都有完整的版本库,某一个人的电脑坏掉了不要紧,随便从其他人那里复制一个就可以了。而集中式版本控制系统的*服务器要是出了问题,所有人都没法干活了。

但是实际应用中,很少在同一局域网工作,因此分布式版本控制系统通常也有一台充当“*服务器”的电脑,但这个服务器的作用仅仅是用来方便“交换”大家的修改,没有它大家也一样干活,只是交换修改不方便而已。

2. 仓库结构

2.1 工作区

工作区就是我们电脑本地能看到的文件

.git是隐藏文件夹,里面是记录版本库的信息,不要去修改它,以免版本库损坏

2.2 版本库

(图片来源网络,侵删)

Git的基本使用

HEAD是一个指向master分支(它也是一个指针,这个指针的指向是当前版本)的一个指针)

3. Git管理的是修改,而不是文件本身

3.1 创建一个Git本地仓库

会用到的一些语法

$ cd <path>
// 跳转到<path>路径下

$ mkdir <name>
// 当前目录下创建一个名为<name>的文件夹

$ git init
// 将当前目录初始化为本地仓库

例如:

我的电脑 MINGW64 /g/warehouse
$ mkdir test

我的电脑 MINGW64 /g/warehouse
$ cd test

我的电脑 MINGW64 /g/warehouse/test
$ git init
Initialized empty Git repository in G:/warehouse/test/.git/

首先创建一个test文件夹,然后跳转到此目录下,将其初始化为本地仓库

3.2 管理修改

会用到的一些语法

$ touch <filename.***>
// 创建文件<filename.***>

$ vi <filename.***>
// 使用vi编辑器编辑文件,具体操作自行查阅

$ git add <filename.***>
// 添加文件到暂存区

$ git status
// 查看暂存区状态

$ git commit -m "<commit message>"
// 提交暂存区到分支,每次提交写上"<commit message>"是个好习惯

例如

我的电脑 MINGW64 /g/warehouse/test (master)
$ touch README.md

我的电脑 MINGW64 /g/warehouse/test (master)
$ vi README.md

我的电脑 MINGW64 /g/warehouse/test (master)
$ git add README.md

我的电脑 MINGW64 /g/warehouse/test (master)
$ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   README.md


我的电脑 MINGW64 /g/warehouse/test (master)
$ git commit -m "add README.md"
[master (root-commit) 48711df] add README.md
 1 file changed, 1 insertion(+)
 create mode 100644 README.md
 
我的电脑 MINGW64 /g/warehouse/test (master)
$ git status
On branch master
nothing to commit, working tree clean

3.3 撤销修改

会用到的一些语法

$ git checkout -- <filename.***>
// 撤销<filename.***>的修改

$ git reset HEAD <filename.***>
// 已经add时,将<filename.***>返回到版本库状态,再使用git checkout -- <filename.md>

例如

3.3.1 未add到暂存区时

我的电脑 MINGW64 /g/warehouse/test (master)
$ git checkout -- README.md

还未add时,只需使用git checkout -- <filename.***>撤销<filename.***>的修改

3.3.2 已经add到暂存区

我的电脑 MINGW64 /g/warehouse/test (master)
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   README.md

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

我的电脑 MINGW64 /g/warehouse/test (master)
$ git add README.md
warning: LF will be replaced by CRLF in README.md.
The file will have its original line endings in your working directory

我的电脑 MINGW64 /g/warehouse/test (master)
$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   README.md


我的电脑 MINGW64 /g/warehouse/test (master)
$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   README.md


我的电脑 MINGW64 /g/warehouse/test (master)
$ git reset HEAD README.md
Unstaged changes after reset:
M       README.md

我的电脑 MINGW64 /g/warehouse/test (master)
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   README.md

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

我的电脑 MINGW64 /g/warehouse/test (master)
$ git checkout -- README.md

已经add时使用git reset HEAD <filename.***>将<filename.***>返回到版本库状态,使用git checkout -- <filename.md>

3.4 删除文件

会用到的一些语法

$ git rm <filename.***>
// 移除文件<filename.***>

例如

// 新建一个文件test.md,并提交到版本库
我的电脑 MINGW64 /g/warehouse/test (master)
$ touch test.md

我的电脑 MINGW64 /g/warehouse/test (master)
$ git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        test.md

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

我的电脑 MINGW64 /g/warehouse/test (master)
$ git add test.md

我的电脑 MINGW64 /g/warehouse/test (master)
$ git commit -m "add test.md"
[master a633db8] add test.md
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 test.md


// 下面是删除此文件
我的电脑 MINGW64 /g/warehouse/test (master)
$ git rm test.md
rm 'test.md'

我的电脑 MINGW64 /g/warehouse/test (master)
$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        deleted:    test.md


我的电脑 MINGW64 /g/warehouse/test (master)
$ git commit -m "delete test.md"
[master 9c1123e] delete test.md
 1 file changed, 0 insertions(+), 0 deletions(-)
 delete mode 100644 test.md

我的电脑 MINGW64 /g/warehouse/test (master)
$ git status
On branch master
nothing to commit, working tree clean

移除之后需要git commit提交到版本库,若是误删且还未提交到版本库,即可使用git checkout -- <filename.***>恢复

4. 远程仓库

4.1 关联远程仓库

$ git remote add origin aaa@qq.com:<your username>/learngit.git

4.2 推送到远程仓库

$ git push -u origin master

由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。

后面的推送:

$ git push origin <name>
// 推送到<name>分支

4.3 从远程仓库克隆

$ git clone aaa@qq.com:<your username>/gitskills.git

注意:这里克隆下来的只有master分支,若要在其他分支上开发,必须创建远程origin<name>分支到本地

$ git checkout -b <name> origin/<name>

5. 分支管理

5.1 创建与合并分支

会用到的语句:

$ git branch
// 打印所有分支,*代表当前分支

$ git branch -d <name>
// 删除<name>分支,前提时已经合并的分支

$ git branch -D <name>
// 强行删除<name>分支,同于未被合并的分支

$ git switch <name>
// 切换到已有的分支<name>

创建时使用语句:

$ git branch <name>
$ git checkout <name>
// 创建名为<name>的分支,并切换到<name>分支

$ git checkout -b <name>
// 此句与上两句等效

$ git switch -c <name>
// 但是Git更鼓励使用此语句

合并时使用的语句:

$ git merge <name>
// 快速合并(Fast-forward),将当前分支合并到<name>分支,但是一旦删除<name>分支,就会失去分支信息

$ git merge --no-ff -m "merge with no-ff" <name>
// 禁用Fast-forward的合并,同时会commit,即便分支删除,也会保留分支信息

查看合并历史

$ git log --graph --pretty=oneline --abbrev-commit

5.2 快照

会用到的语句:

$ git stash
// 将当前的工作现场储存起来

$ git stash apply
// 恢复工作现场

$ git stash drop
// 删除之前储存的工作现场

$ git stash pop
// 恢复工作现场的同时删除之前储存的工作现场

5.3 解决冲突

为什么会冲突呢?很简单,两个分支从一个起点出发,向着两个不同的方向并行,要合并时两个分支的内容不一样,比如同一个文件的内容时不一样的,此时Git会告诉你合并冲突了,要你手动修改以解决冲突。

Git用<<<<<<<=======>>>>>>>标记出不同分支的内容,我们进行选择性的修改就行

5.4 分支策略

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

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

那在哪干活呢?干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;

你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。

添加一个新功能时,你肯定不希望因为一些实验性质的代码,把主分支搞乱了,所以,每添加一个新功能,最好新建一个feature分支,在上面开发,完成后,合并,最后,删除该feature分支。

所以,团队合作的分支看起来就像这样:(引用廖雪峰的图)

Git的基本使用

哪些分支需要推送,哪些不需要呢?

  • master分支是主分支,因此要时刻与远程同步;
  • dev分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;
  • bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;
  • feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。

5.5 Rebase(变基)

还没有领略其中的奥义,大佬们可以看看廖雪峰大神的.

6. 标签管理

会用到的语句:

$ git tag <name>
// 创建新标签,默认打在最新的一次commit上

$ git tag
// 查看所有标签,注意,标签不是按时间顺序列出,而是按字母排序的。

$ git tag <name> <commit id>
// 给<commit id>打上标签<name>

$ git show <name>
// 显示标签的信息

$ git tag -d <name>
// 删除标签,因为创建的标签都只存储在本地,不会自动推送到远程。所以,打错的标签可以在本地安全删除

$ git push origin <name>
// 推送某个标签到远程

$ git push origin --tags
// 推送所有未推送的标签到远程

$ git push origin :refs/tags/<name>
// 删除一个远程标签,先从本地删除

7. 命令行小结

7.1 文件管理

显示当前路径

$ pwd

新建文件

$ touch <filename.***>

编辑文件(使用vi编辑器,关于vi的命令行自行查阅)

$ vi <filename.***>

新建文件夹

$ mkdir <name>

将当前目录初始化为本地仓库

$ git init

跳转

返回上一级的 <path>..

$ cd <path>

添加文件到暂存区

$ git add <filename.***>

从暂存区移除文件

$ git rm --cache <filename.***>

查看暂存区状态

$ git status

提交暂存区到版本库

$ git commit -m "<commit message>"

7.2 打印日志(git log 类)

$ git log 
// 打印日志,内容繁多

$ git log --pretty=oneline
// 打印简单的日志

$ git reflog
// 打印所有的日志,包括被删除的

$ git log --graph --pretty=oneline --abbrev-commit
// 打印分支信息

7.3 远程仓库

关联远程的新仓库

$ git remote add origin aaa@qq.com:<your username>/<name>.git

第一次推送到远程仓库

$ git push -u origin master

后期的推送

$ git push origin <name>

将远程仓库克隆到本地(默认master分支)

git clone aaa@qq.com:<your username>/<name>.git

注意:这里克隆下来的只有master分支,若要在其他分支上开发,必须创建远程origin<name>分支到本地

$ git checkout -b <name> origin/<name>

拉取最新的提交

$ git pull

可能会失败,因为没有建立分支于远程分支的链接,命令如下

$ git branch --set-upstream-to=origin/<name> <name>

7.4 分支

打印所有分支,*代表当前分支

$ git branch

创建时使用语句:

$ git branch <name>
$ git checkout <name>
// 创建名为<name>的分支,并切换到<name>分支

$ git checkout -b <name>
// 此句与上两句等效

$ git switch -c <name>
// 但是Git更鼓励使用此语句

合并时使用的语句:

$ git merge <name>
// 快速合并(Fast-forward),将当前分支合并到<name>分支,但是一旦删除<name>分支,就会失去分支信息

$ git merge --no-ff -m "merge with no-ff" <name>
// 禁用Fast-forward的合并,同时会commit,即便分支删除,也会保留分支信息

删除<name>分支,前提时已经合并的分支

$ git branch -d <name>

强行删除<name>分支,同于未被合并的分支

$ git branch -D <name>

切换到已有的分支<name>

$ git switch <name>

临时储存还未提交的分支

$ git stash
// 将当前的工作现场储存起来

$ git stash apply
// 恢复工作现场

$ git stash drop
// 删除之前储存的工作现场

$ git stash pop
// 恢复工作现场的同时删除之前储存的工作现场

7.5 标签

创建新标签,默认打在最新的一次commit上

$ git tag <name>

查看所有标签,注意,标签不是按时间顺序列出,而是按字母排序的

$ git tag

给打上标签

$ git tag <name> <commit id>

显示标签的信息

$ git show <name>

删除标签,因为创建的标签都只存储在本地,不会自动推送到远程。所以,打错的标签可以在本地安全删除

$ git tag -d <name>

推送某个标签到远程

$ git push origin <name>

推送所有未推送的标签到远程

$ git push origin --tags

删除一个远程标签,先从本地删除

$ git push origin :refs/tags/<name>