Skip to content
Snippets Groups Projects
Commit aa2e488d authored by Mactavish's avatar Mactavish
Browse files

init branch tutorial-2

parent 7fa3e5e6
No related branches found
No related tags found
No related merge requests found
Showing
with 3 additions and 2567 deletions
# ALP4 Tutorial-1 # ALP4 Tutorial-2
This branch contains all materials for the first tutorial session. This branch contains all materials for the second tutorial session.
## Agenda ## Agenda
- Greetings and self-introduction TBD
- [Organization](./orga.md)
- [Development environment setup](./env.md)
- [Git Basics](./git.md)
- [C programming language review](./clang.md)
- Questions for the first assignment
- Groups for assignments
## Usage
Please read the separate markdown files accordingly for detailed information.
This diff is collapsed.
# Development environment setup
This document contains all of the information your need to get started with your development environment.
## Access to Linux-pool
You will need to have an institutional account in order to have access to the Linux-pool (Andorra).
Go to https://portal.mi.fu-berlin.de/login and login in with your ZEDAT account. If you don't have a ZEDAT account yet, you need to reach out to [ZEDAT](https://www.zedat.fu-berlin.de/Home) or [IT-Services](http://www.mi.fu-berlin.de/w/IT).
Further information can be found here: http://www.mi.fu-berlin.de/w/IT/Computeraccess
## Configuring SSH-Key-Based Authentication
After setting up your account, let's configure SSH-key-based authentication for you to have a secure way of connecting to the Linux-Pool(Andorra) and to the Gitlab at FU (via `git`).
The instructions described below only work for Linux-distributions or Unix-like operating systems. For those who are using Windows, please check Microsoft's online documentation for SSH on Windows: https://learn.microsoft.com/en-us/windows-server/administration/openssh/openssh_overview
Alternatively, you can use WSL(Windows Subsystem for Linux), please check Microsoft's online documentation: https://learn.microsoft.com/en-us/windows/wsl/install
### Overview of SSH-Key-Based Authentication
An SSH server can authenticate clients using a variety of different methods. The most basic of these is password authentication, which is easy to use, but not the most secure.
SSH Keys is proved to be a reliable and secure alternative.
SSH key pairs are two cryptographically secure keys that can be used to authenticate a client to an SSH server. Each key pair consists of a **public key** and a **private key**.
The private key is retained by the client and should be **kept absolutely secret**.
The associated public key can be shared freely without any negative consequences. The public key can be used to encrypt messages that only the private key can decrypt.
The public key is uploaded to a remote server that you want to be able to log into with SSH. The key is added to a special file within the user account you will be logging into called `~/.ssh/authorized_keys`
![](./images/ssh-key-auth-flow.png)
### Step 1: Generating SSH Keys
First, open you terminal and enter the following command:
```sh
# create .ssh folder in home directory if needed and cd into it
mkdir -p ~/.ssh && cd ~/.ssh
# command to generate key-pair using recommended ed25519 algorithm
ssh-keygen -t ed25519
```
then you should see the following output:
```sh
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/username/.ssh/id_ed25519):
```
if you press enter directly, the default key-pair will be saved in your user's home directory under the name `id_ed25519` and `id_ed25519.pub`, which, are the private key and the public key.
It's recommended to give it a reasonable name to your keys, so that you can recall it later when you need to manage multiple key-pairs for different servers in the future.
Let's assume that, you given the name `fu`, and then you will see the following output:
```sh
Enter passphrase (empty for no passphrase): [Type a passphrase]
Enter same passphrase again: [Type passphrase again]
```
you can set a passphrase for the key, it's optional. If you enter one, you will have to provide it every time you use this key (unless you are running SSH agent software that stores the decrypted key). If you do not want to set a passphrase, you can press ENTER to bypass this prompt.
You now have a public and private key that you can use to authenticate with output like this:
```sh
Your identification has been saved in /home/username/.ssh/fu
Your public key has been saved in /home/username/.ssh/fu.pub
The key fingerprint is:
SHA256:L2ZhMFacpJhR9q+1eZOo/vJfIDge6sP13l0zoeihGb4 username@hostname
The key's randomart image is:
+--[ED25519 256]--+
| ..ooo. |
| = +o |
| o = . |
| . o o |
| S + . . |
| +.B =.o. .|
| ...*o=o+..o.|
| .oooo*o.+ .o|
| .ooE=oo . |
+----[SHA256]-----+
```
### Step 2: Adding the SSH Public Key to Your Server
The simplest way to copy your public key to an existing server is to use a utility called `ssh-copy-id`. Because of its simplicity, this method is recommended if available.
The `ssh-copy-id` program is included in the OpenSSH packages in many distributions, so you may already have it available on your local system.
Now, use the following command to copy your SSH public key to the target server:
```sh
# make sure you are still in the directory where the keys were generated
# replace [ZEDAT_USER_NAME] with your own ZEDAT account
ssh-copy-id -i fu.pub [ZEDAT_USER_NAME]@andorra.imp.fu-berlin.de
```
You might see an output like this:
```sh
The authenticity of host '203.0.113.1 (203.0.113.1)' can't be established.
ECDSA key fingerprint is fd:fd:d4:f9:77:fe:73:84:e1:55:00:ad:d6:6d:22:fe.
Are you sure you want to continue connecting (yes/no)? yes
```
This means that your local computer does not recognize the remote host. This will happen the first time you connect to a new host. Type yes and press ENTER to continue. And you will be asked to provide the password of your ZEDAT account:
```sh
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
ZEDAT_USER_NAME@andorra.imp.fu-berlin.de's password:
```
After providing the correct password, it will then copy the contents of your `~/.ssh/fu.pub` key into a file in the remote account’s home `~/.ssh` directory called `authorized_keys`.
If you don't have `ssh-copy-id` available, you could copy your SSH public key manually using the following command:
```
# make sure you are loacted in the ~/.ssh directory
cat ~/.ssh/fu.pub | ssh [ZEDAT_USER_NAME]@andorra.imp.fu-berlin.de "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
```
This will copy the content of your public key and append it to the `~/.ssh/authorized_keys` on the remote server.
### Step 3: Connecting to Your Server Using SSH Keys
If you have successfully completed the procedures above, you should be able to log into the remote host without the remote account’s password.
```sh
# since ssh uses the default private key under the name ~/.ssh/id_rsa, ~/.ssh/id_dsa etc.
# We have to use -i to select the private key we just generated explicitly, but we will fix that later
ssh -i ~/.ssh/fu [ZEDAT_USER_NAME]@andorra.imp.fu-berlin.de
```
If this is your first time connecting to this host (if you used the last method above), you may see something like this:
```sh
The authenticity of host '203.0.113.1 (203.0.113.1)' can't be established.
ECDSA key fingerprint is fd:fd:d4:f9:77:fe:73:84:e1:55:00:ad:d6:6d:22:fe.
Are you sure you want to continue connecting (yes/no)? yes
```
This means that your local computer does not recognize the remote host. Type yes and then press ENTER to continue.
If you did not supply a passphrase for your private key, you will be logged in immediately. If you supplied a passphrase for the private key when you created the key, you will be required to enter it now. Afterwards, a new shell session will be created for you with the account on the remote system.
### Step 4: Saving Your SSH options in a Configuration file
Typing `ssh -i identity_file username@hostname` to connect to your target server is quite verbose, we want to create a kind of shortcut to memorize these options so that we can set up the connection quickly without worrying about the details.
Now, let's create a configuration file using the following command:
```sh
touch ~/.ssh/config
```
Then open the file using any text editor you prefer, e.g. `vi ~/.ssh/config` or `nano ~/.ssh.config` and add the following content to the configuration file:
```sh
# change [ZEDAT_USER_NAME] to your own ZEDAT account
# This option is only useful in MacOS, ignore it in other OS
IgnoreUnknown UseKeychain
UseKeychain yes
# For andorra
Host andorra
HostName andorra.imp.fu-berlin.de
User [ZEDAT_USER_NAME]
IdentityFile ~/.ssh/fu
# For gitlab at FU
Host git.imp.fu-berlin.de
User git
IdentityFile ~/.ssh/fu
# Wildcard
Host *
# add the keys automatically to a running ssh-agent
AddKeysToAgent yes
UseKeychain yes
```
We are not going to discuss the syntax of the configuration file here, you can read the man page using `man ssh_config` for further information.
Now, save the file and then test the connection using the following command:
```
# test the connection to Andorra, you make have to invoke CTRL-C to quit
ssh -T andorra
```
Congratulations, from now on, you can always set up a new secure connection between your local device and the Linux-Pool using the command `ssh andorra`. (For Gitlab we won't set up the connection explicitly, but via the `git` command)
## Access to Gitlab at FU
Go to https://git.imp.fu-berlin.de/users/sign_in and sign in with you ZEDAT account and fill in your personal information.
You will be using Gitlab intensively for later assignments, read [this markdown file](./git.md) for more information about Git.
Later we are going to use the `git` command via SSH to manipulate the git repository hosted by Gitlab at FU. But we still need to add our public key to Gitlab, so that we can manipulate the remote repository without using password authentication.
### Adding your SSH Key to your Gitlab account
Just like storing our public key on the andorra server, we need to add our public key to our Gitlab account:
1. Sign in to [GitLab](https://git.imp.fu-berlin.de/).
2. On the top bar, in the upper-right corner, select your avatar.
3. Select **Edit profile**.
4. On the left sidebar, select **SSH Keys**.
5. In the Key box, paste the contents of your public key (use `cat ~/.ssh/fu.pub` to print the contents).
6. Optional. Type a description in the **Title** box, Select the **Usage type** and update the **Expiration date** (clear the field to set the key to be permanent).
7. Add the key
Now, you can run the following command to test the connection to the Gitlab:
```
# test the connection
ssh -T git@git.imp.fu-berlin.de
# try to clone this repository
git clone git@git.imp.fu-berlin.de:mactavish96/alp4-tutorials.git
```
## Installing Git and GCC/Clang
For the assignments you will need to use `git` to submit and `gcc` or `clang` to compile and test the your program.
If you are using MacOS or one of the many Linux-distributions, you should already have both commands available on your machine.
If you are using WSL on Windows, you might need to install `gcc` separately:
```sh
# assuming you are using WSL Ubuntu
sudo apt-get update
sudo apt-get install gcc
```
You can verify if those programs are already available on your machine using the following commands:
```sh
git --version
gcc --version
# or
cc --version
```
Alternatively, you can write your programs directly on Andorra, all these tools are already available to you.
## Troubleshooting
### Gitlab related
Check: https://docs.gitlab.com/ee/user/ssh.html#troubleshooting
## References
- https://www.digitalocean.com/community/tutorials/how-to-configure-ssh-key-based-authentication-on-a-linux-server
- https://docs.gitlab.com/ee/user/ssh.html
- https://docs.github.com/en/authentication/connecting-to-github-with-ssh/about-ssh
# Hamming
Here is a small exercise that helps you understand pointer arithmetic and String in C.
## Instructions
Calculate the Hamming Distance between two DNA sequences.
If we compare two sequences of DNA and count the differences between them we can see how many mismatches occurred.
This is known as the "Hamming Distance".
We read DNA using the letters C,A,G and T. Two sequences might look like this:
```
GAGCCTACTAACGGGAT
CATCGTAATGACGGCCT
^ ^ ^ ^ ^ ^^
```
They have 7 differences, and therefore the Hamming Distance is 7.
## Implementation notes
The Hamming distance is only defined for sequences of equal length, so an attempt to calculate it between sequences of different lengths should not work.
## Tips
You could use auxiliary functions such as `strlen` to get the length of a given string. These functions are defined in `<string.h>`
## Testing
The included makefile can be used to create and run the tests using the following commands:
```bash
# run unit tests
make test
# check memory leaks
make memcheck
# clean all compilation files
make clean
```
## Credit
Adapted from [here](https://github.com/exercism/c/tree/main/exercises/practice/hamming)
#include "hamming.h"
#include <string.h>
int compute(const char *lhs, const char *rhs) {
int count = 0;
if (strlen(lhs) != strlen(rhs)) {
return -1;
}
while (*lhs != '\0') {
if (*lhs != *rhs) {
count++;
}
lhs++;
rhs++;
}
return count;
}
#ifndef HAMMING_H
#define HAMMING_H
int compute(const char *lhs, const char *rhs);
#endif
### If you wish to use extra libraries (math.h for instance),
### add their flags here (-lm in our case) in the "LIBS" variable.
LIBS = -lm
###
CFLAGS = -std=c99
CFLAGS += -g
CFLAGS += -Wall
CFLAGS += -Wextra
CFLAGS += -pedantic
CFLAGS += -Wmissing-declarations
CFLAGS += -DUNITY_SUPPORT_64 -DUNITY_OUTPUT_COLOR
ASANFLAGS = -fsanitize=address
ASANFLAGS += -fno-common
ASANFLAGS += -fno-omit-frame-pointer
.PHONY: test
test: tests.out
@./tests.out
.PHONY: memcheck
memcheck: ./*.c ./*.h
@echo Compiling $@
@$(CC) $(ASANFLAGS) $(CFLAGS) ../unity/unity.c ./*.c -o memcheck.out $(LIBS)
@./memcheck.out
@echo "Memory check passed"
.PHONY: clean
clean:
rm -rf *.o *.out *.out.dSYM
tests.out: ./*.c ./*.h
@echo Compiling $@
@$(CC) $(CFLAGS) ../unity/unity.c ./*.c -o tests.out $(LIBS)
#include "../unity/unity.h"
#include "hamming.h"
void setUp(void) {}
void tearDown(void) {}
static void test_empty_strands(void) { TEST_ASSERT_EQUAL(0, compute("", "")); }
static void test_single_identical_strands(void) {
TEST_ASSERT_EQUAL(0, compute("A", "A"));
}
static void test_single_letter_different_strands(void) {
TEST_ASSERT_EQUAL(1, compute("G", "T"));
}
static void test_long_identical_strands(void) {
TEST_ASSERT_EQUAL(0, compute("GGACTGAAATCTG", "GGACTGAAATCTG"));
}
static void test_long_different_strands(void) {
TEST_ASSERT_EQUAL(9, compute("GGACGGATTCTG", "AGGACGGATTCT"));
}
static void test_disallow_first_strand_when_longer(void) {
TEST_ASSERT_EQUAL(-1, compute("AATG", "AAA"));
}
static void test_disallow_second_strand_when_longer(void) {
TEST_ASSERT_EQUAL(-1, compute("ATA", "AGTG"));
}
static void test_disallow_empty_first_strand(void) {
TEST_ASSERT_EQUAL(-1, compute("", "G"));
}
static void test_disallow_empty_second_strand(void) {
TEST_ASSERT_EQUAL(-1, compute("G", ""));
}
int main(void) {
UnityBegin("test_hamming.c");
RUN_TEST(test_empty_strands);
RUN_TEST(test_single_identical_strands);
RUN_TEST(test_single_letter_different_strands);
RUN_TEST(test_long_identical_strands);
RUN_TEST(test_long_different_strands);
RUN_TEST(test_disallow_first_strand_when_longer);
RUN_TEST(test_disallow_second_strand_when_longer);
RUN_TEST(test_disallow_empty_first_strand);
RUN_TEST(test_disallow_empty_second_strand);
return UnityEnd();
}
# Linked List
Here is a small exercise that helps you understand memory management and pointer operations in C.
## Instructions
Implement a doubly linked list.
You will write an implementation of a doubly linked list with the following functions:
* `push` (*insert value at back*);
* `pop` (*remove value at back*);
* `shift` (*remove value at front*);
* `unshift` (*insert value at front*);
* `count` (*count the number of nodes in the list*);
* `delete` (*delete the node that holds the matched data*);
* etc.
To keep your implementation simple, the tests will not cover error
conditions. Specifically: `pop` or `shift` will never be called on an
empty list.
## Tips
Since linked list is a dynamic data structure, you have to use memory management functions defined in `<stdlib.h>`.
When you create a new node, you should allocate a block of memory for the node. When you delete a node or destroy the whole list, you should deallocate/free all previously allocated data.
## Testing
The included makefile can be used to create and run the tests using the following commands:
```bash
# run unit tests
make test
# check memory leaks
make memcheck
# clean all compilation files
make clean
```
## Credit
Adapted from [here](https://github.com/exercism/c/tree/main/exercises/practice/linked-list)
#include "linked_list.h"
#include <errno.h>
#include <stdlib.h>
#define FAULT(ERRNO, ERR_CODE) \
errno = ERRNO; \
exit(ERR_CODE);
#define FREE_NODE(NODE) \
if (NODE) { \
free(NODE); \
NODE = NULL; \
}
struct list_node {
struct list_node *prev, *next;
ll_data_t data;
};
struct list {
struct list_node *first, *last;
};
struct list_node *create_node(ll_data_t data) {
struct list_node *node;
node = malloc(sizeof(struct list_node));
if (!node) {
FAULT(ENOMEM, EXIT_FAILURE);
}
node->data = data;
return node;
}
// constructs a new (empty) list
struct list *list_create(void) {
struct list *head = malloc(sizeof(struct list));
// create a dummy node, dummy node should not have any previous node
struct list_node *node = create_node(0);
head->first = node;
head->last = node;
node->prev = node->next = NULL;
return head;
}
// counts the items on a list
size_t list_count(const struct list *list) {
size_t count = 0;
if (list->first == list->last) {
return count;
}
struct list_node *dummy = list->first;
struct list_node *node = dummy->next;
while (node != dummy) {
node = node->next;
count++;
}
return count;
}
// inserts item at back of a list
void list_push(struct list *list, ll_data_t item_data) {
struct list_node *node = create_node(item_data);
// empty list with a dummy node
if (list->first == list->last) {
list->first->next = node;
list->last = node;
node->prev = node->next = list->first;
} else {
node->prev = list->last;
list->last->next = node;
node->next = list->first;
list->last = node;
}
}
// removes item from back of a list
ll_data_t list_pop(struct list *list) {
// empty list with a dummy node
if (list->first == list->last) {
FAULT(EFAULT, EXIT_FAILURE);
}
struct list_node *last = list->last;
ll_data_t data = last->data;
list->last = last->prev;
last->prev->next = list->first;
FREE_NODE(last);
return data;
}
// inserts item at front of a list
void list_unshift(struct list *list, ll_data_t item_data) {
// empty list with a dummy node
if (list->first == list->last) {
list_push(list, item_data);
} else {
struct list_node *dummy = list->first, *node = create_node(item_data);
node->next = dummy->next;
node->prev = dummy;
dummy->next->prev = node;
dummy->next = node;
}
}
// removes item from front of a list
ll_data_t list_shift(struct list *list) {
// empty list with a dummy node
if (list->first == list->last) {
FAULT(EFAULT, EXIT_FAILURE);
} else {
struct list_node *dummy = list->first, *node;
node = dummy->next;
ll_data_t data = node->data;
dummy->next = node->next;
// if there are more than one nodes
if (node->next->prev == node) {
node->next->prev = dummy;
} else {
list->last = list->first;
}
FREE_NODE(node);
return data;
}
}
// deletes a node that holds the matching data
void list_delete(struct list *list, ll_data_t data) {
if (list->first == list->last) {
errno = EFAULT;
exit(EXIT_FAILURE);
} else {
struct list_node *dummy = list->first;
struct list_node *node = dummy->next;
while (node != dummy) {
if (node->data == data) {
break;
}
node = node->next;
}
if (node != dummy) {
node->prev->next = node->next;
node->next->prev = node->prev;
if (node == list->last) {
list->last = node->prev;
}
FREE_NODE(node);
}
}
}
// destroys an entire list
// list will be a dangling pointer after calling this method on it
void list_destroy(struct list *list) {
// empty list with a dummy node
if (list->first == list->last) {
FREE_NODE(list->last);
FREE_NODE(list);
} else {
struct list_node *dummy = list->first;
struct list_node *node = dummy->next, *next;
while (node != dummy) {
next = node->next;
FREE_NODE(node);
node = next;
}
FREE_NODE(dummy);
FREE_NODE(list);
}
}
#ifndef LINKED_LIST_H
#define LINKED_LIST_H
#include <stddef.h>
typedef int ll_data_t;
struct list;
// constructs a new (empty) list
struct list *list_create(void);
// counts the items on a list
size_t list_count(const struct list *list);
// inserts item at back of a list
void list_push(struct list *list, ll_data_t item_data);
// removes item from back of a list
ll_data_t list_pop(struct list *list);
// inserts item at front of a list
void list_unshift(struct list *list, ll_data_t item_data);
// removes item from front of a list
ll_data_t list_shift(struct list *list);
// deletes a node that holds the matching data
void list_delete(struct list *list, ll_data_t data);
// destroys an entire list
// list will be a dangling pointer after calling this method on it
void list_destroy(struct list *list);
// handle allocation failure
void alloaction_failure(void);
// helper function for creating bare node
struct list_node *create_node(ll_data_t data);
#endif
### If you wish to use extra libraries (math.h for instance),
### add their flags here (-lm in our case) in the "LIBS" variable.
LIBS = -lm
###
CFLAGS = -std=c99
CFLAGS += -g
CFLAGS += -Wall
CFLAGS += -Wextra
CFLAGS += -pedantic
CFLAGS += -Wmissing-declarations
CFLAGS += -DUNITY_SUPPORT_64 -DUNITY_OUTPUT_COLOR
ASANFLAGS = -fsanitize=address
ASANFLAGS += -fno-common
ASANFLAGS += -fno-omit-frame-pointer
.PHONY: test
test: tests.out
@./tests.out
.PHONY: memcheck
memcheck: ./*.c ./*.h
@echo Compiling $@
@$(CC) $(ASANFLAGS) $(CFLAGS) ../unity/unity.c ./*.c -o memcheck.out $(LIBS)
@./memcheck.out
@echo "Memory check passed"
.PHONY: clean
clean:
rm -rf *.o *.out *.out.dSYM
tests.out: ./*.c ./*.h
@echo Compiling $@
@$(CC) $(CFLAGS) ../unity/unity.c ./*.c -o tests.out $(LIBS)
#include <stddef.h>
#include "../unity/unity.h"
#include "linked_list.h"
struct list *list = NULL;
void setUp(void)
{
list = list_create();
}
void tearDown(void)
{
if (list) {
list_destroy(list);
list = NULL;
}
}
static void test_pop_gets_element_from_the_list(void)
{
list_push(list, 7);
TEST_ASSERT_EQUAL(7, list_pop(list));
}
static void test_push_pop_respectively_add_remove_at_the_end_of_the_list(void)
{
list_push(list, 11);
list_push(list, 13);
TEST_ASSERT_EQUAL(13, list_pop(list));
TEST_ASSERT_EQUAL(11, list_pop(list));
}
static void test_shift_gets_an_element_from_the_list(void)
{
list_push(list, 17);
TEST_ASSERT_EQUAL(17, list_shift(list));
}
static void test_shift_gets_first_element_from_the_list(void)
{
list_push(list, 23);
list_push(list, 5);
TEST_ASSERT_EQUAL(23, list_shift(list));
TEST_ASSERT_EQUAL(5, list_shift(list));
}
static void test_unshift_adds_element_at_start_of_the_list(void)
{
list_unshift(list, 23);
list_unshift(list, 5);
TEST_ASSERT_EQUAL(5, list_shift(list));
TEST_ASSERT_EQUAL(23, list_shift(list));
}
static void test_pop_push_shift_and_unshift_can_be_used_in_any_order(void)
{
list_push(list, 1);
list_push(list, 2);
TEST_ASSERT_EQUAL(2, list_pop(list));
list_push(list, 3);
TEST_ASSERT_EQUAL(1, list_shift(list));
list_unshift(list, 4);
list_push(list, 5);
TEST_ASSERT_EQUAL(4, list_shift(list));
TEST_ASSERT_EQUAL(5, list_pop(list));
TEST_ASSERT_EQUAL(3, list_shift(list));
}
static void test_count_an_empty_list(void)
{
TEST_ASSERT_EQUAL(0, list_count(list));
}
static void test_count_a_list_with_items(void)
{
list_push(list, 37);
list_push(list, 1);
TEST_ASSERT_EQUAL(2, list_count(list));
}
static void test_count_is_correct_after_mutation(void)
{
list_push(list, 31);
TEST_ASSERT_EQUAL(1, list_count(list));
list_unshift(list, 43);
TEST_ASSERT_EQUAL(2, list_count(list));
list_shift(list);
TEST_ASSERT_EQUAL(1, list_count(list));
list_pop(list);
TEST_ASSERT_EQUAL(0, list_count(list));
}
static void test_popping_to_empty_does_not_break_the_list(void)
{
list_push(list, 41);
list_push(list, 59);
list_pop(list);
list_pop(list);
list_push(list, 47);
TEST_ASSERT_EQUAL(1, list_count(list));
TEST_ASSERT_EQUAL(47, list_pop(list));
}
static void test_shifting_to_empty_does_not_break_the_list(void)
{
list_push(list, 41);
list_push(list, 59);
list_shift(list);
list_shift(list);
list_push(list, 47);
TEST_ASSERT_EQUAL(1, list_count(list));
TEST_ASSERT_EQUAL(47, list_shift(list));
}
static void test_deletes_the_only_element(void)
{
list_push(list, 61);
list_delete(list, 61);
TEST_ASSERT_EQUAL(0, list_count(list));
}
static void
test_deletes_the_element_with_the_specified_value_from_the_list(void)
{
list_push(list, 71);
list_push(list, 83);
list_push(list, 79);
list_delete(list, 83);
TEST_ASSERT_EQUAL(2, list_count(list));
TEST_ASSERT_EQUAL(79, list_pop(list));
TEST_ASSERT_EQUAL(71, list_shift(list));
}
static void
test_deletes_the_element_with_the_specified_value_from_the_list_reassigns_tail(
void)
{
list_push(list, 71);
list_push(list, 83);
list_push(list, 79);
list_delete(list, 83);
TEST_ASSERT_EQUAL(2, list_count(list));
TEST_ASSERT_EQUAL(79, list_pop(list));
TEST_ASSERT_EQUAL(71, list_pop(list));
}
static void
test_deletes_the_element_with_the_specified_value_from_the_list_reassigns_head(
void)
{
list_push(list, 71);
list_push(list, 83);
list_push(list, 79);
list_delete(list, 83);
TEST_ASSERT_EQUAL(2, list_count(list));
TEST_ASSERT_EQUAL(71, list_shift(list));
TEST_ASSERT_EQUAL(79, list_shift(list));
}
static void test_deletes_the_first_of_two_elements(void)
{
list_push(list, 97);
list_push(list, 101);
list_delete(list, 97);
TEST_ASSERT_EQUAL(1, list_count(list));
TEST_ASSERT_EQUAL(101, list_pop(list));
}
static void test_deletes_the_second_of_two_elements(void)
{
list_push(list, 97);
list_push(list, 101);
list_delete(list, 101);
TEST_ASSERT_EQUAL(1, list_count(list));
TEST_ASSERT_EQUAL(97, list_pop(list));
}
static void
test_delete_does_not_modify_the_list_if_the_element_is_not_found(void)
{
list_push(list, 89);
list_delete(list, 103);
TEST_ASSERT_EQUAL(1, list_count(list));
}
static void test_deletes_only_the_first_occurrence(void)
{
list_push(list, 73);
list_push(list, 9);
list_push(list, 9);
list_push(list, 107);
list_delete(list, 9);
TEST_ASSERT_EQUAL(3, list_count(list));
TEST_ASSERT_EQUAL(107, list_pop(list));
TEST_ASSERT_EQUAL(9, list_pop(list));
TEST_ASSERT_EQUAL(73, list_pop(list));
}
int main(void)
{
UnityBegin("test_linked_list.c");
RUN_TEST(test_pop_gets_element_from_the_list);
RUN_TEST(test_push_pop_respectively_add_remove_at_the_end_of_the_list);
RUN_TEST(test_shift_gets_an_element_from_the_list);
RUN_TEST(test_shift_gets_first_element_from_the_list);
RUN_TEST(test_unshift_adds_element_at_start_of_the_list);
RUN_TEST(test_pop_push_shift_and_unshift_can_be_used_in_any_order);
RUN_TEST(test_count_an_empty_list);
RUN_TEST(test_count_a_list_with_items);
RUN_TEST(test_count_is_correct_after_mutation);
RUN_TEST(test_popping_to_empty_does_not_break_the_list);
RUN_TEST(test_shifting_to_empty_does_not_break_the_list);
RUN_TEST(test_deletes_the_only_element);
RUN_TEST(test_deletes_the_element_with_the_specified_value_from_the_list);
RUN_TEST(
test_deletes_the_element_with_the_specified_value_from_the_list_reassigns_tail);
RUN_TEST(
test_deletes_the_element_with_the_specified_value_from_the_list_reassigns_head);
RUN_TEST(test_deletes_the_first_of_two_elements);
RUN_TEST(test_deletes_the_second_of_two_elements);
RUN_TEST(test_delete_does_not_modify_the_list_if_the_element_is_not_found);
RUN_TEST(test_deletes_only_the_first_occurrence);
return UnityEnd();
}
# Git Basics
In this document, we will go over some fundamental Git concepts and how to use them. Since Git is a relative huge and complex software and it has lots of commands, we only covers the basics in this document.
## What is Git
Git is a free and open source **distributed version control software** created by Linus Torvalds.
It is the most popular version control system (VCS) in the world. Most of the open source projects are managed using Git.
Being distributed means that every developer working with Git has a copy of that entire repository, which enables the user to coordinate and synchronize their work on different machines.
## Getting Started with Git
In this section, we provide a friendly overview of Git.
### Installing Git
If you are using MacOS or one of the Linux distributions, then you should already have Git installed on you machine. If you are using Windows or doesn't have Git installed on your machine, then you can read this [guide](https://www.atlassian.com/git/tutorials/install-git) which provides lots of useful information about how to install Git on your machine.
Then you can test your Git installation using the following command:
```sh
git --version
```
### The Core of Git - Git Repository
A Git repository, often with the shorter name **repo**, is just a place that stores all your project files where you can save versions of your code, documentations, configurations etc.
There are two types of repositories, one is local repository, the other is central repository. As the names suggested, the local repository is store on your local machine, and the central repository is store on a remote server.
![](./images/git-repo.svg)
### Prepare Yourself
It is a good idea to add some basic information of yourself to Git before doing any operation, so that later when you collaborate with other people you can easily find out who did what operations. The easiest way to do so is:
```sh
git config --global user.name "Your Name"
git config --global user.email "you@yourdomain.example.com"
```
The is actually a global level configuration operation, which is user-specific in your operating system. But you can change that at any time.
### Creating a New Repository Locally
To create a local Git repo, just type the command in any working directory you prefer:
```sh
cd /path/to/your/existing/project
git init
```
This will turn the directory a Git repository, it will create a new `.git` subdirectory in your current working directory.
Once you have a central repo on the server, you will need to add the remote repo url to you Git configuratio using:
```sh
git remote add <remote name> <remote repo url>
```
### Cloning an Existing Repository
If your project has already been set up in a central repository, then you can obtain a local copy of it using:
```sh
git clone <repo url>
```
`<repo url>` can be an URL over HTTPS or SSH etc. And you can clone the remote repository to a specific folder:
```sh
git clone <repo url> <local directory>
```
A typical SSH URL looks like this: `git@HOSTNAME:USERNAME/REPONAME.git`.
### Saving Changes
When working wit Git, the concept of of **saving** is a more subtle process than saving in a traditional file editing application such as Microsoft Word.
In Git, the correct term of saving is **"committing"**. A **commit** is the Git equivalent of a "save". Git commits can be done locally then pushed to a remote server as need using the command:
```sh
# if you are pushing the local branch to the remote target for the first time after using git init
git push -u <remote name> <local branch>
# if you've used git clone to set up your repo, this will send the current branch to its default remote counterpart
git push
```
Don't worry, we will come back to `git push` later.
#### The Three States
Before we start to talk about how to commit changes to the repository, we need to remember this very concept in Git, which is, Git has **three** main states that your files can reside in: **modified**, **staged** and **committed**:
![](./images/git-three-states.png)
#### Modified in Working Directory
The working directory is where you are working on you project, you can change the content of any file and save it using any text editor. The file is **modified** but Git is not aware of it yet.
After changing anything, you can use the command `git status` to see which files are changed. You are likely to see message like this:
```sh
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: <YOU CHANGED FILE>
```
You can also use `git diff` to show all changes that haven't been staged yet. It will give you a comparison view of the file before and after your edits.
#### Staged in Staging Area
If you wish to let Git know the change of a certain file for the next commit, you will have to use the `git add` command, for example:
```sh
# let say, you've just add some lines in hello.c
git add hello.c
# or you can add all modifled files at once
git add .
#
git add --all
```
This will add your changes to the files to the staging area. Now you can use the command `git status` again to see the difference:
```sh
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: hello.c
```
This means that, Git now is aware of the change to this file and ready to "commit (save)" it. However, `git add` needs to be called **every time you alter a file**, otherwise later changes won't be noticed if you try to commit them later.
#### Committed in the Repository
Now, you can commit your changes using the `git commit` command, this will launch a text editor prompting you for a **commit message**. You should enter a message describing what you've done, save the file and close the editor to create the actual commit.
A shortcut command that immediately creates a commit with a passed message is:
```sh
# passing -m option will forgo the text editor prompt
git commit -m "your commit message"
```
Normally, `git commit` will commit all staged files to the repository, but you can commit only specific files (but they still need to be already staged):
```sh
# commit specific files
git commit <path/to/file1> <path/to/file2>
```
After committing you changes to the repository, you can run `git status` again assuming that you haven't made any new changes in the working directory, you will likely to see a message like this:
```sh
nothing to commit, working tree clean
```
Now, you can use `git log` command to show information about the commit.
### More on Git Commits
Every change you commit will be viewable in the respective file or directory in chronological order.
![](./images/git-commit.png)
Git records the entire contents of each file in every commit, it's referred to as **snapshot**.
### Collaborating
Git's distributed collaboration model gives every developer their own copy of the repository, complete with its own local history and branch structure.
Users typically need to share a series of commits rather than a single changeset. Instead of committing a changeset from a working copy to the central repository, Git lets you share entire branches between repositories.
In this chapter, you will learn how to sync your work with other people.
#### Git remote
The `git remote` command lets you create, view, and delete connections to other repositories.
You can use it to view your git remote configuration:
```sh
# list remote connections to other repos with name
git remote
# same as above but with concrete urls
git remote -v
```
You can create, modify and examine your git remote configurations easily:
```sh
# create a new connection to a remote repo
git remote add <remote name> <remote url>
# rename a existing remote connection
git remote rename <old-name> <new-name>
# remove the connetion to the remote repo
git remote rm <name>
# look for detailed information of a remote repo
git remote show <remote name>
# get the url of a remote repo
git remote get-url <remote name>
```
Once a remote record has been configured through the use of the git remote command, the remote name can be passed as an argument to other Git commands to communicate with the remote repo.
##### The origin Remote
When you clone a repository with `git clone`, it automatically creates a remote connection called `origin` pointing back to the cloned repository.
This is useful for developers creating a local copy of a central repository, since it provides an easy way to pull upstream changes or publish local commits.
#### Fetching and Pulling from Git Remotes
After setting up the remote connection to a central repo, you can use `git fetch` to download commits, files and refs etc. from a remote repo into your local repo.
Git isolates fetched content from existing local content; it has absolutely no effect on your local development work.
In contrast, `git pull` is a more aggressive alternative; it will download the remote content for the active local branch and immediately execute `git merge` to create a merge commit for the new remote content.
We will talk about **branches** and command like `git merge` in Git repo in detail. For now, you can use `git fetch` in the following ways:
```sh
# fetch all branches from the remote repo
git fetch <remote>
# fetch only from a specific branch
git fetch <remote> <branch>
# fetch all registered remote repos
git fetch --all
```
Remember that, `git pull` is basically equivalent to `git fetch` + `git merge`.
#### Pushing to Git Remotes
The `git push` command is used to upload local repository content to a remote repository.
Pushing is how you transfer commits from your local repository to a remote repo. It's the counterpart of `git fetch`.
You can use `git push` in the following ways:
```sh
# push your current branch to the <branch> in the remote repo
# Git will prevent you from doing this, if it is not a fast-foward merge in the destination repository
git push <remote> <branch>
# push all of your local branches to the specific remote
git push <remote> --all
```
Now I will show you some voodoo magic, you can use the `--force` flag to overwrite anything in the remote branch:
```sh
# for example, this will overwrite the branch in the remote, and possibly causing inconsistency
git push <remote> --force
```
**DO NOT USE THIS FLAG**, unless you're **absolutely** sure of what you're doing.
### Using Branches
In Git, branches are a part of your everyday development process. Git branches are effectively a **pointer** to a snapshot of your changes.
When you want to add a new feature or fix a bug—no matter how big or how small, you should create a new branch to encapsulate your changes.
![](./images/git-branch.svg)
The figure above depicts a repository of three different branches, they are all independent to each other.
The `git branch` command lets you create, list, rename, and delete branches. But it doesn't allow you to switch between branches, fork a new branch, or even merge branches back together. For this reason, `git branch` is often used in conjunction with `git checkout` and `git merge` commands.
#### Basic Branch Operations
```sh
# list all your branches
git branch
# create a new branch, but will not switch to the newly created branch
git branch <new branch name>
# delete a branch
git branch -d <branch name>
# rename the current branch
git branch -m <new branch name>
# list all remote branches
git branch -a
```
It's important to know that, creating a new branch does not change the repo; it simply creates a new pointer that points to the commit:
![](./images/git-create-branch.png)
The illustration above provides a visual on what happens when the branch is created. The repository is the same, but a new pointer is added to the current commit.
#### Switching Branches
`git checkout` lets you navigates between the branches created by `git branch`. Checking out a branch updates the files in the working directory.
You can switch to a branch easily using:
```sh
git checkout <branch name>
```
Additionally, you can use `git checkout` to create a new branch from the current commit (pointed by a special pointer called **HEAD**) and switch to that newly created branch immediate using `-b` flag:
```sh
git checkout -b <new branch name>
# or you can checkout a new branch from some other branch
git checkout -b <new branch name> <some other exisiting branch>
```
#### Tracking Branches
Lets say you are working on a branch named `dev` which you fetched from the remote named `origin`. Now you want to work on this branch for a quite a long time and want the `git push` and `git pull` using the `dev` branch of `origin` by default. So that you won't have to type `git push origin dev` or `git pull origin dev` every time you want to update or pull the updates to and from the remote branch.
First, you need to tell Git which branch to track:
```c
# suppose you are on the dev branch on you local machine, and there is already a dev branch in the remote repo
git branch --set-upstream-to origin/remote
```
This only works when there is already a `dev` branch in the remote repo. If you want to create a new branch in the remote repo, and track it automatically, then you can use the following command:
```
# this will create a dev branch in the remote and track it using the current branch locally
git push --set-upstream origin dev
# or, same as above
git push -u origin dev
```
#### Merging Branches
Merging in Git is the way to putting forked history back together again. The `git merge` command lets you integrate branches created by `git branch` into a single branch.
In most cases, `git merge` is used to combine two branches. It takes two commit pointers, usually the branch tips, and will find a common base commit between them. Then `git merge` will create a special `merge commit` that combines the changes from both branches.
Take a look at the following example:
![](./images/git-merge-1.png)
Assuming that we are currently at the `main` branch, if we invoke `git merge <branch name>`, the branch will be merged into the `main` branch:
![](./images/git-merge-2.png)
This is also called a 3-way merge, because it involves the `current branch`, the `branch you want to merge`, as well as the `common ancestor`.
##### Fast Forward Merge
A fast forward merge occurs when there is a linear path from the current branch to the branch to be merged ahead. This is the easiest situation for Git, it would only have to move the pointer to the tip of the merging branch:
![](./images/fast-forward-merge.svg)
The fast forward merge is only possible when the branches are not diverged.
#### Resolving Conflicts
If there is a merge operation, then there will most likely be a merge conflict.
When the two branches you are trying to merge both changed the same of a file, Git won't be able to figure out which version to use. When this situation arises, Git simply stops merging and let you resolve the merge conflicts.
The great part of Git's merging process is that it uses the familiar edit/stage/commit workflow to resolve merge conflicts.
When you encounter a merge conflict, running the `git status` command shows you which files need to be resolved.
For example, if both branches modified the same section of `hello.c`:
```sh
On branch main
Unmerged paths:
(use "git add/rm ..." as appropriate to mark resolution)
both modified: hello.c
```
##### Understanding the Conflicts
When Git encounters a conflict during a merge, It will edit the content of the affected files with visual indicators that mark both sides of the conflicted content.
These visual markers are: <<<<<<<, =======, and >>>>>>>. You will likely to see something similar like this in the file that has caused the conflict:
```sh
here is some content not affected by the conflict
<<<<<<< main
this is conflicted text from main
=======
this is conflicted text from feature branch
>>>>>>> feature branch;
```
You can edit the file as you like, resolve the conflicts in a way that suits your need (e.g. delete all the contents). Then you will have to invoke `git add` and `git commit` to finish the merge.
##### Aborting the Merge
However, sometimes you might want to cancel the merge. You can abort the merge in case of conflicts using this command:
```sh
git merge --abort
```
This won't help you resolve the conflicts but it will rollback to the state before invoking `git merge`.
### Git Workflow
There is a variety of of branching strategies and workflows. A well structured workflow promotes organization, efficiency and code quality.
Here we will focus on the **Feature Branch Workflow** which is simple to learn and to use.
In short, developers create separate branches for each feature or bugfix, keeping the ‘main’ branch stable.
When a feature is complete, the developer submits a `pull request` or `merge request` to integrate the changes back into the main branch after a code review.
#### Pull/Merge Request
`Pull request` or `merge request` is usually provided by the collaborating platform such as GitLab and GitHub. A pull request notifies other development team members of changes made in your local repository.
Here is a simple workflow with pull request that you and your team can follow:
![](./images/pull-request.png)
Since we are using GitLab, you can read the documentation [here](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) and learn how to create merge requests on GitLab.
## Common Misconceptions
### Github/Gitlab/etc. != Git
Git is only a software whereas Github or Gitlab is a commercial online platform which provides services that host your git repository remotely.
### Snapshots, Not Differences
The major difference between Git and any other VCS is the way Git thinks about its data.
With Git, every time you commit, or save the state of your project, Git basically takes a picture of what all your files look like at that moment and stores a reference to that snapshot.
If files have not changed, Git doesn’t store the file again, just a link to the previous identical file it has already stored.
## Git Clients
After knowing the basic concepts of Git, you can choose whether to stick with the command-line interface or to use other Git-based clients.
We suggest you first familiarize yourself with the command-line; after that, you can switch to any other tools you like without any troubles.
### GUI Clients
If you prefer to use a GUI client, here are some options:
- [Github Desktop](https://desktop.github.com/)
- [Sourcetree](https://www.sourcetreeapp.com/)
- [GitLens in VS Code](https://gitlens.amod.io/)
### Terminal Clients
If you prefer to use a terminal based client, here are some options:
- [Tig](https://jonas.github.io/tig/)
- [GitUI](https://github.com/extrawurst/gitui)
- [LazyGit](https://github.com/jesseduffield/lazygit)
## Git Cheat Sheets
- [DE](https://training.github.com/downloads/de/github-git-cheat-sheet/)
- [EN](https://training.github.com/downloads/github-git-cheat-sheet/)
## Other Useful Learning Materials
- https://blinry.itch.io/oh-my-git
- https://github.com/initialcommit-com/git-sim
- https://learn.microsoft.com/en-us/training/modules/intro-to-git/
- https://git-scm.com/book/en/v2
### References
- https://git-scm.com/doc
- https://github.com/git-guides
- https://www.atlassian.com/git/tutorials
- https://nulab.com/learn/software-development/git-tutorial/git-basics/
images/c-compilation.png

93.7 KiB

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.2.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Lager_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 800 907" style="enable-background:new 0 0 800 907;" xml:space="preserve">
<style type="text/css">
.st0{fill:none;stroke:#404040;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
.st1{fill:#59AFE1;stroke:#404040;stroke-width:4;stroke-linejoin:round;stroke-miterlimit:10;}
.st2{fill:#FFFFFF;stroke:#404040;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
.st3{fill:#B18BE8;stroke:#404040;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
.st4{fill:#404040;}
.st5{fill:none;stroke:#CCCCCC;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
.st6{fill:#999999;}
.st7{fill:#B3E3FF;stroke:#404040;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
.st8{fill:#414141;}
</style>
<path class="st0" d="M321.6,272.5V249 M332.4,263.8l-10.8,10.9l-10.9-10.9 M615.9,235.4h-83h41.2 M419.2,276.4c0,22.6-18.4,41-41,41
H176 M419.2,276.4c0-22.6,18.4-41,41-41h30.7"/>
<circle class="st1" cx="321.6" cy="317.4" r="21"/>
<ellipse transform="matrix(0.1602 -0.9871 0.9871 0.1602 197.5424 702.9832)" class="st2" cx="511.9" cy="235.4" rx="21" ry="21"/>
<circle class="st2" cx="595.1" cy="235.4" r="21"/>
<ellipse transform="matrix(0.1602 -0.9871 0.9871 0.1602 -113.173 501.7811)" class="st2" cx="238.3" cy="317.4" rx="21" ry="21"/>
<circle class="st2" cx="155.1" cy="317.4" r="21"/>
<path class="st3" d="M524.3,99.5h141.6v50H524.3L524.3,99.5z"/>
<path class="st4" d="M552.1,122.8c-0.1-0.8-0.8-1.8-2.2-1.8c-1.2,0-2.1,0.8-2.1,1.8c0,0.8,0.5,1.3,1.4,1.5l1.6,0.3
c1.8,0.4,2.8,1.5,2.8,3c0,1.6-1.4,3.1-3.7,3.1c-2.6,0-3.8-1.6-4-3.2l1.4-0.4c0.1,1.2,0.9,2.3,2.5,2.3c1.5,0,2.2-0.8,2.2-1.7
c0-0.8-0.5-1.4-1.6-1.7l-1.5-0.3c-1.5-0.3-2.6-1.3-2.6-2.9c0-1.7,1.5-3.2,3.5-3.2c2.4,0,3.4,1.5,3.6,2.6L552.1,122.8L552.1,122.8z
M562.8,126.9c0,2.2-1.5,3.8-3.7,3.8s-3.7-1.6-3.7-3.8s1.5-3.8,3.7-3.8S562.8,124.7,562.8,126.9z M561.4,126.9
c0-1.7-1.1-2.6-2.2-2.6s-2.2,0.9-2.2,2.6c0,1.7,1.1,2.6,2.2,2.6S561.4,128.6,561.4,126.9z M565.3,130.5v-7.2h1.3v1
c0.5-0.8,1.4-1.2,2.2-1.2c0.9,0,1.8,0.4,2.2,1.4c0.6-1,1.5-1.4,2.4-1.4c1.3,0,2.5,0.9,2.5,2.7v4.7h-1.4V126c0-0.9-0.5-1.6-1.5-1.6
s-1.7,0.8-1.7,1.8v4.4H570V126c0-0.9-0.4-1.6-1.5-1.6c-1,0-1.7,0.8-1.7,1.8v4.3L565.3,130.5L565.3,130.5z M585.2,128.5
c-0.4,1.3-1.6,2.3-3.2,2.3c-1.9,0-3.6-1.4-3.6-3.9c0-2.3,1.6-3.8,3.4-3.8c2.2,0,3.5,1.5,3.5,3.8v0.5h-5.4c0,1.3,1,2.2,2.2,2.2
s1.8-0.6,2-1.5L585.2,128.5z M583.8,126.2c0-1-0.7-1.8-2-1.8c-1.2,0-1.9,0.9-2,1.8H583.8z M592.5,130.5v-10.6h6.5v1.4h-5v3.4h4.5
v1.4H594v4.5h-1.5V130.5z M607.1,128.5c-0.4,1.3-1.6,2.3-3.2,2.3c-1.9,0-3.6-1.4-3.6-3.9c0-2.3,1.6-3.8,3.4-3.8
c2.2,0,3.5,1.5,3.5,3.8v0.5h-5.4c0,1.3,1,2.2,2.2,2.2s1.8-0.6,2-1.5L607.1,128.5z M605.7,126.2c0-1-0.7-1.8-2-1.8
c-1.2,0-1.9,0.9-2,1.8H605.7z M611.4,126.4l1.9-0.3c0.4-0.1,0.6-0.3,0.6-0.5c0-0.7-0.5-1.3-1.6-1.3c-1,0-1.5,0.6-1.6,1.5l-1.4-0.3
c0.2-1.4,1.4-2.3,3-2.3c2.2,0,3,1.2,3,2.6v3.6c0,0.6,0.1,1,0.1,1.2H614c0-0.2-0.1-0.5-0.1-1c-0.3,0.5-1,1.2-2.3,1.2
c-1.5,0-2.4-1-2.4-2.2C609.3,127.3,610.2,126.6,611.4,126.4L611.4,126.4z M613.9,127.5v-0.3l-2.2,0.3c-0.6,0.1-1.1,0.4-1.1,1.1
c0,0.5,0.4,1,1.2,1C613,129.6,613.9,129,613.9,127.5z M620.2,123.3h1.6v1.3h-1.6v3.8c0,0.7,0.3,1,1,1c0.2,0,0.4,0,0.6-0.1v1.2
c-0.1,0-0.5,0.1-1,0.1c-1.2,0-2-0.8-2-2.1v-4h-1.4v-1.3h0.4c0.8,0,1.1-0.5,1.1-1.1V121h1.3L620.2,123.3L620.2,123.3z M627,130.8
c-1.7,0-2.7-1.3-2.7-2.9v-4.5h1.4v4.3c0,1,0.4,1.9,1.6,1.9c1.1,0,1.7-0.8,1.7-1.8v-4.3h1.4v5.9c0,0.6,0,1.1,0.1,1.3h-1.4
c0-0.2-0.1-0.6-0.1-0.9C628.7,130.4,627.8,130.8,627,130.8z M637.6,124.8H637c-1.2,0-2,0.6-2,2.2v3.6h-1.4v-7.2h1.4v1.3
c0.5-1.1,1.4-1.4,2.2-1.4h0.5v1.5L637.6,124.8z M646.1,128.5c-0.4,1.3-1.6,2.3-3.2,2.3c-1.9,0-3.6-1.4-3.6-3.9
c0-2.3,1.6-3.8,3.4-3.8c2.2,0,3.5,1.5,3.5,3.8v0.5h-5.4c0,1.3,1,2.2,2.2,2.2s1.8-0.6,2-1.5L646.1,128.5z M644.7,126.2
c0-1-0.7-1.8-2-1.8c-1.2,0-1.9,0.9-2,1.8H644.7z"/>
<path class="st0" d="M595.1,192.7v-23.5 M606,184l-10.9,10.9L584.2,184"/>
<path class="st5" d="M129.3,441.1h541.4"/>
<path class="st6" d="M346.9,17.1c2,0,3.2,1.2,3.2,2.9c0,1.1-0.7,2-1.6,2.3c1.2,0.3,1.9,1.4,1.9,2.6c0,1.7-1.3,2.9-3.3,2.9h-3.7V17.1
C343.4,17.1,346.9,17.1,346.9,17.1z M346.8,21.8c1.2,0,1.9-0.7,1.9-1.7s-0.7-1.7-1.9-1.7H345v3.4C345,21.8,346.8,21.8,346.8,21.8z
M347,26.5c1.2,0,2-0.7,2-1.7s-0.6-1.7-1.9-1.7H345v3.4C345,26.5,347,26.5,347,26.5z M359.4,25.7c-0.4,1.3-1.6,2.3-3.2,2.3
c-1.9,0-3.6-1.4-3.6-3.9c0-2.3,1.6-3.8,3.4-3.8c2.2,0,3.5,1.5,3.5,3.8v0.4H354c0,1.3,1,2.2,2.2,2.2s1.8-0.6,2-1.5L359.4,25.7z
M358,23.4c0-1-0.7-1.8-2-1.8c-1.2,0-1.9,0.9-2,1.8H358z M363.9,21.8v5.9h-1.5v-5.9h-1.3v-1.3h1.3v-1.2c0-1.6,1.1-2.5,2.4-2.5
c0.5,0,0.8,0.1,0.8,0.2v1.3c-0.1,0-0.3-0.1-0.6-0.1c-0.5,0-1.1,0.2-1.1,1.2v1.1h1.7v1.3H363.9L363.9,21.8z M374.4,24.1
c0,2.2-1.5,3.8-3.7,3.8s-3.7-1.6-3.7-3.8s1.5-3.8,3.7-3.8S374.4,21.9,374.4,24.1z M373,24.1c0-1.7-1.1-2.6-2.2-2.6s-2.2,0.9-2.2,2.6
s1.1,2.6,2.2,2.6S373,25.8,373,24.1z M381,22h-0.6c-1.2,0-2,0.6-2,2.2v3.6H377v-7.2h1.4v1.3c0.5-1.1,1.4-1.4,2.2-1.4h0.5V22L381,22z
M389.4,25.7c-0.4,1.3-1.6,2.3-3.2,2.3c-1.9,0-3.6-1.4-3.6-3.9c0-2.3,1.6-3.8,3.4-3.8c2.2,0,3.5,1.5,3.5,3.8v0.4H384
c0,1.3,1,2.2,2.2,2.2s1.8-0.6,2-1.5L389.4,25.7z M388,23.4c0-1-0.7-1.8-2-1.8c-1.2,0-1.9,0.9-2,1.8H388z M406.7,27.7v-8.3l-3.6,8.3
h-1.3l-3.6-8.3v8.3h-1.5V17.1h2l3.7,8.7l3.8-8.7h2v10.6C408.2,27.7,406.7,27.7,406.7,27.7z M417.8,25.7c-0.4,1.3-1.6,2.3-3.2,2.3
c-1.9,0-3.6-1.4-3.6-3.9c0-2.3,1.6-3.8,3.4-3.8c2.2,0,3.5,1.5,3.5,3.8v0.4h-5.4c0,1.3,1,2.2,2.2,2.2s1.8-0.6,2-1.5L417.8,25.7z
M416.3,23.4c0-1-0.7-1.8-2-1.8c-1.2,0-1.9,0.9-2,1.8H416.3z M424.4,22h-0.6c-1.2,0-2,0.6-2,2.2v3.6h-1.4v-7.2h1.4v1.3
c0.5-1.1,1.4-1.4,2.2-1.4h0.5V22H424.4z M427.4,27.8c0.1,1,0.9,1.8,2,1.8c1.5,0,2.2-0.8,2.2-2.3v-1c-0.3,0.7-1.1,1.2-2.2,1.2
c-1.9,0-3.3-1.5-3.3-3.5c0-1.9,1.3-3.5,3.3-3.5c1.1,0,1.9,0.4,2.2,1.1v-1h1.4v6.7c0,1.8-0.9,3.6-3.6,3.6c-1.8,0-3.1-1.1-3.3-2.7
L427.4,27.8z M431.6,23.9c0-1.4-0.8-2.3-2.1-2.3c-1.2,0-2.1,0.9-2.1,2.3s0.8,2.3,2.1,2.3S431.6,25.3,431.6,23.9z M436.6,16.8
c0.6,0,1,0.4,1,1s-0.4,1-1,1s-1-0.5-1-1C435.6,17.2,436.1,16.8,436.6,16.8z M435.9,27.7v-7.2h1.4v7.2
C437.3,27.7,435.9,27.7,435.9,27.7z M441.9,27.7h-1.4v-7.2h1.4v1c0.5-0.9,1.4-1.2,2.2-1.2c1.7,0,2.6,1.2,2.6,2.9v4.6h-1.4v-4.3
c0-1-0.4-1.8-1.7-1.8c-1.1,0-1.7,0.9-1.7,2C441.9,23.7,441.9,27.7,441.9,27.7z M450.5,27.8c0.1,1,0.9,1.8,2,1.8
c1.5,0,2.2-0.8,2.2-2.3v-1c-0.3,0.7-1.1,1.2-2.2,1.2c-1.9,0-3.3-1.5-3.3-3.5c0-1.9,1.3-3.5,3.3-3.5c1.1,0,1.9,0.4,2.2,1.1v-1h1.4
v6.7c0,1.8-0.9,3.6-3.6,3.6c-1.8,0-3.1-1.1-3.3-2.7L450.5,27.8z M454.7,23.9c0-1.4-0.8-2.3-2.1-2.3c-1.2,0-2.1,0.9-2.1,2.3
s0.8,2.3,2.1,2.3S454.7,25.3,454.7,23.9z"/>
<path class="st0" d="M595.6,805.9v23.5 M584.7,814.6l10.9-10.8l10.8,10.8 M615.4,763.6h-83h41.2 M418.7,804.6c0,22.6-18.4,41-41,41
H175.6 M418.7,804.6c0-22.6,18.4-41,41-41h30.7"/>
<circle class="st2" cx="321.1" cy="845.6" r="21"/>
<circle class="st2" cx="237.9" cy="845.6" r="21"/>
<circle class="st1" cx="594.6" cy="763.6" r="21"/>
<ellipse transform="matrix(0.1602 -0.9871 0.9871 0.1602 -324.2571 1146.0814)" class="st2" cx="511.4" cy="763.6" rx="21" ry="21"/>
<circle class="st2" cx="154.6" cy="845.6" r="21"/>
<path class="st0" d="M594.6,720.9v-23.5 M605.5,712.2l-10.9,10.9l-10.8-10.9"/>
<path class="st6" d="M331.9,549.8h-4.7l-1.1,3h-1.6l4.2-10.6h1.7l4.2,10.6H333L331.9,549.8z M327.8,548.4h3.7l-1.8-4.8L327.8,548.4
L327.8,548.4z M338.7,546.8v5.9h-1.5v-5.9h-1.3v-1.3h1.3v-1.2c0-1.6,1.1-2.5,2.4-2.5c0.5,0,0.8,0.1,0.8,0.2v1.3
c-0.1,0-0.3-0.1-0.6-0.1c-0.5,0-1.1,0.2-1.1,1.2v1.1h1.7v1.3H338.7L338.7,546.8z M344.6,545.5h1.6v1.3h-1.6v3.8c0,0.7,0.3,1,1,1
c0.2,0,0.4,0,0.6-0.1v1.2c-0.1,0-0.5,0.1-1,0.1c-1.2,0-2-0.8-2-2.1v-4h-1.4v-1.3h0.4c0.8,0,1.1-0.5,1.1-1.1v-1.2h1.3V545.5
L344.6,545.5z M355,550.7c-0.4,1.3-1.6,2.3-3.2,2.3c-1.9,0-3.6-1.4-3.6-3.9c0-2.3,1.6-3.8,3.4-3.8c2.2,0,3.5,1.5,3.5,3.8v0.4h-5.4
c0,1.3,1,2.2,2.2,2.2s1.8-0.6,2-1.5L355,550.7z M353.5,548.4c0-1-0.7-1.8-2-1.8c-1.2,0-1.9,0.9-2,1.8H353.5z M361.6,547H361
c-1.2,0-2,0.6-2,2.2v3.6h-1.4v-7.2h1.4v1.3c0.5-1.1,1.4-1.4,2.2-1.4h0.5v1.5L361.6,547z M370.1,548.6l1.9-0.3
c0.4-0.1,0.6-0.3,0.6-0.5c0-0.7-0.5-1.3-1.6-1.3c-1,0-1.5,0.6-1.6,1.5l-1.4-0.3c0.2-1.4,1.4-2.3,3-2.3c2.2,0,3,1.2,3,2.6v3.6
c0,0.6,0.1,1,0.1,1.2h-1.4c0-0.2-0.1-0.5-0.1-1c-0.3,0.5-1,1.2-2.3,1.2c-1.5,0-2.4-1-2.4-2.2C367.9,549.5,368.8,548.8,370.1,548.6
L370.1,548.6z M372.6,549.7v-0.3l-2.2,0.3c-0.6,0.1-1.1,0.4-1.1,1.1c0,0.5,0.4,1,1.2,1C371.6,551.8,372.6,551.2,372.6,549.7z
M381.6,552.7v-10.6h6.5v1.4h-5v3.4h4.5v1.4H383v4.5h-1.4V552.7z M391.6,548.6l1.9-0.3c0.4-0.1,0.6-0.3,0.6-0.5
c0-0.7-0.5-1.3-1.6-1.3c-1,0-1.5,0.6-1.6,1.5l-1.4-0.3c0.2-1.4,1.4-2.3,3-2.3c2.2,0,3,1.2,3,2.6v3.6c0,0.6,0.1,1,0.1,1.2h-1.4
c0-0.2-0.1-0.5-0.1-1c-0.3,0.5-1,1.2-2.3,1.2c-1.5,0-2.4-1-2.4-2.2C389.5,549.5,390.4,548.8,391.6,548.6L391.6,548.6z M394.2,549.7
v-0.3l-2.2,0.3c-0.6,0.1-1,0.4-1,1.1c0,0.5,0.4,1,1.2,1C393.2,551.8,394.2,551.2,394.2,549.7z M399.1,550.4c0.1,0.8,0.7,1.3,1.7,1.3
c0.8,0,1.2-0.4,1.2-1c0-0.4-0.3-0.8-0.9-0.9l-1.2-0.3c-1.1-0.2-1.8-1-1.8-2c0-1.2,1.2-2.3,2.6-2.3c2,0,2.6,1.3,2.7,1.9l-1.2,0.5
c-0.1-0.4-0.4-1.2-1.5-1.2c-0.7,0-1.2,0.5-1.2,1c0,0.4,0.3,0.8,0.8,0.9l1.2,0.3c1.3,0.3,2,1.1,2,2.1s-0.9,2.2-2.6,2.2
c-2,0-2.8-1.3-2.9-2.1L399.1,550.4L399.1,550.4z M407.9,545.5h1.6v1.3h-1.6v3.8c0,0.7,0.3,1,1,1c0.2,0,0.4,0,0.6-0.1v1.2
c-0.1,0-0.5,0.1-1,0.1c-1.2,0-2-0.8-2-2.1v-4h-1.4v-1.3h0.4c0.8,0,1.1-0.5,1.1-1.1v-1.2h1.3V545.5L407.9,545.5z M411.6,549.1v-1.2
h4.1v1.2H411.6z M418.4,552.7v-10.6h6.5v1.4h-5v3.4h4.5v1.4h-4.5v4.5h-1.5V552.7z M433.5,549.1c0,2.2-1.5,3.8-3.7,3.8
s-3.7-1.6-3.7-3.8s1.5-3.8,3.7-3.8S433.5,546.9,433.5,549.1z M432.1,549.1c0-1.7-1.1-2.6-2.2-2.6s-2.2,0.9-2.2,2.6
c0,1.7,1.1,2.6,2.2,2.6S432.1,550.8,432.1,549.1z M440.1,547h-0.6c-1.2,0-2,0.6-2,2.2v3.6h-1.4v-7.2h1.4v1.3
c0.5-1.1,1.4-1.4,2.2-1.4h0.5v1.5L440.1,547z M448,545.5l1.9,5.4l1.6-5.4h1.5l-2.3,7.2h-1.5l-1.9-5.5l-1.9,5.5h-1.5l-2.4-7.2h1.5
l1.6,5.4l1.9-5.4H448L448,545.5z M456.8,548.6l1.9-0.3c0.4-0.1,0.6-0.3,0.6-0.5c0-0.7-0.5-1.3-1.6-1.3c-1,0-1.5,0.6-1.6,1.5
l-1.4-0.3c0.2-1.4,1.4-2.3,3-2.3c2.2,0,3,1.2,3,2.6v3.6c0,0.6,0.1,1,0.1,1.2h-1.4c0-0.2-0.1-0.5-0.1-1c-0.3,0.5-1,1.2-2.3,1.2
c-1.5,0-2.4-1-2.4-2.2C454.6,549.5,455.6,548.8,456.8,548.6L456.8,548.6z M459.3,549.7v-0.3l-2.2,0.3c-0.6,0.1-1.1,0.4-1.1,1.1
c0,0.5,0.4,1,1.2,1C458.4,551.8,459.3,551.2,459.3,549.7z M467.7,547h-0.6c-1.2,0-2,0.6-2,2.2v3.6h-1.4v-7.2h1.4v1.3
c0.5-1.1,1.4-1.4,2.2-1.4h0.5v1.5L467.7,547z M474.9,551.7c-0.3,0.7-1.1,1.3-2.2,1.3c-2.1,0-3.4-1.7-3.4-3.8c0-2,1.4-3.8,3.4-3.8
c1.3,0,2,0.6,2.2,1.2v-4.7h1.4v9.5c0,0.7,0.1,1.2,0.1,1.3H475C475,552.5,474.9,552.2,474.9,551.7z M472.8,551.7
c1.3,0,2.1-1.1,2.1-2.6s-0.8-2.5-2.1-2.5s-2.1,1-2.1,2.5S471.4,551.7,472.8,551.7z M494.1,552.7v-8.3l-3.6,8.3h-1.3l-3.6-8.3v8.3
h-1.5v-10.6h2l3.7,8.7l3.8-8.7h2v10.6H494.1z M505.1,550.7c-0.4,1.3-1.6,2.3-3.2,2.3c-1.9,0-3.6-1.4-3.6-3.9c0-2.3,1.6-3.8,3.4-3.8
c2.2,0,3.5,1.5,3.5,3.8v0.4h-5.4c0,1.3,1,2.2,2.2,2.2s1.8-0.6,2-1.5L505.1,550.7z M503.7,548.4c0-1-0.7-1.8-2-1.8
c-1.2,0-1.9,0.9-2,1.8H503.7z M511.7,547h-0.6c-1.2,0-2,0.6-2,2.2v3.6h-1.4v-7.2h1.4v1.3c0.5-1.1,1.4-1.4,2.2-1.4h0.5v1.5L511.7,547
z M514.7,552.8c0.1,1,0.9,1.8,2,1.8c1.5,0,2.2-0.8,2.2-2.3v-1c-0.3,0.7-1.1,1.2-2.2,1.2c-1.9,0-3.3-1.5-3.3-3.5
c0-1.9,1.3-3.5,3.3-3.5c1.1,0,1.9,0.4,2.2,1.1v-1h1.4v6.7c0,1.8-0.9,3.6-3.6,3.6c-1.8,0-3.1-1.1-3.3-2.7L514.7,552.8L514.7,552.8z
M519,548.9c0-1.4-0.8-2.3-2.1-2.3c-1.2,0-2.1,0.9-2.1,2.3s0.8,2.3,2.1,2.3C518.1,551.2,519,550.3,519,548.9z M529.6,550.7
c-0.4,1.3-1.6,2.3-3.2,2.3c-1.9,0-3.6-1.4-3.6-3.9c0-2.3,1.6-3.8,3.4-3.8c2.2,0,3.5,1.5,3.5,3.8v0.4h-5.4c0,1.3,1,2.2,2.2,2.2
s1.8-0.6,2-1.5L529.6,550.7z M528.2,548.4c0-1-0.7-1.8-2-1.8c-1.2,0-1.9,0.9-2,1.8H528.2z"/>
<path class="st3" d="M524.8,625.4h141.6v50H524.8L524.8,625.4z"/>
<path class="st4" d="M552.6,648.7c-0.1-0.8-0.8-1.8-2.2-1.8c-1.2,0-2.1,0.8-2.1,1.8c0,0.8,0.5,1.4,1.4,1.5l1.6,0.3
c1.8,0.4,2.8,1.5,2.8,3c0,1.6-1.4,3.1-3.7,3.1c-2.6,0-3.8-1.6-4-3.2l1.4-0.4c0.1,1.2,0.9,2.3,2.5,2.3c1.5,0,2.2-0.8,2.2-1.7
c0-0.8-0.5-1.4-1.6-1.6l-1.5-0.3c-1.5-0.3-2.6-1.3-2.6-2.9c0-1.7,1.5-3.2,3.5-3.2c2.4,0,3.4,1.5,3.6,2.6L552.6,648.7L552.6,648.7z
M563.3,652.8c0,2.2-1.5,3.8-3.7,3.8s-3.7-1.6-3.7-3.8s1.5-3.8,3.7-3.8S563.3,650.6,563.3,652.8z M561.8,652.8
c0-1.7-1.1-2.6-2.2-2.6s-2.2,0.9-2.2,2.6c0,1.7,1.1,2.6,2.2,2.6S561.8,654.5,561.8,652.8z M565.8,656.4v-7.2h1.3v1
c0.5-0.8,1.4-1.2,2.2-1.2c0.9,0,1.8,0.4,2.2,1.4c0.6-1,1.5-1.4,2.4-1.4c1.3,0,2.5,0.9,2.5,2.7v4.7H575v-4.5c0-0.9-0.5-1.6-1.5-1.6
s-1.7,0.8-1.7,1.8v4.4h-1.4V652c0-0.9-0.4-1.6-1.5-1.6c-1,0-1.7,0.8-1.7,1.8v4.3h-1.4L565.8,656.4z M585.7,654.4
c-0.4,1.3-1.6,2.3-3.2,2.3c-1.9,0-3.6-1.4-3.6-3.9c0-2.3,1.6-3.8,3.4-3.8c2.2,0,3.5,1.5,3.5,3.8v0.4h-5.4c0,1.3,1,2.2,2.2,2.2
s1.8-0.6,2-1.5L585.7,654.4z M584.3,652.1c0-1-0.7-1.8-2-1.8c-1.2,0-1.9,0.9-2,1.8H584.3z M592.9,656.4v-10.6h6.5v1.4h-5v3.4h4.5
v1.4h-4.5v4.5h-1.5V656.4z M607.6,654.4c-0.4,1.3-1.6,2.3-3.2,2.3c-1.9,0-3.6-1.4-3.6-3.9c0-2.3,1.6-3.8,3.4-3.8
c2.2,0,3.5,1.5,3.5,3.8v0.4h-5.4c0,1.3,1,2.2,2.2,2.2s1.8-0.6,2-1.5L607.6,654.4z M606.1,652.1c0-1-0.7-1.8-2-1.8
c-1.2,0-1.9,0.9-2,1.8H606.1z M611.9,652.3l1.9-0.3c0.4-0.1,0.6-0.3,0.6-0.5c0-0.7-0.5-1.3-1.6-1.3c-1,0-1.5,0.6-1.6,1.5l-1.4-0.3
c0.2-1.4,1.4-2.3,3-2.3c2.2,0,3,1.2,3,2.6v3.6c0,0.6,0.1,1,0.1,1.2h-1.4c0-0.2-0.1-0.5-0.1-1c-0.3,0.5-1,1.2-2.3,1.2
c-1.5,0-2.4-1-2.4-2.2C609.7,653.2,610.7,652.5,611.9,652.3z M614.4,653.3V653l-2.2,0.3c-0.6,0.1-1.1,0.4-1.1,1.1c0,0.5,0.4,1,1.2,1
C613.5,655.5,614.4,654.9,614.4,653.3z M620.6,649.2h1.6v1.3h-1.6v3.8c0,0.7,0.3,1,1,1c0.2,0,0.4,0,0.6-0.1v1.2
c-0.1,0-0.5,0.1-1,0.1c-1.2,0-2-0.8-2-2.1v-4h-1.4v-1.3h0.4c0.8,0,1.1-0.5,1.1-1.1v-1.2h1.3L620.6,649.2L620.6,649.2z M627.5,656.7
c-1.7,0-2.7-1.3-2.7-2.9v-4.5h1.4v4.3c0,1,0.4,1.9,1.6,1.9c1.1,0,1.7-0.8,1.7-1.8v-4.4h1.4v5.9c0,0.6,0,1.1,0.1,1.3h-1.4
c0-0.2-0.1-0.6-0.1-0.9C629.2,656.3,628.3,656.7,627.5,656.7L627.5,656.7z M638.1,650.6h-0.6c-1.2,0-2,0.6-2,2.2v3.6h-1.4v-7.2h1.4
v1.3c0.5-1.1,1.4-1.4,2.2-1.4h0.5v1.5L638.1,650.6z M646.5,654.4c-0.4,1.3-1.6,2.3-3.2,2.3c-1.9,0-3.6-1.4-3.6-3.9
c0-2.3,1.6-3.8,3.4-3.8c2.2,0,3.5,1.5,3.5,3.8v0.4h-5.4c0,1.3,1,2.2,2.2,2.2s1.8-0.6,2-1.5L646.5,654.4z M645.1,652.1
c0-1-0.7-1.8-2-1.8c-1.2,0-1.9,0.9-2,1.8H645.1z"/>
<g>
<path class="st7" d="M273.5,176.9h96.2v50h-96.2V176.9z"/>
<g>
<path class="st8" d="M306.4,208v-10h2l2.4,7.1c0.2,0.7,0.4,1.2,0.5,1.5c0.1-0.4,0.3-0.9,0.5-1.6l2.4-7h1.8v10h-1.3v-8.4l-2.9,8.4
h-1.2l-2.9-8.5v8.5H306.4z"/>
<path class="st8" d="M323.4,207.1c-0.5,0.4-0.9,0.7-1.3,0.8c-0.4,0.2-0.9,0.2-1.4,0.2c-0.8,0-1.4-0.2-1.8-0.6s-0.6-0.9-0.6-1.5
c0-0.4,0.1-0.7,0.2-1c0.2-0.3,0.4-0.5,0.6-0.7c0.3-0.2,0.6-0.3,0.9-0.4c0.2-0.1,0.6-0.1,1.1-0.2c1-0.1,1.7-0.3,2.2-0.4
c0-0.2,0-0.3,0-0.3c0-0.5-0.1-0.9-0.3-1.1c-0.3-0.3-0.8-0.4-1.4-0.4s-1,0.1-1.3,0.3c-0.3,0.2-0.5,0.6-0.6,1.1l-1.2-0.2
c0.1-0.5,0.3-0.9,0.5-1.2c0.3-0.3,0.6-0.6,1.1-0.7c0.5-0.2,1-0.3,1.6-0.3c0.6,0,1.1,0.1,1.5,0.2c0.4,0.1,0.7,0.3,0.9,0.6
c0.2,0.2,0.3,0.5,0.4,0.8c0,0.2,0.1,0.6,0.1,1.1v1.6c0,1.1,0,1.9,0.1,2.2c0.1,0.3,0.2,0.6,0.3,0.9h-1.3
C323.5,207.8,323.4,207.5,323.4,207.1z M323.3,204.4c-0.4,0.2-1.1,0.3-2,0.5c-0.5,0.1-0.9,0.2-1.1,0.2c-0.2,0-0.4,0.2-0.5,0.4
c-0.1,0.2-0.2,0.4-0.2,0.6c0,0.3,0.1,0.6,0.4,0.8c0.2,0.2,0.6,0.3,1.1,0.3s0.9-0.1,1.3-0.3c0.4-0.2,0.6-0.5,0.8-0.9
c0.1-0.3,0.2-0.7,0.2-1.2V204.4L323.3,204.4z"/>
<path class="st8" d="M327.1,199.4V198h1.2v1.4H327.1z M327.1,208v-7.3h1.2v7.3H327.1z"/>
<path class="st8" d="M330.9,208v-7.3h1.1v1c0.5-0.8,1.3-1.2,2.3-1.2c0.4,0,0.8,0.1,1.2,0.2c0.4,0.2,0.6,0.4,0.8,0.6
c0.2,0.2,0.3,0.6,0.4,0.9c0,0.2,0.1,0.6,0.1,1.2v4.5h-1.2v-4.4c0-0.5,0-0.9-0.1-1.1c-0.1-0.2-0.3-0.4-0.5-0.6
c-0.2-0.1-0.5-0.2-0.9-0.2c-0.5,0-1,0.2-1.4,0.5c-0.4,0.3-0.6,1-0.6,1.9v4H330.9z"/>
</g>
</g>
<g>
<path class="st7" d="M547.5,849.4h96.2v50h-96.2V849.4z"/>
<g>
<path class="st8" d="M580.4,880.5v-10h2l2.4,7.1c0.2,0.7,0.4,1.2,0.5,1.5c0.1-0.4,0.3-0.9,0.5-1.6l2.4-7h1.8v10h-1.3v-8.4
l-2.9,8.4h-1.2l-2.9-8.5v8.5H580.4z"/>
<path class="st8" d="M597.4,879.6c-0.5,0.4-0.9,0.7-1.3,0.8c-0.4,0.2-0.9,0.2-1.4,0.2c-0.8,0-1.4-0.2-1.8-0.6
c-0.4-0.4-0.6-0.9-0.6-1.5c0-0.4,0.1-0.7,0.2-1c0.2-0.3,0.4-0.5,0.6-0.7c0.3-0.2,0.6-0.3,0.9-0.4c0.2-0.1,0.6-0.1,1.1-0.2
c1-0.1,1.7-0.3,2.2-0.4c0-0.2,0-0.3,0-0.3c0-0.5-0.1-0.9-0.3-1.1c-0.3-0.3-0.8-0.4-1.4-0.4c-0.6,0-1,0.1-1.3,0.3
c-0.3,0.2-0.5,0.6-0.6,1.1l-1.2-0.2c0.1-0.5,0.3-0.9,0.5-1.2c0.3-0.3,0.6-0.6,1.1-0.7c0.5-0.2,1-0.3,1.6-0.3s1.1,0.1,1.5,0.2
c0.4,0.1,0.7,0.3,0.9,0.6c0.2,0.2,0.3,0.5,0.4,0.8c0,0.2,0.1,0.6,0.1,1.1v1.6c0,1.1,0,1.9,0.1,2.2c0.1,0.3,0.2,0.6,0.3,0.9h-1.3
C597.5,880.3,597.4,880,597.4,879.6z M597.3,876.9c-0.4,0.2-1.1,0.3-2,0.5c-0.5,0.1-0.9,0.2-1.1,0.2s-0.4,0.2-0.5,0.4
c-0.1,0.2-0.2,0.4-0.2,0.6c0,0.3,0.1,0.6,0.4,0.8c0.2,0.2,0.6,0.3,1.1,0.3s0.9-0.1,1.3-0.3c0.4-0.2,0.6-0.5,0.8-0.9
c0.1-0.3,0.2-0.7,0.2-1.2V876.9L597.3,876.9z"/>
<path class="st8" d="M601.1,871.9v-1.4h1.2v1.4H601.1z M601.1,880.5v-7.3h1.2v7.3H601.1z"/>
<path class="st8" d="M604.9,880.5v-7.3h1.1v1c0.5-0.8,1.3-1.2,2.3-1.2c0.4,0,0.8,0.1,1.2,0.2c0.4,0.2,0.6,0.4,0.8,0.6
c0.2,0.2,0.3,0.6,0.4,0.9c0,0.2,0.1,0.6,0.1,1.2v4.5h-1.2V876c0-0.5,0-0.9-0.1-1.1c-0.1-0.2-0.3-0.4-0.5-0.6
c-0.2-0.1-0.5-0.2-0.9-0.2c-0.5,0-1,0.2-1.4,0.5c-0.4,0.3-0.6,1-0.6,1.9v4H604.9z"/>
</g>
</g>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.2.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Lager_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 800 458" style="enable-background:new 0 0 800 458;" xml:space="preserve">
<style type="text/css">
.st0{fill:none;stroke:#404040;stroke-width:4;stroke-miterlimit:10;}
.st1{fill:#B18BE8;stroke:#404040;stroke-width:4;stroke-miterlimit:10;}
.st2{fill:#4ED1A1;stroke:#404040;stroke-width:4;stroke-miterlimit:10;}
.st3{fill:#B3E3FF;stroke:#404040;stroke-width:4;stroke-miterlimit:10;}
.st4{fill:#B18BE8;stroke:#404040;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
.st5{fill:#404040;}
.st6{fill:#4ED1A1;stroke:#404040;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
.st7{fill:none;stroke:#404040;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
.st8{fill:#B3E3FF;stroke:#404040;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
.st9{fill:#414141;}
</style>
<path class="st0" d="M148.2,187.3c0,22.6-18.4,41-41,41 M148.2,187.3c0-22.6,18.4-41,41-41h22.4"/>
<circle class="st1" cx="232.6" cy="146.3" r="21"/>
<path class="st0" d="M428.9,269.3c0-22.6-18.4-41-41-41 M428.9,269.3c0,22.6,18.4,41,41,41h214.4"/>
<circle class="st2" cx="513.2" cy="310.3" r="21"/>
<circle class="st2" cx="609.2" cy="310.3" r="21"/>
<circle class="st2" cx="705.2" cy="310.3" r="21"/>
<path class="st3" d="M75.2,228.3h417"/>
<circle class="st3" cx="54.2" cy="228.3" r="21"/>
<circle class="st3" cx="231.6" cy="228.3" r="21"/>
<circle class="st3" cx="328.6" cy="228.3" r="21"/>
<circle class="st3" cx="513.2" cy="228.3" r="21"/>
<path class="st4" d="M166,5.1h133.1v50H166V5.1z"/>
<path class="st5" d="M184.3,36.1V25.5h1.5v9.3h5v1.4h-6.5V36.1z M193.8,25.2c0.6,0,1,0.4,1,1s-0.4,1-1,1s-1-0.5-1-1
C192.8,25.6,193.3,25.2,193.8,25.2z M193.1,36.1v-7.2h1.4v7.2H193.1z M199.6,28.9h1.6v1.3h-1.6V34c0,0.7,0.3,1,1,1
c0.2,0,0.4,0,0.6-0.1v1.2c-0.1,0-0.5,0.1-1,0.1c-1.2,0-2-0.8-2-2.1v-4h-1.4v-1.3h0.4c0.8,0,1.1-0.5,1.1-1.1v-1.2h1.3L199.6,28.9
L199.6,28.9z M205.6,28.9h1.6v1.3h-1.6V34c0,0.7,0.3,1,1,1c0.2,0,0.4,0,0.6-0.1v1.2c-0.1,0-0.5,0.1-1,0.1c-1.2,0-2-0.8-2-2.1v-4
h-1.4v-1.3h0.4c0.8,0,1.1-0.5,1.1-1.1v-1.2h1.3L205.6,28.9L205.6,28.9z M209.8,36.1V25.3h1.4v10.9L209.8,36.1L209.8,36.1z
M220.7,34.1c-0.4,1.3-1.6,2.3-3.2,2.3c-1.9,0-3.6-1.4-3.6-3.9c0-2.3,1.6-3.8,3.4-3.8c2.2,0,3.5,1.5,3.5,3.8v0.4h-5.4
c0,1.3,1,2.2,2.2,2.2s1.8-0.6,2-1.5L220.7,34.1z M219.3,31.8c0-1-0.7-1.8-2-1.8c-1.2,0-1.9,0.9-2,1.8H219.3z M227.9,36.1V25.5h6.5
v1.4h-5v3.4h4.5v1.4h-4.5v4.5L227.9,36.1L227.9,36.1z M242.5,34.1c-0.4,1.3-1.6,2.3-3.2,2.3c-1.9,0-3.6-1.4-3.6-3.9
c0-2.3,1.6-3.8,3.4-3.8c2.2,0,3.5,1.5,3.5,3.8v0.4h-5.4c0,1.3,1,2.2,2.2,2.2s1.8-0.6,2-1.5L242.5,34.1z M241.1,31.8
c0-1-0.7-1.8-2-1.8c-1.2,0-1.9,0.9-2,1.8H241.1z M246.9,32l1.9-0.3c0.4-0.1,0.6-0.3,0.6-0.5c0-0.7-0.5-1.3-1.6-1.3
c-1,0-1.5,0.6-1.6,1.5l-1.4-0.3c0.2-1.4,1.4-2.3,3-2.3c2.2,0,3,1.2,3,2.6V35c0,0.6,0.1,1,0.1,1.2h-1.4c0-0.2-0.1-0.5-0.1-1
c-0.3,0.5-1,1.2-2.3,1.2c-1.5,0-2.4-1-2.4-2.2C244.7,32.9,245.6,32.2,246.9,32z M249.4,33.1v-0.3l-2.2,0.3c-0.6,0.1-1,0.4-1,1.1
c0,0.5,0.4,1,1.2,1C248.5,35.2,249.4,34.6,249.4,33.1z M255.6,28.9h1.6v1.3h-1.6V34c0,0.7,0.3,1,1,1c0.2,0,0.4,0,0.6-0.1v1.2
c-0.1,0-0.5,0.1-1,0.1c-1.2,0-2-0.8-2-2.1v-4h-1.4v-1.3h0.4c0.8,0,1.1-0.5,1.1-1.1v-1.2h1.3V28.9z M262.4,36.4
c-1.7,0-2.7-1.3-2.7-2.9V29h1.4v4.3c0,1,0.4,1.9,1.6,1.9c1.1,0,1.7-0.8,1.7-1.8V29h1.4v5.9c0,0.6,0,1.1,0.1,1.3h-1.4
c0-0.2-0.1-0.6-0.1-0.9C264.2,36,263.3,36.4,262.4,36.4z M273.1,30.4h-0.6c-1.2,0-2,0.6-2,2.2v3.6h-1.4V29h1.4v1.3
c0.5-1.1,1.4-1.4,2.2-1.4h0.5v1.5L273.1,30.4z M281.5,34.1c-0.4,1.3-1.6,2.3-3.2,2.3c-1.9,0-3.6-1.4-3.6-3.9c0-2.3,1.6-3.8,3.4-3.8
c2.2,0,3.5,1.5,3.5,3.8v0.4h-5.4c0,1.3,1,2.2,2.2,2.2s1.8-0.6,2-1.5L281.5,34.1z M280.1,31.8c0-1-0.7-1.8-2-1.8
c-1.2,0-1.9,0.9-2,1.8H280.1z"/>
<path class="st6" d="M643.6,401.4h123.2v50H643.6V401.4z"/>
<path class="st5" d="M668.1,421.7c2,0,3.2,1.2,3.2,2.9c0,1.1-0.7,2-1.6,2.3c1.2,0.3,1.9,1.4,1.9,2.6c0,1.7-1.3,2.9-3.3,2.9h-3.7
v-10.6L668.1,421.7L668.1,421.7z M667.9,426.4c1.2,0,1.9-0.7,1.9-1.7s-0.7-1.7-1.9-1.7h-1.8v3.4L667.9,426.4L667.9,426.4z
M668.2,431.1c1.2,0,2-0.7,2-1.7s-0.6-1.7-1.9-1.7h-2.1v3.4L668.2,431.1L668.2,431.1z M675,421.4c0.6,0,1,0.4,1,1s-0.4,1-1,1
s-1-0.5-1-1C674,421.8,674.4,421.4,675,421.4z M674.3,432.4v-7.2h1.4v7.2H674.3z M679.7,432.4c0.1,1,0.9,1.8,2,1.8
c1.5,0,2.2-0.8,2.2-2.3v-1c-0.3,0.7-1.1,1.2-2.2,1.2c-1.9,0-3.3-1.5-3.3-3.5c0-1.9,1.3-3.5,3.3-3.5c1.1,0,1.9,0.4,2.2,1.1v-1h1.4
v6.7c0,1.8-0.9,3.6-3.6,3.6c-1.8,0-3.1-1.1-3.3-2.7L679.7,432.4L679.7,432.4z M683.9,428.5c0-1.4-0.8-2.3-2.1-2.3
c-1.2,0-2.1,0.9-2.1,2.3s0.8,2.3,2.1,2.3C683,430.8,683.9,429.9,683.9,428.5z M692.9,432.4v-10.6h6.5v1.4h-5v3.4h4.5v1.4h-4.5v4.5
L692.9,432.4L692.9,432.4z M707.5,430.3c-0.4,1.3-1.6,2.3-3.2,2.3c-1.9,0-3.6-1.4-3.6-3.9c0-2.3,1.6-3.8,3.4-3.8
c2.2,0,3.5,1.5,3.5,3.8v0.4h-5.4c0,1.3,1,2.2,2.2,2.2s1.8-0.6,2-1.5L707.5,430.3z M706.1,428c0-1-0.7-1.8-2-1.8
c-1.2,0-1.9,0.9-2,1.8H706.1z M711.8,428.2l1.9-0.3c0.4-0.1,0.6-0.3,0.6-0.5c0-0.7-0.5-1.3-1.6-1.3c-1,0-1.5,0.6-1.6,1.5l-1.4-0.3
c0.2-1.4,1.4-2.3,3-2.3c2.2,0,3,1.2,3,2.6v3.6c0,0.6,0.1,1,0.1,1.2h-1.4c0-0.2-0.1-0.5-0.1-1c-0.3,0.5-1,1.2-2.3,1.2
c-1.5,0-2.4-1-2.4-2.2C709.7,429.1,710.6,428.4,711.8,428.2L711.8,428.2z M714.4,429.3V429l-2.2,0.3c-0.6,0.1-1.1,0.4-1.1,1.1
c0,0.5,0.4,1,1.2,1C713.4,431.4,714.4,430.8,714.4,429.3z M720.6,425.1h1.6v1.3h-1.6v3.8c0,0.7,0.3,1,1,1c0.2,0,0.4,0,0.6-0.1v1.2
c-0.1,0-0.5,0.1-1,0.1c-1.2,0-2-0.8-2-2.1v-4h-1.4V425h0.4c0.8,0,1.1-0.5,1.1-1.1v-1.2h1.3L720.6,425.1L720.6,425.1z M727.4,432.6
c-1.7,0-2.7-1.3-2.7-2.9v-4.5h1.4v4.3c0,1,0.4,1.9,1.6,1.9c1.1,0,1.7-0.8,1.7-1.8v-4.4h1.4v5.9c0,0.6,0,1.1,0.1,1.3h-1.4
c0-0.2-0.1-0.6-0.1-0.9C729.1,432.2,728.2,432.6,727.4,432.6z M738,426.6h-0.6c-1.2,0-2,0.6-2,2.2v3.6H734v-7.2h1.4v1.3
c0.5-1.1,1.4-1.4,2.2-1.4h0.5v1.5H738z M746.5,430.3c-0.4,1.3-1.6,2.3-3.2,2.3c-1.9,0-3.6-1.4-3.6-3.9c0-2.3,1.6-3.8,3.4-3.8
c2.2,0,3.5,1.5,3.5,3.8v0.4h-5.4c0,1.3,1,2.2,2.2,2.2s1.8-0.6,2-1.5L746.5,430.3z M745.1,428c0-1-0.7-1.8-2-1.8
c-1.2,0-1.9,0.9-2,1.8H745.1z"/>
<path class="st7" d="M232.6,100.8V77.3 M243.4,92.1l-10.8,10.8l-10.9-10.8 M513.2,183v-23.5 M524.1,174.3l-10.9,10.8l-10.9-10.8
M705.2,355.7v23.5 M694.3,364.4l10.9-10.9l10.9,10.9"/>
<g>
<path class="st8" d="M463.9,86.8h96.2v50h-96.2V86.8z"/>
<g>
<path class="st9" d="M496.8,117.9v-10h2l2.4,7.1c0.2,0.7,0.4,1.2,0.5,1.5c0.1-0.4,0.3-0.9,0.5-1.6l2.4-7h1.8v10h-1.3v-8.4
l-2.9,8.4H501l-2.9-8.5v8.5H496.8z"/>
<path class="st9" d="M513.8,117c-0.5,0.4-0.9,0.7-1.3,0.8c-0.4,0.2-0.9,0.2-1.4,0.2c-0.8,0-1.4-0.2-1.8-0.6
c-0.4-0.4-0.6-0.9-0.6-1.5c0-0.4,0.1-0.7,0.2-1c0.2-0.3,0.4-0.5,0.6-0.7c0.3-0.2,0.6-0.3,0.9-0.4c0.2-0.1,0.6-0.1,1.1-0.2
c1-0.1,1.7-0.3,2.2-0.4c0-0.2,0-0.3,0-0.3c0-0.5-0.1-0.9-0.3-1.1c-0.3-0.3-0.8-0.4-1.4-0.4c-0.6,0-1,0.1-1.3,0.3
c-0.3,0.2-0.5,0.6-0.6,1.1l-1.2-0.2c0.1-0.5,0.3-0.9,0.5-1.2c0.3-0.3,0.6-0.6,1.1-0.7c0.5-0.2,1-0.3,1.6-0.3s1.1,0.1,1.5,0.2
s0.7,0.3,0.9,0.6c0.2,0.2,0.3,0.5,0.4,0.8c0,0.2,0.1,0.6,0.1,1.1v1.6c0,1.1,0,1.9,0.1,2.2s0.2,0.6,0.3,0.9h-1.3
C513.9,117.7,513.8,117.4,513.8,117z M513.7,114.3c-0.4,0.2-1.1,0.3-2,0.5c-0.5,0.1-0.9,0.2-1.1,0.2c-0.2,0-0.4,0.2-0.5,0.4
c-0.1,0.2-0.2,0.4-0.2,0.6c0,0.3,0.1,0.6,0.4,0.8c0.2,0.2,0.6,0.3,1.1,0.3s0.9-0.1,1.3-0.3c0.4-0.2,0.6-0.5,0.8-0.9
c0.1-0.3,0.2-0.7,0.2-1.2V114.3L513.7,114.3z"/>
<path class="st9" d="M517.5,109.3v-1.4h1.2v1.4H517.5z M517.5,117.9v-7.3h1.2v7.3H517.5z"/>
<path class="st9" d="M521.3,117.9v-7.3h1.1v1c0.5-0.8,1.3-1.2,2.3-1.2c0.4,0,0.8,0.1,1.2,0.2c0.4,0.2,0.6,0.4,0.8,0.6
s0.3,0.6,0.4,0.9c0,0.2,0.1,0.6,0.1,1.2v4.5H526v-4.4c0-0.5,0-0.9-0.1-1.1s-0.3-0.4-0.5-0.6c-0.2-0.1-0.5-0.2-0.9-0.2
c-0.5,0-1,0.2-1.4,0.5s-0.6,1-0.6,1.9v4H521.3L521.3,117.9z"/>
</g>
</g>
</svg>
images/git-commit.png

25.6 KiB

images/git-create-branch.png

16.2 KiB

images/git-merge-1.png

17 KiB

0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment