Skip to content
Snippets Groups Projects
Select Git revision
  • main default protected
  • michael_issue001-set-up-training-instrcutions
  • 4-set-up-add-method
  • erik_5_set_up_multiply_method
  • michael_issue003-script-for-testing
  • michael_issue002_add_gitignore
6 results

git-training

  • Clone with SSH
  • Clone with HTTPS
  • Name Last commit Last update
    img
    .gitignore
    LICENSE
    README.md
    calculator.py
    main.py

    README

    This is a small repository to train version controlling with git. During this training, you will practise how to utilize standard git commands such as git commit, git push, git merge, git cherry-pick and more. Thereby, yu will also become familar with the git-rules defined in our ESDE-group (see this presentation.)

    Software requirements

    • Python 3
    • packages: typing, argparse

    Getting started

    1. Team up with another group member and sit next to each other or open a video call.
    2. One team member only: Create a fork from the landing page of this repository. Fork repo 1 Please fork it to your personal namespace. Fork repo 2
    3. As of version 15, gitlab does not support the creation of merge requests in forked repositories when creating a new issue (see here). Since we would like to use this feature and since we are typically not forking from ESDE-internal git repositories, we are going to destroy the fork relationship explicitly. To do so, select Settings > General on the left side bar and expand Advanced. Scroll down to the Remove relationship-section, select Remove fork relationship and confirm.
    4. Hover over Manage in the left menu bar and click on Members to add your partner to the (private) fork. Assgn him/her the role as a Developer.
    5. Both: Clone the repository either on your local machine or to a proper directory on the JSC HPC-system.
      git clone <url>
      You can obtain the url as shown below. Fork repo 1
    6. If you are working on the HPC-system, load the Python module.
      ml Python
      Ensure that you have Python3 available when you work on local system (e.g. in a conda environment)

    Exercises

    Task 1

    One team member: Set up a dev-branch (starting from the main-branch) from which all feature-branches will be created subsequently. Change to the dev-branch and push the newly created branch to the remote repository.

    Solution Run the following commands in your console:
    git branch dev
    git checkout dev 
    # short-cut: git checkout -b dev 
    git push -u origin dev

    The other team member: Fetch and switch to the dev-branch once it is available in the remote repository.

    Solution Run the following commands in your console:
    git fetch 
    git checkout --track origin/dev

    Task 2

    Go to the git-repository in your web-browser and add two issues - one for implementing the add-method and one for the multiply-method in calculator.py. Each team member should be assigned to one of the issue tasks and is therefore responsible to write a brief description and to create the corresponding issue/feature-branch as well as the merge-request.
    Note: Choose the dev-branch as your source and follow the ESDE naming convention when creating the merge-request.

    Solution After creating the issue, click on the `Create merge request`-button. The source and the new issue-branch can be created as follows: Merge request

    Task 3

    Change to the newly created feature-branch in your working environment's console/IDE and implement the method that you are responsible for in calculator.py. Afterwards add and commit your changes.
    Note: Just change adapt return-statement of your method. We will implement more sophisticated versions of the methods later.

    Solution for add-method First, change to the feature-branch:
    git fetch
    git checkout --track origin/{your_add_branch}
    The content of `calculator.py` should be as follows:
    def add(a: Union[int, float], b: Union[int, float]) -> Union[int, float]:
        """
        Add numbers and return sum.
        :param a: first number
        :param b: second number
        :return: sum of a and b
        """
        return a + b 
    After saving, do the following in your console/IDE:
    git add calculator.py 
    git commit -m "Implement add-method"
    
    Solution for multiply-method First, change to the feature-branch:
    git fetch
    git checkout --track origin/{your_add_branch}
    The content of `calculator.py` should be as follows:
    def multiply(a: Union[int, float], b: Union[int, float]) -> Union[int, float]:
        """
        Multiply numbers and return product.
        :param a: first number
        :param b: second number
        :return: product of a and b
        """
        return a * b
    After saving, do the following in your console/IDE:
    git add calculator.py 
    git commit -m "Implement multiply-method"
    

    Task 4

    Revise the previously created commit to check your statement. Correct it if you find typos or if you would like to provide a better one. Check the functionality of your method by running main.py and push your changes to the remote repository afterwards. For the add-method, run the following:

    python3 main.py -op add 

    Adapt the -op-argument to test the multiply-method.
    Note: Continue to test your implementations in the subsequent tasks.

    Solution The following commands should be run:
    git commit --amend        # adapt commit in text editor and save and quit 
    git push
    

    Task 5

    Set-up two new feature branches (one for each method) to make the methods in calculator.py more robust. Therein, implement checks that the parsed arguments are numbers, i.e. integeres or floats (check the solution for the appropriate lines of code). Proceed as described in Task 2 when setting up the branches. Finalize the modifications by committing and pushing.

    Solution The steps are analogous to the solution of Task 2 and 3. The following lines should be added to the `add`- and `multiply`-method in `calculator.py`, respectively.
    if not (isinstance(a, (int, float)) and isinstance(b, (int, float))):
        raise ValueError("a and b must be numbers")
    
    Afterwards, the revised code can be commited and pushed. For the `add`-method, the following commands are suitable.
    git add calculator.py 
    git commit -m "Implemented check for parsed arguments in add-method."
    git push
    
    The commands for the `multiply`-method are analogous.

    Task 6

    Exchange the revised methods using git cherry-pick <hash>. Ensure that the modifications to the methods in the feature branches are made available via pushing and fetching beforehand.
    Tip: The commit-hash can be obtained from both, the gitlab's web editor and from the command line.

    Solution The required commit hash can be conviently retrieved from the commit-history of the respective feature branch. This can be assessed via the web editor, by clicking onCommits under theCode-section of the left side bar and by choosing the respective feature-branch. Alternatively, one may also get the hash via the command line:
    git checkout {other_feature_branch}    # change branch
    git log      # check commit hashes 
    Afterwards, cherry-picking can be performed in the current feature branch.
    git checkout {my_feature_branch}    # only required if you have changed it to get the hash
    git cherry-pick {hash}

    Task 7

    In this task, both team members will work on the add-method to enable handling of more than two parsing arguments. Each team member creates an individual feature branch (analogous to Task 2, 3 and 5) first. Afterwards, one team member will realize a rather inflexible approach by adding optional keyword arguments (i.e. adding third = None, fourth = None to the signature of the add-method), the second team member will apply Python's *args-variable to pass a varying number of positional arguments (see this post for more information on args and kwargs). After committing and pushing, the feature should be merged into each other with git merge --no-ff {other_feature_branch} to provoke a merge conflict. Finalize the task by solving the merge conflict.

    Solution The inflexible approach with additional keyword arguments may look as follows:
    def add(a: Union[int, float], b: Union[int, float], c: Union[int, float]= None, d: Union[int, float] = None) -> Union[int, float]:
        """
        Add numbers and return sum.
        :param a: first number
        :param b: second number
        :param c: third number (optional)
        :param d: fourth number (optional)
        :return: Sum of the numbers.
        """
        # check if a and b are numbers
        if not (isinstance(a, (int, float)) and isinstance(b, (int, float))):
            raise ValueError("a and b must be numbers")
        result = a + b
        if c is not None:
            if not isinstance(c, (int, float)):
                raise ValueError("c must be a number")  
            result += c
    
        if d is not None:
            if not isinstance(d, (int, float)):
                raise ValueError("d must be a number")
            result += d
    
        return result
    
    The generic approach using*args is implemented with the following code lines:
    def add(*numbers: Union[int, float]) -> Union[int, float]:
        """
        Add numbers and return sum.
    
        :param numbers: Arbitrary number of numbers to be added. At least two numbers must be provided.
        :return: Sum of the numbers.
        """
        # check if at least two numbers are provided
        if len(numbers) < 2:
            raise ValueError("At least two numbers must be provided.")
        
        # get sum while checking if all numbers are numbers
        result = 0
        for number in numbers:
            if not isinstance(number, (int, float)):
                raise ValueError(f"All numbers must be numbers, but got {number} (type: {type(number)}) instead.")
            
            result += number
        
        return result

    The adapted methods are then added, commited and finally pushed to the remote repository.

    git add calculator.py
    git commit -m "More arguments for add-method"
    git push

    Merging the partner's feature branch then yields a merge-conflict merge conflict where the conflicting code parts are separated as follows:

    <<<<<<< HEAD
    from typing import Union
    
    def add(*numbers: Union[int, float]) -> Union[int, float]:
        """
        Add numbers and return sum.
    
        :param numbers: Arbitrary number of numbers to be added. At least two numbers must be provided.
    =======
    def add(a: Union[int, float], b: Union[int, float], c: Union[int, float]= None, d: Union[int, float] = None) -> Union[int, float]:
        """
        Add numbers and return sum.
        :param a: first number
        :param b: second number
        :param c: third number (optional)
        :param d: fourth number (optional)
    >>>>>>> michael_issue004_multiple_args_forr_add
        :return: Sum of the numbers.
        [...]

    Removing the code parts of the inflexible approach (incl. the separators) followed by

    git commit
    git push

    then solves the merge conflict and pushes the final version to the remote repository.

    Task 8

    One team member only: Merge the recent feature-branch into the dev-branch.

    Solution Merging is realized as follows: git checkout dev # switch to dev-branch git merge --no-ff {feature_branch_from_task7}

    Task 9

    In this task, we will mock a situation where stashing is useful. First, switch to the dev-branch and enable handling of flexible arguments for the multiply-method. Since new features shouldnot be implemented directly on this branch, we stash our modifications to calculator.py and create the respective merge request afterwards (incl. the corresponding issue). Make the stashed modification available after switching to the newly created feature branch and finalize the work by adding, committing and pushing to the remote repository. One team member may also merge the feature into the dev-branch.

    Solution After switching to thedev-branch via
    git checkout dev
    the modifiedmultiply-method may look as follows:
    
    def product(*numbers: Union[int, float]) -> Union[int, float]:
        """
        Multiply numbers and return product.
        :param a: first number
        :param b: second number
        :return: product of a and b
        """
        # check if at least two numbers are provided
        if len(numbers) < 2:
            raise ValueError("At least two numbers must be provided.")
        # get product while checking if all numbers are numbers
        result = 1
        for number in numbers:
            if not isinstance(number, (int, float)):
                raise ValueError(f"All numbers must be numbers, but got {number} (type: {type(number)}) instead.")
        
            result *= number
    
        return result
    
    The following command chain will then stash, switch to the new feature branch (cf. Task 2, 3 and 5) and re-apply the stashed modification followed by adding, committing and pushing to the remote repository.
    git stash
    git checkout {feature_branch_task9}    # change to new feature branch 
    git stash pop 
    git add calculator.py 
    git commit -m "Flexible number of arguments for multiply-method"
    git push 

    The final merge to the dev-branch is then realized by

    git checkout dev
    git merge --no-ff {feature_branch_task9}

    Task 10

    The final task deals with undoing a coding error that has already been commited. To do so, modify and commit calculator.py in a way that it breaks the code (e.g. by an indentation error or by a typo). Then correct the code using git reset in an appropriate way.

    Solution After corrupting committing the script
    git add calculator.py 
    git commit -m "Faulty change to calculator.py"
    one can utilizegit log to obtain the commit-hash of the last correct code-version which we would like to reconstruct.
    Removing the faulty commit from the git history is then realized via
    git reset --hard {commit_good_code}

    Congratulations

    You have successfully learned how to version control your software developments wit git!