Git Tutorial (in)

Git Tutorial (in)

Create and merge branches

Each commit, Git regard they strung together a timeline, this timeline is a branch. In Git, this branch is called the main branch, that masterbranch. HEADStrictly speaking is not directed to submit, but the point master, masteris the point of submission, so the HEADpoint is the current branch.
Each submission, masterthe branch will move one step forward, so, as you continue to commit, masterbranch lines are getting longer and longer.

Pictures .png

When we create a new branch, for example, dev, Git built a pointer called dev, points at the same master, and then point to HEAD dev, says that the current branch on the dev:

Pictures .png

For example

First, we create deva branch, then switch to devthe branch:

$ git checkout -b dev
Switched to a new branch 'dev'

git checkoutCommand with the -bparameter indicates and switches, the equivalent of the following two commands:

$ git branch dev
$ git checkout dev
Switched to branch 'dev'

Then, view the current branch with git branch command (there is currently a branch before an asterisk):

$ git branch
* dev
  master

Then, we can properly filed on dev branch, for example, to readme.txtmake a modification, add a line, then submit.

Switch back to masterthe branch, found just modify the content of "not effective" because that is submitted in devthe branch, and the masterbranch point at the moment of the submission has not changed:

$ git checkout master
Switched to branch 'master'

Pictures .png

Now, we have devconsolidated the results of the work branch to masterbranch:

$ git merge dev
Updating d46f35e..b17d20e
Fast-forward
readme.txt | 1 +
1 file changed, 1 insertion(+)

Note: Thegit merge command is used to specify the branch to merge the current branch. The above Fast-forwardinformation, Git tells us that this merger is a "fast-forward mode", that is directly to the masterpoint devcurrently committed, so the merger is very fast.

After the merger is completed, you can safely delete the dev branch:

$ git branch -d dev
Deleted branch dev (was b17d20e).

Create and switch to a new devbranch, you can use: git switch -c dev
switch directly to an existing masterbranch, you can use:git switch master

command

View branch:git branch

Create a branch:git branch <name>

Branch switching: git checkout <name>orgit switch <name>

Create a + to switch branches: git checkout -b <name>orgit switch -c <name>

Merge a branch to the current branch:git merge <name>

Deleted branches:git branch -d <name>

Merge and resolve conflicts

conflict:

  1. New branch dev, to switch to devthe branch and the modified a.txtrear addandcommit
  2. Switching to masterthe branch, modified a.txtafter addandcommit
  3. Try to merge the branch conflict!
$ git merge dev
Auto-merging a.txt
CONFLICT (content): Merge conflict in a.txt
Automatic merge failed; fix conflicts and then commit the result.

Pictures .png

solution

Git tells us that a.txtthere is a conflict files, you must manually resolve the conflict before submitting. git statusFiles can also tell us the conflict:

$ 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:   a.txt

no changes added to commit (use "git add" and/or "git commit -a")

Submit:

$ git add a.txt 
$ git commit -m "conflict fixed"
[master cf810e4] conflict fixed

FIG combined as follows:

Pictures .png

With arguments git logyou can also see the consolidation of branch:

$ git log --graph --pretty=oneline --abbrev-commit
*   cf810e4 (HEAD -> master) conflict fixed
|\  
| * 14096d0 (dev) 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

Finally, remove the devbranches:

$ git branch -d dev
Deleted branch dev (was 14096d0).

Branch Management Strategy

Typically, when merging branches, if possible, Git will use Fast forwardmode, but this mode, delete the branch, the branch will lose information.

If you want to force disable Fast forwardmode, Git will be in mergegenerating a new time commit, so, from the branch history information can be seen on branch

Combat: the mastermerger branch devbranches:

$ git merge --no-ff -m "merge with no-ff" dev
Merge made by the 'recursive' strategy.
readme.txt | 1 +
1 file changed, 1 insertion(+)

After the merger, we git loglook at the branch history:

$ git log --graph --pretty=oneline --abbrev-commit
*   e1e9c68 (HEAD -> master) merge with no-ff
|\  
| * f52c633 (dev) add merge
|/  
*   cf810e4 conflict fixed
...

Do not use Fast forwardpatterns, mergeafter like this:

Pictures .png

分支策略
实际开发中,首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;那在哪干活呢?干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;

你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。所以,团队合作的分支看起来就像这样:

Pictures .png

Bug分支

修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;

当手头工作没有完成时,先把工作现场git stash一下,然后去修复bug,修复后,再git stash pop,回到工作现场;

master分支上修复的bug,想要合并到当前dev分支,可以用git cherry-pick <commit>命令,把bug提交的修改“复制”到当前分支,避免重复劳动。

举例:

当你在dev分支工作时,有一个bug需要尽快解决,此时使用git stash保存工作现场,切换到master分支,创建新分支修复:

$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 6 commits.
  (use "git push" to publish your local commits)

$ git checkout -b issue-101
Switched to a new branch 'issue-101'

$ git add readme.txt 
$ git commit -m "fix bug 101"
[issue-101 4c805e2] fix bug 101
1 file changed, 1 insertion(+), 1 deletion(-)

再切换到dev分支。此时,用git stash list命令列出该分支下的所有工作现场:

$ git stash list
stash@{0}: WIP on dev: f52c633 add merge

工作现场还在,Gitstash内容存在某个地方了,但是需要恢复一下,有两个办法:

一是用git stash apply或者git stash apply stash@{0}恢复,但是恢复后,stash内容并不删除,你需要用git stash drop来删除;

另一种方式是用git stash pop,恢复的同时把stash内容也删了.

修复完成后,因为dev分支是来源于master分支,所以,使用git cherry-pick <提交的版本号>命令,此处版本号为4c805e2,来使dev分支进行同样的提交,避免重复劳动。

$ git cherry-pick 4c805e2
[master 1d4b803] fix bug 101
1 file changed, 1 insertion(+), 1 deletion(-)

feature分支

  • 开发一个新feature,最好新建一个分支;

  • 如果要丢弃一个没有被合并过的分支,可以通过git branch -D 强行删除。

添加一个新功能时,你肯定不希望因为一些实验性质的代码,把主分支搞乱了,所以,每添加一个新功能,最好新建一个feature分支,在上面开发,完成后,合并,最后,删除该feature分支。

实例:

  1. 你接到了一个新任务:开发代号为Vulcan的新功能,该功能计划用于下一代星际飞船。
$ git switch -c feature-vulcan
Switched to a new branch 'feature-vulcan'
  1. 5分钟后,开发完毕:
$ git add vulcan.py

$ git status
On branch feature-vulcan
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

  new file:   vulcan.py

$ git commit -m "add feature vulcan"
[feature-vulcan 287773e] add feature vulcan
1 file changed, 2 insertions(+)
create mode 100644 vulcan.py
  1. 切回dev,准备合并,但是此时接到上级命令,因经费不足,新功能必须取消!虽然白干了,但是这个包含机密资料的分支还是必须就地销毁:
$ git switch dev

$ 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'.
  1. 销毁失败。Git友情提醒,feature-vulcan分支还没有被合并,如果删除,将丢失掉修改,如果要强行删除,需要使用大写的-D参数。
$ git branch -D feature-vulcan
Deleted branch feature-vulcan (was 287773e).

多人协作

当你从远程仓库克隆时,实际上Git自动把本地的master分支和远程的master分支对应起来了,并且,远程仓库的默认名称是origin

要查看远程库的信息,用git remote

$ git remote
origin

git remote -v查看更详细的信息:

$ git remote -v
origin  [email protected]:qujialin/learn.git (fetch)
origin  [email protected]:qujialin/learn.git (push)

上面显示了可以抓取和推送的origin的地址。如果没有推送权限,就看不到push的地址。

推送分支

推送分支,就是把该分支上的所有本地提交推送到远程库。推送时,要指定本地分支,这样,Git就会把该分支推送到远程库对应的远程分支上:

$ git push origin master

如果要推送其他分支,比如dev,就改成:

$ git push origin dev

抓取分支

多人协作时,大家都会往masterdev分支上推送各自的修改。

创建远程origindev分支到本地:

$ git checkout -b dev origin/dev

你的小伙伴已经向origin/dev分支推送了他的提交,而碰巧你也对同样的文件作了修改,并试图推送:

$ cat env.txt
env

$ git add env.txt

$ git commit -m "add new env"
[dev 7bd91f1] add new env
1 file changed, 1 insertion(+)
create mode 100644 env.txt

$ git push origin dev
To github.com:michaelliao/learngit.git
! [rejected]        dev -> dev (non-fast-forward)
error: failed to push some refs to '[email protected]:michaelliao/learngit.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

推送失败,因为你的小伙伴的最新提交和你试图推送的提交有冲突,解决办法也很简单,Git已经提示我们,先用git pull把最新的提交从origin/dev抓下来,然后,在本地合并,解决冲突,再推送:

$ git pull
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details.

    git pull <remote> <branch>

If you wish to set tracking information for this branch you can do so with:

    git branch --set-upstream-to=origin/<branch> dev

git pull也失败了,原因是没有指定本地dev分支与远程origin/dev分支的链接,根据提示,设置devorigin/dev的链接:

$ git branch --set-upstream-to=origin/dev dev
Branch 'dev' set up to track remote branch 'dev' from 'origin'.

pull

$ git pull
Auto-merging env.txt
CONFLICT (add/add): Merge conflict in env.txt
Automatic merge failed; fix conflicts and then commit the result.

这回git pull成功,但是合并有冲突,需要手动解决,解决的方法和分支管理中的解决冲突完全一样。解决后,提交,再push

$ git commit -m "fix env conflict"
[dev 57c53ab] fix env conflict

$ git push origin dev
Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 621 bytes | 621.00 KiB/s, done.
Total 6 (delta 0), reused 0 (delta 0)
To github.com:michaelliao/learngit.git
  7a5e5dd..57c53ab  dev -> dev

因此,多人协作的工作模式通常是这样:

  首先,可以试图用`git push origin <branch-name>`推送自己的修改;

  如果推送失败,则因为远程分支比你的本地更新,需要先用`git pull`试图合并;

  如果合并有冲突,则解决冲突,并在本地提交;

  没有冲突或者解决掉冲突后,再用`git push origin <branch-name>`推送就能成功!

如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to <branch-name> origin/<branch-name>

这就是多人协作的工作模式,一旦熟悉了,就非常简单。

Rebase

在上一节我们看到了,多人在同一个分支上协作时,很容易出现冲突。即使没有冲突,后push的童鞋不得不先pull,在本地合并,然后才能push成功。

每次合并再push后,分支变成了这样:

$ git log --graph --pretty=oneline --abbrev-commit
* d1be385 (HEAD -> master, origin/master) init hello
*   e5e69f1 Merge branch 'dev'
|\  
| *   57c53ab (origin/dev, dev) fix env conflict
| |\  
| | * 7a5e5dd add env
| * | 7bd91f1 add new env
| |/  
* |   12a631b merged bug fix 101
|\ \  
| * | 4c805e2 fix bug 101
|/ /  
* |   e1e9c68 merge with no-ff
|\ \  
| |/  
| * f52c633 add merge
|/  
*   cf810e4 conflict fixed

总之看上去很乱,有强迫症的童鞋会问:为什么Git的提交历史不能是一条干净的直线?

其实是可以做到的!

Git has called rebaseoperation, it was translated into "Variable group." Entrygit rebase

$ git rebase
First, rewinding head to replay your work on top of it...
Applying: add comment
Using index info to reconstruct a base tree...
M hello.py
Falling back to patching base and 3-way merge...
Auto-merging hello.py
Applying: add author
Using index info to reconstruct a base tree...
M hello.py
Falling back to patching base and 3-way merge...
Auto-merging hello.py

This time with a git loglook:

$ git log --graph --pretty=oneline --abbrev-commit
* 7e61ed4 (HEAD -> master) add author
* 3611cfe add comment
* f005ed4 (origin/master) set exit=1
* d1be385 init hello
...

Originally submitted bifurcation has now become a straight line up! This magical operation is how to achieve? In fact, the principle is very simple. We observe, discover our local Git submit "move" position, put f005ed4 (origin/master) set exit=1after this, the entire commit history became a straight line. rebase before and after the operation, the final submission is the same, but our local commitcontent has changed, no longer based on their modification d1be385 init hello, but on f005ed4 (origin/master) set exit=1, but the final submission of 7e61ed4the content is the same.

This is rebasecharacteristic of the operation: the commit history "finishing" bifurcated into a straight line, looks more intuitive. The disadvantage is that the local bifurcation submission has been modified.

Finally, by pushoperating the remote push local branch:

$ git push origin master
Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (6/6), 576 bytes | 576.00 KiB/s, done.
Total 6 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), completed with 1 local object.
To github.com:qujialin/Learn.git
  f005ed4..7e61ed4  master -> master

Remote branch commit history is a straight line. as follows:

$ git log --graph --pretty=oneline --abbrev-commit
* 7e61ed4 (HEAD -> master, origin/master) add author
* 3611cfe add comment
* f005ed4 set exit=1
* d1be385 init hello
...

Reference links:

https://www.liaoxuefeng.com/wiki/896043488029600/900003767775424

Guess you like

Origin www.cnblogs.com/qujialin/p/12099206.html