乐趣区

关于git:Git最强总结

本文曾经收录到 Github 仓库,欢送大家围观、star。此仓库用于分享 Java 外围常识,包含 Java 根底、MySQL、SpringBoot、Mybatis、Redis、RabbitMQ 等等,面试必备。

github 地址:https://github.com/Tyson0314/…

如果 github 拜访不了,能够拜访 gitee 仓库。

gitee 地址:https://gitee.com/tysondai/Ja…

Git 简介

Git 是一个开源的分布式版本控制系统,能够无效、疾速的进行我的项目版本治理。Git 是 Linus Torvalds 为了帮忙治理 Linux 内核开发而开发的一个开放源码的版本控制软件。

Git 工作流程

Git 工作流程如下:

  • 从近程仓库中克隆资源作为本地仓库;
  • 在本地仓库中进行代码批改;
  • 在提交本地仓库前先将代码提交到暂存区;
  • 提交批改,提交到本地仓库。本地仓库中保留批改的所有历史版本;
  • 在须要和团队成员共享代码时,能够将批改的代码 push 到近程仓库。

Git 的工作流程图如下:

图片起源:https://blog.csdn.net/ThinkWo…

存储原理

Git 在保留我的项目状态时,它次要对全副文件制作一个快照并保留这个快照的索引,如果文件没有被批改,Git 不会从新存储这个文件,而是只保留一个链接指向之前存储的文件。

Git 快照

快照就是将旧文件所占的空间保留下来,并且保留一个援用,而新文件中会持续应用与旧文件内容雷同局部的磁盘空间,不同局部则写入新的磁盘空间。

三种状态

Git 的三种状态:已批改(modified)、已暂存(staged)和已提交(committed)。已批改示意批改了文件,但还没保留到数据库。已暂存示意对一个已批改文件的以后版本做了标记,使之蕴含在下次提交的快照中。已提交示意数据曾经平安的保留到本地数据库。

根本的 Git 工作流程:在工作目录批改文件;暂存文件,将文件快照放到暂存区域;提交更新到本地库。暂存区保留了下次将要提交的文件列表信息,个别在 Git 仓库目录中。

图片起源:https://img2018.cnblogs.com/blog/1252910/201907/1252910-20190726163829113-2056815874.png

配置

设置用户名和邮箱地址:

git config --global user.name "dabin"
git config --global user.email xxx@xxx.com

如果应用了 –global 选项,那么该命令只须要运行一次,因为之后无论你在该零碎上做任何事件,Git 都会应用那些信息。当你想针对特定我的项目应用不同的用户名称与邮件地址时,能够在那个我的项目目录下运行没有 –global 选项的命令来配置。

查看配置信息:git config --list

查看某一项配置:git config user.name

获取帮忙

获取 config 命令的手册:git help config

Git 根底

获取 Git 仓库

在现有目录中初始化仓库:进入我的项目目录并输出git init

克隆现有的仓库:git clone https://github.com/...

文件状态

查看文件状态:git status

图片起源:https://img2018.cnblogs.com/blog/1252910/201907/1252910-20190726163854195-886320537.png

状态简览:

新增加的未跟踪文件后面有 ?? 标记,新增加到暂存区中的文件后面有 A 标记,批改过的文件后面有 M 标记,如下图,MM Rakefile呈现两个 M,其中呈现在靠左边的 M 示意该文件被批改了并放入了暂存区,呈现在左边的 M 示意该文件被批改了然而还没放入暂存区。

$ git status -s
 M README # 左边的 M 示意该文件被批改了然而还没放入暂存区
MM Rakefile # 右边的 M 示意该文件被批改了并放入了暂存区;左边的 M 示意该文件被批改了然而还没放入暂存区
A lib/git.rb # A 示意新增加到暂存区中的文件
?? LICENSE.txt # ?? 示意新增加的未跟踪文件

配置别名

有些人可能常常敲错命令,通过配置别名能够简化命令:

通过命令 git config --global alias.st status git status 简化为 git st

$ git config --global alias.st status

$ git st
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

工作区

查看工作区批改:git diff

$ git diff
diff --git a/md/leetcode 刷题笔记.md b/md/leetcode 刷题笔记.md
deleted file mode 100644
index 63a7c90..0000000
--- a/md/leetcode 刷题笔记.md
+++ /dev/null

撤销工作区批改:git checkout -- file_name,会撤销工作区的批改,不可复原,不会撤销暂存区批改。

撤销批改还能够应用 restore 命令(git2.23 版本引入)。

git restore --worktree demo.txt // 撤销文件工作区的批改
git restore --staged demo.txt // 撤销暂存区的批改,将文件状态复原到未 add 之前
git restore -s HEAD~1 demo.txt // 将当前工作区切换到上个 commit 版本,- s 相当于 --source
git restore -s hadn12 demo.txt // 将当前工作区切换到指定 commit id 的版本

暂存区

通过git add filename 将工作区的文件放到暂存区。

git add README.md

查看暂存区批改:git diff --staged。能够看到暂存区中有 README.md 文件,阐明 README.md 文件被放到了暂存区。

$ git diff --staged
diff --git a/README.md b/README.md
index ecd6c7a..653f001 100644
--- a/README.md
+++ b/README.md

撤销暂存区批改 /unstage:git reset HEAD file_name,将文件批改移出暂存区,放到工作区。

git reset 加上 –hard 选项会导致工作目录中所有批改失落。

提交

任何未提交的批改失落后很可能不可复原。提交命令:git commit -m "add readme.md"

git commit -a -m "xxx" 相当于 git addgit commit -m "xxx",将 tracked 的文件间接提交。untracked 的文件无奈应用此命令间接提交,需先执行 git add 命令,再执行 git commit。

独自执行git commit,不带上 - m 参数,会进入 vim 编辑器界面:

此时应该这么操作:

  1. 按下字母键 iao,进入到可编辑状态
  2. 输出 commit 信息之后,按下 Esc 键就可退出编辑状态,回到个别模式
  3. 输出:wq(保留退出)或 :wq!(强行退出,不保留)

批改 commit 信息

如果提交后发现漏掉某些文件或者提交信息写错,应用 git commit --amend 从新提交:

git commit -m 'initial commit'
git add forgotten_file
git commit --amend

查看提交历史

git log列出所有提交的更新。

git log -p -2,-p 用来显示每次提交的内容差别,- 2 示意显示最近两次提交。

git log --stat每次提交上面都会列出所有被批改的文件、有多少文件被批改和哪些行被批改等。

git log --pretty=oneline将每个提交放在一行显示。

git log --pretty=format:"%h %s" --graph format 示意格式化输入,%h 提交对象的简短哈希串,%s 是提交阐明,–graph 能够更形象的展现分支、合并历史。

$ git log --pretty=format:"%h %s" --graph
* 75f8b36 update
* cd72e4f 删除查问性能优化
* 6bddc95 MySQL 总结整顿
* f8ace0e java 常见关键字总结
* 0c4efeb 删除 android
* 4844de5 mysql 执行打算
* 635c140 redis 分布式锁
* 7b65bc3 update
* e563eec update
* 67e1cf7 update readme
* 218f353 调整目录构造
* 9428314 整顿 Java 根底内容

git log --since=2.weeks 依照工夫作限度。

版本回退

版本回退应用 git reset 命令。

git reset --hard commit_id
git reset --hard HEAD^ # 回退所有内容到上一个版本
git reset --hard HEAD^^ # 回退所有内容到上上一个版本
git reset --hard HEAD~100 # 回退到之前第 100 个版本  
git reset HEAD readme.txt  # 把暂存区的批改撤销掉(unstage), 从新放到工作区 

stash

将未提交的批改保存起来。用于后续复原当前工作目录。

git stash
git stash pop stash@{id} // 复原后删除
git stash apply stash@{id}  // 复原后不删除,需手动删除
git stage drop
git stash list // 查看 stash 列表
git stash show -p stash@{0} // 查看 stash 具体内容,- p 查看 diff,stash@{0}能够省略

rm 和 mv

git rm readme.md:文件未被批改过,从暂存区移除文件,而后提交,相当于 rm readme.mdgit add .。如果只是简略地从工作目录中手工删除文件,运行 git status 时就会在“Changes not staged for commit”。

git rm --cached README.md:让文件保留在工作区,然而不想让 Git 持续跟踪。能够应用 –cached 选项来实现。文件被批改过,还没有放进暂存区,则必须要用强制删除选项 -f,以避免误删还没有增加到暂存区的数据,这样的数据不能被 Git 复原。

git rm 反对正则表达式:git rm log/\*.log

对文件改名:git mv README.md README

相当于运行一下三条命令:

mv README.md README
git rm README.md
git add README

疏忽文件

.gitignore 只能疏忽未跟踪状态的文件。

如果近程仓库曾经有了 logs 文件夹,git rm --cached logs/xx.log 能够删除文件的跟踪状态,此时本地工作区批改还在。而后更新 .gitignore 文件,最初git add . & git commit -m "xx" & git push 就能够删除近程仓库对应的文件。

skip-worktree 和 assume-unchanged

skip-worktree:

  • git update-index --skip-worktree [file] 能够实现批改本地文件不会被提交,但又能够拉取最新更改的需要。实用于一些不常常变动,然而必须本地化设置的文件。
  • 勾销 skip-worktree:git update-index --no-skip-worktree [file]
  • 查看 skip-worktree 列表:git ls-files -v | grep '^S\'

assume-unchanged:

  • git update-index --assume-unchanged [file] 该命令只是假如文件没有变动,应用 reset 时,会将文件批改回去。当近程仓库相应的文件被批改时,pull 更新之后,–assume-unchanged 会被革除。
  • 勾销疏忽:git update-index --no-assume-unchanged file/path
  • 查看疏忽了哪些文件:git ls-files -v | grep '^h\'

近程仓库

近程仓库是指托管在网络中的我的项目版本库。

查看近程仓库

查看近程仓库地址:

$ git remote -v
origin https://github.com/schacon/ticgit (fetch)
origin https://github.com/schacon/ticgit (push)

增加近程仓库

运行 git remote add <shortname> <url> 增加近程 Git 仓库,同时指定一个简写名称。

git remote add pb https://github.com/paulboone/ticgit

如上命令,能够在命令行中应用字符串 pb 来代替整个 URL。如git fetch pb

如果应用 clone 命令克隆了一个仓库,命令会主动将其增加为近程仓库并默认以 origin 为默认简写名称。

勾销关联 Git 仓库 git remote remove origin

如果想要给 origin 设置两个近程仓库地址(git add 会报错),能够应用 git remote set-url --add origin url 来设置。

$ git remote add origin  xxx.git
fatal: remote origin already exists.

$ git remote set-url --add origin xxx.git
#success

批改近程仓库

批改近程仓库地址:

git remote set-url origin git@github.com:Tyson0314/Blog.git

pull 和 fetch

从近程仓库获取数据:git fetch [remote-name]

git fetch 命令将数据拉取到本地仓库,但它并不会主动合并到本地分支,必须手动将其合并本地分支。

git pull 通常会从近程仓库拉取数据并主动尝试合并到以后所在的分支。

git pull = git fetch + git merge FETCH_HEAD 
git pull --rebase =  git fetch + git rebase FETCH_HEAD 

本地仓库上传 git 服务器

git init # 将目录变成本地仓库
git add .
git commit -m 'xxx' # 提交到本地仓库
git remote add origin https://github.com/Tyson0314/profile # 关联近程仓库
git branch --set-upstream-to=origin/master master  # 本地分支关联近程分支
git pull origin master --allow-unrelated-histories # 容许合并不相干的历史
git push -u origin master  # 如果以后分支与多个主机存在追踪关系,则 - u 会指定一个默认主机,这样前面就能够不加任何参数应用 git push。

推送到近程仓库

推送应用命令:git push [remote-name] [branch-name]

git push origin master

查看近程仓库

git remote show origin

近程仓库移除和命名

移除近程仓库:

git remote rm paul

重命名近程仓库:

git remote rename old-name new-name

标签

给历史的某个提交打标签,如标记公布节点(v1.0 等)。

tag 标签能够帮忙咱们回退到某个版本的代码,咱们通过 tag 的名称即可回退,而不须要依据某个提简短的 commit ID 来回退:

  • 查看本地 tag:git tag
  • 新建 tag:git tag -a v2.0 -m ‘msg’
  • 推送指定 tag 至近程:git push origin v2.0
  • 推送本地所有 tag 至近程:git push origin –tags
  • 删除本地 tag:git tag -d v2.0
  • 删除近程 tag:git push origin –delete tag 2.0
  • 本地查看不同 tag 的代码:get checkout v1.0
  • 查看标签详情(蕴含 commitId):git show v1.0
  • 回退到某个版本:git reset –hard commitId
  • 获取近程分支:git fetch origin tag V2.0

创立标签

Git 应用两种次要类型的标签:轻量标签(lightweight)与附注标签(annotated)。一个轻量标签很像一个不会扭转的分支 – 它只是一个特定提交的援用。然而,附注标签是存储在 Git 数据库中的一个残缺对象。它们是能够被校验的;其中蕴含打标签者的名字、电子邮件地址、日期工夫;还有一个标签信息;并且能够应用 GNU Privacy Guard(GPG)签名与验证。通常倡议创立附注标签。

创立的标签都只存储在本地,不会主动推送到近程。

附注标签

git tag -a v1.4 -m 'my version 1.4' -m 选项指定了一条将会存储在标签中的信息。

应用 git show v1.4 命令能够看到标签信息与对应的提交信息。

轻量标签

git tag v1.4-tyson 此时运行 git show v1.4-tyson不会看到额定的标签信息,只显示提交信息。

推送标签

推送某个标签到近程,应用命令 git push origin <tagname>
一次性推送全副尚未推送到近程的本地标签 git push origin --tags
删除近程标签(先删除本地标签) git push origin :refs/tags/<tagname>

前期打标签

比方给上面的这个提交(modified readme.md)打标签: git tag -a v1.2 c1285b

$ git log --pretty=oneline
22fb43d9f59b983feb64ee69bd0658f37ea45db6 (HEAD -> master, tag: v1.4-tyson, tag: v1.4) add file note.md
aab2fda0b604dc295fc2bd5bfef14f3b8e3c5a98 add one line
c1285bcff4ef6b2aefdaf94eb9282fd4257621c6 modified readme.md
ba8e8a5fb932014b4aaf9ccd3163affb7699d475 renamed
d2ffb8c33978295aed189f5854857bc4e7b55358 add readme.md

共享标签

git push 命令并不会传送标签到近程仓库服务器上。在创立完标签后你必须显式地推送标签到共享服务器上:git push origin v1.5

把所有不在近程仓库服务器上的标签全副传送到那里:git push origin --tags

检出标签

如果你想要工作目录与仓库中特定的标签版本齐全一样,能够应用 git checkout -b [branchname] [tagname] 在特定的标签上创立一个新分支:

$ git checkout -b version2 v2.0.0
Switched to a new branch 'version2'

git 别名

勾销暂存别名:git config --global alias.unstage 'reset HEAD --'

最初一次提交:git config --global alias.last 'log -1 HEAD'

git 分支

Git 激励在工作流程中频繁地应用分支与合并。

Git 保留的不是文件的变动或者差别,而是一系列不同时刻的文件快照。git 提交对象会蕴含一个指向暂存内容快照的指针。

分支创立

$ git branch testing

查看近程分支:git branch -r

分支切换

应用 git checkout branch-name 切换分支:

git checkout testing

查看各个分支以后所指的对象:git log --oneline --decorate

$ git log --oneline --decorate
22fb43d (HEAD -> master, tag: v1.4-tyson, tag: v1.4, tyson) add file note.md
aab2fda add one line
c1285bc (tag: v1.2) modified readme.md
ba8e8a5 renamed
d2ffb8c add readme.md

master 和 tyson 分支都指向校验和为 22fb43d 的提交对象。

$ git checkout -b iss53 相当于 git branch iss53 加上 git checkout iss53

分支合并

合并 iss53 分支到 master 分支:

git checkout master
git merge iss53

squash merge:合并多个 commit 为一个,合并完须要从新提交,会批改原 commit 的提交信息,包含 author。

合并抵触

当合并产生抵触时不会主动地创立一个新的合并提交。Git 会暂停下来,期待你去解决合并产生的抵触。你能够在合并抵触后的任意时刻应用 git status 命令来查看那些因蕴含合并抵触而处于 unmerged 状态的文件。

<<<<<<< HEAD:index.html
<div id="footer">contact : email.support@github.com</div>
=======
<div id="footer">
please contact us at support@github.com
</div>
>>>>>>> iss53:index.html

在你解决了所有文件里的抵触之后,对每个文件应用 git add 命令来将其标记为抵触已解决。而后输出 git commit -m "merge branch iss53"实现合并提交。

rebase

当初咱们有这样的两个分支,test 和 master,提交如下:

       D---E test
      /
 A---B---C---F--- master

在 master 执行 git merge test,会生成额定的提交节点 G:

       D--------E
      /          \
 A---B---C---F----G---   test, master

在 master 执行 git rebase test,本地提交以补丁模式打在分支的最初面:

A---B---D---E---C‘---F‘---   test, master

merge 操作会生成一个新的节点,之前的提交离开显示。
而 rebase 操作不会生成新的节点,是将两个分支交融成一个线性的提交。

合并 commit:git rebase -i

pick c38e7ae rebase content
s 595ede1 rebase

# Rebase 8824682..595ede1 onto 8824682 (2 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit

s 595ede1 rebase会将 595ede1 合到前一个 commit,按下 :wq 之后会弹出对话框,合并 commit message。

删除分支

删除本地分支:git branch -d iss53

删除近程分支:git push origin --delete master

分支治理

失去以后所有分支的一个列表:

$ git branch
* master
  tyson

* 代表以后 HEAD 指针所指向的分支。

查看每一个分支的最初一次提交:

$ git branch -v
* master 22fb43d add file note.md
  tyson  22fb43d add file note.md

查看哪些分支曾经合并到以后分支:

$git    branch    --merged        
iss53 
*master

查看所有蕴含未合并工作的分支:

$git branch --no-merged
testing

如果分支蕴含未合并的工作,应用 git branch -d testing 删除时会出错,能够应用 git branch -D testing强制删除。

近程分支

推送

git push origin master 将本地的 master 分支推送到近程仓库 origin/master 分支。git push origin tyson:tyson-branch 将本地的 tyson 分支推送到近程仓库的 tyson-branch 分支。

如果以后本地分支是 tyson,抓取近程仓库数据后,须要进行合并:

git fetch origin
git merge origin/tyson

将本地的所有分支都推送到近程主机:git push -all origin

强制推送:git push --force origin

跟踪分支

$ git checkout --track origin/tyson
Branch tyson set up to track remote branch tyson from origin.
Switched to a new branch 'tyson'

本地分支与近程分支设置为不同名字:

$ git checkout -b tyson-branch origin/tyson
Branch tyson-branch set up to track remote branch tyson from origin.
Switched to a new branch 'tyson-branch'

设置已有的本地分支跟踪一个刚刚拉取下来的近程分支,应用 -u 或 –set-upstream-to 选项:

git branch -u origin master

查看设置的所有跟踪分支:

$ git branch -vv
iss53 7e424c3 [origin/iss53: ahead 2] forgot the brackets
master 1ae2a45 [origin/master] deploying index fix
* serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] this should do it
testing 5ea463a trying something new

这些数据是本地缓存的服务器数据,如果须要最新的数据,能够先运行:git fetch --all 而后再运行:git branch -vv

fetch 和 pull

git fetch 会将近程仓库的更新拉取到本地近程仓库的正本,不会主动合并到本地仓库。

git fetch 步骤:

git fetch origin master:tmp  // 在本地新建一个 tmp 分支,并将近程 origin 仓库的 master 分支代码下载到本地 tmp 分支
git diff tmp // 来比拟本地代码与刚刚从近程下载下来的代码的区别
git merge tmp// 合并 tmp 分支到本地的 master 分支
git branch -d tmp// 如果不想保留 temp 分支 能够用这步删除

git pull = git fetch + git merge

删除近程分支

git push origin --delete tyson Git 服务器会保留数据一段时间,误删的近程分支很容易复原。

创立近程分支

基于本地分支创立近程分支:git push origin backup_foreign:backup_foreign

本地新分支和近程新分支关联:git push --set-upstream origin backup_foreign

cherry-pick

参考自:cherry-pick

能够用于将在其余分支上的 commit 批改,移植到以后的分支。

git cherry-pick <commit-id>

当执行完 cherry-pick 之后,将会主动生成一个新的 commit 进行提交,会有一个新的 commit ID,commit 信息与 cherry-pick 的 commit 信息统一。遇到抵触则解决抵触,而后 git add 产生抵触的文件,而后应用 git cherry-pick --continue 持续。这个过程中能够应用 git cherry-pick --abort,复原分支到 cherry-pick 之前的状态。

git cherry-pick -x <commit_id> 减少 -x 参数,示意保留原提交的作者信息进行提交。

在 Git 1.7.2 版本开始,新增了反对批量 cherry-pick,就是能够一次将一个间断的工夫序列内的 commit,设定一个开始和完结的 commit,进行 cherry-pick 操作。

git cherry-pick <start-commit-id>…<end-commit-id>

上述命令将从 start-commit-id 开始到 end-commit-id 之间的所有 commit-id 提交记录都合并过去,须要留神的是,start-commit-id 必须比 end-commit-id 提前提交。

cherry-pick 与 rebase 的区别

cherry-pick 操作的是某一个或某几个 commit,rebase 操作的是整个分支。

补丁

git apply xx.patch 须要本人从新 commit。xx.patch 必须从 git diff 中取得,能力应用 git apply

git am yy.patch 会保留 commit 信息,yy.patch 是从 git format–patch 取得的。

码字不易,如果感觉对你有帮忙,能够 点个赞 激励一下!

退出移动版