Git(三)

2021-05-09  本文已影响0人  浅墨入画

一. Git Stash

思考: Git操作每次都要求我们commit,日常开发不能保证每次commit都有效。比如我们正在dev1分支进行开发,此时发现dev2分支上有一个bug,这个时候我们就需要切换到dev2分支去解决问题,可是我们当前dev1分支上的任务还没有完成,代码要不要提交呢?

下面我们就来进行git stash的操作

首先打开工程LGClass,我们看到本地有三个分支

image.png

使用GitUp工具(直接把工程拖入GitUp工具即可)可以看到三个分支目前的状态

image.png
// 进入LGClass工程目录
$ cd /Users/wn/Documents/资料/Stash/初始代码/01-LGClass-Start
// 查看LGClass工程本地所有分支
$ git branch
  hPopAnimator
  kTeacherListView
* master
// 切换到kTeacherListView分支
$ git checkout kTeacherListView
M   LGClass.xcodeproj/project.pbxproj
Switched to branch 'kTeacherListView'

// 修改LGTeacherModel.swift文件下LGTeacher结构体内容
extension LGTeacher {
    static var all: [LGTeacher] {
        [
            LGTeacher( name: "Cooci" ),
            LGTeacher( name: "Kody" ),(修改前)   -> LGTeacher( name: "布加迪Kody" )(修改后)
            LGTeacher( name: "Hank" ),
            LGTeacher( name: "CC" ),
            LGTeacher( name: "Cat" )
        ]
    }
}
// 上面工作内容没有完成,我们不想commit,这个时候就可以使用git stash把本次修改push到thirty workspace工作目录
// 向stash栈中push修改的内容
$ git stash push -m '修改kody-》布加迪'
Saved working directory and index state On kTeacherListView: 修改kody-》布加迪

// push到stash之后我们发现上面修改的内容还原了
extension LGTeacher {
    static var all: [LGTeacher] {
        [
            LGTeacher( name: "Cooci" ),
            LGTeacher( name: "Kody" ),
            LGTeacher( name: "Hank" ),
            LGTeacher( name: "CC" ),
            LGTeacher( name: "Cat" )
        ]
    }
}
// 查看暂存区状态发现没有内容可提交,说明上面已经还原
$ git status
On branch kTeacherListView
nothing to commit, working tree clean

// 查看stash列表内容
$ git stash list
stash@{0}: On kTeacherListView: 修改kody-》布加迪
// 查看某一次stash修改信息
$ git stash show stash@{0}
 LGClass.xcodeproj/project.pbxproj | 2 ++
 LGClass/LGTeacherModel.swift      | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)
// 查看当前操作的diff
$ git stash show -p stash@{0}
diff --git a/LGClass.xcodeproj/project.pbxproj b/LGClass.xcodeproj/project.pbxproj
index 1dd18e2..8bdaf99 100644
--- a/LGClass.xcodeproj/project.pbxproj
+++ b/LGClass.xcodeproj/project.pbxproj
@@ -296,6 +296,7 @@
                                ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
                                CODE_SIGN_STYLE = Automatic;
                                INFOPLIST_FILE = LGClass/Info.plist;
+                               IPHONEOS_DEPLOYMENT_TARGET = 14.0;
                                LD_RUNPATH_SEARCH_PATHS = (
                                        "$(inherited)",
                                        "@executable_path/Frameworks",
@@ -314,6 +315,7 @@
                                ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
                                CODE_SIGN_STYLE = Automatic;
                                INFOPLIST_FILE = LGClass/Info.plist;
+                               IPHONEOS_DEPLOYMENT_TARGET = 14.0;
                                LD_RUNPATH_SEARCH_PATHS = (
                                        "$(inherited)",
                                        "@executable_path/Frameworks",
diff --git a/LGClass/LGTeacherModel.swift b/LGClass/LGTeacherModel.swift
index b32fd42..b4d9c1c 100755
--- a/LGClass/LGTeacherModel.swift
+++ b/LGClass/LGTeacherModel.swift
@@ -16,7 +16,7 @@ extension LGTeacher {
     static var all: [LGTeacher] {
         [
             LGTeacher( name: "Cooci" ),
// 修改LGTeacherModel.swift文件下LGTeacher结构体内容
extension LGTeacher {
    static var all: [LGTeacher] {
        [
            LGTeacher( name: "Cooci" ),
            LGTeacher( name: "Kody" ),
            LGTeacher( name: "Hank" ),(修改前)   -> LGTeacher( name: "钻石讲师Hank" )(修改后)
            LGTeacher( name: "CC" ),
            LGTeacher( name: "Cat" )
        ]
    }
}
// git stash是git stash push简写形式,默认push
$ git stash
Saved working directory and index state WIP on kTeacherListView: ec310cf 添加讲师图片

// git stash之后我们发现上面修改的内容还原了
extension LGTeacher {
    static var all: [LGTeacher] {
        [
            LGTeacher( name: "Cooci" ),
            LGTeacher( name: "Kody" ),
            LGTeacher( name: "Hank" ),
            LGTeacher( name: "CC" ),
            LGTeacher( name: "Cat" )
        ]
    }
}

$ git stash list
stash@{0}: WIP on kTeacherListView: ec310cf 添加讲师图片
stash@{1}: On kTeacherListView: 修改kody-》布加迪
// stash list里面存储有两次修改的内容,现在我们想应用其中的一个
$ git stash apply stash@{0}
On branch kTeacherListView
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:   LGClass/LGTeacherModel.swift

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

// 查看代码,成功回到某一次修改的状态
extension LGTeacher {
    static var all: [LGTeacher] {
        [
            LGTeacher( name: "Cooci" ),
            LGTeacher( name: "Kody" ),
            LGTeacher( name: "钻石讲师Hank" ),
            LGTeacher( name: "CC" ),
            LGTeacher( name: "Cat" )
        ]
    }
}

// 上面已经成功回到某一次修改的状态,这个时候我们发现stash list还有两次修改的记录
$ git stash list
stash@{0}: WIP on kTeacherListView: ec310cf 添加讲师图片
stash@{1}: On kTeacherListView: 修改kody-》布加迪

// 通过git stash show -p stash@{0}返回一个补丁,管道符把返回的补丁作为参数传递到后面   -R逆转补丁
$ git stash show -p stash@{0} | git apply -R
// 再次成功还原
extension LGTeacher {
    static var all: [LGTeacher] {
        [
            LGTeacher( name: "Cooci" ),
            LGTeacher( name: "Kody" ),
            LGTeacher( name: "Hank" ),
            LGTeacher( name: "CC" ),
            LGTeacher( name: "Cat" )
        ]
    }
}

// 再次应用到修改的状态
$ git stash apply stash@{0}
On branch kTeacherListView
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:   LGClass/LGTeacherModel.swift

no changes added to commit (use "git add" and/or "git commit -a")
// 添加并提交
$ git add . && git commit -m '修改Hank-》钻石Hank'
[kTeacherListView 4d3fee5] 修改Hank-》钻石Hank
 1 file changed, 1 insertion(+), 1 deletion(-)
// 查看本地commit提交记录
$ git log --oneline --decorate --graph --stat
* 4d3fee5 (HEAD -> kTeacherListView) 修改Hank-》钻石Hank
|  LGClass/LGTeacherModel.swift | 2 +-
|  1 file changed, 1 insertion(+), 1 deletion(-)
* ec310cf 添加讲师图片
|  LGClass/Assets.xcassets/CC.imageset/CC.jpg   | Bin 0 -> 67008 bytes
|  .../CC.imageset/Contents.json                |  21 +++++++++++++++++
|  LGClass/Assets.xcassets/Cat.imageset/Cat.jpg | Bin 0 -> 212225 bytes
|  .../Cat.imageset/Contents.json               |  21 +++++++++++++++++
|  .../Cooci.imageset/Contents.json             |  21 +++++++++++++++++
|  .../Assets.xcassets/Cooci.imageset/Cooci.jpg | Bin 0 -> 449771 bytes
|  .../Hank.imageset/Contents.json              |  21 +++++++++++++++++
|  .../Assets.xcassets/Hank.imageset/Hank.jpg   | Bin 0 -> 103714 bytes
|  .../Kody.imageset/Contents.json              |  21 +++++++++++++++++
|  .../Assets.xcassets/Kody.imageset/kody.jpg   | Bin 0 -> 533864 bytes
|  10 files changed, 105 insertions(+)
... 
// 这个时候我们后悔上面的提交,回退到上一次提交
$ git rebase -i ec310cf
Successfully rebased and updated refs/heads/kTeacherListView.

// 查看stash列表里面是两条修改记录
$ git stash list
stash@{0}: WIP on kTeacherListView: ec310cf 添加讲师图片
stash@{1}: On kTeacherListView: 修改kody-》布加迪
$ git stash pop stash@{1}
On branch kTeacherListView
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:   LGClass/LGTeacherModel.swift

no changes added to commit (use "git add" and/or "git commit -a")
Dropped stash@{1} (81e9263fff012111f29454c541b0122f1b83d38d)

// 回到stash@{1}的修改状态
extension LGTeacher {
    static var all: [LGTeacher] {
        [
            LGTeacher( name: "Cooci" ),
            LGTeacher( name: "布加迪Kody" ),
            LGTeacher( name: "Hank" ),
            LGTeacher( name: "CC" ),
            LGTeacher( name: "Cat" )
        ]
    }
}

// 此时stash list中只有一条修改记录
$ git stash list
stash@{0}: WIP on kTeacherListView: ec310cf 添加讲师图片
// 按照相同的方法把 stash@{0}  pop出去
// 最后清除stash list
$ git stash clear
// 查看stash list,发现为空
$ git stash list

二. Git Merge

下面我们就来进行git merge的操作

首先打开工程LGClass,切换到kTeacherListView分支

$ cd /Users/wn/Documents/资料/Merge/初始代码/01-LGClass-Start
$ git branch
  hPopAnimator
  kTeacherListView
* master
$ git checkout kTeacherListView
M   LGClass.xcodeproj/project.pbxproj
Switched to branch 'kTeacherListView'
// 合并hPopAnimator分支到当前kTeacherListView分支,这里产生了冲突
$ git merge hPopAnimator
Auto-merging LGClass/ViewController.swift
CONFLICT (content): Merge conflict in LGClass/ViewController.swift
Automatic merge failed; fix conflicts and then commit the result.
image.png
// 查看有没有设置conflictstyle,默认上面冲突的代码都会放在工程中
$ git config merge.conflictstyle
// 回退代码到合并之前的状态
$ git reset --hard HEAD
HEAD is now at ec310cf 添加讲师图片
// 设置merge合并方式
$ git config merge.conflictstyle diff3
// 再次合并,依然报了冲突
$ git merge hPopAnimator
Auto-merging LGClass/ViewController.swift
CONFLICT (content): Merge conflict in LGClass/ViewController.swift
Automatic merge failed; fix conflicts and then commit the result.
image.png
// 查看两个分支共同的父节点
$ git log --oneline --decorate --graph --stat b5b4e2a
* b5b4e2a 修改ViewController.preferredStatusBarStyle
|  LGClass/ViewController.swift | 5 +++++
|  1 file changed, 5 insertions(+)
*   0ae8a58 Merge branch 'kTeacherDetail'
|\
| * f5a99ff 根据模型设置background.image和titleView.text
| |  LGClass/TeacherDetailsViewController.swift | 2 ++
| |  1 file changed, 2 insertions(+)
| * f519ce7 添加TeacherDetailsViewController init(coder: NSCoder, teacher: LGTeacher)
| |  LGClass/TeacherDetailsViewController.swift | 7 +++++++
| |  1 file changed, 7 insertions(+)
| * 6b6f430 添加TeacherDetailsViewController required init?(coder: NSCoder) { fatalError() }
...
// 查看b5b4e2a  commit提交节点的diff
$ git log -p b5b4e2a
commit b5b4e2a56d3add40729442f14531eea11c0142ac
Author: Cat <cat@logic.com>
Date:   Tue Dec 15 16:04:24 2020 +0800

    修改ViewController.preferredStatusBarStyle

diff --git a/LGClass/ViewController.swift b/LGClass/ViewController.swift
index 013e220..ee85e6a 100644
--- a/LGClass/ViewController.swift
+++ b/LGClass/ViewController.swift
@@ -28,3 +28,8 @@ public extension UIViewController {
     .instantiateInitialViewController(creator: `init`)
   }
 }
+
+extension ViewController {
+  override var preferredStatusBarStyle: UIStatusBarStyle { .lightContent }
+
+}
...
// 再次回退代码到合并之前的状态
$ git reset --hard HEAD
// 查看b5b4e2a提交节点的完整形式
$ git checkout b5b4e2a
Note: switching to 'b5b4e2a'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:
  git switch -c <new-branch-name>
Or undo this operation with:
  git switch -
Turn off this advice by setting config variable advice.detachedHead to false
HEAD is now at b5b4e2a 修改ViewController.preferredStatusBarStyle
// 恢复到kTeacherListView分支待提交状态
$ git checkout kTeacherListView
Previous HEAD position was b5b4e2a 修改ViewController.preferredStatusBarStyle
Switched to branch 'kTeacherListView'
// 合并分支,产生diff3形式的冲突
$ git merge hPopAnimator
Auto-merging LGClass/ViewController.swift
CONFLICT (content): Merge conflict in LGClass/ViewController.swift
Automatic merge failed; fix conflicts and then commit the result.
// 指定merge.tool 为opendiff形式
$ git config merge.tool opendiff
// 打开FileMerge工具已解决冲突
$ git mergetool
image.png

使用FileMerge工具解决完冲突之后,退出保存解决冲突后的代码

image.png
// 查看暂存区状态如下图
$ git status
image.png
// 更直观的查看暂存区状态 -s 表示简单状态 -b 表示指定当前分支状态
$ git status -sb
image.png
// 添加指定文件到暂存区
$ git add LGClass/ViewController.swift
// 提交合并的代码
$ git commit -m 'merge two branch'
// 删除hPopAnimator分支
$ git branch -d hPopAnimator

三. Git Ignore

3.1 git ignore编写

把忽略的文件直接放入.gitignore文件中即可

// .gitignore文件内容如下
.DS_Store
// 使用 *通配符的形式,如果想要强制不忽略该文件,可以加!号 !*.pbxuser
*.pbxuser
*.perspective
*.perspectivev3
...

$ cd /Users/wn/Documents/资料/gitignore分支问题/初始代码/01-LGClass
// 查看有没有配置全局. gitignore文件
$ git config --global core.excludesfile
/Users/wn/.gitignore_global
// 如果全局没有配置. gitignore文件,可以这样配置
$ git config --global core.excludesfile ~/.gitignore_global
// 查看.gitignore_global文件配置
$ cat ~/.gitignore_global
*~   //忽略以~为结尾的文件
.DS_Store  //忽略MacOS系统下的DS文件
image.png

需要忽略的文件添加到.gitignore文件中

// 需要忽略的文件内容如下
这是一个需要忽略的文件,未添加到.gitignore中。

// 把需要忽略的文件添加到.gitignore文件中
.DS_Store
需要忽略的文件
*.pbxuser
*.perspective
*.perspectivev3
...

// 查看暂存区状态,提示修改了. gitignore文件
$ git status
On branch 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:   .gitignore

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

// 修改需要忽略的文件 内容如下
这是一个需要忽略的文件,未添加到.gitignore中。
Master branch

// 再次查看暂存区状态
$ git status
On branch 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:   .gitignore
    modified:   "\351\234\200\350\246\201\345\277\275\347\225\245\347\232\204\346\226\207\344\273\266"

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

请思考: 上面提示有两个文件被修改,我们是先把需要忽略的文件添加到.gitignore文件,再修改需要忽略的文件内容,为什么会提示需要忽略的文件被修改呢?
因为需要忽略的文件是中途添加到.gitignore文件,git就会追踪需要忽略的文件

现在我们要怎么忽略.gitignore文件对 需要忽略的文件的追踪呢?
// --assume-unchange 指明 需要忽略的文件 永远不会发生改变,让git不再追踪
$ git update-index --assume-unchange 需要忽略的文件
// 查看暂存区状态,发现不在提示 需要忽略的文件 的更改
$ git status
On branch 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:   .gitignore

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

提示:上面指定忽略只是针对本地文件,其他人操作的话依然会提示,所以我们还是要在索引区中把它删除,只有在索引区中删除,git才会停止追踪

// 查看当前git忽略哪些文件,发现并没有我们添加的 需要忽略的文件,说明没有在索引区中删除
$ git status --ignored
On branch 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:   .gitignore

Ignored files:
  (use "git add -f <file>..." to include in what will be committed)
    .DS_Store
    LGClass.xcodeproj/project.xcworkspace/xcuserdata/
    LGClass.xcodeproj/xcuserdata/wn.xcuserdatad/
    LGClass/.DS_Store
    LGClass/Assets.xcassets/.DS_Store

no changes added to commit (use "git add" and/or "git commit -a")
// 查看git rm 功能
$ git rm --help
$ git rm --cached 需要忽略的文件
rm '需要忽略的文件'
// 发现 需要忽略的文件 在当前git忽略文件列表里,这是git就把它当做真正忽略的文件
$ git status --ignored
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
    deleted:    "\351\234\200\350\246\201\345\277\275\347\225\245\347\232\204\346\226\207\344\273\266"

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:   .gitignore

Ignored files:
  (use "git add -f <file>..." to include in what will be committed)
    .DS_Store
    LGClass.xcodeproj/project.xcworkspace/xcuserdata/
    LGClass.xcodeproj/xcuserdata/wn.xcuserdatad/
    LGClass/.DS_Store
    LGClass/Assets.xcassets/.DS_Store
    "\351\234\200\350\246\201\345\277\275\347\225\245\347\232\204\346\226\207\344\273\266"

注意:这里有一个问题,需要忽略的文件在commit之前可能存在一段时间,这个文件中可能存在密码之类的敏感信息,我们不想让这个文件暴露出去,这时就需要对之前的一些提交信息进行修改,使用git rebase并不是很好的方式,下面我们探讨更好的解决方法?

// 查看git filter-branch 功能
$ git filter-branch --help
// -f 表示 -force强制,--index-filter表示索引区
// git rm忽略不匹配的文件,--ignore-unmatc从索引区移除不存在的文件时避免报错
$ git filter-branch -f --index-filter 'git rm --cached --ignore-unmatch -- 需要忽略的文件' --prune-empty HEAD
WARNING: git-filter-branch has a glut of gotchas generating mangled history
     rewrites.  Hit Ctrl-C before proceeding to abort, then use an
     alternative filtering tool such as 'git filter-repo'
     (https://github.com/newren/git-filter-repo/) instead.  See the
     filter-branch manual page for more details; to squelch this warning,
     set FILTER_BRANCH_SQUELCH_WARNING=1.

Proceeding with filter-branch...

Cannot rewrite branches: You have unstaged changes.
Additionally, your index contains uncommitted changes.
// 上面提示有暂存内容未提交,下面我们添加暂存区并提交
$ git add .
$ git commit -m '修改.gitignore'
[master 5d9fff1] 修改.gitignore
 2 files changed, 1 insertion(+), 2 deletions(-)
 delete mode 100644 "\351\234\200\350\246\201\345\277\275\347\225\245\347\232\204\346\226\207\344\273\266"
// 重写之前的commit,把当前分支之前的commit记录完全重写,上面的问题成功解决
$ git filter-branch -f --index-filter 'git rm --cached --ignore-unmatch -- 需要忽略的文件' --prune-empty HEAD
WARNING: git-filter-branch has a glut of gotchas generating mangled history
     rewrites.  Hit Ctrl-C before proceeding to abort, then use an
     alternative filtering tool such as 'git filter-repo'
     (https://github.com/newren/git-filter-repo/) instead.  See the
     filter-branch manual page for more details; to squelch this warning,
     set FILTER_BRANCH_SQUELCH_WARNING=1.
Proceeding with filter-branch...

Rewrite 70b33203dd528be9db007f232541848c442026f1 (1/27) (0 seconds passed, remaiRewrite b1b80be13e4aaa1842c6e4f53745f81493a0cc54 (2/27) (0 seconds passed, remaiRewrite b0eb0b3ff4bca4a22385722d44fc163e373c25de (3/27) (1 seconds passed, remaiRewrite b0f59f5a176f6fb82d0e38e08ba091a1d4c13f79 (3/27) (1 seconds passed, remaiRewrite 316ed203312a2e3bf00a79127f8b8f56f7a36aa3 (3/27) (1 seconds passed, remaiRewrite 5747424a5468493ed8d738709e6653782b2ef576 (3/27) (1 seconds passed, remaiRewrite
...
上一篇下一篇

猜你喜欢

热点阅读