阅读 1133

Git命令详解和实战技巧

git init

git init 命令可以创建一个空的Git Repository ,也可以把任何一个目录变成一个 Git Repository 。

git init 命令后跟着一个目录名就会创建一个空的Git Repository,否则就是把当前的目录变成一个 Git Repository。

一个空的Git Repository目录里面除了有一个.git目录之外什么都没有。

git clone

clone 命令可以克隆一个版本库。非常简单好用,完整形式是 git clone 仓库 <目录> ,目录可以省略。 新克隆出来的这个版本库里的.git/config文件会记录上游版本库repository的位置

$git clone git@gitlab.demo.com:gp/git-demo.git
Cloning into 'git-demo'...

#git clone <repository> <directory>  
$git clone git@gitlab.demo.com:gp/git-demo.git abc
Cloning into 'abc'...

#使用Git下载v2分支代码,使用命令:
git clone -b v2  https://github.com/vuejs/vue-cli.git

#克隆出来的版本库不包括工作区,直接就是版本库的内容,也就是不包括.git目录。
#而是直接就是.git目录里面的内容。这样的版本库称为裸版本库
git clone --bare   <repository> <directory>

#也是克隆出一个裸版本库。不过是可以通过git fetch命令与上游版本库repository持续同步。
git clone --mirror <repository> <directory>
复制代码

git-clone官网

git add

git add . git add -A 和 git add -u的区别

经我验证,我的git version 2.9.2 是这样的。1版本的有不同。

  • git add . 操作的对象是当前目录下的所有变更(增+改+删),. 表示当前目录。
  • git add -A 操作的对象是整个工作区的所有变更(增+改+删),无论当前位于哪个目录下。
  • git add -u 操作的对象是整个工作区已经跟踪的变更(update: 只包括更新和删除,不包括新增),无论当前位于哪个目录下。
  • 但是别的文章写道 git add *会忽略.gitignore把任何文件都加入,然尔,我试过后和git add -A一样。
 ➜  daybyday git:(master) git add * # 如果想添加,只能用-f强制加入               
The following paths are ignored by one of your .gitignore files:
dist1
Use -f if you really want to add them.
复制代码
  • $git add READMD.md .gitignore 多个文件用空格分开
  • git add命令可以用-f(force)选项添加被忽略的文件

git push

git push 命令会把本地版本库的git对象上传到远程版本库,并用本地分支引用更新远程版本库对应分支的引用。

  • push命令的比较完整的写法是git push 上游版本库 本地分支:远程分支 ,当本地分支于远程分支同名时只需 git push 上游版本库 本地分支

  • push不光可以推送到远程已经存在的分支,也可以推送到不存在的分支,当推送到不存在分支时,就创建了这个远程分支。

  • 在每次push前 一定要先pull一下,同步一下远程版本库的最新信息。当push到不存在的分支时一定是成功的。

$git checkout develop
$git push origin develop:feature                        
* [new branch]      develop -> feature #这样就在远程版本库创建了一个feature新分支

# 删除远程的feature分支
➜  daybyday git:(master) git push origin :feature 
To git@gitlab.demo.com:gaopo/daybyday.git
- [deleted]         feature
复制代码

git pull 和 git fetch

git fetch

  • git fetch 命令可以把上游版本库的更新下载到本地版本库,这个更新包括Git对象和分支引用。

当上游版本库有新的提交后,上游版本库相关的分支文件会被更新,objects目录里会多了最新提交所对应的commit , tree,和blob对象。git fetch命令就是负责把这些更新下载到本地版本库。

本地版本库执行了git pull或 git fetch命令后,.git/refs/heads/remotes/origin目录下会生成对应的分支文件。

git pull

git pull 命令等价于 git fetch + git merge

git pull 命令先把远程版本库的更新下载到本地,然后和本地的分支合并 。

$git pull origin develop
#上面这条命令和用下面的两条命令的做的事情一样
$git fetch
$git merge origin/develop
复制代码

git remote

  • git clone之后本地就会有一个名为 origin的上游,上游的分支信息保存在 .git/refs/remotes/origin 目录下 。

  • 其实git版本库可以有多个上游版本库,这完全取决于实际的需要。

  • git remote add 上游名 URL 命令可以添加上游版本库。现在我们就用这个命令再添加一个上游版本库,随便起个名字比如叫 upstream2

查看

$ git remote -v
bakkdoor  https://github.com/bakkdoor/grit (fetch)
bakkdoor  https://github.com/bakkdoor/grit (push)
cho45     https://github.com/cho45/grit (fetch)
cho45     https://github.com/cho45/grit (push)
#查看某一个远程仓库的更多信息
$ git remote show origin
复制代码

新增

$git remote add upstream2 http://git.demo.com/gp/git-demo2.git
$cat .git/config
...
[remote "origin"]
    url = git@gitlab.demo.com:gp/git-demo.git
    fetch = +refs/heads/*:refs/remotes/origin/*
#多了一个[remote]节点,名为upstream2
[remote "upstream2"]
    url = http://git.demo.com/gp/git-demo2.git
    fetch = +refs/heads/*:refs/remotes/upstream2/*
    
复制代码

修改、重命名和删除

#修改upstream2上游版本库的URL
$git remote set-url upstream2 git@gitlab.demo.com:gp/git-demo.git 
#把upstream2重命名成upstream1
$git remote rename upstream2 upstream1                                       
$cat .git/config
...
[remote "origin"]
    url = git@gitlab.demo.com:gp/git-demo.git
    fetch = +refs/heads/*:refs/remotes/origin/*
...
#名字变为了upstream1,之前是upstream2
[remote "upstream1"] 
    url = git@gitlab.demo.com:gp/git-demo.git  
    #URL变成了git-demo.git , 之前是git-demo2.git
    fetch = +refs/heads/*:refs/remotes/upstream1/*
#删除上游版本库upstream1,.git/config文件的[remote "upstream1"]节点会被删掉  
$git remote rm upstream1                   
复制代码

git remote 的相关命令就是修改 .git/config文件而已,其实我们也可以手动编辑完成。

分支

git branch 查看本地分支 , git branch -r 查看远程分支 , git branch -a 查看所有分支, git branch -v 现实分支对应的提交号 git branch 分支名 ,基于头指针(HEAD)创建一个分支 git branch 分支名 提交号 基于指定的提交号创建一个分支 git branch -D 分支名删除一个分支 git branch -m 旧分支名 新分支名 重命名一个分支

#git checkout -b 新建并切换分支, 等价于 git branch feature ; git checkout feature
$git checkout -b feature 

$git branch
  develop
* feature
  master
$git checkout master
$git branch -D feature   #git branch -D 删除一个分支
Deleted branch feature (was e6361ed).
复制代码

tag

在 Git 中列出已有的标签是非常简单直观的。 只需要输入 git tag:

$ git tag
v0.1
v1.3
...
#如果只对 1.8.5 系列感兴趣,可以运行:
$ git tag -l 'v1.8.5*'
复制代码

创建标签

Git 使用两种主要类型的标签:轻量标签(lightweight)与附注标签(annotated)。

  • 一个轻量标签很像一个不会改变的分支 - 它只是一个特定提交的引用。
#创建轻量标签,不需要使用 -a、-s 或 -m 选项,只需要提供标签名字:
$ git tag v1.4-lw
$ git tag
v1.4
v1.4-lw
v1.5
复制代码
  • 在 Git 中创建一个附注标签是很简单的。 最简单的方式是当你在运行 tag 命令时指定 -a 选项:
$ git tag -a v1.4 -m 'my version 1.4'
$ git tag
v0.1
v1.3
v1.4
复制代码

通过使用 git show 命令可以看到标签信息与对应的提交信息:

$ git show v1.4
tag v1.4
Tagger: Ben Straub <ben@straub.cc>
Date:   Sat May 3 20:19:12 2014 -0700

my version 1.4

commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Mon Mar 17 21:52:11 2008 -0700

    changed the version number
复制代码

默认情况下,git push 命令并不会传送标签到远程仓库服务器上。

如果想要一次性推送很多标签,也可以使用带有 --tags 选项的 git push 命令。 这将会把所有不在远程仓库服务器上的标签全部传送到那里。

$ git push origin v1.5
$ git push origin --tags
复制代码

删除标签

要删除掉你本地仓库上的标签,可以使用命令 git tag -d <tagname>。例如,可以使用下面的命令删除掉一个轻量级标签:

$ git tag -d v1.4-lw Deleted tag 'v1.4-lw' (was e7d5add) 应该注意的是上述命令并不会从任何远程仓库中移除这个标签,你必须使用 git push <remote> :refs/tags/<tagname>来更新你的远程仓库:

#git push 上游版本库 :tagname 删除远程里程碑
$ git push origin :refs/tags/v1.4-lw
To /git@github.com:schacon/simplegit.git
 - [deleted]         v1.4-lw
复制代码

git status

$git status
On branch develop
Your branch is up-to-date with 'origin/develop'.
Changes to be committed:                          #暂存区需要commit到版本库的文件
  (use "git reset HEAD <file>..." to unstage)
  
    modified:   .gitignore
  
Changes not staged for commit:                    #已经加入到暂存区之后又修改了的文件,这时要么再次add暂存区,要么用暂存区的快照覆盖工作区这个文件
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)
  
    modified:   README.md
  
Untracked files:                                  #还从来没有add到暂存区的文件 ,Untracked ,未跟踪
  (use "git add <file>..." to include in what will be committed)
  
    a.txt
复制代码

git config

用户名和邮箱地址相当于你的身份标识,是本地Git客户端的一个变量,不会随着Git库而改变。

每次commit都会用用户名和邮箱纪录。

github的contributions跟你的邮箱是有关联的。

#查看自己的用户名和邮箱地址
$ git config user.name
$ git config user.email

#修改自己的用户名和邮箱地址
$ git config --global user.name "xxx"
$ git config --global user.email "xxx"

复制代码

git diff

git diff #命令可以查看工作区,暂存区,版本库之间文件的差别
git diff #工作区和暂存区之间的差别
git diff HEAD  #工作区和版本库之间的差别
git diff --staged #暂存区和版本库之间的差别
复制代码

git commit + log

git commit 命令生成一个commit对象以及这个commit对象对应的一系列tree对象和blob对象。这个commit对象的tree对象的与暂存区的目录树指向同样的内容。 常用的用法是 git commit -m 'commit message' ,最近的一次 'commit message'会保存在 .git/COMMIT_EDITMSG 文件中。


git log --graph    #通过简单图形现实分支之间的merge关系,但是不太好用,一般都用工具看。
#git log --pretty=raw 现实提交的详细内容
commit 44842943fc03c341e7ec98e909de9cae9f814d22
tree 4a9cfd52af007896b16466a08391f6823907456f
parent 66c9c59da472f310284371bcae7f88ca707991a1
parent f27425799dfa432b015e44788d05443a38545266
author gaopo <gaopo@demo.com> 1554785199 +0800
committer gaopo <gaopo@demo.com> 1554785199 +0800

    解决冲突

#git log --stat 可以现实本次提交所新增和修改的文件
 .idea/workspace.xml             | 18 ++++++++----------
 app/controllers/api/dingtalk.js |  8 ++++----
 2 files changed, 12 insertions(+), 14 deletions(-)

git log -数字   #只现实数字指定的最近几次提交


复制代码

可以通过 git commit --amend -m 'commit 的要改成的内容' 修改上一次提交的描述,也可以 git commit --amend 直接打开编辑器修改(vim)。

更多技巧>Git 基础 - 查看提交历史

reset

git reset 命令是Git最常用的命令之一,用来重置分支的引用和替换暂存区和工作区。

git reset --hard 提交号 这个命令会将当前分支的引用指向新的提交号。替换暂存区,替换后暂存区的内容和新提交的tree一致。替换工作区,替换后工作区内容和暂存区一致。执行这个命令后会让工作区 暂存区 版本库的内容一致。

git reset --soft 提交号 这个命令只会更变当前分支的引用,不影响暂存区和工作区。比如 git reset --soft HEAD^ 会将引用向前回退一次。

git reset --mixed 提交号 这是git reset命令默认的形式,改变当前分支的引用和替换暂存区,不影响工作区。

git reset 或 git reset HEAD 命令会用HEAD指向的目录树(tree)重置暂存区,不影响工作区。

git reset 文件名 或 git reset HEAD 文件名 这个命令会将对应文件的改动撤出暂存区,即用HEAD提交中的文件替换暂存区中的文件,不影响工作区。

git reset 可以重置分支引用,是因为他修改了 refs/heads/下的分支文件的内容。

.gitignore 忽略说明

常用如下:

`dist` #忽略文件夹dist/,dist文件名,dist.各种文件后缀如(dist.html,dist.js...),无论哪个文件夹级。
`dist/` #忽略文件夹dist/,根目录或者其他子目录里面有dist/ 都忽略。
`/dist` #只忽略根目录文件夹dist/,不忽略其他子目录里面dist/。

/dist/*
!/dist/bin/
#忽略 /dist/目录下全部内容,但是不忽略bin目录下的

/dist/*
!/dist/5.html
#忽略 /dist/目录下全部内容,但是不忽略5.html

/abc/*
!/abc/*.html
#忽略 /dist/目录下全部内容,但是不忽略`html`为扩展名的文件

#注意:如果父目录已经被忽略,要先对父目录使用!规则`!/dist/`,使其不被排除。

# 删除掉.gitignore里面过滤的文件
➜  daybyday git:(master) ✗ git clean -fX
Removing .DS_Store
Removing fw/hul.js

复制代码

git rm

git rm 会把工作区和暂存区都删掉

删除远程仓库中以前上传的此类文件而保留本地文件

# -r 递归删除
# --cached 只删除索引区(暂存区),无论工作区修改没有都将保留工作区。
➜  daybyday git:(master) ✗ git rm --cached dist1     
fatal: not removing 'dist1' recursively without -r
➜  daybyday git:(master) ✗ git rm --cached -r  dist1
rm 'dist1/dist/sdf.html'
rm 'dist1/new.html'
rm 'dist1/sdf.html'
rm 'dist1/up.html'

复制代码

cat-file

git cat-file 命令可以查看一个Git对象的类型和对象内容

git cat-file -t 对象引用名或SHA1 ,查看对象类型;

git cat-file -p 对象引用名或SHA1 查看对象内容

$git cat-file -t HEAD
commit
$git cat-file -t HEAD^{tree}
tree

➜  notify git:(master) ✗ git cat-file -p HEAD 
tree 7676819607cc8c2b0310dbc0f90a7d3789f2e300
parent 44842943fc03c341e7ec98e909de9cae9f814d22
author gaopo <gaopo@demo.com> 1554785677 +0800
committer gaopo <gaopo@demo.com> 1554785677 +0800

不限部门

$git cat-file -p e6361ed
复制代码

rev-parse

git rev-parse 可以查看一个引用名字所对应的提交SHA1哈希值

$git rev-parse HEAD
e6361ed35aa40f5bae8bd52867885a2055d60ea2
$git rev-parse master
e6361ed35aa40f5bae8bd52867885a2055d60ea2
$git rev-parse refs/heads/master
e6361ed35aa40f5bae8bd52867885a2055d60ea2
$git rev-parse v1.0
baa10bc4dc2ba6ff13e0bd0cdd50d8e9d36564a8
$git rev-parse origin/master
e6361ed35aa40f5bae8bd52867885a2055d60ea
复制代码

别名

查看别名设置:

# 用 alias gcm 查看该别名设置:
➜  ~ alias gcm
gcm='git checkout master'



# 或者用shell 命令type
➜  ~ type gaa
gaa is an alias for git add --all

复制代码

查看当前 SHELL

➜  ~ env
SHELL=/bin/zsh
ZSH=/Users/gaopo/.oh-my-zsh
复制代码

~/.zshrc 设置别名

因为用的是 zsh ,就在 ~/.zshrc

alias gpull="git pull origin"
alias gpush="git push origin"
alias gs="git status"

alias npmr="npm run dev"
alias npmb="npm run build"
alias npms="npm run server"
alias wsm="webstorm"   # webstorm 编辑器的别名
复制代码

zsh 安装了 oh-my-zsh,自带了一个 git 插件

cd ~/.oh-my-zsh/plugins/git
ls
README.md      git.plugin.zsh
复制代码

git.plugin.zsh 里面的内容有特别多的别名设置

# Aliases
# (sorted alphabetically)

alias g='git'
alias ga='git add'
alias gaa='git add --all'
alias gapa='git add --patch'
alias gau='git add --update'
alias gb='git branch
alias gl='git pull'
alias gp='git push'
alias gcm='git checkout master'
alias gcd='git checkout develop'
alias gcmsg='git commit -m'
alias gco='git checkout'
。。。
...

复制代码

更新下配置文件

source ./zshrc
复制代码

关注我,更多好文奉上!!!