Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[testcase notes] #26: git merge options #64

Open
dorawyy opened this issue Nov 4, 2017 · 3 comments
Open

[testcase notes] #26: git merge options #64

dorawyy opened this issue Nov 4, 2017 · 3 comments

Comments

@dorawyy
Copy link
Owner

dorawyy commented Nov 4, 2017

To test git merge configuration parameters

git merge categorization --> #75

References

Merge process

(Took from git merge documentation)
When it is not obvious how to reconcile the changes, the following happens:

  • The HEAD pointer stays the same.
  • The MERGE_HEAD ref is set to point to the other branch head.
  • Paths that merged cleanly are updated both in the index file and in your working tree.
  • For conflicting paths, the index file records up to three versions: stage 1 stores the version from the common ancestor, stage 2 from HEAD, and stage 3 from MERGE_HEAD (you can inspect the stages with git ls-files -u). The working tree files contain the result of the "merge" program; i.e. 3-way merge results with familiar conflict markers <<< === >>>.
  • No other changes are made. In particular, the local modifications you had before you started merge will stay the same and the index entries for them stay as they were, i.e. matching HEAD

Synopsis

git merge [-n] [--stat] [--no-commit] [--squash] [--[no-]edit]
	[-s <strategy>] [-X <strategy-option>] [-S[<keyid>]]
	[--[no-]allow-unrelated-histories]
	[--[no-]rerere-autoupdate] [-m <msg>] [<commit>…​]
git merge --abort
git merge --continue

--commit & --no-commit

--no-commit

With --no-commit perform the merge but pretend the merge failed and do not autocommit, to give the user a chance to inspect and further tweak the merge result before committing

--squash & --no-squash

--squash

Produce the working tree and index state as if a real merge happened (except for the merge information), but do not actually make a commit, move the HEAD, or record $GIT_DIR/MERGE_HEAD (to cause the next git commit command to create a merge commit). This allows you to create a single commit on top of the current branch whose effect is the same as merging another branch (or more in case of an octopus).

--no-squash

With --no-squash perform the merge and commit the result. This option can be used to override --squash.

--ff & --no-ff & --ff-only

--ff

When the merge resolves as a fast-forward, only update the branch pointer, without creating a merge commit. This is the default behavior.

--no-ff

Create a merge commit even when the merge resolves as a fast-forward. This is the default behaviour when merging an annotated (and possibly signed) tag.

--ff-only

Refuse to merge and exit with a non-zero status unless the current HEAD is already up to date or the merge can be resolved as a fast-forward.

Tools to use when resolving conflicts

(Took from git merge documentation)

git mergetool

Use a mergetool. git merge tool to launch a graphical mergetool which will work you through the merge.

git diff

Look at the diffs. git diff will show a three-way diff, highlighting changes from both the HEAD and MERGE_HEAD versions.

git log merge -p <path>

Look at the diffs from each branch. git log --merge -p <path> will show diffs first for the HEAD version and then the MERGE_HEAD version.

git show :n:filename

Look at the originals.

  • git show :1:filename shows the common ancestor,
  • git show :2:filename shows the HEAD version, and
  • git show :3:filename shows the MERGE_HEAD version.

Merge strategies

(reference: git merge documentation)

  • resolve
  • recursive
    • ours
    • theirs
    • patience
    • diff-algorithm=[patience|minimal|histogram|myers]
    • ignore-space-change
    • ignore-all-space
    • ignore-space-at-eol
    • renormalize
    • no-renormalize
    • no-renames
    • find-names[=<n>]
    • rename-threshold=<n>
    • subtree[=<path>]
  • octopus
  • ours
  • subtree
@dorawyy
Copy link
Owner Author

dorawyy commented Nov 6, 2017

Test1 ( no conflict)

wechatimg306

#2 
git checkout mt1
git commit test26_merge_test -m "mt1: x=1"

#3
git checkout mt2
git commit test26_merge_test -m "mt2: z=1"

#4
git checkout mt1
git commit test26_merge_test -m "mt1: x=2"

#5 
git checkout mt2
git commit test26_merge_test -m "mt2: z=2"

The project status is:
setting

  • checkout mt1, merge mt2, different types of merging
git checkout mt1

Option1: Normal merge: git merge mt2

git checkout mt1
git merge mt2 

Will be an auto three-way merging, as there is no conflict
screen shot 2017-11-05 at 11 22 27 am

screen shot 2017-11-05 at 11 25 32 am

Option2: git merge mt2 --no-commit

git checkout mt1
git merge mt2 --no-commit

--no-commit param will combine all changes, simulate there is conflict when merging, then ask users to manually save commit; Note that when potential conflict, all changes will be saved in working tree (while when no conflict, all changes will be saved in index)
screen shot 2017-11-05 at 11 28 37 am

Option3: git merge mt2 --squash

git checkout mt1
git merge mt2 --squash

--squash will squash all commits from the other branch into 1 single commit, then apply to current branch
screen shot 2017-11-05 at 2 49 31 pm
Resolve the conflict
screen shot 2017-11-05 at 2 52 13 pm
Then manually commit, but the commit is a normal commit ( with only 1 parent)
(The automatically filled-in message of the squashed commit)
screen shot 2017-11-05 at 2 55 16 pm
screen shot 2017-11-05 at 3 02 54 pm

Here is the details about the commit:
screen shot 2017-11-05 at 3 07 20 pm

Test --ff & --no-ff & --ff-only

--ff-only

As the merge here is not a fast-forward merge, with --ff-only, no merge should happen

git checkout mt1
git merge mt2 --ff-only

screen shot 2017-11-05 at 10 10 45 pm

--ff & --no-ff

Merge mt1 to mt12, which should be a fast-forward merge

git checkout mt2
git merge mt1 --no-ff

Adds-on

Create another commit on mt2, which created a new file test26_mt2, to test if mt1 can receive the file when using different merging options;
wechatimg308

option1: merge normally

git checkout mt1
git merge mt2

Yes, able to see everything

option2: --no-commit

git checkout mt1
git merge mt2 --no-commit

Yes, everything in index
screen shot 2017-11-06 at 3 05 57 pm

option3: --squash

git checkout mt1
git merge mt2 --squash

Yes, everything in working dir
screen shot 2017-11-06 at 3 07 09 pm

@dorawyy
Copy link
Owner Author

dorawyy commented Nov 6, 2017

Test2 ( single conflict)

wechatimg307

#2
git checkout mt3
git commit test26_merge_test -m "mt3:x=1"

#3
git checkout mt4
git commit test26_merge_test -m "mt4:z=1"

#4
git checkout mt3
git commit test26_merge_test -m "mt3:y=1"

#5
git checkout mt4
git commit test26_merge_test -m "mt4:y=2,z=2"

Option1: normal merge, git merge mt4

git checkut mt3
git merge mt4

Will have conflict that need to be resolved
screen shot 2017-11-05 at 12 00 24 pm
screen shot 2017-11-05 at 12 01 16 pm

Fix the conflict, then merge
screen shot 2017-11-05 at 12 02 12 pm
screen shot 2017-11-05 at 12 04 17 pm

Option2: git merge mt4 --no-commit

git checkout mt3
git merge mt4 --no-commit

--no-commit param will combine all changes, simulate there is conflict when merging, then ask users to manually save commit

screen shot 2017-11-05 at 12 06 01 pm

screen shot 2017-11-05 at 12 06 33 pm

Then, fix the conflict, then continue merge
screen shot 2017-11-05 at 12 11 01 pm

screen shot 2017-11-05 at 12 10 31 pm

Option3: git merge mt4 --squash

git checkout mt3
git merge mt4 --squash

screen shot 2017-11-05 at 8 23 09 pm

screen shot 2017-11-05 at 8 23 48 pm

  • Modify the file to resolve the conflict:

screen shot 2017-11-05 at 8 24 28 pm

  • Then commit again, the tree becomes:

screen shot 2017-11-05 at 8 26 46 pm

Thus, there is still only one commit. In other words, all commits from the other branch are squashed into one normal commit on current branch (with only one parent)

  • The details of the squashed commit is:

screen shot 2017-11-05 at 8 28 45 pm

Adds-on

Create another commit on mt2, which created a new file test26_mt2, to test if mt1 can receive the file when using different merging options;

wechatimg309

Option1: normally merge

git checkout mt3
git merge mt4

Yes, updated in working tree
screen shot 2017-11-06 at 3 16 41 pm

Option2: --no-commit

git checkout mt3
git merge mt4 --no-commit

Yes, saved in working tree, same as normal merge
screen shot 2017-11-06 at 3 20 21 pm

Option3: --squash

git checkout mt3
git merge mt4 --squash

Yes, saved in woking tree, same as option1 and 2
screen shot 2017-11-06 at 3 21 37 pm

@dorawyy
Copy link
Owner Author

dorawyy commented Nov 6, 2017

Fast-forward merge

After mt2 is merged to mt1, mt1 is a commit ahead of mt2, now, try:

git checkout mt2
git merge mt1

Way1: normal fast-forward merge, (--ff)

Just move the head pointer of mt2 one commit forward

git checkout mt2
git merge mt1

Regular fast-forward merge, move head forward.

Way2: --no-commit (--ff)

git checkout mt2
git merge mt1 --no-commit

As there is no commit created for fast-forward by default, thus no difference with this param only. Still moves the mt2 head pointer 1 commit forward.
( same as normal fast-forward merge)

Way3: --squash (--ff)

git checkout mt2
git merge mt1 --squash

Instead of performing a fast-forward commit, this will force the merge to create a squash commit on mt2 branch (which is a normal commit).

Way4: --commit (--ff)

git checkout mt2
git merge mt1 --commit

The same as normal fast-forward merge.

Way5: --no-ff

git checkout mt2
git merge mt1 --no-ff

An explicit commit will be created for the merge, the original fast-forward merge is forced to become a three-way merge, with an explicit merge commit

Way6: --squash & --no-ff

git checkout mt2
git merge mt1 --no-ff --squash

Error.
This two param cannot be combined together.
screen shot 2017-11-05 at 11 21 24 pm

Way7: --no-commit & --no-ff

git checkout mt2
git merge mt1 --no-ff --no-commit

All changes are saved in the working tree, when commit, create a merge commit.

Way8: --ff-only

git checkout mt2
git merge mt1 --ff-only 

Pass the assertion, performing a regular fast-forward merge commit
screen shot 2017-11-05 at 11 28 32 pm

Way9: --squash & --no-commit

git checkout mt2
git merge mt1 --squash --no-commit

same as --squash only

git merge mt1 --squash

In the middle of squashing commits:
screen shot 2017-11-05 at 11 31 56 pm
The version of the file is:
screen shot 2017-11-05 at 11 32 44 pm
If git commit, continue creating the squashed commit:
screen shot 2017-11-05 at 11 33 59 pm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant