经常用到的git操作,简单易懂演示一波
虽然现在编辑器或者各种git扩展很好用,并极大的提高了生产力。但是也出现了一些现象:一些工程师对诸如webstorm或者vscode之类的可视化git操作用得心应手,但对一些其中的git命令的意思却不求甚解。对,说的就是我以前的我。
而且还有个现象,一旦你依赖于编辑器的可视化操作,那么对命令行的操作会出现恐惧的心理,我以前是这样。所以为了改变现状,现在彻底告别可视化操作,拥抱命令行。
说到git的一些操作,常用的诸如:
$ git clone
$ git branch
$ git branch -a #查看远程分支列表
$ git push origin --delete <分支> #删除远程分支
$ git branch -D <分支> #删除本地分支
$ git checkout 分支名
$ git checkout -b 分支名
$ git checkout origin/<远程分支> -b <本地分支>
$ git add
$ git checkout -- <file>
$ git reset
$ git commit
$ git push
$ git fetch #并没更改本地仓库的代码,只是拉取了远程commit数据,将远程仓库的commit版本号 更新为最新。分支git log信息不会变
$ git pull #fetch+merge,把远程代码拉到本地并merge,git log信息会更新
$ git merge
$ git rebase
$ git log
$ git rebase -i <提交版本号>
$ git log master..dev #查看 dev 中比 master 中多提交了哪些内容
比如下面我要开发新项目,新项目已经在远程仓库了
- 首先我拉项目到本地
$ git clone <远程仓库地址>
# 通常拉下来的是默认分支master,那么想要拉下的是另一个分支的代码的话
$ git clone -b <分支名> <远程仓库地址>
- 开发阶段,首先要从master上切出一个开发分支
$ git checkout -b <分支名>
# 我给开发分支起名叫:dev
$ git checkout -b dev
Switched to a new branch 'dev'
- 如果有个同事已经有了个开发分支,让我直接用他的开发分支开发功能
# 使用
$ git checkout origin/<远程分支> -b <本地分支>
# 他的分支叫:dev1
$ git checkout origin/dev1 -b dev1
- 此时我想看下本地和远程分别有哪些分支
# 查看本地分支列表,*号所在的那个是当前分支
$ git branch
* dev1
master
# 查看远程分支列表,打印出的列表,红颜色的代表远程分支
$ git branch -a
- 我新增了一个“git-test.js”文件、改了一个"index.html"文件
# 输入git status查看状态
$ git status
On branch dev1
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: index.html
Untracked files:
(use "git add <file>..." to include in what will be committed)
git-test.js
no changes added to commit (use "git add" and/or "git commit -a")
# 打印出的信息表示,index.html 文件<修改的部分>还未添加到git暂存区。
# Untracked files表示:新增的 git-test.js 文件还未被跟踪
- 我想了一下,决定不对 index.html 做更改了,想一下子把它返回到未更改状态
$ git checkout -- index.html
# 如果想将多个文件撤销呢,文件名用一个“.”代替
$ git checkout -- .
- 现在我将未跟踪的 git-test.js 文件加到git 暂存区
# 此处的“.”,和上面的“.”作用一样,代表多个文件
$ git add .
# 现在查看下状态
$ git status
On branch dev1
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: git-test.js
# 然后我又想将刚加到暂存区的git-test.js移出暂存区(我是不是傻)
$ git reset HEAD git-test.js
$ git status
On branch dev1
Untracked files:
(use "git add <file>..." to include in what will be committed)
git-test.js
- 现在git-test.js又被加到了暂存区,并且要提交了
$ git commit -m "add git-test.js"
[dev1 5198153] add git-test.js
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 git-test.js
# 现在看下git log
$ git log
commit 51981532d54b62811d8afb9b2493cb3320752eae
Author: xxx <xx@xx.com>
Date: Wed Jul 11 18:04:00 2018 +0800
add git-test.js
- 此时我又对index.html文件做了更改
# 将更改后的index.html加到暂存区
$ git add index.html
# 提交,但是我想将这次的提交和上次的提交合并
$ git commit --amend
# 打印出以下信息,这是vim编辑窗口
add git-test.js
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# Date: Wed Jul 11 18:04:00 2018 +0800
# On branch dev
# Changes to be committed:
# modified: index.html
# new file: git-test.js
# 按shift+:,输入q,退出编辑
[dev1 3da072a] add git-test.js
Date: Wed Jul 11 18:04:00 2018 +0800
2 files changed, 1 insertion(+)
create mode 100644 git-test.js
有时候我们提交了好几个commit,但是想要回到某次的提交
# 回退到上一个版本
$ git reset --hard HEAD^
# 回退到往上 n 个版本
$ git reset --hard HEAD~n
# 回退到某个版本号的版本
$ git reset --hard <版本号>
好了,开发一段时间了,今天要把master分支给合并过来
$ git merge master
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.
# 打印出来的信息说:修复冲突,然后提交结果
# 看下git状态
$ git status
On branch dev1
You have unmerged paths.
(fix conflicts and run "git commit")
Unmerged paths:
(use "git add <file>..." to xxx resolution)
both modified: index.html
# 修复冲突后
$ git add index.html
$ git commit -m "merge master"
$ git log
commit 3030e65c149442a26649fb5e6a2bdb89c976cbc8
Merge: 3da072a 78363ff
Author: zhangqinmiao <564777189@qq.com>
Date: Wed Jul 11 18:47:27 2018 +0800
merge master
commit 78363ff222bc847076bbc96e26f56b04b58ad19d
Author: xxx <xxx@xx.com>
Date: Wed Jul 11 18:34:55 2018 +0800
update index.html
commit 3da072aee0eacf7a8315c3ead1ead88bb0fcf3ed
Author: xxx <xxx@xx.com>
Date: Wed Jul 11 18:04:00 2018 +0800
add git-test.js
##########################################
# 如果在合并状态下,不想合并分支了的话
$ git merge --abort
有人说了,我合并用rebasbe呢,和merge有何不同
# 我们切到master分支,看下log
$ git checkout master
Switched to branch 'master'
$ git log
commit c5d5bd4046c6c8fb75addfad49e5c396f53f9da1
Author: xxx <xxx@xx.com>
Date: Wed Jul 11 18:52:46 2018 +0800
update 0711
commit 78363ff222bc847076bbc96e26f56b04b58ad19d
Author: xxx <xxx@xx.com>
Date: Wed Jul 11 18:34:55 2018 +0800
update index.html
commit 784f9f65951386344e5073652a88d70a2276f35e
Author: xxx <xxx@xx.com>
Date: Wed Jul 11 11:21:13 2018 +0800
################################################
# 上面打印出的log,显示是最近三次的master分支的提交
# 下面我们看下dev1分支的log
$ git checkout dev1
$ git log
commit 3da072aee0eacf7a8315c3ead1ead88bb0fcf3ed
Author: xxx <xxx@xx.com>
Date: Wed Jul 11 18:04:00 2018 +0800
add git-test.js
################################################
# 当dev1分支rebase master分支后
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: add git-test.js
$ git log
commit b5e1b59c1adb19e6e49e937364f5d00b23942324
Author: xxx <xxx@xx.com>
Date: Wed Jul 11 18:04:00 2018 +0800
add git-test.js
commit c5d5bd4046c6c8fb75addfad49e5c396f53f9da1
Author: xxx <xxx@xx.com>
Date: Wed Jul 11 18:52:46 2018 +0800
update 0711
commit 78363ff222bc847076bbc96e26f56b04b58ad19d
Author: xxx <xxx@xx.com>
Date: Wed Jul 11 18:34:55 2018 +0800
update index.html
注意: 虽然“update 0711”这次提交的时间比“add git-test.js”这次提交的时间晚,一个18:52:46,一个18:04:00。这是因为rebase master是以master分支作为基础,然后合并就以master的提交记录开始依序开始。 详细介绍
如果你想合并多个commit
# 看下本分支的log
$ git log
commit b5e1b59c1adb19e6e49e937364f5d00b23942324
Author: xxx <xxx@xx.com>
Date: Wed Jul 11 18:04:00 2018 +0800
add git-test.js
commit c5d5bd4046c6c8fb75addfad49e5c396f53f9da1
Author: xxx <xxx@xx.com>
Date: Wed Jul 11 18:52:46 2018 +0800
update 0711
commit 78363ff222bc847076bbc96e26f56b04b58ad19d
Author: xxx <xxx@xx.com>
Date: Wed Jul 11 18:34:55 2018 +0800
update index.html
- 复制“update index.html”这次提交的版本号,到下面的 -i 后面
$ git rebase -i 78363ff222bc847076bbc96e26f56b04b58ad19d
- 打印出以下vim编辑信息
pick c5d5bd4 update 0711
pick b5e1b59 add git-test.js
# Rebase 78363ff..b5e1b59 onto 78363ff (2 command(s))
# 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
# These lines can be re-ordered; they are executed from top to bottom.
# If you remove a line here THAT COMMIT WILL BE LOST.
前两行前面的pick,在Commands下面有解释,如下我将前两行改为以下形式:
pick c5d5bd4 update 0711
s b5e1b59 add git-test.js
上面修改的意思是:使用
b5e1b59
这个的提交,但是合并到之前的提交。
- 修改完成后,保存。然后打印出以下vim编辑信息
# This is a combination of 2 commits.
# The first commit's message is:
update 0711
# This is the 2nd commit message:
add git-test.js
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# Date: Wed Jul 11 18:52:46 2018 +0800
# interactive rebase in progress; onto 78363ff
# Last commands done (2 commands done):
# pick c5d5bd4 update 0711
- 此时你可以修改信息为以下形式
rebase -i test
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# Date: Wed Jul 11 18:52:46 2018 +0800
# interactive rebase in progress; onto 78363ff
# Last commands done (2 commands done):
# pick c5d5bd4 update 0711
- 保存后,打印出以下信息。提示成功
[detached HEAD 747712c] rebase -i test
Date: Wed Jul 11 18:52:46 2018 +0800
3 files changed, 218 insertions(+), 4 deletions(-)
create mode 100644 git-test.js
Successfully rebased and updated refs/heads/dev1.
# 查看下log
$ git log
commit 747712c3b99e734d85defcacdc0a1d4610c6d9af
Author: xxx <xxx@xx.com>
Date: Wed Jul 11 18:52:46 2018 +0800
rebase -i test