git简介
一:Git是什么?
Git是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。 工作原理 / 流程:
Workspace:工作区 Index / Stage:暂存区 Repository:仓库区(或本地仓库) Remote:远程仓库
二:SVN与Git的最主要的区别?
SVN是集中式版本控制系统,版本库是集中放在中央服务器的,而干活的时候,用的都是自己的电脑,所以首先要从中央服务器哪里得到最新的版本,然后干活,干完后,需要把自己做完的活推送到中央服务器。集中式版本控制系统是必须联网才能工作,如果在局域网还可以,带宽够大,速度够快,如果在互联网下,如果网速慢的话,就纳闷了。 Git是分布式版本控制系统,那么它就没有中央服务器的,每个人的电脑就是一个完整的版本库,这样,工作的时候就不需要联网了,因为版本都是在自己的电脑上。既然每个人的电脑都有一个完整的版本库,那多个人如何协作呢?比如说自己在电脑上改了文件A,其他人也在电脑上改了文件A,这时,你们两之间只需把各自的修改推送给对方,就可以互相看到对方的修改了。
三:初始化设置
1. 设置用户名及邮箱信息
全局设置
git config --global user.name "Name" git config --global user.email "Email"
针对项目设置
git config user.name "Name" git config user.email "Email"
2. 设置换行符自动转换
git config --global core.autocrlf [true | input | false] # 全局设置
git config --local core.autocrlf [true | input | false] # 针对本项目设置
true
提交时转换为LF,检出时转换为CRLFinput
提交时转换为LF,检出时不转换false
提交与检出的代码都保持文件原有的换行符不变(不转换)
推荐设置:
- windows
git config --global core.autocrlf true
- other OS
git config --global core.autocrlf input
初始化仓库
版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。
git init
git add 初始化.md
git commit Or git commit -m<message>
版本管理
一、版本回退
1). 获取仓库当前log列表
使用
git log
命令查看$ git log commit 310f02083e0bfd1762ddbd33664d01881cef8fd3 (HEAD -> master) Author: Pota <[email protected]> Date: Wed Oct 21 17:57:12 2020 +0800 feat: 第三次改动 commit ff1eb142c143b9498d57ad3c8218bd62019d3f18 Author: Pota <[email protected]> Date: Wed Oct 21 17:56:53 2020 +0800 feat: 第二次改动 commit 62ea36c7ed237ec92d333a4fc5a5d2f7f929665e Author: Pota <[email protected]> Date: Wed Oct 21 17:56:24 2020 +0800 feat: 第一次改动 commit 25bae0398fc1fe2fb10add954fba4202f8142f32 Author: Pota <[email protected]> Date: Wed Oct 21 17:55:13 2020 +0800 feat: 首次提交
git log
命令显示从最近到最远的提交日志,我们可以看到4次提交,如果嫌输出信息太多,看得眼花缭乱的,可以试试加上--pretty=oneline
参数:git log --pretty=oneline 310f02083e0bfd1762ddbd33664d01881cef8fd3 (HEAD -> master) feat: 第三次改动 ff1eb142c143b9498d57ad3c8218bd62019d3f18 feat: 第二次改动 62ea36c7ed237ec92d333a4fc5a5d2f7f929665e feat: 第一次改动 25bae0398fc1fe2fb10add954fba4202f8142f32 feat: 首次提交
使用 IDE或图形化工具查看
2). 版本回退
版本回退仅限本地仓库中使用,若提交已push至远程仓库,则无法回退远程仓库内容
- 命令
git reset –-[soft | hard | mixed] commit_id
--soft
、--mixed
、--hard
是三个恢复等级:--soft
仅将头指针HEAD恢复,已经add的缓存以及工作空间的所有东西都不变;暂存区和工作区不会被切换;保留源码,只回退到commit 信息到某个版本.不涉及index的回退,如果还需要提交,直接commit即可。--mixed
将头HEAD恢复掉,已经add的缓存也会丢失掉,工作空间的代码之类的不变;暂存区会更新至指定的commit,工作区不会受影响;会保留源码,只是将git commit和index 信息回退到了某个版本。--hard
将一切全都恢复,头HEAD改变,add的缓存消失,代码等也恢复到以前状态;暂存区和工作区同时更新到指定的commit;源码也会回退到某个版本,commit和index 都回回退到某个版本.
注意事项
reset --hard
操作会导致当前缓存区和工作区的改动重置reset --mixed
操作会导致当前缓存区的改动重置
分支管理
一、创建与合并分支
git 初始化后会默认创建master
分支 开发过程中一般会采用多分支进行项目管理
创建分支
git branch <branch name> # 基于当前HEAD指向分支创建新分支
git checkout -b <branch name> # 基于当前HEAD指向分支创建新分支并切换到该分支
git switch -c <barnch name> # 基于当前HEAD指向分支创建新分支并切换到该分支
切换分支
git checkout <branch name>
git switch <branch name>
合并分支
git merge <branch name> # 合并指定分支改动到当前分支
删除分支
git branch -d <branch name> # 删除本地分支
git push origin -d <branch name> # 删除远程分支
合并模式
合并分支是默认使用Fast forward模式合并,合并后会丢失分支信息 使用--no-ff
参数禁用Fast forward模式后合并会保留分支信息
二、解决冲突
两个分支同一个文件都进行了提交导致节点无法连续后 合并会导致冲突
冲突产生后 **必须 ** 解决冲突后再次提交
$ git merge develop
Auto-merging readme.md
CONFLICT (content): Merge conflict in readme.md
Automatic merge failed; fix conflicts and then commit the result.
$ git status
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: readme.md
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: "\346\225\231\347\250\213.md"
no changes added to commit (use "git add" and/or "git commit -a")
查看readme.md文件后会发现git
将冲突内容依据HEAD
和冲突分支形式列出
$ cat readme.md
第一次改动内容
第二次改动内容
第三次改动内容
<<<<<<< HEAD
master:第四次改动内容
=======
develop 第四次改动内容
>>>>>>> develop
此时需要将冲突文件修改为合并后内容后再次添加到缓存区并提交
$ cat readme.md
第一次改动内容
第二次改动内容
第三次改动内容
master:第四次改动内容
$ git add readme.md
$ git commit -m"第四次提交"
此时git 主分支线路应该如下
$ git log --graph --pretty=oneline --abbrev-commit
* c6fba0d (HEAD -> master) 第四次提交
|\
| * 63fcc15 (develop) feat: 第四次改动
| * 55c58f4 feat: 第四次改动
* | 9de4e23 feat: 第四次改动
* | e2a6980 feat: 第四次改动
|/
* 983093c feat: 分支前教程
* 310f020 feat: 第三次改动
* ff1eb14 feat: 第二次改动
* 62ea36c feat: 第一次改动
* 25bae03 feat: 首次提交
三、rebase
命令说明
$ git rebase -i HEAD~4
pick 55c58f4 feat: 第四次改动
pick 63fcc15 feat: 第四次改动
pick 2f5f83d 第五次提交
pick 5abf70e 第六次提交
pick 5e96e00 feat: rebase前提交
# Rebase 9de4e23..5e96e00 onto 5abf70e (5 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
pick
pick
只表示包含提交。 在变基进行时重新排列pick
命令的顺序会更改提交的顺序。 如果选择不包含提交,应删除整行。reword
reword
命令类似于pick
,但在使用后,变基过程就会暂停,让您有机会改变提交消息。 提交所做的任何更改都不受影响。edit
如果选择
edit
提交,您将有机会修订提交,也就是说,可以完全添加或更改提交。 您也可以创建更多提交后再继续变基。 这样您可以将大提交拆分为小提交,或者删除在提交中执行错误更改。squash
此命令可用于将两个或以上的提交合并为一个。 下面的提交压缩到其上面的提交。 Git 让您有机会编写描述两次更改的新提交消息。
fixup
这类似于
squash
,但要合并的提交丢弃了其消息。 提交只是合并到其上面的提交,之前提交的消息用于描述两次更改。exec
这可让您对提交运行任意 shell 命令。
示例
假设当前git提交历史如下
$ git log --pretty=oneline
e85216ae5739c9eb1835a913b2c9449abd45ed74 这个提交移动到B文件提交前
046dfd07a3fc537871e837a8e5209a12ab37eaca 这个commit写错了
c50bd16a3ad4ef8b9cfc4ab5a7ee465609c1c976 文件A追加
de5cd71b26e94f137c7b202db0c4bee5600b2442 文件B修复
1bbbc6c8efa86e60aee2916dc46c173d1fea4f1d 文件B提交
8dbb92ae88b9d868a4817d8f25537bb83bf6c20c 文件A提交
$ git rebase -i HEAD~6
pick 8dbb92a 文件A提交
pick 1bbbc6c 文件B提交
pick de5cd71 文件B修复
pick c50bd16 文件A追加
pick 046dfd0 这个commit写错了
pick e85216a 这个提交移动到B文件提交前
# Rebase 412c835..e85216a onto c50bd16 (6 commands)
准备进行以下变更:
- 将
c50bd16
压缩到8dbb92a
中 - 将最后一个提交(
e85216a
)向上移动到文件B提交
提交(1bbbc6c
)之前,并保留为pick
- 将
文件B修复
提交(de5cd71
)合并到文件B提交
提交(1bbbc6c
)中,并忽略提交消息 - 使用
reword
修复拼写错误的提交 (046dfd0
) 的提交消息
将编辑器中文件修改为以下内容:
pick 8dbb92a 文件A提交
squash c50bd16 文件A追加
pick e85216a 这个提交移动到B文件提交前
pick 1bbbc6c 文件B提交
fixup de5cd71 文件B修复
reword 046dfd0 这个commit写错了
保存并关闭编辑器,开始交互式rebase
pick 8dbb92a
命令因无内容改动被跳过squash c50bd16
命令因合并提交需手动修改 会打开默认编辑器进行改动如下:# This is a combination of 2 commits. # This is the 1st commit message: 文件A提交 # This is the commit message #2: 文件A追加 # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # Date: Tue Oct16:07:46+0800 # # interactive rebase in progress; onto 412c835 # Last commands done (2 commands done): # pick 8dbb92a 文件A提交 # squash c50bd16 文件A追加 # Next commands to do (4 remaining commands): # pick e85216a 这个提交移动到B文件提交前 # pick 1bbbc6c 文件B提交 # You are currently rebasing branch 'master' on '412c835'. # # Changes to be committed: #▸ modified: a #
修改内容为想要的提交信息后保存文件
# This is a combination of 2 commits. # This is the 1st commit message: 文件A提交 # This is the commit message #2: #文件A追加
pick e85216a
、pick 1bbbc6c
、fixup de5cd71
因无需干预会自动进行,其中fixup de5cd71
会将de5cd71
提交合并到1bbbc6c
中并舍弃commit信息reword 046dfd0
会再次打开编辑器并显示一下信息:这个commit写错了 # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # Date: Tue Oct 27 16:08:56 2020 +0800 # # interactive rebase in progress; onto 412c835 # Last commands done (6 commands done): # fixup de5cd71 文件B修复 # reword 046dfd0 这个commit写错了 # No commands remaining. # You are currently editing a commit while rebasing branch 'master' on '412c 835'. # # Changes to be committed: #▸ modified: c #
将内容改为想要的commit后保存 并完成此次rebase
[detached HEAD 5a30ce2] 文件A提交 Date: Tue Oct 27 16:07:46 2020 +0800 1 file changed, 2 insertions(+) [detached HEAD 46eb136] 这个commit写错了 现在修复了 Date: Tue Oct 27 16:08:56 2020 +0800 1 file changed, 1 insertion(+) Successfully rebased and updated refs/heads/master.
在完成rebase后查看git历史
$ git log --pretty=oneline
46eb136e6d0f70536069aa27dd603a27c8ceb4a1 这个commit写错了 现在修复了
0b17895ec112456d4e337f678bf1c2c95a85cd03 文件B提交
40b2e81db35a3e66fa4d57911df8a52dd5ff3c7b 这个提交移动到B文件提交前
5a30ce23ef594f73429ef7c77ffc0f09ceac01bf 文件A提交
412c83521248caafcfe89c1afeffb6de3551dc43 init
冲突解决
在rebase过程中如果遇到冲突 按照正常冲突解决过程一样 修改完成后使用命令
$ git add <file>
$ git rebase --continue
四、stash
当在某个分支正在进行某项修改时,此时出现了一个bug必须优先解决,这个时候需要切换到hot-fix分支进行bug修复,此时进行到一半的工作也不能提交,这个时候就需要将当前未完成的修改存储起来,等bug修改完成以后再继续进行修改
储藏你的工作
为了演示这一功能,你可以进入你的项目,在一些文件上进行工作,有可能还暂存其中一个变更。如果你运行 git status
,你可以看到你的中间状态:
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: d.txt
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: a
现在你想切换分支,但是你还不想提交你正在进行中的工作;所以你储藏这些变更。为了往堆栈推送一个新的储藏,只要运行 git stash
:
$ git stash
Saved working directory and index state WIP on master: 46eb136 这个commit写错了 现在修复了
你的工作目录就干净了:
$ git status
On branch master
nothing to commit, working tree clean
这时,你可以方便地切换到其他分支工作;你的变更都保存在栈上。要查看现有的储藏,你可以使用 git stash list
:
$ git stash list
stash@{0}: WIP on master: 46eb136 这个commit写错了 现在修复了
使用储藏
当bug修复完成后回到develop分支想要继续之前的工作,此时使用 git stash apply
即可将之前储藏的改动重新应用,默认情况下如果有多个储藏内容时git stash apply
会默认使用最新的一条。如果想用更早的储藏,可以使用名字指定git stash apply stash@{0}
$ git stash apply
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: d.txt
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: a
apply
选项只尝试应用储藏的工作——储藏的内容仍然在栈上。要移除它,你可以运行 git stash drop
,加上你希望移除的储藏的名字:
$ git stash list
stash@{0}: WIP on master: 46eb136 这个commit写错了 现在修复了
$ git stash drop stash@{0}
Dropped stash@{0} (2def785d0c921b679077086faefc40804212e732)
你也可以运行 git stash pop
来重新应用储藏,同时立刻将其从堆栈中移走。
从储藏中创建分支
如果你储藏了一些工作,暂时不去理会,然后继续在你储藏工作的分支上工作,你在重新应用工作时可能会碰到一些问题。如果尝试应用的变更是针对一个你那之后修改过的文件,你会碰到一个归并冲突并且必须去化解它。如果你想用更方便的方法来重新检验你储藏的变更,你可以运行 git stash branch
,这会创建一个新的分支,检出你储藏工作时的所处的提交,重新应用你的工作,如果成功,将会丢弃储藏。
$ git stash branch testchanges
Switched to a new branch 'testchanges'
On branch testchanges
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: d.txt
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: a
Dropped refs/stash@{0} (5945c48cdc350188c675eb2f78c8dcdae72a5870)