theme | fonts | class | highlighter | lineNumbers | info | title | author | authorUrl | background | drawings | css | hideInToc | |||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
default |
|
text-center |
prisim |
false |
## Git Beyond the Basics
Learn about Git, commands, and techniques to manage your workflows.
|
Git Beyond the Basics |
Majed Al-Chatti |
alchatti.com |
yancy-min-842ofHC6MaI-unsplash.jpg |
|
unocss |
true |
Solution Architect for Web & Mobile, experienced in Web Security, DevOps, and Digital Marketing. Branching into VR and Machine Learning.
- 👔 Web Architect at American University of Sharjah.
- ⌛ 15+ years in software development.
- 🧑💻 Tech .Net, Node.js, Drupal, Docker, CI/CD, Linux, Windows, SQL, and more.
- GitHub Enterprise & Azure DevOps team and org manager.
alchatti | alchatti | alchatti | alchatti.com
<style> h1 { background-color: #2B90B6; background-image: linear-gradient(45deg, #4EC5D4 10%, #146b8c 20%); background-size: 100%; -webkit-background-clip: text; -moz-background-clip: text; -webkit-text-fill-color: transparent; -moz-text-fill-color: transparent; } </style>sequenceDiagram
Working Directory ->> Staging Area: git add
Staging Area ->> Local Repo: git commit
Local Repo ->> Remote Repo: git push
Remote Repo -->> Local Repo: git fetch / pull
Create an empty Git repository or reinitialize an existing one
# inside a directory
git init
# create a new directory and initialize it
git init $directory
# Initialize with a default branch name
git inti -b $branchName
.git directory with subdirectories for objects, refs/heads, refs/tags, and template files.
Local & Global configuration
git config --global user.name "$Full_Name"
git config --global --add user.useConfigOnly true
git config --global --unset-all user.email
# Ignore file mode changes
git config --global core.fileMode false
# Set default editor
git config --global core.editor "code -w"
git config --global core.editor "code --wait"
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait $MERGED'
git config --global diff.tool vscode
git config --global difftool.vscode.cmd 'code --wait --diff $LOCAL $REMOTE'
# Set default branch name
git config --global init.defaultBranch main
# Edit global config
git config --global -e
git config user.email "$email"
Show the working tree status
git status
# Short
git status -s
# Short with Branch
git status -sb
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
index.md
nothing added to commit but untracked files present (use "git add" to track)
Add file contents to the index
git add $file
# Add all files
git add .
# Add all files with a specific extension
git add *.md
git add -p $file
y
- stage this hunkn
- do not stage this hunke
- manually edit the current hunk
.gitignore file to ignore files and directories. .gitkeep to keep empty directories.
Record changes to the repository
git commit -m "Commit message"
# Add all files and commit
git commit -am "Commit message"
# Change the last commit message
git commit --amend -m "New commit message"
# Undo the last commit
git reset --soft HEAD~1
# Add more files to the last commit without changin the message
git commit --amend --no-edit
# Rest author of the last commit
git commit --amend --reset-author
# Change the author of the last commit
git commit --amend --author="Majed Al-Chatti <[email protected]>" --no-edit
Check out git revert for undoing changes without rewriting history
%%{init: { 'logLevel': 'debug', 'theme': 'default' , 'themeVariables': {
'git3': 'red'
} } }%%
gitGraph
commit id: "1"
commit id: "2"
branch featureA
checkout featureA
commit id: "3"
checkout main
commit id: "4"
checkout featureA
branch featureB
checkout featureB
commit id: "5"
checkout main
commit id: "6"
checkout featureA
commit id: "7"
checkout main
merge featureA id: "merge A" tag: "R/1" type: REVERSE
checkout featureB
commit id: "8"
checkout main
branch hotfix
commit id: "9"
checkout main
merge hotfix id: "merge hotfix" tag: "R/1.1" type: REVERSE
checkout featureB
commit id: "10"
checkout main
merge featureB id: "merge B" tag: "R/2" type: REVERSE
List, create, or delete branches
# Create a new branch
git branch -b $branchName
# Or Switch and create a new branch
git switch -c $branchName
git checkout -b $branchName
# Delete a branch
git branch -d $branchName
# Delete a branch without merging
git branch -D $branchName
# List all branches
git branch -a
# List all remote branches
git branch -r
# List all branches with last commit
git branch -av
Multiple remotes with same branch name --track
git switch -c -t $remoteBranchName
Copies a commit from a branch to another.
# Cherry pick a commit
git cherry-pick $commitHash
# Cherry pick with commit
git cherry-pick $commitHash --no-commit
# Cherry pick with commit and message
# keep track of origin to avoid merge conflicts
git cherry-pick -x $commitHash
- Deploy a specific commit from one branch to another.
- Made a commit on the wrong branch.
- Apply a hot fix without rebasing or mergin.
⚠️ Can cause duplicate commits if the commit is already in the branch.
Create, list, delete or verify a tag object signed with GPG
# Create a new tag
git tag $tagName
# Create a new tag with a message
git tag -a $tagName -m "Tag message"
# Create a new tag from a commit
git tag -a $tagName $commitHash -m "Tag message"
# List all tags
git tag
# List all tags with a specific pattern
git tag -l "v1.*"
Switch branches or restore working tree files
# Checkout a file from a commit
git checkout $commitHash $file
# Checkout a file from a branch
git checkout $branchName $file
# Checkout a commit
git checkout $commitHash
# checkout a tag
git checkout $tagName
check git checkout for more options
Running git merge
, default strategy. All the individual commits in the pull request branch are preserved as-is, and a new merge commit is created to unite them.
Take each individual commit and cherry-pick them onto the master branch. Running git rebase master
on current branch and followed by git merge pr --ff-only
on the master branch.
Squashing will take the tree that’s produced in a merge and creates a single new commit with those repository contents. It emulates running git merge --squash
from the master branch.
A mix of rebase and a merge, running git rebase master
on the pull request branch, followed by git merge pr --no-ff
on the master branch.
Join two or more development histories together
# Merge a branch into the current branch
git merge $branchName
# Merge a branch into the current branch and squash all commits
git merge --squash $branchName
# Favour current branch
git merge -our $other_branch
# Favour Other Branch branch
git merge -Xtheirs $other_branch
# Checkout files in conflict
git checkout --[thiers|ours] .
git checkout --[thiers|ours] $pathfilename
# During merge
git rebase [--continue|--skip|--abort]
Reapply commits on top of another base tip.
# Rebase the current branch on top of a branch
git rebase $baseBranch
# Rebase the current branch on top of the master branch and interactively
git rebase -i $baseBranch
# Rebase from root
git rebase -i --root
# During rebase
git rebase [--continue|--skip|--abort]
# Favour current branch
git rebase -Xtheirs $otherBranch
# favour other branch
git rebase -Xours $otherBranch
# Checkout files in conflict
git checkout --[thiers|ours] .
git checkout --[thiers|ours] $pathfilename
Reset current HEAD to the specified state
# Reset the last commit
git reset --soft HEAD~1
# Reset the last commit and keep the changes
git reset --mixed HEAD~1
# Reset the last commit and discard the changes
git reset --hard HEAD~1
# Reset to remote branch
git reset --hard $remote/$branch
Use
~
most of the time — to go back a number of generations, usually what you want
Use^
on merge commits — because they have two or more (immediate) parents
Tilde
~
is almost linear in appearance and wants to go backward in a straight line
Caret^
suggests an interesting segment of a tree or a fork in the road
Stash the changes in a dirty working directory away
# Stash all changes
git stash
# pop the last stash
git stash pop
# list all stashes
git stash list
# Delete stash
git stash drop stash@{$n}
# Stash with message
git stash save "message"
Remote repository management
# Show remote URLs
git remote -v
# Add a new remote
git remote add $remoteName $remoteUrl
# Remove a remote
git remote remove $remoteName
# Rename a remote
git remote rename $oldName $newName
# set a remote URL
git remote set-url $remoteName $remoteUrl
origin is the default remote name
upstream is the default remote name for forked repositories
::right::
Update remote refs along with associated objects
# Push current branch to a remote
git push $remoteName
# Push to a remote and set upstream
git push -u $remoteName $branchName
# Delete a remote branch
git push $remoteName :$branchName
git push -d $remoteName $branchName
# Push all tags
git push --tags
# Push a tag
git push $remoteName $tagName
# Delete a tag
git push $remoteName :refs/tags/$tagName
# Force push to overwrite remote branch
git push $remoteName --force-with-lease
⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ Don't use--force
⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️
Clone a repository into a new directory
# Clone a repo
git clone $remoteUrl
# Clone a repo with a directory name
git clone $remoteUrl $directoryName
# Shalllow clone
git clone --depth 1 $remoteUrl
# Exact copy of a repo
git clone --mirror $remoteUrl
Download commits & refs without update
# Fetch a remote
git fetch $remoteName
# Fetch a remote and prune
git fetch -p $remoteName
# Fetch all remotes
git fetch --all
# fetch and updated other branche
git fetch $remoteName $branchName:$branchName
Download commits & refs and merge, fetch then merge.
# Pull from a remote
git pull $remoteName
# Pull from a remote and rebase
git pull --rebase $remoteName
Remove untracked files from the working tree
# Dry Run
git clean -n
# Delete files
git clean -f
# Remove everything not tracked by git
git clean -xdf
Add another git repository into a subdirectory
# Add a submodule
git submodule add $submoduleRemoteUrl $submodulePath
# Update all submodules recursively
git submodule update --init --recursive
# clone a repo with submodules
git clone --recurse-submodules $remoteUrl
submodule is git repo inside another git repo
switching branching will not switch submodules you will need to update them manually
- 📦 External Library
- 🌐 Full Stack App ( Front & Backend)
- 🫧 Microservices
- 💄 Theme
- 📚 Documentation
Checkout multiple branches at the same time in different directories
# Add a worktree
git worktree add $worktreePath $branchName
# List all worktrees
git worktree list
# Remove a worktree
git worktree remove $worktreePath
# Prune worktrees
git worktree prune
# Add Command
git worktree add --track -b $branch $path $remote/$branch
# Amend starting from a commit
git rebase -i $commitHash
# `r` change commit message,
# `s` to squash ,
# `f` to fixup squash with no message change
# `d` to drop the commit
# `e` to edit
# on `e` reset the changes
git reset HEAD^
# Stage files
git add $file
# Commit
git commit -m $message
# Continue
git rebase --continue
"conventionalCommits.autoCommit": false,
"conventionalCommits.showEditor": true,
"conventionalCommits.emojiFormat": "emoji",
- Create an empty repo on GitHub.
- Create an empty repo on GitLab.
- On local repo add the remotes.
git remote add github $githubUrl
git remote add gitlab $gitlabUrl
git push $remote --all --tags
# OR
git push $remote --mirror
add remote origin with any URL
- Clone workshop repo
- Create a new branch
dev/githubUserName
- Pick a Programming language and create
about.md
file andframeworks.md
file - Push your changes
- Create a
languageName
folder and move your files into it usinggit mv $filePath $newPath
- Create a pull request to
languageName
branch and merge it with others, if you are the firstpush
.
<style> h1{ font-size: 2rem; } </style>