git命令详细版


使用的时候常忘记,因此记录一下长点心吧!
注:文档较长,可以转到目录有选择查阅。
在这里插入图片描述
Git 是目前最流行、最好用的版本控制系统,在它的基础之上催生出了 GitHub 和 GitLab 这两个当前最流行的代码托管平台。本文梳理了一些常用的Git命令。

Git(读音为/gɪt/。)是一个开源的分布式版本控制系统,可以有效、高速地处理从
很小到非常大的项目版本管理。Git 是 Linus Torvalds 为了帮助管理 Linux 内核
开发而开发的一个开放源码的版本控制软件。

git整个工作流的whole picture可以参考下面这张图片:

image-20190831105613619

图中的各部分分别表示:

  • 工作区Workspace:就是你在电脑里能看到的目录,即你代码放的那个文件夹。即时性强,对文件的所有更改都会立刻提现在这里
  • 版本库:工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库
  • 暂存区 Index/Stage:git add以后,当前对文件的更改会保存到这里
  • 本地仓库Repository:git commit以后,当前暂存区里对文件的更改会提交到本地仓库
  • 远程仓库Remote:远程仓库名一般默认叫origin。git push以后,本地仓库里优先于远程仓库的commit会被push到远程仓库
    在这里插入图片描述

一些基本概念:

  • SVN是集中式版本控制系统,版本库是集中放在中央服务器的。
  • Git是分布式版本控制系统,那么它就没有中央服务器的,每个人的电脑就是一个完整的版本库。
  • origin - 这是 Git 给你克隆的仓库服务器的默认名字。
  • HEAD - 在 Git 中,它是一个指针,指向当前所在的本地分支的最新一次提交(可将 HEAD 想象为当前分支的别名)。
$ cat .git/HEAD
ref: refs/heads/master # 当前指向master

在这里插入图片描述

1.Quick Start

1. 配置用户信息

第一步需要配置你的git用户信息

$ git config --global user.name "yourname"
$ git config --global user.email [email protected]

如果使用了 --global 选项,那么该命令只需要运行一次,因为之后无论你在该系统上做任何事情, git 都会使用那些信息。
当你想针对特定项目使用不同的用户名称与邮件地址时,可以在那个项目目录下运 行没有 --global 选项的命令来配置。
配置为之后,可以用以下命令查看:

 git config --list

注意:github的提交记录,需要你本地配置的email被加入到了github设置中才会记录为有效提交。

详情参考:

Setting your commit email address on GitHub
Adding an email address to your GitHub account
Why are my contributions not showing up on my profile?

2. 初始化

把普通目录改成用git管理的仓库。目录下会多了一个.git的目录,这个目录是git来跟踪管理版本的

$ git init

3. 常用命令

下面这几个命令是最最最常用,最最最基本的git命令,可以先走一遍流程。

git status # 查看目前文件夹git的状态
git add . # 将本地所有的修改添加到暂存区
# git checkout -- <file> # 放弃对某个文件的修改
git commit -m "your description"
git push -u origin master # the first time with -u
# git push origin <要推送的本地分支名>

4. 查看版本库的更新过程

可以用log查看版本库的更新过程:

git log
# 查看各版本号及信息(所有的commit:本地commit + 其他同事的commit)
git log –pretty=oneline
git log --graph --pretty=oneline --abbrev-commit
# --pretty=oneline:一行显示,只显示哈希值和提交说明(--online本身也可以作为单独的属性)
# --abbrev-commit:仅显示SHA-1的前几个字符,而非所有的40个字符

2. 常用的撤销或回退操作

人非圣贤孰能无过,在执行了不想执行的git add 或者 git commit 或者 git push操作,我们需要执行相应的撤销操作。

2.1 git add的撤销

用命令git reset HEAD 可以把暂存区的修改撤销掉(unstage),重新放回工作区:

$ git reset HEAD readme.txt
Unstaged changes after reset:
M    readme.txt

git reset命令既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用HEAD时,表示最新的版本(上一个commit)。

2.2 直接丢弃在工作区对某个文件做的修改

git reset --hard HEAD # 撤销工作目录中所有未提交文件的修改内容
git checkout -- readme.txt  # 撤销工作目录中制定的未提交文件的修改内容

意思就是,把readme.txt文件在工作区做的修改全部撤销,这里有2种情况

  1. 如果 readme.txt修改后还没有放到暂存区,使用撤销修改就回到和版本库一模一样的状态(last commit)。
  2. 另外一种是readme.txt已经放入暂存区了,接着又作了修改,撤销修改就回到添加暂存区后的状态。但一旦执行了git commit -m “*”,就不能再使用上面的命令回退。
    如果文件已经提交到了暂存区,可以采取以下两个步骤放弃修改。
git reset HEAD <file> # to unstage, 撤销git add 
git checkout -- <file> 

git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。所以git checkout – [file] 是一个危险的命令。 你对那个文件做的任何修改都会消失 - 你只是拷贝了另一个文件来覆盖它。 除非你确实清楚不想要那个文件了,否则不要使用这个命令。

2.3 git commit撤销(没有push)

git reset --hard HEAD~1 # git reset --hard HEAD^
# 撤销之前的提交:
# 因为你使用了 --hard,所有你的文件将重置到上一次提交时的状态。
# uncommit for reworking: 去掉"--hard",这个对于非merge的commit有效,对于merge的commit最好删除merge后重新创建。

git reset --soft HEAD~1 # git reset --soft HEAD^
# 撤销提交但保留文件和索引:
# 从当前分支移除上一次commit,但是当前文件的修改会保留在你的工作区(working tree),同时暂存区(index)的修改也会保留。
# 此时直接用git commit就可以回到git reset之前的状态。

git reset HEAD~1 # git reset HEAD^
# 要撤销提交但保留更改:mixed mode,与soft mode非常像。
# 但是只把更改保留在工作区(working tree)而非暂存区(index),此时需要先git add然后git commit即可回到git reset之前的状态。

注意git rest --hard HEAD~1的操作非常危险,本地工作区如果有unstaged的修改就会丢失,所以在使用这个命令前一定要保证本地没有unstaged files,即git status是空的! 所幸:git reset --keep HEAD~1可以作为git rest --hard HEAD~1的安全版本。

image-20190831123230822

如果某次commit后发现漏了一个文件,可以使用下面命令把这个文件加上上一次的commit中。

$ git add missing_file
$ git commit --amend --no-edit   # "--no-edit": 不编辑, 直接合并到上一个 commit
$ git log --oneline    # "--oneline": 每个 commit 内容显示在一行

2.4 git push的撤销

对于已经push的版本,进行回退

# step 1,本地回退到指定的版本
git reset --hard 版本号

# step 2,将远程的也回退到指定版本
git push  -f origin dev    

2.5 版本回退

# 回到上一个版本
git reset --hard HEAD^ 
# HEAD指向的版本就是当前版本
# 或者使用 git reset --hard HEAD~ 
# ------------------------------ #
# 如果想回退到100个版本:
git reset –-hard HEAD~100
# 本地回退到指定的版本
git reset --hard 版本号 
# ------------------------------ #
# 查看以往版本号(本地的commit)

git log
# 如果要回到未来的版本可以用这个查看
git reflog

2.6 git强制覆盖本地代码(与git远程仓库保持一致)

$ git fetch --all
$ git reset --hard origin/master 
$ git pull

3. 远程操作

Git远程操作详解: git pull/git fetch/git push等。

3.1 git pull

$ git pull <远程主机名> <远程分支名>:<本地分支名>

比如,要取回origin主机的next分支,与本地的master分支合并,需要写成下面这样 -

$ git pull origin next:master

# 相当于:
$ git fetch origin next
$ git merge origin/next

如果远程分支是与当前分支合并,则冒号后面的部分可以省略。

$ git pull origin next

在某些场合,Git会自动在本地分支与远程分支之间,建立一种追踪关系(tracking)。比如,在git clone的时候,所有本地分支默认与远程主机的同名分支,建立追踪关系,也就是说,本地的master分支自动”追踪”origin/master分支。
Git也允许手动建立追踪关系。

git branch --set-upstream master origin/next 
# 新版本git已经不支持该命令,改为:
git branch --set-upstream-to=origin/master master

上面命令指定master分支追踪origin/next分支。
如果当前分支与远程分支存在追踪关系,git pull就可以省略远程分支名。

$ git pull origin

上面命令表示,本地的当前分支自动与对应的origin主机”追踪分支”(remote-tracking branch)进行合并。
如果当前分支只有一个追踪分支,连远程主机名都可以省略。

$ git pull

上面命令表示,当前分支自动与唯一一个追踪分支进行合并。
如果合并需要采用rebase模式,可以使用–rebase选项。

$ git pull --rebase <远程主机名> <远程分支名>:<本地分支名>

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

$ git pull -p
# 等同于下面的命令
$ git fetch --prune origin 
$ git fetch -p

3.2 git fetch

$ git fetch <远程主机名>

默认情况下,git fetch取回所有分支(branch)的更新。如果只想取回特定分支的更新,可以指定分支名。

$ git fetch <远程主机名> <分支名>
比如,取回origin主机的master分支。
$ git fetch origin master

所取回的更新,在本地主机上要用”远程主机名/分支名”的形式读取。比如origin主机的master,就要用origin/master读取。

3.3 git push

$ git push <远程主机名> <本地分支名>:<远程分支名>
$ git push origin master

上面命令表示,将本地的master分支推送到origin主机的master分支。如果后者不存在,则会被新建。
如果省略本地分支名,则表示删除指定的远程分支,因为这等同于推送一个空的本地分支到远程分支。

$ git push origin :master
# 等同于
$ git push origin --delete master

上面命令表示删除origin主机的master分支。
如果当前分支与远程分支之间存在追踪关系,则本地分支和远程分支都可以省略。

$ git push origin

上面命令表示,将当前分支推送到origin主机的对应分支。
如果当前分支只有一个追踪分支,那么主机名都可以省略。

$ git push

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

$ git push -u origin master

上面命令将本地的master分支推送到origin主机,同时指定origin为默认主机,后面就可以不加任何参数使用git push了。

$ git push --force origin 

上面命令使用–force选项,结果导致远程主机上更新的版本被覆盖。

4. 分支管理

branch management

A successful Git branching model

Understanding the Git Workflow

4.1 概述

并不是一定要把本地分支往远程推送:

  • master分支是主分支,因此要时刻与远程同步;一般来说,代码库有且只有一个主分支。Git主分支的名字,默认叫做Master。它是自动建立的,版本库初始化以后,默认就是在主分支在进行开发。
  • dev分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;
  • bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;
  • feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。
# 查看分支:
$ git branch -a

# 创建本地分支:
$ git branch <分支名>

# 切换本地分支:
$ git checkout <分支名> 

# 创建+切换本地分支:
$ git checkout -b <name> 
# 相当于:git branch <分支名> + git checkout <分支名>  

# 合并某分支到当前分支:
$ git merge <要合并的分支>
# 将本地分支推送到远程
$ git push origin <要推送的本地分支名>
# 以远程分支为基础,建一个本地分支
$ git checkout -b <本地分支名> origin/<远程分支名>
# 删除本地分支:
$ git branch -d <本地分支名>
# 删除远程分支。将本地空分支推送到远程分支,相当于删除远程分支
$ git push origin  :<要删除的远程分支名>

4.2 git tag

Git 使用的标签有两种类型:轻量级的(lightweight)和含附注的(annotated)。轻量级标签就像是个不会变化的分支,实际上它就是个指向特定提交对象的引用。而含附注标签(git tag -a ),实际上是存储在仓库中的一个独立对象,它有自身的校验和信息,包含着标签的名字,电子邮件地址和日期,以及标签说明,标签本身也允许使用 GNU Privacy Guard (GPG) 来签署或验证。一般我们都建议使用含附注型的标签,以便保留相关信息;当然,如果只是临时性加注标签,或者不需要旁注额外信息,用轻量级标签也没问题。创建一个含附注类型的标签非常简单,用git tag -a (annotated 的首字母)指定标签名字即可。

注意:标签总是和某个commit挂钩。如果这个commit既出现在master分支,又出现在dev分支,那么在这两个分支上都可以看到这个标签。

  • 命令git tag -a :用于新建一个标签,默认为HEAD,也可以指定一个commit id;
  • 可以用git log --pretty=oneline --abbrev-commit : 找到历史提交的commit_id
  • 命令git tag -a -m “blablabla…”: -m 选项则指定了对应的标签说明,Git 会将此说明一同保存在标签对象中。
  • 命令git tag可以查看所有标签。
  • 可以使用 git show 命令查看相应标签的版本信息,并连同显示打标签时的提交对象。
git tag # 列出所有标签
git tag -l 'v1.4.2.*' # 搜索模式
git tag -a v1.4 -m 'my version 1.4' 
git show v1.4

后期加注标签:

# 后期加注标签,在提交 “updated rakefile” 后为此项目打上版本号 v1.2
$ git log --pretty=oneline
15027957951b64cf874c3557a0f3547bd83b3ff6 Merge branch 'experiment'
a6b4c97498bd301d84096da251c98a07c7723e65 beginning write support
0d52aaab4479697da7686c15f77a3d64d9165190 one more thing
6d52a271eda8725415634dd79daabbc4d9b6008e Merge branch 'experiment'
0b7434d86859cc7b8c3d5e1dddfed66ff742fcbc added a commit function
4682c3261057305bdd616e23b64b0857d832627b added a todo file
166ae0c4d3f420721acbb115cc33848dfcc2121a started write support
9fceb02d0ae598e95dc970b74767f19372d61af8 updated rakefile
964f16d36dfccde844893cac5b347e7b3d44abbc commit the todo
8a5cbc430f1a9c3d00faaeffd07798508422908a updated readme

$ git tag -a v1.2 9fceb02

默认情况下,git push 并不会把标签传送到远端服务器上,只有通过显式命令才能分享标签到远端仓库。其命令格式如同推送分支,运行 git push origin [tagname] ,比如:

$ git push origin v1.5

如果要一次推送所有本地新增的标签上去,可以使用 --tags 选项:

$ git push origin --tags

4.3 master和dev分支

git clone 默认会把远程仓库整个给clone下来,但只会在本地默认创建一个master分支,可以使用checkout命令来把远程分支取到本地。

git clone ...
git checkout -b dev origin/dev
# 或者使用-t参数,它默认会在本地建立一个和远程分支名字一样的分支
git checkout -t origin/dev

git branch

git branch -r # 查看远程分支
git branch -a # 查看所有分支
# Git创建Develop分支的命令:
git checkout -b develop master

# 将Develop分支发布到Master分支的命令:
# 切换到Master分支
git checkout master

# 对Develop分支进行合并
git merge --no-ff develop
# 可能需要进行一下分支的关联,指定本地dev分支与远程origin/dev分支的链接:
$ git branch --set-upstream-to=origin/dev dev

4.4 Fast-Forward

当前分支合并到另一分支时,如果没有分歧解决,就会直接移动文件指针。这个过程叫做fast forward
举例来说,开发一直在master分支进行,但忽然有一个新的想法,于是新建了一个develop的分支,并在其上进行一系列提交,完成时,回到 master分支,此时,master分支在创建develop分支之后并未产生任何新的commit。此时的合并就叫fast forward

About parameter: --no-ff
在这里插入图片描述

4.5 临时性分支

Master和Develop是版本库的主要分支。前者用于正式发布,后者用于日常开发。常设分支只需要这两条就够了。

但是,除了常设分支以外,还有一些临时性分支,用于应对一些特定目的的版本开发。临时性分支主要有三种:

  • 功能(feature)分支
# 功能分支的名字,可以采用feature-*的形式命名。
# 创建一个功能分支:
git checkout -b feature-x develop
# 开发完成后,将功能分支合并到develop分支:
git checkout develop
git merge --no-ff feature-x
# 删除feature分支:
git branch -d feature-x
  • 预发布(release)分支
# 创建一个预发布分支:
git checkout -b release-1.2 develop
# 确认没有问题后,合并到master分支:
git checkout maste
git merge --no-ff release-1.2
# 对合并生成的新节点,做一个标签
git tag -a 1.2
# 再合并到develop分支:
git checkout develop
git merge --no-ff release-1.2
# 最后,删除预发布分支:
git branch -d release-1.2
  • 修补bug(fixbug)分支
# 创建一个修补bug分支:
git checkout -b fixbug-0.1 master
# 修补结束后,合并到master分支:
git checkout master
git merge --no-ff fixbug-0.1
git tag -a 0.1.1
# 再合并到develop分支:
git checkout develop
git merge --no-ff fixbug-0.1
# 最后,删除"修补bug分支":
git branch -d fixbug-0.1

4.6 git stash

具体操作时,可能会用到 git stash

1、储藏更改:将当前更改的代码储藏起来,等以后恢复使用

git stash

2、恢复储藏的代码

git stash pop 
//恢复的同时把stash内容删掉

或者

git stash apply  
//恢复stash,但是stash内容并不删除
git stash drop 
//在上面操作的基础上,以此来删除stash

注: git stash list : 查看全部的stash列表。

3、将stash空间清空

git stash clear

4、git stash popgit stash apply 区别

原来git stash pop stash@{id}命令会在执行后将对应的stash idstash list里删除,而 git stash apply stash@{id} 命令则会继续保存stash id

4.7 Example

git checkout -b newbranch # create a new branch
# do something...
git add .
git commit -m "do sth"
git checkout master
git merge --no-ff -m "merge new branch" newbranch # merge with no fast forward 
git branch -d newbranch
git branch
git push origin master
git push origin dev

# 将本地分支branch1推到远端的branch2:
git push origin branch1:branch2

# 删除分支
git branch -D issues1234  //本地强制删除分支issues1234    
git push origin  :issues1234  //推到远程
master分支是主分支,因此要时刻与远程同步。
#一些修复bug分支不需要推送到远程去,
#可以先合并到主分支上,然后把主分支master推送到远程去。
#把远程的origin的dev分支到本地来,可使用命令创建本地dev分支:
git checkout  –b dev origin/dev

5. Conflicts

发生冲突的文件

<<<<<<< HEAD

Creating a new branch is quick & simple.

=======

Creating a new branch is quick AND simple.

>>>>>>> feature1

其中,git使用 <<<<<<<, =======, >>>>>>> 标记文件中自己和别人产生冲突的部分。

<<<<<<<, ======= 之间为自己的代码,先出现;

=======, >>>>>>> 之间为别人的代码,后出现。

查看远程库信息,使用`git remote -v`;
修改远程仓库地址`git remote set-url origin new_git_url`
本地新建的分支如果不推送到远程,对其他人就是不可见的;
从本地推送分支,使用git push origin branch-name,如果推送失败,先用git pull抓取远程的新提交;
在本地创建和远程分支对应的分支,使用`git checkout -b branch-name origin/branch-name`,本地和远程分支的名称最好一致;
建立本地分支和远程分支的关联,使用`git branch --set-upstream branch-name origin/branch-name`;
从远程抓取分支,使用`git pull`,如果有冲突,要先处理冲突。

6. diff

要查看尚未暂存的文件更新了哪些部分,不加参数直接输入git diff

$ git diff

此命令比较的是工作目录中当前文件和暂存区域快照之间的差异, 也就是修改之后还没有暂存起来的变化内容。
如果暂存了,用git diff就没有反应了。
若要查看已暂存的将要添加到下次提交里的内容,可以用 git diff --cached 命令。(Git 1.6.1 及更高版本还允许使用 git diff --staged,效果是相同的,但更好记些。)

总结:

git diff # shows unstaged changes.
git diff --cached # shows staged changes.
git diff HEAD # shows all changes (both staged and unstaged).
版本之间的差异
# 上次提交:HEAD^
git diff HEAD^ HEAD

# As of Git 1.8.5, @ is an alias for HEAD, so you can use:
git diff @~..@

#The following will also work:
git show

# If you want to know the diff between head and any commit you can use:
git diff commit_id HEAD

# And this will launch your visual diff tool (if configured):
git difftool HEAD^ HEAD

# Since comparison to HEAD is default you can omit it (as pointed out by Orient):

git diff @^
git diff HEAD^
git diff commit_id

7. submodule

https://www.cnblogs.com/nicksheng/p/6201711.html

https://git-scm.com/book/zh/v2/Git-%E5%B7%A5%E5%85%B7-%E5%AD%90%E6%A8%A1%E5%9D%97

REFERENCE

git cheat sheet

GitHub 漫游指南 – GitHub 漫游指南

git - 简明指南

廖雪峰git

GIT tutorial

GIT PRO BOOK (Chinese)

git tutorial

how to teach git

Follow these simple rules and you’ll become a Git and GitHub master

Git重要概念与常用命令(中文版,速查)

Implementing Git in Data Science

https://www.runoob.com/git/git-basic-operations.html
https://www.w3cschool.cn/git/git-cheat-sheet.html
https://git-scm.com/book/zh/v2

猜你喜欢

转载自blog.csdn.net/low5252/article/details/106365210
今日推荐