Git 详细使用指南

作者: 王炳明 分类: 工具库 发布时间: 2020-10-26 22:05 热度:1,678

一、Git 入门操作

1.1 创建版本库

$ mkdir learngit
$ cd learngit
$ git init

1.2 添加文件

$ git add readme.txt

git add 的各种区别:

git add -A   // 添加所有改动
git add *     // 添加新建文件和修改,但是不包括删除
git add .      // 添加新建文件和修改,但是不包括删除
git add -u   // 添加修改和删除,但是不包括新建文件

1.3 提交修改

$ git commit -m "新增文件"

1.4 远程仓库

$ git remote add [shortname] [url] 

# 举例
$ git remote add origin git@github.com:iswbm/magic-python.git

1.5 推送提交

# origin 是之前为远程仓库设置的别名,master是你要推送到的远程仓库的分支名字
git push -u  origin master 

# 它等价于 git push -u origin master:master

1.6 克隆项目

$ git clone git@github.com:iswbm/magic-python.git

1.7 拉取提交

$ git pull
$ git pull origin

有些可视化软件上的按键对应的是 git fetch

Git 详细使用指南

二、其他操作

2.1 删除文件

# 删除工作区的实体文件
$ git rm readme.txt  

2.2 查看远程

$ git remote
origin

再加 -v 就可以 看到远程仓库的地址,v 是 verbose的缩写,显示详细信息

$ git remote -v
origingit@github.com:iswbm/magic-python.git (fetch)
origingit@github.com:iswbm/magic-python.git (push)

2.3 更改远程

$ git  remote set-url origin git@gitee.com:iswbm/magic-python.git

三、状态回滚

**往下看之前,请先理解这三个Git区域: ** -> ->

3.1 撤消工作区修改

这里分为两种情况:

  1. 实体文件被修改,但还没add到暂存区
  2. add到暂存区,但是实体文件又被修改

无论是哪种情况的撤消,本质都是将工作区的修改直接丢弃,并选择还原到该文件最近的一个状态。

对于第一种情况,离它最近的是版本库,所以撤消完后会还原到版本库的状态;

对于第二种情况,离它最近的是暂存区,所以撤消完后会还原到暂存区的状态。

那么如何撤消呢?

可以用直接删除的方式

git restore <file>

也可以用回退到版本库中版本的方式来

# 注意--之后有空格,最后加你要撤消的文件u
$ git checkout -- readme.txt

3.2 撤消你的 add

可以用删除 add 的方式

# 也可以用 restore,只要加上 --staged
git restore --staged <file>

也可以用回退到版本库中版本的方式来

# 回退到版本库中的版本
git reset HEAD readme.txt

#  由于 HEAD 是默认的选项,因此下面两条命令都是将文件回退到版本库中的版本 git reset <file>             // 撤销单个文件的add
$ git reset                    // 撤销所有文件的add

3.3 撤消 commit

撤消 commit,并且撤消 add,不删除工作区修改

如下两条命令效果一样,因为 --mixed 是默认参数,它的意思是 不删除工作空间改动代码,撤销 commit,并且撤销git add . 操作。

其中 的意思是上一个版本,它等同于 ,如果你进行了 2 次 commit,想都撤回,可以使用 。

$ git reset HEAD^
$ git reset --mixed HEAD^

**只撤消 commit 到暂存区:soft 模式 **

不管暂存区(不管工作区)现在是啥,都删除掉,并回退到上一次 commit 的状态

$ git reset --soft HEAD^

**撤消 commit 到工作区:hard 模式 **

不管暂存区和工作区现在是啥,都删除掉,并回退到上上一次 commit 的状态

$ git reset --hard HEAD^

若只想修改commit message

$ git commit --amend

3.4 回退到特定版本

上面都是介绍回退到上一版本,如果要回退到前几个版本,怎么整呢?

用 HEAD 指定是前几个版本

使用 git reset ,直接回退,不生成新的提交

# HEAD是当前版本
# HEAD^是上一个版本
# HEAD^^是上上个版本
# HEAD~100是前100个版本

# 回到上一个版本
git reset --hard HEAD^ 

# 若本地不小心修改或删除了很多文件,一个一个恢复太麻烦,可以这样,回到上一个版本 git reset --hard HEAD

使用 git revert,间接回退,会生成新的提交

# 会生成一次新的提交,提交重新会有三次提交
git revert HEAD 

# 相反使用 reset,直接将指针指向上一次提交之前,会有 0 次提交 git reset HEAD  

使用 commit id 回退

如果有很多个版本,你也不想去数到底前几个版本,可以使用 commit id 精准回退,就像下面这样

$ git reset --hard 04c632e244 
# hard后面这一串字符是commit id(版本号),只要前面几位就ok,但是如果我们关掉git,想恢复到之前的新版本,但是不知道id了,那就要用第三种方法了

那么问题就来了,如何获取这个 commit id呢?主要有如下两种方法

# 最前面那个即是 commit id,这个commit id 是短的
git reflog git log --oneline

# 这里的 commit id 是长的
git log git log --pretty=online

3.5 撤消你的撤消

当你对本地工作区的修改已经add并commit后,你发现你想撤消你的这些commit,但是你一不小心执行了

$ git reset --hard HEAD^

这条命令会将你的本地工作区的修改也还原到上一次commit。相当于你之前做的所有修改全部都丢失了。

而我们原本只是想撤消 commit 和 add,而不想连本地的修改也丢弃。

这时候如何补救呢?

很简单,先使用 git reflog 找到你的 reset 的 commit id

Git 详细使用指南

然后再次使用 git reset 指定 commit id 回到一次修改add前的状态

Git 详细使用指南

3.6 撤消已经Push到远程的提交

有时,在git push之后,才发现还有一些代码需要进行很小的改动,这些改动在原则上不应该作为一次新的提交。
这时,我们需要撤销这次推送(git push)与提交(git commit),然后进行代码修改,再重新进行提交和推送。

分为两步:

  1. 本地先回退到上一个版本:git reset --soft HEAD^ (使用 hard 会删除本地修改)
  2. 将本地的这次回退推送到远程:git push origin stable/2.3.9 --force (不加–force是推送不了的,stable/2.3.9 是分支名,请对应更改)

如果你不仅是撤消一个提交,而是要回退到多个提交之前,就要找出你要回退到的那个 commit 的 id

  1. 使用 git log --oneline 找出 commit id
  2. 回退到该 commit id 的版本:git reset --soft commit_id
  3. 将本地的这次回退推送到远程:git push origin stable/2.3.9 --force

3.7 回退到远程均分支的版本

$ git reset --hard origin/master

3.7 删除版本库里的文件

# 加了 --cached 就不会删除工作区的文件
git rm --cached file1.txt git commit -m "remove file1.txt"

$ git push origin branch_name

四、分支管理

4.1 新建分支

新建分支

$ git branch -f dev     # 新建, -f 是强制的意思,视情况加不加

但一般情况下,我们希望创建完成后,能立马切换过去,那可以使用下面这条命令

# 创建dev分支,把HEAD指针切换到dev
$ git checkout -b dev

上面这条命令相当于下面两条命令

$ git branch -f dev     # 新建, -f 是强制的意思,视情况加不加
$ git checkout dev   # 切换指针

4.2 查看分支

查看分支

# 查看所有本地分支,*表示当前分支
git branch    

# 查看所有远程分支 git branch -r  

# 查看所有分支
$ git branch -a

4.3 切换分支

# 切换到 dev
git checkout dev

# 切换到 master git checkout master

4.4 合并分支

请参阅:廖雪峰:分支管理策略

合并分支可以一个一个合并,也可以将多个分支一起合并

# 将dev合并到当前分支
git merge dev

# 静默合并,不会输出任何信息 git merge –quiet dev

# 将 dev1 和 dev2 合并到当前分支的顶部
$ git merge dev1 dev2

第一种情况

默认情况下,使用 merge 合并分支,git 会先优先使用 Fast Forward 快速合并,这种模式不会产生新的 commit,如果 master 分支在创建 dev 分支后有内容更新,那么就会产生一个新的 commit

$ git merge  dev

# 等价于
$ git merge --ff  dev

具体什么情况下使用快速合并,什么情况下不使用 快速合并,可前往 分支的合并 ,里面有图解,可以帮助你理解。

你可能发现了,有时候使用 快速合并,有时候又不使用 快速合并,这实在太不可控了。

第二种情况

如果你想在可以进行 Fast Forward 快速合并的时候,而不使用快速合并,该怎么做呢?

你只要加上 --no-ff 参数即可,由于会产生一个新的 commit ,你可以加上 -m 添加合并信息,当然不加的话,Git 会帮你生成默认的合并信息

$ git merge dev --no-ff -m "sometext"

第三种情况

如果你只想使用 Fast Forward 快速合并呢,又该怎么做呢?

只要加上 --ff-only 参数即可

$ git merge dev --ff-only

4.5 删除分支

# 删除本地dev分支:dev不能是当前分支
git branch -d dev

# 删除本地的远程分支 git branch --delete --remotes <remote>/<branch>
git branch --delete --remotes origin/stable/2.2.5 git branch -dr origin/stable/2.2.5

# 直接删除远程分支
git push origin --delete stable/2.2.5

4.6 分支冲突

请查阅:廖雪峰:解决合并冲突问题

  1. master分支:只有a.txt,但在分支dev提交了b.txt,b.txt在master分支是没有的。这种合并是不会有问题的,合并后,master,将增加b.txt
  2. 在分支dev修改了内容,切换到master,对同一文件修改同一处地方的不同内容。这时候合并,就会出现冲突,我们需要手动修改文件为我们需要的内容,然后最后提交。

当合并代码时出现冲突的时候,有两种情况:

1、在本地 merge 就发现冲突

2、在远程 pr 才发现冲突

如果是远程 pr 才发现有冲突,可以将远程的 pr 及 commit 撤消掉

git reset --soft head
git push origin -f

然后在本地要合并的分支里,pull 一下

git checkout feature/2.5.1
git pull origin

再切换到个人分支,支持 merge

git checkout 2.5.1-by-wangbm
git merge feature/2.5.1

这时候本地就会发现冲突,切换到 idea 中,右键项目就会有一个 解决冲突的按钮(这个按钮只有在有冲突的时候才会出现),然后就可以看到有冲突的文件,对每个文件点 merge,进行冲突的处理。

都处理好后,再提交代码到远程,再提交 pr 合并代码。

4.7 本地分支与远程分支

  1. 本地分支如果和远程分支同名,push时只要写一个分支名即可
  2. 如果不同名,可以使用”git push -u origin local_branch_name:remote_branch_name”

五、保存现场stash

假如我们当前正在dev分支工作,但是master主分支有bug需要紧急修复,但是dev的工作才进行到一半,完成还需要一天,我们想在不提交的情况下,把bug修复好,改怎么做?

1、先使用 git stash 将当下修改的内容很保存,此时 git status 就不会有已修改的任何内容

2、然后在当前分支将 bug 修复

3、将修复 bug 的代码合并提交到 master 上

4、再通过 git stash list 可以看到自己保存的内容,使用 git stash pop 恢复之前保存的内容

5、如果 list 中有多个stash,可以选择 git stash apply stash@{1}

6、git stash pop = git stash apply + git stash drop

六、标签管理

6.1 标签的意义

  1. 标签的作用相当于commit ID
  2. 区别在于commit ID是机器生成的,不便于记忆和可读性,tag是人为设定的,有特殊意义,有很强的可读性

6.2 如何打标签

首先切换到你要打标签的分支上,通常是master

$ git tag v1.0  #给当前分支打上v1.0的标签
$ git tag v1.0 6a5819e #如应该在之前版本打的标签没打,可以这样补打
-------------------------------------------------------------------------------

$ git tag  #显示当前分支的所有标签
$ git show v1.0 #查看v1.0的信息:commit ID,Author,Date
--------------------------------------------------------------------------------

$ git tag -a v1.1 -m "version 1.1 released" 3628164 
# -m 添加说明文字,-a v0.1:使用git show v1.1,有tag的信息

标签不自动push到远程,若要push,可以使用命令

$ git push origin v1.0  #推送单个tag
$ git push origin --tags  #一次性推送所有tag

6.3 删除标签

1. 本地删除
git tag -d v1.0  #删除标签v1.0

2. 远程删除(如果已经推送到远程,要先本地删除,再远程删除两个步骤) 
git push origin :refs/tags/v1.0

# 要查看是否远程删除了,可以上GitHub上看

七、查看状态

7.1 文件状态

$ git status #如果修改了文件,状态会提示你有文件被修改(但不能告诉你哪里被修改),提示你要commit
$ cat readme.txt #查看实体文件的内容 
$ git ls-files #查看哪些文件在版本控制下

查看当前目录下有哪些远程仓库

$ git remote     # 远程仓库名字
$ git remote -v  # verbose的缩写,显示详细信息,包括项目url
需要注意的是,当前Git Shell在不同目录下,git remote显示的远程仓库就不同

查看提交的历史

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

查看不同的地方(修改)

$ git diff           # 工作区(work dict)和暂存区(stage)的比较
$ git diff --cached  # 是暂存区(stage)和分支(master)的比较
意思就是说,我们修改文件并保存实体文件,可以使用git diff查看不同之处,再确定是否add到暂存区
保存到暂存区后可以用git diff --cached查看stage暂存区和master分支的不同之处,决定是否commit

$ git diff HEAD -- readme.txt  # 比较工作区和master最新版本readme.txt的不同

查看某个文件的变更记录

# 列出某个文件的变更记录,有 commitID
git log -- filename <filename>

# 查看具体变更了啥 git show <commitID>

# 若该次提交的文件很多,可以只查看指定文件
$ git show <commitID> <filename>

或者

# 相当于上面两个命令的合体
git log -p <filename>

7.2 Git日志

第一种方法

可以查看who在when修改了文件(会写出版本说明),但是这个看着眼花缭乱

 $ git log

第二种方法

显示所有修改的日志

$ git reflog

Git 详细使用指南

第三种方法

以图表的方法

$ git log --oneline --graph -10

Git 详细使用指南

7.3 查看修改

使用 diff 进行查看

Git 详细使用指南

查看两个 commit 之间的修改

$ git diff commit_id1 commit_id2
$ git diff commit_id^!

# 如果只想看改了哪些文件
$ git diff commit_id1 commit_id2 --stat

查看某个 commit 的改动

$ git show commit_id
$ git show --stat commit_id

查看两个分支之间的差异

# 查看两个分支有哪些文件发生改变了
git diff stable/2.2.9 stable/2.3.0 --stat

# 对比某一个文件在两个文件中的变化 
git diff stable/2.2.9 stable/2.3.0 -- README.md
git diff stable/2.2.9:README.md stable/2.3.0:README.md

八、实用命令

8.1 打包最近修改的文件

打包最近一次提交的文件到 zip 包里

git archive --format=zip -o update.zip HEAD $(git diff --name-only HEAD^)

8.2 保留开源项目提交

首先当然是要 git clone

git clone https://github.com/kubevirt/containerized-data-importer.git

然后修改一下 remote

git remote remove origin
git remote add origin https://code.ecp.xxxx.net/scm/kubevirt/containerized-data-importer.git

删除原来的 origin 后,会丢失所有的 release 提交记录,最后只能提交 main 分支

git push -u origin main

8.3 私有仓库用户更换

内网仓库原来的用户名是域帐号,现在全换成名字全拼。

因此底下的 git 凭据要更换,正常来说,是修改两个地方

1、git config

# 如果仓库存在,且有 local 配置才执行,没有就不执行
git config --local user.name "xxx"
git config --local user.email "xxx"

# 都要执行
git config --global user.name "xxx" //非必须执行
git config --global user.email "xxx" //非必须执行

2、windows 凭据

win 里搜索 凭据,删除git仓库的凭据(如果有的话)

正常来说是以上两个步骤,但我这种情况属于第三种情况。

该仓库只有部分人有权限,意味着去 clone 的时候,就会检查是不是 public 的,如果不是,就没有权限查看,这样一来连出现重新输入用户名的机会都没有

因为需要将该 git url 与用户名绑定,当访问该 git url 时,就使用该用户名去访问。

两个方法:

1、使用 git config –global key "value" 格式设置下面两个配置

credential.https://code.ecp.xxxx.net.helper=store
credential.https://code.ecp.xxxx.net.username=wangbingming

2、使用 TortoiseGit 可以 点 Setting ,在 Credential 里添加一个 Helper

URL: https://code.ecp.xxxx.net
Helper: store
Username: wangbingming

文章有帮助,请作者喝杯咖啡?

发表评论