--- GIT TUTORIAL 2020-T --- BEFORE YOU START: Correct -> HEAD IS A POINTER TO YOUR CURRENT WORKSPACE LOCATION That is HEAD will always point to the current branch you're working at. MASTER is the current/main branch you'll be using for your project. COMMITS are literal reference points for each commited changes you've made in your project. File Update/Insertion/Removal (also, 'git add' and 'git rm') inside the MASTER Branch blocks you from switching to other branches, until modifications are actually COMMITED - that's unless you're in other branches. VERY IMPORTANT: Take note that GIT uses a global buffer for implementing non-commited changes made to files called INDEX, so when you move between branches/heads, you're taking the INDEX to whatever branches you are moving from/to, until you 'git commit -m "Commit Name"' those changes, only then it turns these changes from global to local modifications within that specific branch(aka.: where your current HEAD is point at). Further More.: Index is a view of your working directory that is ready for commit. It can be seen as a pre-commit state and is not as simple as a "list of files". When you do git add, the file (with the change) is added to the index and the newer changes will not be see until you add them too. Note.: INDEX/Staging Area are the same thing! Also, note that GIT is a DVCS - Distributed Version Controlling Software, that means each user has it's own repo and it's own working area. VCS - Versionning Control Software only has 1 main repository, and each user has it's own working area. Git was made by Linus Trovalids read more about Checking WORKING AREA, STAGING AREA, HEAD VERY IMPORTANT: Staging Area are the files being staged by GIT! The Working Area are the modifications being done to the Staging Area. ex.: "git diff" will only show differences between commits for the Working Areas, it'll however show no issues whether new_files are or not on the STAGING AREA. THEREFORE The Staging area and Working Area are different things! ----------------- BEFORE YOU CONTINUE: On linux, you can get easy git documentation by typing: $man git-log ^ this will allow you check manual pages on git log command, which would be the same as doing: $git help log There's also a good GIT GUI Client called git-tower: https://www.git-tower.com/ GIT EXERCISES: https://gitexercises.fracz.com/committer/ny4 ---- EXERCISES SOLUTION: Exercise 7: git rebase ***-bugfix manual: https://www.benmarshall.me/git-rebase/ https://git-scm.com/docs/git-rebase ----------------- Working Area, Staging Area, Head Area: seus repositórios locais consistem em três "árvores" mantidas pelo git. a primeira delas é sua Working Directory que contém os arquivos vigentes. a segunda Index que funciona como uma área temporária e finalmente a HEAD que aponta para o último commit (confirmação) que você fez. Working Area, Staging Area, Repository: The Working Area: It's the Area that currently holds all your physical files you're currently working with in the current branch. The Staging Area: It's a Memory Buffer Area that holds all file modifications/insertions you've done so at the moment. Moving to a different branch will also move the Staging Area with the same modified/inserted files from the branch before. Which will need to be either commited or dropped. The Repository Area: Whenever you type 'git commit -m "MyCommit"' you're applying the changes in the staging area to the the Repo. -- NEEDS TO CHECK To summon it up, this is how it goes: GIT ADD will add changes made to the 'Working Area' to the 'Staging Area' GIT COMMIT will add changes made to the 'Staging Area' to the 'Repository Area' GIT CHECKOUT -- file will remove changes made to the Working Area FROM the Staging Area and UNDO them - BEFORE THEY ARE COMMITED GIT RESET will undo changes made to the Working Area from the Repository Area AFTER they've ALREADY been commited to the Repository Area Example: typing 'git diff' will show all diferences between the Working Area and the Staging Area 'git diff --staged' will show differences between The Staging Area and the Repo Area. 'git diff ' will show differences between Different Repos Importante Notes: On Git branches are just a reference for a commit ---IMPORTANT GIT LOG NOTES---- git log --onoline --decorate *you can type cat .git/HEAD to show where you actually are *HEAD == WHERE YOU ARE *switching branches will switch the files at the Workspace Area *git log #shows all commits - check *git log --all #shows commits that are ahead of that branch normally 'git log' only shows commits done up to that moment that the branch was located. *git log --oneline --graph #shows divergence between branches. example: when you have made modifications/merges in different branches this will make git show divergences/merges between branches. git log --graph *Fixing Merge Conflicts:(GIT MERGE & GIT MERGE --ABORT) What happens when you make modifications on the same file at different branches and then try to merge? git will warn you about conflict, and SET THE WORKING AREA with the conflictuous file(s) - note.: if merge runs without conflict, there is neither files to be added nor commits - then you can just open the file in a normal text editor and edit it to fix the conflicts. After that's done you can finally add the modifications done into the Working Area to the Staging Area with 'git add ' and then commit the modifications to the Repository Area with ' commit -m <"commitname"> '. Alternatively you can drop modifications with 'git merge --abort' to abort merge. The second syntax ("git merge --abort") can only be run after the merge has resulted in conflicts. git merge --abort will abort the merge process and try to reconstruct the pre-merge state FILE STATUS LIFECYLE: There are 4 File Status: 1 - Untracked When files are added to the Working Area, but are not being Tracked. using 'git add ' will start tracking them, adding them to the Unmodified Status. When files are Untracked, git will not touch them when moving between branches or commits! they'll be left untouched by git's engine! - VERY IMPORTANT 2 - Unmodified Files are kept as unmodified status after being tracked, editing a file will turn them to Modified Status. Renaming/Moving a file will set them as have been deleted. And the Renamed/Moved file will be set as untracked. Same thing happens if files get Renamed/Moved AFTER being Modified. *After the files have been moved/rename, undoing changes will require the 'old' file to be 'git checkout -- ' and the new files to be manually deleted. 3 - Modified After files are being tracked and get some modification through editing, they receive a Modified Status, these files will require to be added to the Staging Area with 'git add ', thus turning them into the Staged Status. 4 - Staged Staged Status is the final step in the File Status Lifecycle of GIT before they are finally commited to the Repository, thus making permanent changes. to move a file from the Staging Area(staged status), all that's needed is to make a commit 'git commit -m <"commitname">'. http://thomascgreen.com/tech/?p=7 https://latedreamer.blogspot.com/2016/11/working-directory-staging-area.html ----------------------------- *Note, some of the description bellows need to be updated with the Staging Area Eplanation git --help or man git git help config #gets help about configuration git config --global user.name "Your Name" git config --global user.email "Email Address" git config --list git config --global core.editor nvim #sets nvim as main text editor for git git init #Initilizaes empty Git repository in .git/ creates a .git folder inside the workspace directory - creates a git repository ex.: ~/MyGitProject/ by typing 'git init' makes it starts a new repo on it on a hidden .git folder git add #This command updates the INDEX using the current content found in the working tree ^ before commiting those changes. #a 2nd 'git add' to an already added file, allows to save unmodified ^ files onto the repo. git add * #Recursively adds all files to the INDEX(Staging Area) git add . #Same as above git add Documentation/\*.txt #Adds all .txt files under that directory to the INDEX(Staging Area) git add git-*.txt #Adds all files that start with git- and ends with .txt to the INDEX(Staging Area) (note.: all files under the Staging Area will need to be commited) git restore --staged B.txt #Removes B.txt from the Staging Area git ls-remote #List references in a remote repository along with the associated commit IDs --- HOW TO IGNORE FILES FROM BEING TRACKED/UNTRACKED --- 1 - Create a file called .gitignore, 2 - Add the following content as follows: *.o *.jar *.exe libraries/ 3 - then add to the Staging Area: git add ./.gitignore 4 - finally commit it: git commit -m "IgnoringFiles" Source: https://git-scm.com/docs/gitignore ADVANCED COMMANDS: git log --graph --abbrev-commit --oneline --all --reflog #SHOWS ALL COMMITS -------------------------------------------------------- Study Source: https://www.w3schools.com/git/ git status #Shows modified files, unmodified files, tracked, untracked, and staged files git log #Shows all commits that have been done git log --oneline #Shows 1 commit per line git reflog #Shows all commits, INCLUDING branch merge commits - VERY IMPORTANT git reflog #Shows all Heads git branch #Shows all branches git branch -d #Deletes Branch / Removes Branch git checkout -b #Creates branch from current commit or commit_id git commit #Opens default text editor for both: naming commit and choosing files to commit git commit -a #Commit current work with an editor git commit -m "Commit 1" #Commmits all currently added files, and names commit as "Commit 1" git commit -m "Commit 1" File1.txt #Commits changes made to File1.txt, names commit as "Commit 1" git commit [filename] -m "message" #Commits a single file in the current branch ^ you can check which files can be commited using git status git commit --amend -m "message" #Fixes/Reverts current head(previous commit) message(commit message) ^ on a remote repo, it'll be required to use git pull right afterwards ^ and make a new commit. git commit --amend #Allows to edit the current head(previous commit) without actually creating a new commit ^ Hint.: Modified files should be added with git add, and then git commit --ammend should be used to edit commit message git commit -a -m "Commit Message" #Git adds all files and creates a new commit / Makes a new commit git commit -a --amend #Git adds all file modifications and edits the last commit ^ Useful for changing/editing commits git commit -m "Message" #Commits changes to a given file. ^ VERY IMPORTANT: you can auto-complete directory/filenames using key ^ ex.: git commit ./source/Main ^ will auto-complete to: ./source/MainComponentes/StaggedFile.cpp git restore #Restores git working tree: reverses/undoes any change made to the working/staging area ^ VERY IMPORTANT: you can auto-complete directory/filenames using key ^ ex.: git restore ./source/Main ^ will auto-complete to: ./source/MainComponentes/StaggedFile.cpp git stash #Saves current working tree instead of reversing/undoing it, and stashes it away. git stash pop #Opens stash within current working tree for commiting. git stash list git stash help source: http://git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages git rm #removes a file from being Tracked AND DELETES IT SAFELY git rm -f #forcefully removes a file from being checked AND DELETES IT git rm --cached #removes a file from being checked, retainning the original file ^remove a file from being tracked with --cached flag, will also require file to be physically removed. git mv #Moves/renames files withing git git switch #Switches to a different branch git checkout - #Goes back to where previous HEAD was set git checkout -- #Discard changes from being made in the commit AND UNDOES them, setting them to their original previous state ^- Use in case File has been Modified/Updated Checkout only works for undoing changes in the staging area. git checkout #Sets HEAD into given branch git checkout #Goes back to the previous commit changes! git checkout -b #Turns all current work into a new Branch without commiting git branch -d #Deletes Branch / Removes Branch git revert #Pulls out any modification made by a given commit in such a way that it would be like if the commit has never happened. Avoid using this in public/remote repos. git reset #Resets the working space/staging area to that of the given commit ^This reset also sets all of the staging area from the given commit before the commit was realized. changes that have been made to the given commit, will also have to be "recommited" if you intend on keeping those changes ONLY. always checkout the changes with git diff after reset. git reset --hard #Undoes commits, Reverses Current Working Space to the one in the Given Commit State ^ if file has been forcibily removed, git checkout -- is needed. NOTE.: Checkout can't discard nor undo changes that already have been commited 'git reset' undoes changes made permanently - Need to check git reset --soft HEAD~1 #Undoes commit to the previous commit/HEAD state. ^ Does not touch the index file or the working tree at all (but resets the head to , just like all modes do). This leaves all your changed files "Changes to be committed", as git status would put it. git reset --hard HEAD~1 #Undoes commits and sets it to the previous commit_ID/HEAD state Resets the index and working tree. Any changes to tracked files in the working tree since are discarded. git reset --mixed HEAD~1 #DEFAULT BEHAVIOR: Resets the index but not the working tree (i.e., the changed files are preserved but not marked for commit) and reports what has not been updated. This is the default action. If -N is specified, removed paths are marked as intent-to-add (see git-add(1)). git reset --keep HEAD~1 #Resets index entries and updates files in the working tree that are different between and HEAD. If a file that is different between and HEAD has local changes, reset is aborted. in other words, reset only occurs if same existing files have no difference between them in the different commit_ID/HEAD States. git reset --merge HEAD~1 #Resets the index and updates the files in the working tree that are different between and HEAD, but keeps those which are different between the index and working tree (i.e. which have changes which have not been added). If a file that is different between and the index has unstaged changes, reset is aborted. In other words, --merge does something like a git read-tree -u -m , but carries forward unmerged index entries. (note.: check man pages for actual examples -> $man git-reset) git stash #Saves all uncommited work, for committing later on any branch/head git stash pop #Opens the stash for commiting in any branch/head git diff stash #Checks difference between HEAD(or Branch) and Stash git branch #Lists all branches in existance git branch #Creates a new branch git branch #Creates new branch from old_branch commits git branch -d #Deletes a branch git switch #Switches to a different branch git reset HEAD [filename|branchname] #Undoes file or branch deletion git checkout #Switches current branch to git checkout -b #Creates new branch with all the current branch commits and ^ automatically switches to it. git checkout -b #Creates a new branch called new_feature with master branch commits ^ and switches to it. git diff #Checks difference between two different branches git diff stash #Checks difference between HEAD(or Branch) and Stash. git diff #Checks difference between Head(or branch) with branch_id. git merge #Commits new modifications from to the CURRENT actual branch you're working with, ex.: git checkout master git merge newbranch ^Will merge all modifications from newbranch to master branch, It's now possible to safely delete newbranch if not needed. git merge #Merges New Commit into Currrent Branch Note.: You can only Merge Commits ^ Warning: Running git merge with non-trivial uncommitted changes is discouraged: while possible, it may leave you in a state that is hard to back out of in the case of a conflict. git merge --abort #The second syntax ("git merge --abort") can only be run after the merge has resulted in conflicts. ^ git merge --abort will abort the merge process and try to reconstruct the pre-merge state. warning: avoid using with uncommited changes on INDEX! git merge --continue #The third syntax, can only be used when merge conflicts has appeared. git mergetool #Executes tool for resolving merging conflicts manually ^Requires merge tool to be set and configured. git rebase #Merges ALL OF THE COMMITS from a given branch into the current one! The difference between git merge and git rebase is that git merges only merges the last of commit of a given branch into the current commit of the current branch; however, git rebase merges ALL OF THE COMMITS into the current branch?? - NEEDS TO CHECK - WRONG! Rebase will present conflicts one commit at a time whereas merge will present them all at once. It is better and much easier to handle the conflicts but you shouldn’t forget that reverting a rebase is much more difficult than reverting a merge if there are many conflicts. Rebase Golden Rule: Never use rebase on a public/shared branch, only use rebase if you're the only developer of a given branch! ^public branches are branches that other people might have checked out. If you’re developing a branch on your own and not sharing it with anyone, you could rebase it to keep the branch up to date with respect to the main branch. Moreover, the main branch can move forward with a fast-forward merge rather than a regular merge commit. Rebasing rewrites history, and anyone having branches that were checked out of the history you just unmade will be sad, angry or worse. That’s one reason you can’t just push rebased branch on GitHub (unless you force it and sacrifice a kitten). So just say no. Rebasing private branches is perfectly fine, and in fact often done when squashing or rearranging commits, cleaning up a branch before going public with it, or just updating long-running feature branch (go easy on the last one, though). source: https://www.benmarshall.me/git-rebase/ git rebase --onto #Rebases branch_1 and branch_2 onto base_branch git rebase --onto topicA~5 topicA~3 topicA #Removes Commits from 3rd(excluded) to 5th(included) from being rebased. *included: 5th gets removed. This is useful if F and G were flawed in some way, or should not be part of topicA. Note that the argument to --onto and the parameter can be any valid commit-ish. - NEEDS TO CHECK git rebase --continue #Continues rebase after conflicts have been solved git rebase --abort #Aborts & Reverts rebase in case of conflict -- HOW TO DROP MODIFICATIONS FROM STAGING AREA -- git restore --staged B.txt #Removes B.txt from the Staging Area git restore #Also works as of date: 2021 -- HOW TO REVERT COMMITS -- Once you have made an accidental commit in your LOCAL REPO by mistake, it's possible to revert it by checking the last commits you've made with: git log then pick the commit ID you want to revert to and do a checkout in it: git checkout if you're working on only 1 branch, you'll need to make a spare one: git branch backup finally delete the branch that has been commited by accident: git branch -d ^ note.: this isn't a good idea, because it'll erase all that branch's history recreate it: git branch Now your accidental commit should be reverted. -------------------------- -------------------------- ADVANCED GIT: man pages and tldr are the best place for checking out git command examples, for example: $man git-log #The bottom-page displays a small list of examples for git-log commands. $tldr git-log #Requires tldr Installed ----GIT LOG: git log --graph --abbrev-commit --oneline --all --reflog #SHOWS ALL COMMITS git log --no-merges #Show the whole commit history, but skip any merges git log v2.6.12.. include/scsi drivers/scsi #Show all commits since version v2.6.12 that changed any file in - VERY IMPORTANT ^ the include/scsi or drivers/scsi subdirectories git log --since="2 weeks ago" -- gitk #Show the changes during the last two weeks to the file gitk. ^ The -- is necessary to avoid confusion with the branch named gitk git log --name-status release..test #Show the commits that are in the "test" branch but not yet in the - IMPORTANT ^ "release" branch, along with the list of paths each commit modifies. git log --follow builtin/rev-list.c #Shows the commits that changed builtin/rev-list.c, including those commits ^ that occurred before the file was given its present name. git log --branches --not --remotes=origin #Shows all commits that are in any of local branches but not in any of remote-tracking ^ branches for origin (what you have that origin doesn’t). - IMPORTANT git log master --not --remotes=*/master #Shows all commits that are in local master but not in any remote repository master branches. - IMPORTANT git log -p -m --first-parent #Shows the history including change diffs, but only from the “main branch” perspective, ^ skipping commits that come from merged branches, and showing full diffs of changes introduced by the merges. This makes sense only when following a strict policy of merging all topic branches when staying on a single integration branch. git log -L '/int main/',/^}/:main.c #Shows how the function main() in the file main.c evolved over time. - VERY IMPORTANT git log -3 #Limits the number of commits to show to 3. ----GIT LOG(2): git log -p #Show the history of a particular file or directory, including differences. - VERY IMPORTANT git log --stat #Show an overview of which file(s) changed in each commit. - VERY IMPORTANT git log --oneline --graph #Show a graph of commits in the current branch using only the first line of each commit message. IMPORTANT git log --oneline --decorate --all --graph #Show a graph of all commits, tags and branches in the entire repo. - IMPORTANT git log -i --grep search_string #Show only commits whose messages include a given string (case-insensitively). git log -n number --author=author #Show the last N commits from a certain author. - VERY IMPORTANT git log --before="2017-01-29" --after="2017-01-17" #Show commits between two dates (yyyy-mm-dd). - VERY IMPORTANT ---- GIT COMMIT git commit -m "message" #Commit staged files to the repository with a message. git commit --file path/to/commit_message_file #Commit staged files with a message read from a file. git commit -a -m "message" #Auto stage all modified files and commit with a message. git commit -S -m "message" #Commit staged files and [S]ign them with the GPG key defined in `~/.gitconfig` - VERY IMPORTANT git commit --amend #Update the last commit by adding the currently staged changes, changing the commit's hash. - VERY IMPORTANT git commit path/to/file1 path/to/file2 #Commit only specific (already staged) files. git commit -m "message" --allow-empty #Create a commit, even if there are no staged files. - VERY IMPORTANT --- -- THE FOLLOWING BELOW NEEDS TO BE MORE EXPLAINED!! -- git remote #lists all local and remote repos git remote rm #deletes repo git remote add origin #creates local repo on pre-existing path ^ example: git remote add origin ~/gittest/REPO/ git remote add origin https://github.com/marcelojo/artigo_git.git #creates a remote repo called origin git clone #Creates a local repo based on a remote repository example: git clone https://github.com/marcelojo/artigo_git.git git push #Pushes current branch modifications into remote one git push -u #Sends modifications from branch to remote repository example: git push -u origin master git pull #Incorporates changes from a remote repository into the current branch. ^ In its default mode, git pull is shorthand for git fetch followed by git merge FETCH_HEAD. More precisely, git pull runs git fetch with the given parameters and calls git merge to merge the retrieved branch heads into the current branch. With --rebase, it runs git rebase instead of git merge. ex.: git pull origin ---MISC COMMANDS--- git config color.ui true #sets colored output git config format.pretty oneline #exibir logs apenas uma linha por commit git add -i #fazer inclusões interativas gitk #interface padrão do git git tag 1.0.0 1b2e1d63ff #rotulando um commit ID ---GIT HEAD COMMANDS--- OBS.: Note that both MASTER and HEAD are pre-existing branches - RE-EXPLAIN so in order to switch back to master do: git checkout master You also can't move from HEADs to BRANCHES when making changes without COMITTING them first on the master branch. you can, however, if you are in another branch. - RE-EXPLAIN After merging different branches, it's necessary ADD or REFUSE each changes and make a new commit in case you have accepted any changes. git reflog #Lists all history of head movements git checkout HEAD^ #Goes to the previous COMMIT by 0 or 1 git checkout HEAD~ #Goes to the previous COMMIT by Nth - Needs Check git checkout HEAD@{} #Goes to Nth Head - check rflog git checkout #Goes to the head ID git branch 35e6ab4 #Creates a new branch with all modifications from head ID ^ it differs from git checkout -b "new branch", because 'checout -b' doesn't requires ID, and it 'checkout -b' not only creates a new branch, but also switches you to it whereas 'branch' doesn't do that. also, what 'branch' does is simply copy one branch/head to another. 'checkout -b' is useful when you've made modifications to the working area, and want to bring modifications to a new branch, instead of modifying the original branch. Whenever you want to make a modification to the master branch, do the following: - REVIEW git checkout HEAD~ #ID Number of commit ... make modification to files... git add #Adds Modification to current head git commit -m #Makes a new commit with all the added modifications git checkout master #Switches to Master Branch git merge #Merges New Commit into Master Note.: You can only Merge Commits *Note.: Whenever you make modifications to a HEAD's Files, you need to either ADD modification or UNDO them either with: 1 - git reset HEAD #same as below, but for undoing deletion git checkout -- #for undoing changes or 2 - git add #for confirming file modification/insertions And then finally commit those changes with 'git commit -m "New Commit" [filename]', only then you'll be able to switch branches/head *Note: You can save Head IDs on different VIM Registers, so you don't need to 'git reflog' all the time. git reflog example: 35e6ab4 (HEAD) HEAD@{0}: checkout: moving from 0a028cb8ff4af74ec2cdc0d4c953b015121dc81a to HEAD@{20} ^ HEAD@{0} - HEAD Number on List History everytime there's a head movement, there will also be a new head number added at the end of the list. ^ Checkout: Moving from XYZ to HEAD@{20} #Shows the operation that has been done, and the movement. --- GIT END TUTORIAL ---