He Wang PRO
Knowledge increases by sharing but not by saving.
第 1 部分 编程开发环境与工作流
主讲老师:王赫
2023/11/19
ICTP-AP, UCAS
Git 分布式版本控制系统
# Response
# Git
现代的版本控制系统可以帮助您轻松地(甚至自动地)回答以下问题:
Linux就该这么学:使用Git分布式版本控制系统
Git不仅是一款开源的分布式版本控制系统,而且有其独特的功能特性,
# Git
$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"
$ git config --global core.editor vim
$ git config --list # 查看刚刚配置的工作环境
$ git init
ICTP-AP operates in affiliation to UCAS.
Taiji Lab is systematic project, not simple scientific laboratory.
$ git add readme.txt
git add
告诉Git,把文件添加到版本库里:$ git commit -m "wrote a readme file"
git commit
告诉Git,把所有文件提交:git status 查看在当前版本库的状态
$ git status
$ git diff readme.txt
-
表示第 1 个文件+
表示第 2 个文件@@ -1,2 +1,2@@
表示比较的区块:
$ git add readme.txt
$ git commit -m "fix bug: association, add a"
ICTP-AP operates in association with UCAS.
Taiji Lab is a systematic project, not a simple scientific laboratory.
ICTP-AP operates in affiliation to UCAS, fostering collaboration.
Taiji Lab is a systematic project, not a simple scientific laboratory.
$ git reset --hard HEAD^ # 回退到上一个版本
$ git reset --hard <commit id> # 跳转到某一个版本
HEAD表示当前版本,上一个版本就是HEAD^上上一个就是HEAD^^
git reset
回退到某版本:git log 查看历史记录(版本号)
$ git log --pretty=oneline
$ git reflog # 记录了工作区里的每一次git命令
$ git add readme.txt
$ git commit -m "append collaboration"
$ cat readme.txt # 看看内容是哪个版本
$ git log # 看看Git在哪个历史版本
$ ls -lht # 实际上对文件是修改的
工作区
(Working Directory)
版本库
(Repository)
暂存区
(stage/index)
master
add
commit
HEAD
ICTP-AP operates in affiliation to UCAS, fostering collaboration.
Taiji Lab is a systematic project, not a simple scientific laboratory.
Git has a mutable index called stage.
readme.txt
做个修改,比如加上一行内容:git add
实际上就是把文件修改添加到暂存区;git commit
实际上就是把暂存区的所有内容提交到当前分支。$ git status
$ git add readme.txt LICENSE
$ git status
工作区
(Working Directory)
版本库
(Repository)
暂存区
(stage/index)
master
add
commit
HEAD
readme.txt
LICENSE
readme.txt*
ICTP-AP operates in affiliation to UCAS, fostering collaboration.
Taiji Lab is a systematic project, not a simple scientific laboratory.
Git has a mutable index called stage.
readme.txt
做个修改,比如加上一行内容:$ git status
$ git add readme.txt LICENSE
$ git status
git add
实际上就是把文件修改添加到暂存区;git commit
实际上就是把暂存区的所有内容提交到当前分支。工作区
(Working Directory)
版本库
(Repository)
暂存区
(stage/index)
master
add
commit
HEAD
readme.txt
LICENSE
readme.txt
LICENSE
readme.txt*
ICTP-AP operates in affiliation to UCAS, fostering collaboration.
Taiji Lab is a systematic project, not a simple scientific laboratory.
Git has a mutable index called stage.
readme.txt
做个修改,比如加上一行内容:$ git status
$ git add readme.txt LICENSE
$ git status
$ git commit -m "understand how stage works"
$ git status
git add
实际上就是把文件修改添加到暂存区;git commit
实际上就是把暂存区的所有内容提交到当前分支。工作区
(Working Directory)
版本库
(Repository)
暂存区
(stage/index)
master
add
commit
HEAD
readme.txt
LICENSE
readme.txt
LICENSE
ICTP-AP operates in affiliation to UCAS, fostering collaboration.
Taiji Lab is a systematic project, not a simple scientific laboratory.
Git has a mutable index called stage.
Git tracks changes.
readme.txt
做个修改,比如加上一行内容:$ git add readme.txt
$ git status
工作区
(Working Directory)
版本库
(Repository)
暂存区
(stage/index)
master
add
commit
HEAD
readme.txt*
LICENSE
readme.txt
LICENSE
readme.txt*
ICTP-AP operates in affiliation to UCAS, fostering collaboration.
Taiji Lab is a systematic project, not a simple scientific laboratory.
Git has a mutable index called stage.
Git tracks changes of files.
readme.txt
做个修改,比如修改最后一行内容:$ git status
$ git commit -m "Add: Git tracks changes"
$ git status
工作区
(Working Directory)
版本库
(Repository)
暂存区
(stage/index)
master
add
commit
HEAD
readme.txt**
LICENSE
LICENSE
readme.txt*
ICTP-AP operates in affiliation to UCAS, fostering collaboration.
Taiji Lab is a systematic project, not a simple scientific laboratory.
Git has a mutable index called stage.
Git tracks changes of files.
readme.txt
做个修改,比如修改最后一行内容:$ git status
$ git commit -m "Add: Git tracks changes"
$ git status
工作区
(Working Directory)
版本库
(Repository)
暂存区
(stage/index)
master
add
commit
HEAD
readme.txt**
LICENSE
LICENSE
readme.txt*
$ git diff HEAD -- readme.txt
git diff HEAD -- readme.txt
命令可以查看工作区和版本库里面最新版本的区别:git diff HEAD
ICTP-AP operates in affiliation to UCAS, fostering collaboration.
Taiji Lab is a systematic project, not a simple scientific laboratory.
Git has a mutable index called stage.
Git tracks changes of files.
readme.txt
做个修改,比如修改最后一行内容:$ git status
$ git commit -m "Add: Git tracks changes"
$ git status
工作区
(Working Directory)
版本库
(Repository)
暂存区
(stage/index)
master
add
commit
HEAD
readme.txt**
LICENSE
LICENSE
readme.txt**
$ git diff HEAD -- readme.txt
git diff HEAD -- readme.txt
命令可以查看工作区和版本库里面最新版本的区别:git diff HEAD
$ git commit -am "Append: of files"
git commit -am
ICTP-AP operates in affiliation to UCAS, fostering collaboration.
Taiji Lab is a systematic project, not a simple scientific laboratory.
Git has a mutable index called stage.
Git tracks changes of files.
My stupid boss ...
readme.txt
做个错误修改,比如添加最后一行内容:工作区
(Working Directory)
版本库
(Repository)
暂存区
(stage/index)
master
add
commit
HEAD
readme.txt*
LICENSE
LICENSE
readme.txt
$ git status
$ git restore readme.txt
readme.txt
git restore [--worktree]
ICTP-AP operates in affiliation to UCAS, fostering collaboration.
Taiji Lab is a systematic project, not a simple scientific laboratory.
Git has a mutable index called stage.
Git tracks changes of files.
My stupid boss ...
readme.txt
做个错误修改,比如添加最后一行内容:$ git add readme.txt
$ git status
$ git restore --staged readme.txt
$ git status
$ git restore readme.txt
工作区
(Working Directory)
版本库
(Repository)
暂存区
(stage/index)
master
add
commit
HEAD
readme.txt*
LICENSE
LICENSE
readme.txt
readme.txt
git restore [--worktree]
readme.txt*
git restore --staged
ICTP-AP operates in affiliation to UCAS, fostering collaboration.
Taiji Lab is a systematic project, not a simple scientific laboratory.
Git has a mutable index called stage.
Git tracks changes of files.
My stupid boss ...
readme.txt
做个错误修改,比如添加最后一行内容:$ git add readme.txt
$ git status
$ git restore --staged readme.txt
$ git status
$ git restore readme.txt
$ git restore --staged --worktree readme.txt
工作区
(Working Directory)
版本库
(Repository)
暂存区
(stage/index)
master
add
commit
HEAD
readme.txt*
LICENSE
LICENSE
readme.txt
readme.txt
git restore [--worktree]
readme.txt*
git restore --staged --worktree
git restore --staged
$ git add .
$ git commit -m "delete test.txt"
test.txt
到Git并且提交:版本库
(Repository)
暂存区
(stage/index)
master
add
commit
HEAD
LICENSE
readme.txt
test.txt
$ git add test.txt
$ git commit -m "add test.txt"
$ rm test.txt
$ git status
$ git restore .
工作区
(Working Directory)
(deleted)
LICENSE
readme.txt
test.txt
git restore [--worktree]
版本库
(Repository)
暂存区
(stage/index)
master
HEAD
readme.txt
LICENSE
test.txt
工作区
(Working Directory)
LICENSE
readme.txt
test.txt
git add
git commit
git restore [--worktree]
git restore --staged
git restore --staged --worktree
readme.txt
LICENSE
git reset --hard
HEAD^
$ git status -s
$ git diff
$ git commit --amend = git reset --soft head~1 + git commit
版本库
(Repository)
暂存区
(stage/index)
master
readme.txt
LICENSE
test.txt
工作区
(Working Directory)
LICENSE
readme.txt
test.txt
git add
git commit
git restore [--worktree]
git restore --staged
git restore --staged --worktree
readme.txt
LICENSE
git reset --hard
HEAD^
git diff
git diff HEAD
git diff --staged
HEAD
$ git remote add origin git@github.com:<你的用户名>/<仓库名称>.git
origin
,这是Git默认的叫法,也可以改成别的,但是origin
这个名字一看就知道是远程库。$ git remote add origin git@github.com:<你的用户名>/<仓库名称>.git
$ git remote -v # 查看该本地库关联的远程库的信息
$ git remote rm origin # 解除本地和远程的绑定关系
# 第一次推送master分支的所有内容;
$ git push -u origin master
# 把本地master分支的最新修改推送至GitHub
$ git push origin master
版本库
(Repository)
暂存区
(stage/index)
master
工作区
(Working Directory)
本地 Local
远程库 Remote Repository
HEAD
add
commit
push
pull
master
分支。HEAD
严格来说不是指向提交,而是指向 master
,master
才是指向提交的,所以,HEAD
指向的就是当前分支。master
HEAD
HEAD
master
master
分支。HEAD
严格来说不是指向提交,而是指向 master
,master
才是指向提交的,所以,HEAD
指向的就是当前分支。master
HEAD
dev,即
新建了一个指针叫 dev
,指向 master
相同的提交,再把HEAD
指向dev
,就表示当前分支在dev
上。$ git switch -c dev # 创建并切换分支到 dev
master
分支。HEAD
严格来说不是指向提交,而是指向 master
,master
才是指向提交的,所以,HEAD
指向的就是当前分支。master
dev,即
新建了一个指针叫 dev
,指向 master
相同的提交,再把HEAD
指向dev
,就表示当前分支在dev
上。dev
HEAD
$ git switch -c dev # 创建并切换分支到 dev
$ git branch # 查看当前分支
git branch
命令会列出所有分支,当前分支前面会标一个*
号。master
分支。HEAD
严格来说不是指向提交,而是指向 master
,master
才是指向提交的,所以,HEAD
指向的就是当前分支。master
dev
分支上正常提交,对readme.txt
做个修改,加上一行:dev
HEAD
$ echo "Creating a new branch is quick." >> readme.txt
$ git commit -am "branch test"
$ git log
$ cat readme.txt
master
分支。HEAD
严格来说不是指向提交,而是指向 master
,master
才是指向提交的,所以,HEAD
指向的就是当前分支。master
dev
分支的工作完成,我们就可以切换回 master
分支:dev
$ git switch master
$ git log
$ cat readme.txt
HEAD
master
分支。HEAD
严格来说不是指向提交,而是指向 master
,master
才是指向提交的,所以,HEAD
指向的就是当前分支。master
dev
HEAD
dev
分支的工作成果合并到当前的 master
分支上:$ git merge dev
$ git log
$ cat readme.txt
Fast-forward
信息,Git告诉我们,这次合并是“快进模式”,也就是直接把master
指向dev
的当前提交,所以合并速度非常快。master
分支。HEAD
严格来说不是指向提交,而是指向 master
,master
才是指向提交的,所以,HEAD
指向的就是当前分支。master
dev
分支了:HEAD
$ git branch -d dev
$ git branch
master
feature1
分支,继续我们的新分支开发:HEAD
$ git switch -c feature1
$ echo "Creating a new branch is quick AND simple." >> readme.txt
$ cat readme.txt
$ git commit -am "AND simple"
master
feature1
分支,继续我们的新分支开发:$ git switch -c feature1
$ echo "Creating a new branch is quick AND simple." >> readme.txt
$ cat readme.txt
$ git commit -am "AND simple"
feature1
HEAD
master
master
分支:$ git switch master
feature1
HEAD
master
分支比远程的master
分支要超前1个提交。master
分支上把 readme.txt
文件的最后一行按如下修改,并再一次提交。Creating a new branch is quick & simple.
$ git commit -am "& simple"
$ git merge feature1
$ git status
readme.txt
文件存在冲突,必须手动解决冲突后再提交。git status
也可以告诉我们冲突的文件:$ git status
feature1
$ vim readme.txt
<<<<<<<
,=======
,>>>>>>>
标记出不同分支的内容,我们把最后一行修改如下后保存,并再一次重新提交。Creating a new branch is quick and simple.
$ git commit -am "conflict fixed"
$ git status
$ git log
$ git log --graph --pretty=oneline --abbrev-commit
$ git branch -d feature1
master
HEAD
$ git switch -c feature2
$ echo "Try --ff and --no-ff here." >> readme.txt
$ git commit -am "try --ff"
$ git log
$ git switch master
$ git merge feature2 --ff
$ cat readme.txt
$ git log --graph --pretty=oneline --abbrev-commit
Fast forward
模式 (--ff
),但这种模式下,删除分支后,会丢掉分支信息。feature2
master
HEAD
master
HEAD
git merge --ff
$ git switch master
$ git merge feature2 --ff
$ cat readme.txt
$ git log --graph --pretty=oneline --abbrev-commit
$ git branch -d feature2
# 回退到 merge 之前的状态
$ git reset HEAD~
$ git status # 暂存区为空
$ git restore readme.txt
# 再稍微修改下 feature2 中上一次commit的message内容
$ git commit --amend
$ git log
Fast forward
模式 (--no-ff
),Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。feature2
master
HEAD
master
HEAD
git merge --no-ff
# 构建一个未提交的 dev 分支
$ git switch -c dev
$ echo "Try stash on stage" >> readme.txt
$ git add readme.txt
$ echo "Try stash on worktree" >> readme.txt
$ git status
# 在不同分支上观察工作区和暂存区
$ git switch master
$ git status
git stash
。
当你接到一个修复一个代号101的bug的任务时,很自然地,你想创建一个分支issue-101
来修复它,但是,等等,当前正在dev
上进行的工作还没有提交:
工作区
(Working Directory)
暂存区
(stage/index)
版本库
(Repository)
dev
master
HEAD
readme.txt*
readme.txt*
Bug files
$ git switch dev
$ git stash # 保存当前工作区和暂存区的修改,但不保存已提交的修改
$ git status
$ git stash list # 列出所有临时的存储记录
git stash
。
当你接到一个修复一个代号101的bug的任务时,很自然地,你想创建一个分支issue-101
来修复它,但是,等等,当前正在dev
上进行的工作还没有提交:
工作区
(Working Directory)
暂存区
(stage/index)
版本库
(Repository)
master
readme.txt**
readme.txt*
# 开始修复bug并合并到master主分支上
$ git switch -c issue-101
$ echo "Fix a bug" >> readme.txt
$ git commit -am 'A bug is fixed'
$ git switch master
$ git merge issue-101 --no-ff -m "merged bug fix 101"
$ git branch -d issue-101
$ git log
$ git switch dev
$ git status
dev
HEAD
堆栈区
(Stack)
Stashed Changes
git stash
。
当你接到一个修复一个代号101的bug的任务时,很自然地,你想创建一个分支issue-101
来修复它,但是,等等,当前正在dev
上进行的工作还没有提交:
工作区
(Working Directory)
暂存区
(stage/index)
版本库
(Repository)
master
readme.txt**
readme.txt*
$ git stash pop # 恢复最近一个的同时把stash内容也删了
$ git status
$ cat readme.txt
$ git stash list
$ git stash save "try stach apply"
$ git stash list
$ git status
$ cat readme.txt
$ git stash apply # 恢复后,stash内容并不删除
# git stash apply stash@{0} # 可以指定某一次内容来恢复
$ git status
$ cat readme.txt
$ git stash list
$ git stash drop stash@{0} # 删除存储的内容
dev
HEAD
git stash
。
工作区
(Working Directory)
暂存区
(stage/index)
版本库
(Repository)
master
dev
HEAD
Git Stash的用途非常广泛,特别适用于以下几种常见场景:
堆栈区
(Stack)
Stashed Changes
在master分支上修复了bug后,我们要想一想,dev 分支是早期从 master分支分出来的,所以,这个bug其实在当前dev分支上也存在。
那怎么在dev分支上修复同样的bug?重复操作一次,提交不就行了?
有木有更简单的方法?有!
为了方便操作,Git专门提供了一个 cherry-pick
命令,让我们能从一个特定的提交合并到当前分支:
工作区
(Working Directory)
暂存区
(stage/index)
版本库
(Repository)
master
dev
HEAD
$ git switch master
$ git commit -am 'Try stash'
# 记下你想要合并的某一次 commit id
$ git log --graph --pretty=oneline --abbrev-commit
$ git switch dev
$ git cherry-pick <commit id>
$ git status
$ vim readme.txt # 解决冲突问题
$ git commit -am 'Try cherry-pick'
$ git log --graph --pretty=oneline --abbrev-commit
$ cat readme.txt
dev
HEAD
软件开发中,总有无穷无尽的新的功能要不断添加进来。
添加一个新功能时,你肯定不希望因为一些实验性质的代码,把主分支搞乱了,所以,每添加一个新功能,最好新建一个feature分支,在上面开发,完成后,合并,最后,删除该feature分支。
软件开发中,总有无穷无尽的新的功能要不断添加进来。
添加一个新功能时,你肯定不希望因为一些实验性质的代码,把主分支搞乱了,所以,每添加一个新功能,最好新建一个feature分支,在上面开发,完成后,合并,最后,删除该feature分支。
本地新建的分支如果不推送到远程,对其他人就是不可见的。
多人协作的工作模式通常是这样:
首先,可以试图用 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>
git rebase
操作可以把本地未 push 的分叉提交历史整理成直线;git rebase
的目的是使得我们在查看历史提交的变化时更容易,因为分叉的提交需要三方对比(在不同分支间)。
git tag [commit id]
Platforms: Mac, Windows
Price: Free
License: MIT
Platforms: Mac, Windows
Price: Free
License: Proprietary
Platforms: Linux, Mac, Windows
Price: Free / $59+/user annually
License: Proprietary
# Homework
$ git clone git@github.com:<你的github账户名>/GWData-Bootcamp.git
homework
分支上完成。你需要在你的本地仓库中新建目录 /GWData-Bootcamp/2023/homework/<你的名字>/
;并最终把 homework 分支的作业 push 到你自己的关于本课程的远程仓库中,即: $ git push origin homework
;最后,在GitHub上你的远程仓库中,在 homework 分支下发起 Pull Request (PR) 至本课程远程仓库。
Repo of the course: https://github.com/iphysresearch/GWData-Bootcamp
<你的github账户名>
不要勾选,可以把homework分支也一并fork
By He Wang
引力波数据探索:编程与分析实战训练营。课程网址:https://github.com/iphysresearch/GWData-Bootcamp