##Installing Git ###Linux On debian based systems ```bash apt-get install git ``` Latest stable upstream git version ```bash add-apt-repository ppa:git-core/ppa apt update apt install git ``` ###Windows Go to the following links: - https://git-scm.com/download/win - https://gitforwindows.org/ Launch exe file. To check version or existance of the git in system ```bash git --version ``` Check global settings ```bash git config --list ``` To start working with git we need to set several global variables ```bash git config --global user.name "your_name" git config --global user.email "your_email" ``` To get the manual for the command ```bash git help command git command --help ``` To create a repository and start tracking files got to the directory you want to track and use next command ```bash git init ``` To check the status of the tracked files ```bash git status ``` ###Working with remote We can clone existing repository (remote or on the same machine) ```bash git clone <url> <where_to_clone> ``` To get information about remote repositories ```bash git remote ``` This command will show list of remote handles that have been specified. To show also the links of remote repositories use `-v` flag. ```bash git remote -v ``` By default remote handle has name `origin`. It is done automaticaly by using `clone` command. But you can create local git repository manually by `git init` and add remote repository manually. ```bash git remote add name-of-handle url --- example --- git remote add origin https://github.com/someproj ``` To get more information about remote repository ```bash git remote show name-of-handle --- example --- git remote show origin ``` No we are able to download all new information from remote repository. ```bash git fetch name-of-handle --- example --- git fetch origin ``` After it we will have all the branches from remote project. __Important to note that `fetch` command only downloads changes from remote repository. It does not merge with any of your local branches and does not make any changes to your local work__. When `clone` command is used git also set up your current branch to track the remote branch so you can use `pull` command. ```bash git pull name-of-handle branch-name --- example --- git pull origin master ``` This command will download changes and merge remote branch with your local branch. If `clone` was used no additional moves required. Otherwise we need to set it up manually. ```bash git branch -u name-of-remote-branch --- example --- git branch -u origin/master ``` Or if your local branch is not current branch ```bash git branch -u name-of-remote-branch name-of-local-branch --- example --- git branch -u origin/master testbranch ``` Also we can checkout remote branch. After it local branch will be created and set up for tracking remote branch. ```bash git checkout name-of-remote-branch --- example --- git checkout origin/master ``` May be a problem when pulling info from remote branch due to unrelated histories. So use `--allow-unrelated-histories` flag when pulling. ```bash git pull --allow-unrelated-histories ``` To rename remote repository ```bash git remote rename current-name new-name --- example --- git remote rename origin pb ``` If you want to stop tracking remote repository ```bash git remote remove name-of-handle --- example --- git remote remove origin ``` This command will fetch changes from remote repository for specified branch and merge it with local branch. ##Tracking files If we dont want some files to be tracked we can create special file with the name of `.gitignore`. Here we can specify filenames, folder names, file extenstions that we dont want to track. `.gitignore` file has to exist near `.git` folder. ```bash touch .gitignore echo *.pyc >> .gitignore ``` Now files with extension *.pyc are ignored by git To record changes in the file ```bash git add filename ``` If we now check the status ```bash git status ``` Added file will be marked with green color. This means this file is in `staging` area. Also there are several ways of using `git add` command. [Image Name 1]:https://secretnotes.space/articleimage?id=157 ![Image Name 1] ##Git add specifics First flag is `-A` or `--all`. This flag will stage all changes made in entire working tree (deleted files, modified files,created files in current, upper and subdirectories except those files and folders specified in `.gitignore` file). Even if u run `git add -A` from the subdirectory entire working tree will be staged despite the fact that some files or folders were upper in the path. ```bash git add -A git add --all ``` Also it can be used with argument. For example if we want to stage only one folder ```bash git add -A folder/ git add --all folder/ ``` `git add -A` or `git add --all` is a default behaviour for the `git add` command. So we can it can be used next way ```bash git add file git add folder/ --- for example --- git add main.py git add src/ ``` There is a flag `--no-all` or `--ignore-removal` that does not track deleted files.This command stages created files, modified files but no deleted files. ```bash git add --no-all folder/ git add --ignore-removal folder/ ``` Another flag is `-u` or `--update`. With the help of this flag git stages modified and deleted files for the whole working tree but no untracked files (new files) ```bash git add -u git add --update ``` Without argument this command will work for the whole working tree. Or we can specify folder as argument. ```bash git add -u folder/ git add --update folder/ ``` As the argument we can specify `.`. This will work only for current directory. It does not work for the whole working tree. It is similar to calling `git add -A` as long as you are in the top directory. But if you are in the subdirectory __git will not stage files in the upper direcotries__. One more possible argument is `*`. It is a shell command. If we specify it as a git add argument git will stage all files in the current directory and subdirectories except deleted (not allways) and hidden files. Also git will not stage files in the upper directories. ```bash git add * git add * folder/ ``` To remove file from staging area we can use `reset` command ```bash git reset file ``` If it is used without arguments git will remove all files from staging area. ```bash git reset ``` If files are in the staging area they can be commited ```bash git commit -m "Some comment" ``` To check the history of commits ```bash git log ``` To see what files were changed in latest commit ```bash git log --stat ``` For the each commit we can see commit hash, branch, author, date and message. ##Branches To list all branches (including remote) ```bash git branch -a ``` To create branch ```bash git branch name-of-the-branch ``` To list all local branches ```bash git branch ``` To change current branch ```bash git checkout name-of-the-branch ``` If we make changes in other branch it has no effect on the main (master) branch. We can push it to the remote repository but remote repository may not have branch that we have created. To create new branch in the remote repo ```bash git push -u origin name-of-the-new-branch ``` After this command branch will be created in the remote repo. Sooner or later branches are merged with each other, ussually side branch are merged with main. To do this we have to swith to the main branch (usually master branch) ```bash git checkout master ``` With the help of next command we can check all branches that were merged into the branch we are currently on. ```bash git branch --merged ``` Then merge with created branch ```bash git merge name-of-the-other-branch ``` If there are no conflicts merge will run successfully. Now we can push changes from master branch to remote repository. ```bash git push origin master ``` __It is a good practise to to `git pull` before pushing changes to remote repository. Someone could do changes to the repository when you was working on your part__. Now after changes from side branch were merged with main branch we dont need the side branch. We can delete it. ```bash git branch -d name-of-the-branch ``` To delete remote branch ```bash git push origin --delete name-of-the-branch ``` To see what have changed in files from the last commit ```bash git diff ``` ##Git commit specifics As was mentioned before to commit changes they have to be in staging area. We can check it with `git status`. To commit changes `git commit` is used ```bash git commit -m "Comment" ``` If mistake was made in latest commit message we can fix it without undoing latest commit. ```bash git commit --amend -m "New Message" ``` If we forgot to add some file to the staging area and commited it we are still able to add files we need in the latest commit. ```bash git add file-or-files-we-need ``` Now use `git commit` with `--amend` flag ```bash git commit --amend ``` Files that we added to staging area will be commited to the latest commit without creating a new one. `--amend` __flag rewrites the histroy of git commits__. It may not be the best idea if several people are working with one remote repository. If we want to undo some changes in one of the commits without changing git history we can use `revert` command. To do this we need to know commit hash which we can find out with the help of `git log`. ```bash git revert hash-of-the-commit ``` It will create a new commit that fully cancels another commit and everyone will be able to pull it. `revert` __does not change git commit history__. If we made changes and commited them to the wrong branch we can use `git cherry-pick` to create new commits based on other commits that exist in other branch. To create new commit based on other we need to know hash of the commit. To find out it we can use `git log` command. After getting hash of the commit change the branch. ```bash git branch branch-we-need ``` Now create a new commit based on original ```bash git cherry-pick hash-of-the-commit ``` After running this command new commit will be created and added to git history. Files also will be changed. Original commit on the other branch will not disappear so we can reset that branch to the state we need. ##Git reset specifics There are 3 types of reset: - Soft - Mixed (default) - Hard __Soft__ - Resets all tracked files to the staging area of specified commit. ```bash git reset --soft hash-of-the-commit ``` Tracked files are in staging area (Green) but not yet commited. We are ready to make commit. __Mixed (default)__ - Resets all tracked files to the working directory of specified commit. ```bash git reset --mixed hash-of-the-commit --- or --- git reset hash-of-the-commit ``` Tracked files are in working directory (Red) but not yet commited. In order to make commit we need to add it and then commit. __Hard__ - Resets all tracked files to the specified commit. File content is also changed. This command reverts all the tracked files but it does not touch untracked files. ```bash git reset --hard hash-of-the-commit ``` Now don\`t have changes in working directory. Files are in the same state as in latest commit. To get rid of untracked files ```bash git clean -df ``` We can use `git reset` without arguments. ```bash git reset --soft --- or --- git reset --mixed --- or --- git reset --- or --- git reset --hard ``` In this case git will reset all files to the latest commit. We can also provide `git reset` with filepath argument. In these case `--soft` and `--hard` flags will not work. Only `--mixed` flag will work with filepath and because it is default we have no need to provide it. ```bash git reset --mixed filepath --- or --- git reset filepath ``` This command will do oposite to adding file. File that was added before will be moved from staging area to the working directory (In git status file will change color from green to red) but content of the file will not be changed. Also we can provide a folder name as an argument ```bash git reset --mixed folder --- or --- git reset folder --- or current folder --- git reset . --- or --- git reset --mixed . ``` In this case operation will be done with files in folder. Using `--soft` flag with reset command on the filepath or folder has no point because it reverts files from commited state to the staging area where we usually call `reset` command. But if we want to make full reset on the file or files in some folder with changing its content back we can\`t use `git reset --hard filepath-or-folder`. Analogue to this command is ```bash git checkout HEAD filepath-or-folder-name --- or --- git checkout HEAD -- filepath-or-folder-name ``` This command will change the contents of the file to the state it was in the latest commit. `--` strings specifies that we work with file but not branch (in case we have a file in working directory with the same name as one of the branches). If file was changed but was not added to staging area we can reset file with the help of next command. ```bash git checkout filepath-or-folder-name --- or --- git checkout -- filepath-or-folder-name ``` File will be changed to the state of the latest staging area state. (Will work only if changes in git status are red). ##Git stash Great for changes that you are not ready to commit. You can save changes in the specific area. ```bash git stash save "comment" ``` After saving them as stash all the changes will revert to the last commit. Stuff that we worked on will be in stash. To check stash ```bash git stash list ``` To change files to the state they were in stash ```bash git stash apply id --- example --- git stash apply stash@{0} ``` After changes were applied from stash we still have stash record in the list. To apply changes from latest stash record and delete it ```bash git stash pop ``` To delete stash record without applying it ```bash git stash drop id --- example --- git stash drop stash@{1} ``` To remove all stash saves ```bash git stash clear ``` __Git stash works between branches. You can save stash in one branch and apply it in the other branch.__ ##Git reflog There is a story of git commands. To check it ```bash git reflog ``` Here we can find hashes of operations in git. To revert to some point ```bash git revert hash-of-operation ``` Now we are in deteched branch (HEAD). We can check it. ```bash git branch ``` Our working directory is in state right after that commit was made. To save changes from HEAD to branch just create new branch and switch to it. ```bash git branch new-branch git checkout new-branch ```