Git学习笔记

Git学习笔记

​​ Remote:远程仓库 Repository:本地仓库

​​ Workspace: 工作区 Index: 暂存区


安装Git

Windows

​ 在官网下载安装程序, 然后按默认选项安装即可。

Git学习笔记

​ 安装完成后,在开始菜单里找到“Git”->“Git Bash”,蹦出一个类似命令行窗口的东西,就说明Git安装成功!

Git学习笔记

Linux

​ 系统版本:CentOS 7.3,x86_64 , root用户

Git学习笔记

​ 查看系统是否已安装git :git --version , 如果提示bash: /usr/bin/git: No such file or directory,则说明系统中还没有安装git; 如果显示了git 版本号,则证明系统中已经安装了git。

​ Redhat系的Linux发行版,安装git最便捷的方法是直接使用yum 安装:yum install git , 但是经过测试,CentOS 7.3 通过yum 安装的Git 版本默认为v1.8.3 , 而目前git最新版本为v2.16.0,低版本的git存在安全漏洞,所以不建议使用yum安装,推荐使用源码安装git.

  1. 卸载已经安装的低版本的git:yum remove git

  2. 安装git依赖包

sudo yum groupinstall "Development Tools" 
sudo yum install -y curl-devel expat-devel gettext-devel openssl-devel perl-CPAN perl-devel zlib-devel
  1. 依赖包安装完成后,需要找出并 下载最新版本的git,,位于列表顶部的是最新版本,注意不要选择带有-rc的版本,因为它代表了一个候选发布版本。

    Git学习笔记

    选择最新的版本 ,使用wget下载:

wget https://github.com/git/git/archive/v2.15.1.tar.gz
  1. 安装git
#解压
tar -zxvf git.tar.gz 
#编译
cd git*   #进入git解压目录
make configure
./configure   --prefix=/usr/local/
make prefix=/usr/local/ all
make install
  1. 查看版本 git --version , 如果显示的git版本还是v1.8或提示找不到git目录,执行命令:cp /usr/local/bin/git* /usr/bin/ ,就可以了。

    Git学习笔记

设置Git

​ 设置你的一些个人信息,如你提交的姓名和电子邮件:

$ git config --global user.name 'shijianzhihu'
$ git config --global user.email 'shijianzhihu@foxmail.com'

#查看所有已配置的全局信息
$ git config --list 

Git 常用命令

以下所有的命令说明都基于Git v2.13.0,不同版本的Git ,命令可能会有所区别!
$ git --version #查看git 版本
$ git [command] --help #查看command用户手册

git clone

git clone 用来从从远程主机克隆一个版本库,语法为:git clone <版本库地址> ,该命令会在本地主机生成一个与远程主机版本库同名的目录,如果要指定不同的目录名,可以将目录名作为git clone命令的第二个参数:
git clone <版本库的网址> <本地目录名>

git remote

Git要求每个远程主机都必须指定一个主机名。git remote命令就用于管理主机名.

#查看所有远程主机名
$ git remote
origin

#查看远程主机地址
$ git remote -v
origin  https://github.com/naver/ngrinder.git (fetch)
origin  https://github.com/naver/ngrinder.git (push)

git fetch

一旦远程主机的版本库有了更新,需要将这些更新取回本地,这时就要用到git fetch命令.

#将远程主机的所有分支的更新取回本地
$ git fetch <远程主机名>
如:git fetch origin

#取回指定分支的更新
$ git fetch <远程主机名> <分支名>
如:git fetch origin dev

git branch

git branch 用来显示、创建或删除分支。

OPTIONS

# 不带参数时,会列出所有本地分支,并且在当前分支前加"*";
$ git branch
  dev
  master
* test

<newBranch>
#新建本地分支,但不会自动切换到该分支
$ git branch bug-fixed

<-r, --remotes>
#列出所有远程分支
$ git branch -r
  origin/bug-fixed
  origin/b2b
  origin/beta
  origin/collections
  origin/chart

<-a --all>
#列出所有本地分支和远程分支
$ git branch -a

<-m ,--move | -M>
#移动/重命名一个分支和相应的历史信息
#<-M>:强制move/rename
$ git branch -m bug-fixed bug-fixed2

<-d, --delete | -D>
#删除本地分支,不能删除当前checkout的分支;
#如果要删除的分支有未合并的内容,则会报错:'the branch  XXX is not fully merged',解决办法:使用'-D' 强制删除;
$ git branch -D 'bug-fixed'

#补充:利用shell管道命令实现批量删除分支
$ git branch | grep 'branchName' | xargs branch -D

<--set-upstream-to origin/branchname localBranchname>
注意,<–set-upstream-to> 在已经替代了 <–set-upstream>,二者跟随的参数需要对调一下位置;
#设置本地分支与远程分支关联,如果没有关联的情况下,git pull 会提示如下信息:
$ git push origin test
$ git pull
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details.

    git pull <remote> <branch>

If you wish to set tracking information for this branch you can do so with:

    git branch --set-upstream-to=origin/<branch> test
    
设置远程关联分支的方法,如下
$ git branch --set-upstream-to origin/test test
Branch test set up to track remote branch test from origin.
$ git pull
Already up-to-date.

<-v, --verbose | -vv>
#<-v>:查看本地分支最后的修改信息,当前分支名称前会带有'*'
$ git branch -av
  bug-fixed3 fdcbdf7 add bug -fixed2
  dev        1599863 test
* master     9faecaf [ahead 1] update test.txt  #[ahead 1]表示本地分支比远程分支领先一个commit
  test       1599863 test
  remotes/origin/HEAD       -> origin/master
  remotes/origin/bug-fixed3 fdcbdf7 add bug -fixed2


#<-vv>:在git branch -v的基础上,显示本地分支的远程关联分支(upstream branch);
#查看远程关联分支,可以使用git config --list命令
$ git branch -vv
  bug-fixed3 fdcbdf7 add bug -fixed2
  dev        1599863 test
* master     9faecaf [origin/master: ahead 1] update test.txt 
  test       1599863 test

git checkout

git checkout 用来切换分支或恢复工作树文件。

OPTIONS

<branch>
#切换当前分支到本地已有分支
$ git checkout dev
Switched to branch 'dev'

#新建本地分支,并切换到该分支
$ git checkout -b five
Switched to a new branch 'five'

#新建本地分支,并切换到该分支,而且关联远程分支
$ git checkout -b six --track origin/dev
Switched to a new branch 'six'
Branch six set up to track remote branch dev from origin.

第三条命令相当于以下命令的合集:
$ git branch 
$ git checkout six
$ git branch --set-upstream-to origin/dev six

<-- fileNmae> #'--' 和'fileName'之间有空格!
#将指定文件在工作区的修改撤销到最近一次git add 或git commit时的内容(只对tracked file有效)
比如下面的两个例子:
$ cat test.txt
one
$ git add . -v
add 'test.txt'
$ git commit -m 'update test.txt'
[test a2d987d] update test.txt
 1 file changed, 1 insertion(+)
$ vim test.txt
$ cat test.txt
one
two
$ git checkout -- test.txt #注意空格,否则报错
$ cat test.txt
one
$ git status 
nothing to commit, working tree clean
****************************************
$ cat test.txt
one
two
$ vim test.txt
$ cat test.txt
one
two
three
$ vim test.txt
$ cat test.txt
one
two
three
four
$ git checkout -- test.txt
$ cat test.txt
one
two

补充:
$ git checkout -- stu.txt test.txt
$ git checkout -- *
$ git checkout -- *.txt

# git checkout -- 不加文件名来查看当前工作区修改了哪些文件
$ git checkout --
M       blog.txt
D       start.txt
Your branch is up-to-date with 'origin/sprider'.

# 取文件在commit_id时的版本
$ git checkout 1599863 fileName

git status

git status 用来显示工作树状态, git会非常友好的提示用户下一步的操作,请看下面的例子:

$ git status
On branch test
Your branch is up-to-date with 'origin/test'.
Untracked files:
  (use "git add <file>..." to include in what will be committed)

        blog.txt

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

$ git add blog.txt

$ git status
#
On branch test
Your branch is up-to-date with 'origin/test'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        new file:   blog.txt

$ git commit -m 'add blog.txt'
$ git status
On branch test
Your branch is ahead of 'origin/test' by 1 commit.
  (use "git push" to publish your local commits)
nothing to commit, working tree clean

git add

git add命令主要用于把我们要提交的文件的信息添加到索引库(Index)中。当我们使用git commit时,git将依据索引库中的内容来进行文件的提交。git add命令可以在commit之前多次执行。

Git学习笔记
git add file

COMMON OPTIONS

<pathspec>
#可以使用'*'模糊匹配路径
$ git add *.c
# 路径可以到目录层级
$ git add test/

<-v,--verbose>
#显示本次added的文件名
$ git add -v file3.txt
add 'file3.txt'
$ git add -v study/
add 'study/study.txt'

<-f, --force>
#允许添加被忽略的文件
#关于git忽略文件的介绍,见下一小节
$ git add -f commonVars.pyc

<-u, --update>
#add被修改(modified)和被删除(deleted)文件,不包含新文件(new,untracked file)
$ git add -uv

<-A, --all>
#add所有变化,包括被修改(modified)、被删除(deleted)文件和包括新文件(new)
$ git add -Afv

git add -A | git add -u |git add .

  • git add .:他会监控工作区的状态树,使用它会把工作时的所有变化提交到暂存区,包括modified、new和deleted ;
  • git add -u:他仅监控已经被add的文件(即tracked file),他会将被修改的文件提交到暂存区。add -u 不会提交new(untracked file);
  • git add -A:等同于 git add .;
    注意,在Git v1.x.x版本,git add . 不能添加deleted文件

git 特殊文件

有些时候,我们必须或被必须把某些文件放到Git的工作目录中,但是又不能提交它们。这就导致每次git status都会显示Untracked files ... 。为了解决这个文件,可以在Git工作区的根目录下创建一个特殊的.gitignore文件,这个文件的作用就是告诉Git哪些文件不需要添加到版本管理中。实际项目中,很多文件都是不需要版本管理的,比如Python的.pyc文件和一些包含密码的配置文件等等。这个文件的内容是一些规则,Git会根据这些规则来判断是否将文件添加到版本控制中。

Git bash创建".gitignore" : vim .gitignore , GitHub中已经为我们准备了各种配置文件,只需要组合一下就可以使用了。所有配置文件可以直接在线浏览:https://github.com/github/gitignore
常用的规则有:

1. /mtk/        #过滤整个文件夹
2. *.zip          #过滤所有.zip文件
3. /mtk/do.c   #过滤某个具体文件

忽略文件的原则是:

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

git commit

git commit 记录对存储库的更改信息,此命令默认提交的是暂存区的内容,也就是 Changes to be committed 中的文件,最常用的参数是<-m>,用来添加本次提交的相关信息,如:git commit -m 'update file'

如果使用了<-a>参数,则除了将暂存区里的文件提交外,还提交 Changes but not updated 中的文件。通常我们提交git的时候都是通过以下三大步:

git add .
git commit -m "some str"
git push

实际上,你只需要两条命令就够了,除非有新的文件(untracked file)要被添加进去。

git commit -am "some str"
git push

git pull

git pull命令的作用是,取回远程主机指定分支的更新,再与本地的指定分支合并。实质上等同于先做git fetch,再做git merge.

#完整格式
$ git pull <远程主机名> <远程分支名>:<本地分支名>

#比如:取回origin主机的bugifx分支与本地的bugfix2分支合并,需要写成下面这样
git pull origin bugfix:bugfix2

#如果远程分支是与当前分支合并,则本地分支名可以省略
$ git pull origin dev

#如果当前分支与远程分支存在关联关系,远程分支名也可以省略
$ git pull origin

#如果当前分支只有一个追踪分支,则远程主机名也可以省略
$ git pull
#上面命令表示为:当前分支自动与唯一一个追踪分支进行合并

**********************************************************
#如果合并需要使用rebase模式,可以加上'-- rebase'选项
$ git pull --rebase <远程主机名> <远程分支名>:<本地分支名>
**********************************************************

#如果远程主机删除了某个分支,默认情况下,git pull 不会在拉取远程分支的时候,删除对应的本地分支。这是为了防止,由于其他人操作了远程主机,导致git pull不知不觉删除了本地分支。但是,你可以改变这个行为,加上参数 -p 就会在本地删除远程已经删除的分支。
$ git pull -p
# 等同于下面的命令
$ git fetch --prune origin 
$ git fetch -p

git:查看追踪分支

#这个信息实际是存在config 文件中的,可以用下面的命令来查看xxx分支的信息
$ git config -l |grep 'branch.xxx'

# git v2.15+版本,可以使用以下命令查看追踪分支信息
$ git branch -vv
Git学习笔记

Git学习笔记

git:手动设置追踪分支

#方法一
$ git branch --set-upsteam XXX origin/xxxx

#方法二
#删掉本地分支,然后重新创建此分支,并且指定其 track 信息
$ git checkout -b XXX --track origin/xxxx

git push

git push命令用于将本地分支的更新,推送到远程主机。它的命令格式与git pull命令相仿但不要搞混了,其实很容易理解区分的.

#完整格式
$ git push <远程主机名> <本地分支名>:<远程分支名>

#如果省略远程分支名,则表示将本地分支推送与之存在"追踪关系"的远程分支(通常两者同名)
#如果该远程分支不存在,则会被新建。
$ git push origin dev

#如果省略本地分支名,则表示删除指定的远程分支,因为这表示推送一个空的本地分支到远程分支。
$ git push origin :dev
#注意origin 和冒号之间需要有空格

#如果当前分支与远程分支存在关联关系,远程分支名也可以省略
$ git push origin
如果当前分支与远程分支没有追踪关系,则会报错:
fatal: The current branch bug-fixed2 has no upstream branch.
To push the current branch and set the remote as upstream, use
    git push --set-upstream origin bug-fixed2
    
#如果当前分支只有一个追踪分支,则远程主机名也可以省略
$ git push

git log | git reflog

git log 用来查看当前分支的提交历史,不包含已经被撤销的commit:

$ git log
commit 150089329868f665cfd6a1f1ac301d31ff232c75 (HEAD -> sprider)
Author: xxxxx <shijianzhihu@foxmail.com>
Date:   Tue Feb 6 14:14:06 2018 +0800
    Revert "test"
    This reverts commit 5e2d6fc0bd652de0e612e50b84edb9b933d2d459.
commit 5e2d6fc0bd652de0e612e50b84edb9b933d2d459
Author: xxxxx <shijianzhihu@foxmail.com>
Date:   Tue Feb 6 14:13:54 2018 +0800
    test

如果嫌输出信息太多,以试试加上--oneline参数:

$ git log --oneline
1500893 (HEAD -> sprider) Revert "test"
5e2d6fc test
a0eb8b5 update blog.txt
ec9734c Revert "start test"
1616640 Revert "blog"

显示每次提交的内容差异可以使用< -p> 参数,<-n>则为仅显示最近的n次历史:

$ git log -p -1
commit 150089329868f665cfd6a1f1ac301d31ff232c75 (HEAD -> sprider)
Author: xxxxx <shijianzhihu@foxmail.com>
Date:   Tue Feb 6 14:14:06 2018 +0800
    Revert "test"
    This reverts commit 5e2d6fc0bd652de0e612e50b84edb9b933d2d459.
diff --git a/blog b/blog
index 40a3b4a..9daeafb 100644
--- a/blog
+++ b/blog
@@ -1 +1 @@
-test111
+test

git reflog 用来显示整个本地仓储的commit, 包括所有branch的commit, 甚至包括已经撤销的commit, 只要HEAD发生了变化(如checkout branch, pull, commit等), 就会在reflog里面看得到。

$ git reflog
1500893 (HEAD -> sprider) HEAD@{0}: checkout: moving from six to sprider
02cffe0 (six) HEAD@{1}: commit: branch six
1599863 (origin/dev, five) HEAD@{2}: checkout: moving from sprider to six
1500893 (HEAD -> sprider) HEAD@{3}: revert: Revert "test"
5e2d6fc HEAD@{4}: commit: test

git revert | git reset

git revert 用来回滚一些现有的提交, 但并不是从项目历史中移除这个commit,旧的commit还是保留在历史项目里面的,而git reset 则会删除旧的commit, 这样做的好处是防止了项目丢失历史。

用法: git revert <commit-id>

$ git log --oneline | head -n 1
a0eb8b5 update blog.txt

$ git revert HEAD
[sprider 60d4654] Revert "update blog.txt"
 1 file changed, 1 insertion(+), 2 deletions(-)
 
$ git log --oneline | head -n 2
60d4654 Revert "update blog.txt"
a0eb8b5 update blog.txt

git reset <--hard|soft|mixed|merge|keep> commit 也是常用的版本回滚命令,其中比较重要的参数是mode,也就是 --hard、--soft、--mixed。。。比较常见的是--hard和--soft;

--hard是指完全重设,会把回退到某版本之后的修改全部删除,

--soft这是个回退解体,让版本库回退到某个版本,这个版本之后的修改全部存在缓存区,这个时候在commit的话,又会把会退的部分重新加载到最新版本中;

git diff

git diff用于比较两次修改之间的差异。

  • 比较工作区与暂存区

git diff 不加参数即默认比较工作区与暂存区

$ git diff
diff --git a/b2.txt b/b2.txt
index be738a5..2ffe5d8 100644
--- a/b2.txt
+++ b/b2.txt
@@ -1,2 +1,2 @@
 test1
-test222
+22dsada2
  • 比较暂存区与最新本地版本库
    git diff --cached
  • 比较工作区与最新本地版本库
    git diff HEAD
  • 比较工作区与指定commit-id的差异
    git diff commit-id
  • 比较暂存区与指定commit-id的差异
    git diff --cached commit-id
  • 比较两个commit-id之间的差异
    git diff commit-id commit-id

git stash

git stash 用来备份当前的工作区的内容,从最近的一次提交中读取相关内容,让工作区保证和上次提交的内容一致。同时,将当前的工作区内容保存到Git栈中。

git stash list 显示Git栈内的所有备份,可以利用这个列表来决定从那个地方恢复。
git stash clear 清空Git栈.
git stash pop 从Git栈中读取最近一次stash的内容,恢复工作区的相关内容。

两种恢复方法:

  • 用git stash apply恢复,但是恢复后,stash内容并不删除,你需要用git stash drop来删除;
  • 用git stash pop,恢复的同时把stash内容也删了;

可以多次stash,恢复的时候,先用git stash list查看,然后恢复指定的stash,用命令:
git stash apply stash@{0}

git rm

git rm用于从从工作树和暂存区中删除文件,他作用的对象只能是tracked files .

它的作用和git add 类似,可以理解为一个是添加一个是修改。git rm 要和git commit 配合使用,才真正能起到删除的作用。

$ git rm test.txt stu.txt
rm 'stu.txt'
rm 'test.txt'
$ git status
On branch test
Your branch is up-to-date with 'origin/test'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        deleted:    stu.txt
        deleted:    test.txt
$ git commit -m 'delete two files'
[test ccd7143] delete two files
 2 files changed, 4 deletions(-)
 delete mode 100644 stu.txt
 delete mode 100644 test.txt
$ git status
On branch test
Your branch is ahead of 'origin/test' by 1 commit.
  (use "git push" to publish your local commits)
nothing to commit, working tree clean

#删除文件夹,-r表示递归删除,-f表示强制删除
$ git rm -rf qt/ 
rm 'qt/file.txt'

$ git rm -f rainbow.txt #不能对untracked file使用
fatal: pathspec 'rainbow.txt' did not match any files

git rm 和 rm 的区别

通过上面简单的介绍,我们发现git rm 和 shell 命令rm 非常相似,我们是否可以不使用git rm,而是直接rm后,然后再git add/commit,这样是否可以呢? 答案当然是可以的。

使用git rm来删除文件,git同时会将操作日历记录下来,git log就可以看到;而使用rm来删除文件,git并不会记录,这也是十分易于理解的。直观的来讲,git rm 删除过的文件,执行 git commit -m "abc"提交时,会自动将删除该文件的操作提交上去;而对于用 rm 命令直接删除的文件,执行 git commit -m "abc" 提交时,则不会将删除该文件的操作提交上去。不过不要紧,即使你已经通过 rm 将某个文件删除掉了,也可以再通过 git rm 命令重新将该文件从 git 的记录中删除掉,这样的话,在执行 git commit -am "abc"后,也能将这个删除操作提交上去。(git commit -am 写成git commit -ma 会报错)

一般说来,在git目录下删除文件时,可以选择以下两种方式:

  • git rm + git commit -m 'text'
  • rm + git commit -am 'text'

git mv

git mv 用来移动或重命名文件、目录或符号链接。

$ git mv b1.txt b2.txt
$ git mv rainbow.txt sprider/
$ git status
On branch sprider
Your branch is ahead of 'origin/sprider' by 1 commit.
  (use "git push" to publish your local commits)
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
        renamed:    b1.txt -> b2.txt
        renamed:    rainbow.txt -> sprider/rainbow.txt
        
$ git commit -m 'rename and move'
[sprider b08e44d] rename and move
 2 files changed, 0 insertions(+), 0 deletions(-)
 rename b1.txt => b2.txt (100%)
 rename rainbow.txt => sprider/rainbow.txt (100%)

参考文档

  1. Git 教程,廖雪峰

  2. Git远程操作详解,阮一峰

  3. Git忽略规则.gitignore梳理 ,散尽浮华

  4. git的reset和checkout的区别,chanjarster

  5. git add -A 和 git add . 的区别 ,PajamaCat

  6. git branch用法总结 ,KKK_Kevin

  7. Git自学之路(四) - gitbranch 分支,JunkChen-程开均

  8. Git中的upstream和downstream概述,易生一世

  9. “git rm” 和“rm”的区别,jfkidear

  10. git commit -m与git commit -am的区别

  11. Git的撤消操作 - 重置, 签出 和 撤消

上一篇:从零搭建Robot Framework+Jenkins持续集成环境


下一篇:使存储虚拟化更智能的五种方法