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 initICTP-AP operates in affiliation to UCAS.
Taiji Lab is systematic project, not simple scientific laboratory.$ git add readme.txtgit 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)
masteradd
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)
masteradd
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 statusgit add 实际上就是把文件修改添加到暂存区;git commit 实际上就是把暂存区的所有内容提交到当前分支。工作区
(Working Directory)
版本库
(Repository)
暂存区
(stage/index)
masteradd
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 statusgit add 实际上就是把文件修改添加到暂存区;git commit 实际上就是把暂存区的所有内容提交到当前分支。工作区
(Working Directory)
版本库
(Repository)
暂存区
(stage/index)
masteradd
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)
masteradd
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)
masteradd
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)
masteradd
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)
masteradd
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)
masteradd
commit
HEAD
readme.txt*
LICENSE
LICENSE
readme.txt
$ git status
$ git restore readme.txtreadme.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)
masteradd
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)
masteradd
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)
masteradd
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)
masterHEAD
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)
masterreadme.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:<你的用户名>/<仓库名称>.gitorigin,这是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 指向的就是当前分支。masterHEAD
HEAD
mastermaster 分支。HEAD 严格来说不是指向提交,而是指向 master,master 才是指向提交的,所以,HEAD 指向的就是当前分支。masterHEAD
dev,即新建了一个指针叫 dev,指向 master 相同的提交,再把HEAD指向dev,就表示当前分支在dev上。$ git switch -c dev # 创建并切换分支到 devmaster 分支。HEAD 严格来说不是指向提交,而是指向 master,master 才是指向提交的,所以,HEAD 指向的就是当前分支。masterdev,即新建了一个指针叫 dev,指向 master 相同的提交,再把HEAD指向dev,就表示当前分支在dev上。devHEAD
$ git switch -c dev # 创建并切换分支到 dev
$ git branch # 查看当前分支git branch 命令会列出所有分支,当前分支前面会标一个*号。master 分支。HEAD 严格来说不是指向提交,而是指向 master,master 才是指向提交的,所以,HEAD 指向的就是当前分支。masterdev 分支上正常提交,对readme.txt做个修改,加上一行:devHEAD
$ echo "Creating a new branch is quick." >> readme.txt
$ git commit -am "branch test"
$ git log
$ cat readme.txtmaster 分支。HEAD 严格来说不是指向提交,而是指向 master,master 才是指向提交的,所以,HEAD 指向的就是当前分支。masterdev 分支的工作完成,我们就可以切换回 master 分支:dev$ git switch master
$ git log
$ cat readme.txtHEAD
master 分支。HEAD 严格来说不是指向提交,而是指向 master,master 才是指向提交的,所以,HEAD 指向的就是当前分支。masterdevHEAD
dev 分支的工作成果合并到当前的 master分支上:$ git merge dev
$ git log
$ cat readme.txtFast-forward信息,Git告诉我们,这次合并是“快进模式”,也就是直接把master指向dev的当前提交,所以合并速度非常快。master 分支。HEAD 严格来说不是指向提交,而是指向 master,master 才是指向提交的,所以,HEAD 指向的就是当前分支。masterdev分支了:HEAD
$ git branch -d dev
$ git branchmasterfeature1 分支,继续我们的新分支开发:HEAD
$ git switch -c feature1
$ echo "Creating a new branch is quick AND simple." >> readme.txt
$ cat readme.txt
$ git commit -am "AND simple"masterfeature1 分支,继续我们的新分支开发:$ git switch -c feature1
$ echo "Creating a new branch is quick AND simple." >> readme.txt
$ cat readme.txt
$ git commit -am "AND simple"feature1HEAD
mastermaster分支:$ git switch masterfeature1HEAD
master分支比远程的master分支要超前1个提交。master 分支上把 readme.txt 文件的最后一行按如下修改,并再一次提交。Creating a new branch is quick & simple.$ git commit -am "& simple"$ git merge feature1
$ git statusreadme.txt文件存在冲突,必须手动解决冲突后再提交。git status也可以告诉我们冲突的文件:$ git statusfeature1$ 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 feature1masterHEAD
$ 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-commitFast forward模式 (--ff),但这种模式下,删除分支后,会丢掉分支信息。feature2masterHEAD
masterHEAD
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 logFast forward模式 (--no-ff),Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。feature2masterHEAD
masterHEAD
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 statusgit stash。
当你接到一个修复一个代号101的bug的任务时,很自然地,你想创建一个分支issue-101来修复它,但是,等等,当前正在dev上进行的工作还没有提交:
工作区
(Working Directory)
暂存区
(stage/index)
版本库
(Repository)
dev
masterHEAD
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)
masterreadme.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 statusdev
HEAD
堆栈区
(Stack)
Stashed Changes
git stash。
当你接到一个修复一个代号101的bug的任务时,很自然地,你想创建一个分支issue-101来修复它,但是,等等,当前正在dev上进行的工作还没有提交:
工作区
(Working Directory)
暂存区
(stage/index)
版本库
(Repository)
masterreadme.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)
masterdev
HEAD
Git Stash的用途非常广泛,特别适用于以下几种常见场景:
堆栈区
(Stack)
Stashed Changes
在master分支上修复了bug后,我们要想一想,dev 分支是早期从 master分支分出来的,所以,这个bug其实在当前dev分支上也存在。
那怎么在dev分支上修复同样的bug?重复操作一次,提交不就行了?
有木有更简单的方法?有!
为了方便操作,Git专门提供了一个 cherry-pick 命令,让我们能从一个特定的提交合并到当前分支:
工作区
(Working Directory)
暂存区
(stage/index)
版本库
(Repository)
masterdev
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.txtdev
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.githomework 分支上完成。你需要在你的本地仓库中新建目录 /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