本文我将将学习一些高级的 Git 技术,包括分支、合并、恢复、保存更改、选择性提交以及冲突解决等等。这些技术对于软件开发项目中的有效协作和版本控制至关重要。那么,让我们开始吧。
Git 分支是 Git 中的一项功能,允许我们在存储库中创建独立的开发线。它使我们能够同时处理不同的功能或者修复,而不会营销主分支的代码库。
分支相当于独立的工作区,可以在其中进行更改、提交更改,并在完成后将它们合并会主分支。它提供了一种组织和管理项目内不同版本和代码流的方法。
git revert
是一个命令,它通过创建一个新提交来撤销特定提交,该新提交将撤销该提交中所做的更改。这是一种在不更改提交历史记录的情况下撤销更改的安全方法。
git reset
也是一个命令,允许我们将分支指针移动到不同的提交。它可用于将分支重置到以前的状态。但是,应该谨慎使用它,因为它可能会丢弃或修改流程中所做的更改。
简而言之,git revert
通过创建新提交来撤销提交,而 git reset
将分支指针移动到不同的提交。
git rebase
是一个命令,允许你用另一个分支的最新改动更新你的分支。它会将你的改动移到更新的分支之上,从而重新排列提交历史。这有助于创建更简洁明了的修改历史。它有助于整合变更,保持分支最新,并在合并前让提交历史更有条理。
git merge
是一条将不同分支的改动合并到一个分支的命令。它将一个分支中的改动整合到另一个分支中,创建一个包含两个分支改动的新提交。它用于将一个分支中的工作合并到另一个分支中,比如将功能分支合并到主分支中。合并操作会保留单个分支的历史记录,并将其合并为统一的分支历史记录。
从这里[1]可以详细变基和合并的知识。
git stash
是一个方便的命令,允许我们临时保存在工作目录中所做的更改而不提交。当我们需要切换到不同分支来处理单独的任务但想要保留当前的更改时,这就很有用了。
想要使用 git stash
,可以创建一个新的分支并进行一些更改。然后通过运行 git stash
,就可以保存这些更改。此操作将从工作目录中删除更改并将他们存储在新的存储中。可以使用git stash list
命令查看这些暂存的更改,并可以使用 git stash drop
来删除特定的暂存。如果想清楚所有暂存,可以使用 git stash clear
。
git cherry-pick
是一个功能强大的命令,允许从一个分支选择特定的提交并将其应用到另一个分支。当我们只想将一个分支的特定更改合并到另一个分支而不是合并整个分支的时候,这个命令就非常有用。
要选择性提交,可以创建两个分支并对两个分支进行提交。然后使用 git cherry-pick <commit>
,我们就可以选择从一个分支应用到另一个分支的特定提交。这提供了对目标分支包含哪些更改的细粒度控制。
合并或变基分支时可能会产生冲突。解决冲突是 Git 的一项重要技能,Git 提供了一些有用的命令来简化这一过程。
当发生冲突时,使用 git status
来识别有冲突的文件。通过运行 git diff
,可以检查冲突版本之间的差异,帮助我们理解冲突的行。要解决冲突,请手动编辑冲突的文件,保留所需的更改并删除冲突标记。解决冲突后,使用 git add
暂存已解决的文件。这会通知 Git 冲突已解决,并允许合并或变基过程顺利进行。
下面,我们将演示如何创建分支、添加具有不同的内容的提交已将将文件恢复到以前的版本。操作如下:
main
分支创建一个名为 dev
的分支:# 创建分支
git branch dev
# 切换分支到 dev
git checkout dev
操作过程:
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (main)$ git branch dev
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (main)$ git checkout dev
Switched to branch 'dev'
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$
version01.txt
的文本文件,在文件中随便写入一串内容。例:这是应用程序的第一个版本
,操作过程如下:Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ echo "这是应用程序的第一个版本" > version01.txt
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ ls
README.md devops.txt version01.txt
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ cat version01.txt
这是应用程序的第一个版本
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ git status
On branch dev
Untracked files:
(use "git add <file>..." to include in what will be committed)
version01.txt
nothing added to commit but untracked files present (use "git add" to track)
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ git add .
warning: in the working copy of 'version01.txt', LF will be replaced by CRLF the next time Git touches it
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ git status
On branch dev
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: version01.txt
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ git commit -m "add new feature"
[dev b0de460] add new feature
1 file changed, 1 insertion(+)
create mode 100644 version01.txt
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ git status
On branch dev
nothing to commit, working tree clean
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$
dev
分支推送到远程存储库:Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ git push origin dev
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 6 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 346 bytes | 346.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
remote:
remote: Create a pull request for 'dev' on GitHub by visiting:
remote: https://github.com/zerodot618/devops-study/pull/new/dev
remote:
To https://github.com/zerodot618/devops-study.git
* [new branch] dev -> dev
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$
version01.txt
文件的内容,将新提交添加到dev
分支中:Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ vi version01.txt
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ cat version01.txt
这是应用程序的第一个版本,添加了新功能1
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ git add .
warning: in the working copy of 'version01.txt', LF will be replaced by CRLF the next time Git touches it
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ git commit -m "add new feature1"
[dev 12affd2] add new feature1
1 file changed, 1 insertion(+), 1 deletion(-)
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ git push origin dev
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 6 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 308 bytes | 308.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To https://github.com/zerodot618/devops-study.git
b0de460..12affd2 dev -> dev
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ vi version01.txt
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ git add .
warning: in the working copy of 'version01.txt', LF will be replaced by CRLF the next time Git touches it
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ git commit -m "this feature code is bad"
[dev f0c8979] this feature code is bad
1 file changed, 1 insertion(+), 1 deletion(-)
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ git push origin dev
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 6 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 325 bytes | 325.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To https://github.com/zerodot618/devops-study.git
12affd2..f0c8979 dev -> dev
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ vi version01.txt
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ git add .
warning: in the working copy of 'version01.txt', LF will be replaced by CRLF the next time Git touches it
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ git commit -m "this feature code is fixed"
[dev 798bc3a] this feature code is fixed
1 file changed, 1 insertion(+), 1 deletion(-)
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ git push origin dev
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 6 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 296 bytes | 296.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
To https://github.com/zerodot618/devops-study.git
f0c8979..798bc3a dev -> dev
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$
version01.txt
文件恢复到以前的版本,其中提交的内容为:“add new feature1”。 使用 git log --oneline
,我们就可以找到 <commit>
的提交信息并识别我们想要重置的提交。Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ git log --oneline
798bc3a (HEAD -> dev, origin/dev) this feature code is fixed
f0c8979 this feature code is bad
12affd2 add new feature1
b0de460 add new feature
1c97339 (origin/main, main) add new file
03dd5a3 add readme file
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$
git reset <commit>
命令重置我们想要重置的提交:Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ git reset 12affd2
Unstaged changes after reset:
M version01.txt
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$
image.png
这个练习,演示的是分支、合并和变基的概念。操作如下:
git branch
命令创建 2 个或多个具有不同名称的分支。本练习中,我们使用 main
和 dev
分支:git branch dev
对 dev
分支进行一些更改并提交。
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ git status
On branch dev
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: version01.txt
no changes added to commit (use "git add" and/or "git commit -a")
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ git add .
warning: in the working copy of 'version01.txt', LF will be replaced by CRLF the next time Git touches it
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ git commit -m "modify file"
[dev 0103829] modify file
1 file changed, 1 insertion(+), 1 deletion(-)
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ git log --oneline
0103829 (HEAD -> dev) modify file
12affd2 add new feature1
b0de460 add new feature
1c97339 (origin/main, main) add new file
03dd5a3 add readme file
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$
dev
分支合并到 main
分支:# 先切换到 main 分支
git checkout main
# 将 dev 分支合并到 main 分支
git merge dev
操作过程:
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ git checkout main
Switched to branch 'main'
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (main)$ git merge dev
Updating 1c97339..0103829
Fast-forward
version01.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 version01.txt
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (main)$ git log --oneline
0103829 (HEAD -> main, dev) modify file
12affd2 add new feature1
b0de460 add new feature
1c97339 (origin/main) add new file
03dd5a3 add readme file
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (main)$
git rebase
操作并查看和git merge
的差异:Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (main)$ git checkout dev
Switched to branch 'dev'
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ echo "this is a rebase test" > rebasetestfile.txt
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ git add .
warning: in the working copy of 'rebasetestfile.txt', LF will be replaced by CRLF the next time Git touches it
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ git commit -m "add rebase test file"
[dev d4f8abe] add rebase test file
1 file changed, 1 insertion(+)
create mode 100644 rebasetestfile.txt
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ git log --oneline
d4f8abe (HEAD -> dev) add rebase test file
0103829 (main) modify file
12affd2 add new feature1
b0de460 add new feature
1c97339 (origin/main) add new file
03dd5a3 add readme file
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ git checkout main
Switched to branch 'main'
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (main)$ ls
README.md devops.txt version01.txt
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (main)$ git rebase dev
Successfully rebased and updated refs/heads/main.
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (main)$ ls
README.md devops.txt rebasetestfile.txt version01.txt
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (main)$ git log --oneline
d4f8abe (HEAD -> main, dev) add rebase test file
0103829 modify file
12affd2 add new feature1
b0de460 add new feature
1c97339 (origin/main) add new file
03dd5a3 add readme file
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (main)$
合并(merge)保留分支结构并创建新的合并提交,而变基(rebase)重写提交历史记录并提供线性提交序列。合并和变基之间的选择取决于特定的用例、项目要求和协作工作流程。
这个练习,我们将使用分支并使用 git stash
命令保存更改而不提交他们。操作如下:
git checkout -b dev2
,创建一个新分支:Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (main)$ git checkout -b dev2
Switched to a new branch 'dev2'
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev2)$
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev2)$ ls
README.md devops.txt rebasetestfile.txt version01.txt
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev2)$ echo "this is a new file." > stashfile.txt
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev2)$ git status
On branch dev2
Untracked files:
(use "git add <file>..." to include in what will be committed)
stashfile.txt
nothing added to commit but untracked files present (use "git add" to track)
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev2)$ git add .
git stash
保存更改而不提交:Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev2)$ git stash
Saved working directory and index state WIP on dev2: d4f8abe add rebase test file
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev2)$
git checkout main
切换到 main
分支:Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev2)$ git checkout main
Switched to branch 'main'
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (main)$
main
分支的文件进行一些更改并提交:Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (main)$ ls
README.md devops.txt rebasetestfile.txt version01.txt
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (main)$ vi newfile.txt
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (main)$ git add .
warning: in the working copy of 'newfile.txt', LF will be replaced by CRLF the next time Git touches it
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (main)$ git commit -m "add newfile.txt"
[main 0d9b412] add newfile.txt
1 file changed, 1 insertion(+)
create mode 100644 newfile.txt
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (main)$ git log --oneline
0d9b412 (HEAD -> main) add newfile.txt
d4f8abe (dev2, dev) add rebase test file
0103829 modify file
12affd2 add new feature1
b0de460 add new feature
1c97339 (origin/main) add new file
03dd5a3 add readme file
git stash pop
恢复刚刚暂存的更改并将它们应用到 main
分支上:Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (main)$ git stash pop
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: stashfile.txt
Dropped refs/stash@{0} (1cebad483b7d13f7fc02bddea1ff20360b367046)
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (main)$ ls
README.md devops.txt newfile.txt rebasetestfile.txt stashfile.txt version01.txt
这个练习,我们将从一个分支挑选特定的更改提交到另一个分支,并对其进行一些更改。操作如下:
dev
分支的提交历史记录,选择一个想要切换的提交,再切换到 prod
分支:Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ git log --oneline
d4f8abe (HEAD -> dev, dev2) add rebase test file
0103829 modify file
12affd2 add new feature1
b0de460 add new feature
1c97339 (origin/main) add new file
03dd5a3 add readme file
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (dev)$ git checkout prod
Switched to branch 'prod'
git cherry-pick <commit-hash>
命令选择性提交 dev
分支中 12affd2 add new feature1
这个提交:Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (prod)$ ls
README.md devops.txt newfile.txt rebasetestfile.txt stashfile.txt version01.txt
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (prod)$ git cherry-pick 12affd2
Auto-merging version01.txt
CONFLICT (content): Merge conflict in version01.txt
error: could not apply 12affd2... add new feature1
hint: After resolving the conflicts, mark them with
hint: "git add/rm <pathspec>", then run
hint: "git cherry-pick --continue".
hint: You can instead skip this commit with "git cherry-pick --skip".
hint: To abort and get back to the state before "git cherry-pick",
hint: run "git cherry-pick --abort".
Administrator@ZEXDWFABYXCPTJF MINGW64 /d/Codes/devops/devops-study (prod|CHERRY-PICKING)$ ls
README.md devops.txt newfile.txt rebasetestfile.txt stashfile.txt version01.txt
[1]
这里: https://www.simplilearn.com/git-rebase-vs-merge-article