创建版本库
git init #初始化本地版本库
git add fileName #添加文件到暂存区,文件可一次添加多个
git commit -m "description" #提交到仓库
####
$ git status #查看状态
On branch master
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: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
比较仓库与工作区文件差别
$ git diff readme.txt
diff --git a/readme.txt b/readme.txt
index 46d49bf..9247db6 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,2 +1,2 @@
-Git is a version control system.
+Git is a distributed version control system.
Git is free software.
比较文件需要两个文件在一起比较,idea可以比较当前文件与不同提交历史文件、与其他目录文件、与不同分支、本地不同修改时刻文件的差别。
查看提交记录
$ git log
commit 1094adb7b9b3807259d8cb349e7df1d4d6477073 (HEAD -> master)
Author: Michael Liao <askxuefeng@gmail.com>
Date: Fri May 18 21:06:15 2018 +0800
append GPL
commit e475afc93c209a690c39c13a46716e8fa000c366
Author: Michael Liao <askxuefeng@gmail.com>
Date: Fri May 18 21:03:36 2018 +0800
add distributed
commit eaadf4e385e865d25c48e7ca9c8395c3f7dfaef0
Author: Michael Liao <askxuefeng@gmail.com>
Date: Fri May 18 20:59:18 2018 +0800
wrote a readme file
$ git log --pretty=oneline #简化输出
1094adb7b9b3807259d8cb349e7df1d4d6477073 (HEAD -> master) append GPL
e475afc93c209a690c39c13a46716e8fa000c366 add distributed
eaadf4e385e865d25c48e7ca9c8395c3f7dfaef0 wrote a readme file
版本回退
$ git reset --hard HEAD^ #回退到上一个版本
HEAD is now at e475afc add distributed
$ git reset --hard 1094a #回退到指定commit id号提交
HEAD is now at 83b0afe append GPL
git内部有个HEAD指针,指向不同分支,如master、release、feature分支,分支指向提交,git管理的是修改,而不是文件。
查看历史命令
$ git reflog #可以找到所有commit id以及解决冲突、切换分支等历史记录
e475afc HEAD@{1}: reset: moving to HEAD^
1094adb (HEAD -> master) HEAD@{2}: commit: append GPL
e475afc HEAD@{3}: commit: add distributed
eaadf4e HEAD@{4}: commit (initial): wrote a readme file
工作区、版本库、暂存区、分支的概念
工作区:就是电脑里能看到的目录
版本库:工作区有一个隐藏目录.git,这个不算工作区,而是git的版本库。
暂存区:版本库里存了很多东西,其中最重要的就是称为stage的暂存区,还有git为我们自动创建的第一个分支master,以及指向master的一个指针叫 HEAD。
往git版本库里添加文件分两步执行的:
-
用git add把文件添加进去,实际上把文件修改添加到暂存区;
-
用git commit提交更改,实际上把暂存区的所有内容提交到当前分支。
可以把需要提交的文件修改统统放到暂存区,然后一次性提交暂存区的所有修改。
撤销修改
-
已提交到分支,参见版本回退一节。
-
修改后添加到暂存区:
$ git status
On branch master
Your branch is up to date with 'origin/master'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: test.txt
bijingwang@DESKTOP-PSO1H64 MINGW64 /d/test02/gitee/git22/git-test (master)
$ git restore --staged test.txt #将暂存区的修改撤销掉
$ git status
On branch master
Your branch is up to date with 'origin/master'.
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: test.txt
no changes added to commit (use "git add" and/or "git commit -a")
$ git restore test.txt #撤销工作区修改
-
如果提交到暂存区后又修改了,同2
删除文件
工作区删除->提交到暂存区->提交到版本库
$ rm test.txt
$ git rm test.txt #或者用git add命令
rm 'test.txt'
$ git commit -m "remove test.txt"
[master d46f35e] remove test.txt
1 file changed, 1 deletion(-)
delete mode 100644 test.txt
删错了,用git reset可以恢复。
添加远程库
一开始在github或者私有git服务器建远程仓库时,可以在本机从远程仓库克隆,也可以把一个已有的本地仓库与之关联。
$ git remote add origin git@github.com:michaelliao/learngit.git #将一个已有的本地仓库与远程仓库建立关联 $ git clone git@github.com:michaelliao/gitskills.git #克隆 Cloning into 'gitskills'... remote: Counting objects: 3, done. remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 3 Receiving objects: 100% (3/3), done.
创建分支
HEAD严格来说不是指向提交,而是指向master,master才是指向提交的。
-
查看当前分支
$ git branch #当前分支前面会标一个*号 * dev master
-
创建、切换分支
$ git switch -c dev #创建并切换到dev分支 $ git switch master #切换到dev分支
-
合并分支
$ git merge dev #将dev分支合到当前分支上 Updating d46f35e..b17d20e Fast-forward #无冲突快进模式,有冲突需解决冲突再合并 readme.txt | 1 + 1 file changed, 1 insertion(+) $ git branch -d dev #合并后删除dev分支 Deleted branch dev (was b17d20e).
解决冲突
$ git merge feature1 Auto-merging readme.txt CONFLICT (content): Merge conflict in readme.txt #说明在readme.txt发生冲突 Automatic merge failed; fix conflicts and then commit the result. $ git status On branch master Your branch is ahead of 'origin/master' by 2 commits. #比远程领先两个提交 (use "git push" to publish your local commits) 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.txt #冲突文件 no changes added to commit (use "git add" and/or "git commit -a")
此时冲突文件变为:
Git is a distributed version control system. Git is free software distributed under the GPL. Git has a mutable index called stage. Git tracks changes of files. <<<<<<< HEAD Creating a new branch is quick & simple. ======= #分割冲突 Creating a new branch is quick AND simple. >>>>>>> feature1
需要选择保留的内容,删除不需要的。对于java文件,不建议在notepad上操作,涉及到依赖,notepad不会自动引入或删除依赖。
合并后如图:
$ git log --graph --pretty=oneline --abbrev-commit * cf810e4 (HEAD -> master) conflict fixed #这里解决冲突,两个分支连线 | | * 14096d0 (feature1) AND simple * | 5dc6824 & simple |/ * b17d20e branch test * d46f35e (origin/master) remove test.txt * b84166e add test.txt * 519219b git tracks changes * e43a48b understand how stage works * 1094adb append GPL * e475afc add distributed * eaadf4e wrote a readme file
保留现场
如果不提交就切换到其他分支,会导致修改丢失。可以将当前工作现场“储藏”起来,等以后恢复现场后继续工作(不常用):
$ git stash #保留现场,进栈 Saved working directory and index state WIP on dev: f52c633 add merge $ git stash list #栈里有多个 stash@{0}: WIP on dev: f52c633 add merge $ git stash pop #恢复现场 On branch dev Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: hello.py 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: readme.txt Dropped refs/stash@{0} (5d677e2ee266f39ea296182fb2354265b91b3b2a) $ git stash apply stash@{0} #指定恢复“哪个现场” $ git cherry-pick 4c805e2 #从其他分支复制提交,有可能冲突 [master 1d4b803] fix bug 101 1 file changed, 1 insertion(+), 1 deletion(-)
删除分支
新建的分支修改后提交,一般需要合到其他分支才能合并。
$ git branch -d feature-vulcan #无法删除 error: The branch 'feature-vulcan' is not fully merged. #提示还没合并 If you are sure you want to delete it, run 'git branch -D feature-vulcan'. $ git branch -D feature-vulcan #-D参数可以删除 Deleted branch feature-vulcan (was 287773e).
查看远程仓库信息
$ git remote -v origin git@github.com:michaelliao/learngit.git (fetch) origin git@github.com:michaelliao/learngit.git (push)
推送分支
$ git push origin master #需使本地分支与远程分支对应起来
建立本地分支与远程分支关系
$ git branch #当你从远程仓库克隆时,实际上Git自动把本地的master分支和远程的master分支对应起来了,并且,远程仓库的默认名称 #是origin。 * master $ git branch --set-upstream-to=origin/dev dev #方法1:本地创建分支dev,然后设置dev与远程dev的链接 Branch 'dev' set up to track remote branch 'dev' from 'origin'. $ git switch -c feature origin/feature #方法2:创建分支时直接指定与远程分支的链接 Switched to a new branch 'feature' Branch 'feature' set up to track remote branch 'feature' from 'origin'.
拉取分支
$ git pull #拉取,可能会出现冲突 Auto-merging env.txt CONFLICT (add/add): Merge conflict in env.txt Automatic merge failed; fix conflicts and then commit the result.
合并情形总结
冲突发生在两个分支对同一个文件修改,在合并时发生,都是通过选择保留的内容后提交到分支来解决冲突,此后再对这个文件修改不会再引起冲突了,除非其他人在你提交前对同一个文件进行提交
现有feature、release、originfeature、origin elease四个分支:
feature往originfeature上合:
合并成功
发生冲突,git原生命令拒绝合并,提示先pull再push。idea集成工具马上让你解决冲突,并将feature落后origin/feature上的提交合到feature。
origin/feature---》feature:
拉取成功
冲突,解决冲突提交即为解决冲突。idea解决冲突后不需要手动提交。
origin/feature---->>origin/release:
merge成功
冲突,解决冲突后将origin/feature落后origin/release上的提交合到origin/feature。此类情形,不建议远程解决冲突,可以本地feature-->>release,原生的git merge和idea操作不会在解决冲突后进行release-->feature污染feature分支。
idea解决冲突界面
左右两边为冲突双方,中间为最终保留结果,可以保留一方,也可以两个都保留。