gitGraph commit commit branch develop checkout develop commit commit checkout main merge develop checkout develop commit commit checkout main commit branch fix_1 commit commit checkout main merge fix_1 commit checkout develop
A graphical introduction to Git
gitGraph commit commit branch develop checkout develop commit commit checkout main merge develop checkout develop commit commit checkout main commit branch fix_1 commit commit checkout main merge fix_1 commit checkout develop
Scenario
First we init the repo, then create a new file.
The init creates a new repo in the specified directory.
We add modified files so git knows we may want to save them.
< myscript.py >
[+1] def add_numbers(num1, num2):
[+2] “““Add two things together”“”
[+3] answer = num1 + num2
[+4] print(f”{num1} + {num2} is {answer}“)
[+5]
[+6] add_numbers(2, 2)
The add command stages files, which means they are marked to be saved.
Then commit to saving them. Note the Tag.
[9d6b7c…] < myscript.py >
[+1] def add_numbers(num1, num2):
[+2] “““Add two things together”“”
[+3] answer = num1 + num2
[+4] print(f”{num1} + {num2} is {answer}“)
[+5]
[+6] add_numbers(2, 2)
The commit command saves the changes we added (staged). Add a message in the commit command or an editor will open automatically.
This creates our first commit (dot) on the default branch (main).
“HEAD” refers to the latest commit on the current branch.
gitGraph commit id: "9d6b7c"
The structure of the full commit HASH:
6fd21da172fa169568a996bc2c7e97461bec7110
A very long string of hexadecimal numbers (0-9 and a-f)
Fortunately, you can reference a commit with a few of the left characters:
6fd21d
Each commit has metadata.
The show can be used to see metadata about a commit
Next, we make some changes.
Next, we make some changes.
Then diff to see difference between saved and current state.
< myscript.py >
[-3] answer = num1 + num2
[-4] print(f”{num1} + {num2} is {answer}“)
[-6] print(f”{num1} + {num2} is {answer}“)
[+3] return num1 + num2
[+5] assert add_numbers(1, 1) == 2
The diff commands shows changes between commits, files, branches, etc.
Then add the changes.
< myscript.py >
-4 answer = num1 + num2
-5 print(f”{num1} + {num2} is {answer}“)
-7 add_numbers(2, 2)
+3 return num1 + num2
+5 assert add_numbers(1, 1) == 2
And finally commit them.
Which adds a new commit to our main branch.
gitGraph commit id: "9d6b7c" commit id: "046a7a"
gitGraph commit id: "9d6b7c" commit id: "046a7a"
We can create branches with their own commits
(think parallel universe)
gitGraph commit id: "9d6b7c" commit id: "046a7a" branch branch_1 commit id: "2-a577878" commit id: "3-c17d954"
The branch command is used to see, create, and destroy branches.
Then merge branches (e.g., back into main)
gitGraph commit id: "9d6b7c" commit id: "1-046a7a" branch branch_1 commit id: "4c0f818" commit id: "221d22" checkout main merge branch_1
The merge command joins branches together.
Which has the same effect (on the code) as committing on main
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22"
But what if changes are made on main before the merge?
gitGraph commit id: "9d6b7c" commit id: "046a7a" branch branch_1 commit id: "4c0f818" commit id: "221d22" checkout main commit commit
We can still merge branch_1 into main but….
there might be conflicts
gitGraph commit id: "9d6b7c" commit id: "046a7a" branch branch_1 commit id: "4c0f818" commit id: "221d22" checkout main commit commit merge branch_1
What should happen if the changes aren’t compatible?
Make the merger sort it out!
Dealing with conflicts isn’t fun (in git or life). Here are a few commands that might help.
Example: myscript.py on main
Example: myscript.py on branch_2
myscript.py after merge command
Next, manually edit myscript.py so it is correct
Now that we have fixed the file:
Commits can be be tagged (usually with a version)
gitGraph commit id: "9d6b7c" commit id: "046a7a" tag: "v1.0.0" commit id: "4c0f818" commit id: "221d22" tag: "v1.1.0"
Tag is like adding an alias to refer to a commit with a shorter string. Usually, but not always, tags are used for versioning.
Commits can be Cherry-Picked
gitGraph commit id: "9d6b7c" commit id: "046a7a" branch develop commit id: "dc12a2" commit id: "ca2259" checkout main commit id: "4c0f818" commit id: "221d22"
Commits can be Cherry-Picked
gitGraph commit id: "9d6b7c" commit id: "046a7a" branch develop commit id: "dc12a2" commit id: "ca2259" checkout main commit id: "4c0f818" commit id: "221d22" commit id: "dc12a2"
The cherry-pick command allows you to apply as single commit (from any branch) to HEAD. Watch out though, you can still get conflicts.
Branches can be rebased
gitGraph commit id: "9d6b7c" commit id: "046a7a" branch develop commit id: "dc12a2" commit id: "ca2259" checkout main commit id: "4c0f818" commit id: "221d22"
Branches can be rebased.
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22" branch develop commit id: "dc12a2" commit id: "ca2259"
The rebase command changes the starting point of a branch. MIt is often used to bring changes back into a feature branch from the main branch.
Rebase changes the git history. Make sure no one else is working on the branch before rebasing.
HEAD can be reset, keeping or discarding commits/unsaved changes.
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22"
The reset command cab be used to undo commits or staging.
Soft reset
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "Unsaved" type: HIGHLIGHT
Hard reset
gitGraph commit id: "9d6b7c" commit id: "046a7a"
Hard reset
Commits can be squashed (combined)
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22"
Commits can be squashed (combined)
gitGraph commit id: "ab3b7c" commit id: "046a7a" type: REVERSE commit id: "4c0f818" type: REVERSE commit id: "221d22" type: REVERSE
There actually isn’t a squash command, but a few ways to squash commits together
Git is a distributed version control system
This means it can interact with remote copies of the repository (like one hosted by github).
Remote repos have names, like “origin” (think github).
Git can clone remote (non-local) repositories.
remote: origin
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22" branch develop commit id: "dc12a2" commit id: "ca2259"
Git can clone remote (non-local) repositories.
local
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22"
remote: origin
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22" branch develop commit id: "dc12a2" commit id: "ca2259"
The clone command downloads a remote repository (and all its branches).
Git can also fetch new branches since clone.
local
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22"
remote: origin
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22" branch develop commit id: "dc12a2" commit id: "ca2259"
Git can also fetch new branches since clone.
local
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22" branch develop commit id: "dc12a2" commit id: "ca2259"
remote: origin
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22" branch develop commit id: "dc12a2" commit id: "ca2259"
Git fetch gets specific info from a remote repo (like a small clone).
Note: After cloning it may appear not all branches were downloaded. Just make sure to use the -a flag on branch to see them. All you need to do is checkout one of the remote branches to make a it a local one.
We push local changes to the remote repo.
local
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22" branch develop commit id: "dc12a2" commit id: "ca2259" commit id: "5dab5d"
remote: origin
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22" branch develop commit id: "dc12a2" commit id: "ca2259"
The push command shares local commits/branches with a remote repo. If the local and remote history have diverged you may have to force the push. Careful though, make sure no one else depends on that history!
We push local changes to the remote repo.
local
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22" branch develop commit id: "dc12a2" commit id: "ca2259" commit id: "5dab5d"
remote: origin
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22" branch develop commit id: "dc12a2" commit id: "ca2259" commit id: "5dab5d"
We pull changes from remote to local (fetch + merge).
local
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22" branch develop commit id: "dc12a2" commit id: "ca2259"
remote: origin
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22" branch develop commit id: "dc12a2" commit id: "ca2259" commit id: "5dab5d"
The pull command is used to fetch and merge changes from a remote repo into your current branch.
We pull changes from remote to local (fetch + merge).
local
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22" branch develop commit id: "dc12a2" commit id: "ca2259" commit id: "5dab5d"
remote: origin
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22" branch develop commit id: "dc12a2" commit id: "ca2259" commit id: "5dab5d"
fork creates remote clones.
remote: origin
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22" branch develop commit id: "dc12a2" commit id: "ca2259" commit id: "5dab5d"
There is no fork command. Forking done from Github’s web interface.
fork creates remote clones.
remote: fork
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22" branch develop commit id: "dc12a2" commit id: "ca2259" commit id: "5dab5d"
remote: origin
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22" branch develop commit id: "dc12a2" commit id: "ca2259" commit id: "5dab5d"
Name that Git Command (1)
gitGraph commit id: "9d6b7c" commit id: "046a7a"
Name that Git Command (1)
gitGraph commit id: "9d6b7c" commit id: "046a7a" branch develop
Name that Git Command (2)
gitGraph commit id: "9d6b7c" commit id: "046a7a"
Name that Git Command (2)
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818"
Name that Git Command (3)
remote: origin
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" branch develop commit id: "34ad12"
Name that Git Command (3)
local
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818"
remote: origin
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" branch develop commit id: "34ad12"
Name that Git Command (4)
local
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818"
remote: origin
gitGraph commit id: "9d6b7c" commit id: "046a7a"
Name that Git Command (4)
local
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818"
remote: origin
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818"
Name that Git Command (5)
gitGraph commit id: "9d6b7c" commit id: "046a7a" branch develop commit id: "4c0f818" checkout main commit id: "14359ab" commit id: "a2b55ce"
Name that Git Command (5)
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "14359ab" commit id: "a2b55ce" branch develop commit id: "4c0f818"
fork a repo
remote: origin
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22"
fork a repo
remote: fork
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22"
remote: origin
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22"
clone the fork
remote: fork
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22"
clone the fork
local
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22"
remote: fork
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22"
branch to create a new feature
local
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22"
branch to create a new feature
local
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22" branch new_feature
Write some code, add, commit
local
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22" branch new_feature
Write some code, add, commit
local
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22" branch new_feature commit id: "a342bc" commit id: "adeb12"
push new code to fork
local
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22" branch new_feature commit id: "a342bc" commit id: "adeb12"
remote: fork
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22"
push new code to fork
local
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22" branch new_feature commit id: "a342bc" commit id: "adeb12"
remote: fork
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22" branch new_feature commit id: "a342bc" commit id: "adeb12"
Submit a pull request to add changes to origin/main.
Get it approved!
squash commits on branch
remote: fork
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22" branch new_feature commit id: "a342bc" commit id: "adeb12"
squash commits on branch
remote: fork
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22" branch new_feature commit id: "ba34dc"
merge remote/new_feature into origin/main
remote: fork
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22" branch new_feature commit id: "ba34dc"
remote: origin
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22"
merge remote/new_feature into origin/main
remote: fork
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22" branch new_feature commit id: "ba34dc"
remote: origin
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22" commit id: "ba34dc"
Git can ignore certain files, or patterns, with a single file called “.gitignore”.
gitGraph commit id: "9d6b7c" commit id: "046a7a" commit id: "4c0f818" commit id: "221d22"
gitGraph commit id: "9d6b7c" commit id: "046a7a" tag: "v1.0.1" branch bug_fix_1 commit id: "6bc3a3" commit id: "f23da3" checkout main branch feature_1 commit id: "4c0f818" commit id: "221d22" commit id: "ac1d25" checkout main merge bug_fix_1 tag: "v1.0.2" merge feature_1 tag: "v1.1.0"
gitGraph commit id: "ab3490" branch develop commit id: "ac231c" commit id: "0931dc" checkout main commit id: "046a7a" tag: "v1.0.0" branch bug_fix_1 commit id: "6bc3a3" commit id: "f23da3" checkout main merge bug_fix_1 tag: "v1.0.1" checkout develop branch feature_1 commit id: "4c0f818" commit id: "221d22" checkout develop merge feature_1 checkout main merge develop tag: "v1.1.0"