Skip to content

Hosting a git-course repository to allow students to solve a git-merge problem

Notifications You must be signed in to change notification settings

dtudk/dcc-git-course-conflicts

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 

Repository files navigation

Reproducible research

How to ensure a reproducible research output while simultaneously developing and gathering data.

This project has two branches used for testing purposes.

The following explantions refer to how a project maintainer would consider the branches and their relationship.

The current commit history looks like this:

          A topic
         /
... B---C---D main

[main]

This branch is the development branch and where every development goes into.

This branch has 1 commit that the [topic] branch does not have.

[topic]

Branch with some feature development. This branch is diverging its development from the [main] branch.

This branch has 1 commit that the [main] branch does not have.

Difference using git diff

Using git diff is an important command when mastering a development process.

git diff <> Description
between staged and unstaged changes
--staged between HEAD and staged changes
<1>..<2> a patch that can be applied to <1> to be equivalent to <2>
<1>...<2> what has been added to <2> since <1> and <2> had a common ancestor

The difference of the last two are shown below in 4 examples.

  • git diff topic..main

    diff --git a/src/source_2.py b/src/source_2.py
    index ca55c68..8ba15bc 100644
    --- a/src/source_2.py
    +++ b/src/source_2.py
    @@ -1,5 +1,5 @@
     def foo():
         print("foo")
    
    -def foo2():
    -    print("foo2")
    +def foo_other():
    +    print("foo_other")
  • git diff topic...main

    Note the extra "."!

    diff --git a/src/source_2.py b/src/source_2.py
    index af3cbda..8ba15bc 100644
    --- a/src/source_2.py
    +++ b/src/source_2.py
    @@ -1,2 +1,5 @@
     def foo():
         print("foo")
    +
    +def foo_other():
    +    print("foo_other")
  • git diff main..topic

    diff --git a/src/source_2.py b/src/source_2.py
    index 8ba15bc..ca55c68 100644
    --- a/src/source_2.py
    +++ b/src/source_2.py
    @@ -1,5 +1,5 @@
     def foo():
         print("foo")
    
    -def foo_other():
    -    print("foo_other")
    +def foo2():
    +    print("foo2")
  • git diff main...topic

    Note the extra "."!

    diff --git a/src/source_2.py b/src/source_2.py
    index af3cbda..8ba15bc 100644
    --- a/src/source_2.py
    +++ b/src/source_2.py
    @@ -1,2 +1,5 @@
     def foo():
         print("foo")
    +
    +def foo2():
    +    print("foo2")

Tutorial 1

Execute sh setup.sh 1 from the commandline (requires BASH/Unix) and follow instructions from the output.
The following elements describe the situation in more detail.

In tutorial 1 we will examine what happens when you try to git pull a remote branch which has diverged from your own commits.

The commit branch looks like this:

... A---B---C  [remote]
    |   |
... A---B---D  [local]

Or as though they were local commits:

          C [remote]
         /
... A---B---D [local]

Pulling will try to update the current branch's commits to match the ones on the remote.

This will fail since both repositories have a commit meaning that there is no linear history.

With git there are always multiple ways of doing things.

Resolution 1 -- manual rebase

Generally one cannot push to remotes as they are "protected" by some admin user.
The only solution is to backtrack ones changes and re-apply the changes to have a linear history.

In this case we know that we have 1 additional commit that the remote does not have. So we can do:

git diff HEAD~1 > our_commit.patch
git reset --hard HEAD~1
git pull host
patch -p1 < out_commit.patch
git commit -am "[main]: updated source_2"

Resolution 2 -- direct rebase

A direct rebase will do the above commands in a smart way by letting you change things if conflicts happen. Its use is somewhat magical and one should carefully look at the output of git commands to see how to proceed. For instance, problems will result in users needing to intervene and correct merge conflicts, then git add, then git rebase --contine.

If things goes completely bad, one can always abort by doing git rebase --abort to revert everything that has been done in the rebase command.

This is, probably the easiest way in the long-term, but can be quite hard when rebasing many commits with large conflicts.

This procedure is started with:

git rebase host/main1

and simply do what it says.

Resolution 3 -- merge

In this case a merge will not be applicable since the branches are meant to be coherent (i.e. every commit needs to be 1-1). In git words this is called being able to fast-forward.
A merge would result in the local branch having a different history from the remote, although the content would be the same. Thus meaning that you would never be able to push from your local branch to the remote branch.

Tutorial 2

Execute sh setup.sh 2 from the commandline (requires BASH/Unix) and follow instructions from the output.
The following elements describe the situation in more detail.

This is the same scenario as in 1, but you were trying to do a push (instead of pull) to the remote. The resolutions are the same as in Tutorial 1, but in Resolution 2, replace host/main1 with host/main2.

One should appreciate that the resolution is often the same procedure, since it all boils down to differing commits. Any resolution can often done by aligning commits (if merge is not an option).

Tutorial 3

Execute sh setup.sh 3 from the commandline (requires BASH/Unix) and follow instructions from the output.

About

Hosting a git-course repository to allow students to solve a git-merge problem

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published