Minimal Git Knwo-How

This post is for people, who once in a while have to deal with git and therefore don’t repeat the commands frequently enough in order to keep them in longtime memory. 😛 I’ll provide a simple short reference containing the commands needed most frequently and enrich the reference when necessary.

Clone an existing Repository from Remote

If you have an existing remote repository of a project you want to work for but which is not available locally, then you need to switch to the directory, wehre you want the repository to be fetched into and use the clone-comamnd in order to get a local copy from the repository:

$ git clone https://github.com/your_account/your_repo.git
Cloning into 'fractals'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.

After this command has been completed you’ll find a folder named ‘your_repo’ at the current location in your command line containing all files from the remote repository pointing to the master branch.

Add local Changes to a Repository

If you have made changes in files of a given project / repository, navigate to the project root folder. Now type the following to check the current status:

$ git status
On branch master
Your branch is up to date with 'origin/master'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        doc/source/file_xyz.py

nothing added to commit but untracked files present (use "git add" to track)
$ 

Git now lists all untracked files or potentially previously added changes to the index. If you want to add all changes to the index, so you can push them to the online repo later, type the following:

$ git add -A .

Now all newly added or modified files have been added to the index. The index is a collection of files and changes to be collected for the next commit operation. Now you typically want to perform a commit operation and provide a commit-message, which identifies all changes you have done in this step. To commit all these changes to your local repository, type the following:

$ git commit -m "my important commit message"
[master ffdebed] my important commit message
 6 files changed, 329 insertions(+)
 create mode 100644 src/core/vrp
tw_core.py
$ 

Now you have bundled all changes applied on your code by this commit operation. All changes will now be reproducible later and you can checkout this very state of your repository at any point in time, if required. However, your changes haven’t yet been pushed and are only available on your local machine.

To upload your changes onto the current branch in your remote repository and make them available to other teammates, do the following:

$ git push
Counting objects: 18, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (18/18), done.
Writing objects: 100% (18/18), 2.11 MiB | 983.00 KiB/s, done.
Total 18 (delta 5), reused 0 (delta 0)
remote: Resolving deltas: 100% (5/5), completed with 5 local objects.
To https://github.com/company/repo_name.git
   38036ca..ffdebed  master -> master

Now your laptop can get lost, but your work is still safe. 🙂 I rather prefer to push once too much instead of risking to lose some of my work.

Update you local repository

To update your repository use the pull-command:

$ git pull
Already up to date.

Revert all local changes

Sometimes just shit happens. If you want to reset local changes you have made to a file and not yet been added to the index, type the following:

$ git checkout -- <filename>

If you want to reset all your local changes and replace it with the version from the repository, type the following:

$ git fetch origin
$ git reset --hard origin/master

This would even delete new local files, which have been previously added to the index. If you also want to delete additional files from your local repository which haven’t been added to the index, the following command displays all these files:

$ git clean -n -d -x
Would remove src/java/.settings/
Would remove src/java/src/main/java/org/
Would remove src/java/src/test/
Would remove src/java/target/

The -n switch prevents git from deleting the files and instead lists them, the -d switch allows traversing subdirectories where as the -x switch tells git to also consider ignored files as configured by .gitignore settings. To finally delete these files, replace the -n switch by the -f (force) switch in order to physically delete your local files (use with care!):

$ git clean -f -d -x
Removing src/java/.settings/
Removing src/java/src/main/java/org/
Removing src/java/src/test/
Removing src/java/target/

How to create Tags

To handle tags you can use the git tag-command (see here for complete reference). To display the existing tags of your current repository switch to the required git repo and type the following:

$ git tag
v0.8
v1.0
v1.1
$ 

To add a new tag use the -a option and provide a message adding the -m option as shown in the following command:

$ git tag -a v1.1.1 -m "report test release for customer"

Now the tag only exists on your local machine. To push the newly created tag type:

$ git push origin v1.1.1
Counting objects: 1, done.
Writing objects: 100% (1/1), 179 bytes | 179.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0)
To https://github.com/ims-fhs/customer.git
 * [new tag]         v1.1.1 -> v1.1.1
$ 

Alternatively, you could push all your tags which haven’t yet been pushed issueing the following command:

$ git push origin --tags
Writing objects: 100% (1/1), 179 bytes | 179.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0)
To https://github.com/ims-fhs/customer.git
 * [new tag]         v1.1.1 -> v1.1.1
$ 

How to work with Branches

To create a new branch, type the following:

$ git checkout -b new_feature
Switched to a new branch 'new_feature'

To push the new branch to the remote repository, type the following:

$ git push origin new_feature
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
remote:
remote: Create a pull request for 'new_feature' on GitHub by visiting:
remote:      https://github.com/your_repo/pull/new/new_feature
remote:
To github.com:your_repo.git
 * [new branch]      new_feature -> new_feature

You can switch back to your original branch as follows:

$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.

Keep in mind, that the original branch can sometimes also be named main instead. In most cases, after having implemented the feature you want to merge the feature-branch back onto the master branch. You can do that issueing the following commands:

$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.</code></pre>
$ git pull
Already up to date.
$ git merge new_feature --no-ff

The commands above first make sure you’re back on the master branch, where you want to merge your feature branch to. The pull command assures that all recent changes are fetched and merged. Now you’re ready to merge the new_feature branch onto the master branch, which is done with the last command.

The option ‘–no-ff’ (no-fastforward) causes git to create a merge commit. This way you will keep traceability about the origin and development path of the merge. If you don’t care about that, just drop the option.

keep traceability with the no-fastforward merge option

Sometimes you want to create a branch based on an old commit. Then just do the following:

$ git branch branchname <sha1-of-commit>

Afterwards you can check out the branch as usually with ‘git checkout -b branchname’. In order to locally delete the branch ‘new_feature’, just type ‘git branch -d new_feature’.

$ git branch -d new_feature
Deleted branch new_feature (was 93fabee).

This way you deleted your local branch. If you also want to delete the remote branch, type the following:

$ git push origin --delete <branch_name>
To repo.git
 - [deleted]         <branch_name>

How to Clean Local Repository

If you work in a team on the same repository and code is refactored, it sometimes happens that files and directories have to be deleted.

The clean-command is required so that deleted files and directories of other team members are also removed from git.

The git clean command removes all untracked files from the Git working directory. Which untracked Git files to remove can be controlled through the git clean command’s three important flags or switches:

  1. The -f flag forces the removal of untracked files. Directories and ignored files are left alone.
  2. The -d flag forces removal of untracked git directories.
  3. The -x flag removes untracked files, even those that map to .gitignore entries.

There are two important additional options for controlling ‘git clean’:

  • The -n flag does not delete anything, but list the files and folders, which would be deleted
  • The -i flag which puts the clean command into interactive mode

To ensure that the wrong files are not inadvertently deleted, it is advisable to first output a list of the files to be deleted by activating the -n flag. In a second step, all files to be deleted can then be marked and deleted in interactive mode.

Let’s demonstrate this process on an example. We first only list the files to be deleted using the -n flag, suppressing the actual deletion:

$ git clean -nfdX
Would remove Python/.idea/
Would remove Python/simpy-streamlit/.coverage
Would remove Python/simpy-streamlit/.idea/
Would remove Python/simpy-streamlit/.pytest_cache/
Would remove Python/simpy-streamlit/analytics/__pycache__/
Would remove Python/simpy-streamlit/datamodel/__pycache__/
Would remove Python/simpy-streamlit/venv/

Now, say we don’t want to remove the last entry. We repeat the clean command without the -n flag, but add the -i flag to activate the interactive mode:

$ git clean -fdXi
Would remove the following items:
  Python/.idea/
  Python/simpy-streamlit/.coverage
  Python/simpy-streamlit/.idea/
  Python/simpy-streamlit/.pytest_cache/
  Python/simpy-streamlit/analytics/__pycache__/
  Python/simpy-streamlit/datamodel/__pycache__/
  Python/simpy-streamlit/venv/
*** Commands ***
    1: clean                2: filter by pattern    3: select by numbers
    4: ask each             5: quit                 6: help
What now>

Now we can iteratively select the files to be removed by first choosing 3, then providing the numbers of files to be removed. We then get a nenumerated list of all files and can provide the numbers step by step of those, we want to remove. After each input, the list is updated and files to be deleted are marked:

What now> 3
    1: Python/.idea/
    2: Python/simpy-streamlit/.coverage
    3: Python/simpy-streamlit/.idea/
    4: Python/simpy-streamlit/.pytest_cache/
    5: Python/simpy-streamlit/analytics/__pycache__/
    6: Python/simpy-streamlit/datamodel/__pycache__/
    7: Python/simpy-streamlit/venv/
Select items to delete> 1
  * 1: Python/.idea/
    2: Python/simpy-streamlit/.coverage
    3: Python/simpy-streamlit/.idea/
    4: Python/simpy-streamlit/.pytest_cache/
    5: Python/simpy-streamlit/analytics/__pycache__/
    6: Python/simpy-streamlit/datamodel/__pycache__/
    7: Python/simpy-streamlit/venv/

Now we continue to select the files for deletion typing the number indicated in the list. To prevent the ‘venv’ from deletion, we just do not select the 7th entry.

After having finished the selection, we hit ENTER without typing a number, which brings us back to the menu. There we choose option 1 to perform the deletions:

*** Commands ***
    1: clean                2: filter by pattern    3: select by numbers
    4: ask each             5: quit                 6: help
What now> 1
Removing Python/.idea/
Removing Python/simpy-streamlit/.coverage
Removing Python/simpy-streamlit/.idea/
Removing Python/simpy-streamlit/.pytest_cache/
Removing Python/simpy-streamlit/analytics/__pycache__/
Removing Python/simpy-streamlit/datamodel/__pycache__/

That’s it. Now all untracked files and directories have been removed, except the one not chosen (number 7 in the list).