Skip to content

Latest commit

 

History

History
1064 lines (722 loc) · 32.2 KB

git.md

File metadata and controls

1064 lines (722 loc) · 32.2 KB

Git

Table of Contents

Git Basics

  • Version Control System (VCS) manages the changes to documents, computer programs, large web sites, and other collections of information
    • distributed version control
    • coordinates work between multiple developers
    • who made what changes and when
    • revert back at any time
    • local & remote repos
  • git is a free and open source distributed version control system
    • keeps track of code history
    • takes "snapshots" of your files
    • you decide when to take a snapshot by making a "commit"
    • you can visit any snapshots at any time
    • you can stage files before committing
  • Github: a platform for hosting and collaborating on Git repositories
  • commit" a Git object, a snapshot of your entire repository compressed into a SHA
  • branch is a lightweight movable pointer to a commit
  • clone: a local version of a repository, including all commits and branches
  • remote: a common repository on Github that all team member use to exchange their changes
  • fork: a copy of a repository on Github owned by a different user
  • pull request: a place to compare and discuss the differences introduced on a branch with reviews, comments, integrated tests, and more
  • HEAD: representing your current working directory, the HEAD pointer can be moved to different branches, tags, or commits when using git checkout

Git Commands

  • git init initializes a brand new Git repository locally
  • git status shows the status of changes as untracked, modified, or staged
  • git clone copy a repository from the Github to your local machine
  • git add track your files and changes with Git
  • git commit save your changes into Git
  • git branch shows the branches being worked on locally
  • git push upload your changes (commit) to your remote repository on Github
  • git pull download changes from remote repository to your local machine
  • git merge merges combine changes made on two distinct branches

GitHub flow

  1. Create a branch
  2. Add commits
  3. Open a pull request
  4. Discuss and review code
  5. Merge
  6. Deploy

Add a new repo from your machine to GitHub

$ echo "# repo-name" >> README.md # add repo name to README.md
$ git init # init the repository
$ git add README.md
$ git commit -m "first commit"
$ git remote add origin https://github.com/username/repo-name.git
$ git push -u origin master

# or push an existing repository from the command line
$ git remote add origin https://github.com/username/repo-name.git
$ git push -u origin master

Clone a repo and give it a different name

$ git clone https://github.com/user/repoNameYouToChange NameYouWantToGiveToRepo

Latest changes from repo to your machine

$ git pull

Add tracking information to your work

Assuming that you are working on the master branch then

$ git branch --set-upstream-to=origin/master

You can set it to whatever branch you want to track changes for

$ git branch --set-upstream-to=origin/<branch>

This will mean you can just do git pull and the latest changes will be pulled to your origin

What branch

$ git branch # shows what branch you're on
$ git branch -r # shows remote branches
$ git branch -a # shows all branches

Create a local branch and push it to GitHub

Want to make your feature branch and get it on GitHub?

Make your branch first then:

# git push --set-upstream <REMOTE_NAME> <BRANCE_NAME> or git push -u <REMOTE_NAME> <BRANCE_NAME>
$ git push -u origin feature

Create a PR [Pull Request]

Fork other users repo in GitHub, then clone to your machine:

$ git clone https://github.com/<username>/<repo-name>

Add the remote repo:

$ git remote add upstream https://github.com/<OthersUsername>/<repo-name>

Create your branch:

$ git branch <BRANCE_NAME>

Check it out:

$ git checkout <BRANCE_NAME>

If adding a folder use:

$ git add folderName/\\*

Make your commit and push to your new branch:

$ git add .
$ git commit -m 'initial commit'
$ git push origin branch-name

Manage the rest of the PR via GitHub

Check remotes

$ git remote -v

Sync a remote fork on your machine

First configure the local to point to the remote upstream:

$ git remote -v
$ git remote add upstream https://$ github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY.git
$ git remote -v
$ git fetch upstream
$ git checkout master
$ git merge upstream/master

You then use git merge to update any branch on the upstream repository:

$ git merge upstream/dev

Take a look at syncing a fork for more details.

Sync a remote fork on Github

  1. Open your fork on GitHub.
  2. Click on Pull Requests.
  3. Click on New Pull Request. By default, GitHub will compare the original with your fork, a there shouldn't be anything to compare if you didn't make a changes.
  4. Click on Try switching the base. Now GitHub will compare your fork with the original, and you should see all the latest changes.
  5. Click on Click to create a pull request for this comparison and assign a predictable name to your pull request (e.g., Update from original).
  6. Click on Send pull request.
  7. Scroll down and click Merge pull request and finally Confirm merge. If your fork didn't have any changes, you will be able to merge it automatically.

2fa

Using two factor authentication? Then use the following so you're not adding in your auth token each time you want to push your code.

$ git remote set-url origin https://yourgithubuser:your-token@github.com/yourgithubuser/yourrepo.git

Change origin url

If you want to change the origin url you can use the set-url command

$ git remote set-url origin https://github.com/user/new-repo-name

Add code on your machine to new repo

Via terminal navigate to your code folder:

$ git init

Add all your files:

$ git add .

Adding a folder use the following syntax or it'll get added as a BLOB:

$ git add folderName/\\*

Commit to local repo:

$ git commit -m 'some detailed message'

To add your files to the remote repo, first add your remote repo:

$ git remote add origin [remote repository URL] # Sets the new remote
$ git remote -v # verifies the new remote URL
$ git push origin master

For more info check out: adding an existing project to github using the command line

Delete Branch Locally

-d option alias for --delete, which deletes the branch if it has already been merged in its upstream branch. -D option alias for --delete --force which deletes the branch irrespective of its merged status.

# git branch -d <BRANCE_NAME>
$ git branch -d feature/login

Remove local branches that are not on the remote:

$ git remote prune <REMOTE_NAME>

Remove local branches that were created from remote branches:

$ git branch --merged master | grep -v '^[ *]*master$' | xargs git branch -d

Delete Branch Remotely

# git push <REMOTE_NAME> :<BRANCE_NAME>
# git push <REMOTE_NAME> --delete <BRANCE_NAME>
# git push <REMOTE_NAME> -d <BRANCE_NAME>

$ git push origin -d feature/login

Merge master branch into feature branch

How to merge the master branch into the feature branch? This will come up often if you are working on a team with other devs and you want to update your feature branch to include the latest changes:

# checkout your feature branch
$ git checkout feature1

# merge master into it
$ git merge master

Merge two repos

If you want to merge project-b into project-a:

$ cd path/to/project-a
$ git remote add project-b path/to/project-b
$ git fetch project-b
$ git merge --allow-unrelated-histories project-b/master # or whichever branch you want to merge
$ git remote remove project-b

Stop tracking a file

If you have .env files that are tracked by Git and want to ignore them so your API keys don't get added to GitHub use:

$ git update-index --assume-unchanged <FILE>

Stop tracking a previously tracked folder

Add the folder first to your .gitignore then remove the folder from your local git tracking with:

$ git rm -r --cached <folder>
$ git commit -m "removing <folder">

Start tracking a previously un-tracked file

$ git update-index --no-assume-unchanged <FILE>

Cloning a repo from someone else's GitHub and pushing it to a repo on my GitHub

So you make a clone, make some changes then realise that you need to add it to your GitHub account before making a pull:

$ git remote -v
origin  https://github.com/OtherUser/OtherUserRepo (fetch)
origin  https://github.com/OtherUser/OtherUserRepo (push)

You just need to set the origin to yours then add the upstream as the original origin make sense?

So change origin to yours:

$ git remote set-url origin http://github.com/YourUser/YourRepo

Then add upstream as theirs:

$ git remote add upstream https://github.com/OtherUser/OtherUserRepo

Now it should look something like this:

$ git remote -v
origin  http://github.com/YourUser/YourRepo (fetch)
origin  http://github.com/YourUser/YourRepo (push)
upstream        https://github.com/OtherUser/OtherUserRepo (fetch)
upstream        https://github.com/OtherUser/OtherUserRepo (push)

Remove an upstream repository

If you no longer need a reference to a forked repository then remove it with the following:

$ git remote rm upstream

How can I delete file from remote git repository? I have a file that is just deleted from working copy local repository, and I want delete it from corresponding remote repository.

If you deleted a file from the working tree, then commit the deletion:

$ git commit -a -m "A file was deleted"

And push your commit upstream:

$ git push

Remove commit from pull request

Read for more detail on how to revert.

# Checkout the desired branch
$ git checkout <BRANCH_NAME>

# Undo the desired commit
$ git revert <COMMIT>

# Update the remote with the undo of the code
$ git push origin <BRANCH_NAME>

Rather than use the last part, unstaged the changes in VSCode which is most likely the same thing.

How to read last commit comment?

$ git show # shows you the diff as well
$ git log -1
$ git log -1 --pretty=%B # just the commit message

Lots of complicated and dangerous answers here, but it's actually easy:

git revert --no-commit 0766c053..HEAD
git commit

This will revert everything from the HEAD back to the commit hash, meaning it will recreate that commit state in the working tree as if every commit since had been walked back. You can then commit the current tree, and it will create a brand new commit essentially equivalent to the commit you "reverted" to.

(The --no-commit flag lets git revert all the commits at once- otherwise you'll be prompted for a message for each commit in the range, littering your history with unnecessary new commits.)

This is a safe and easy way to rollback to a previous state. No history is destroyed, so it can be used for commits that have already been made public.

Add the modified file(s) and amend it:

$ (some_branch) git add changelog.md
$ (some_branch) git commit --amend

Amending a commit without changing its message with no-edit flag:

$ (some_branch) git commit --amend --no-edit

Pushing an amended commit that's not yet on the remote, otherwise use -f option rewrite your commit history:

$ (some_branch) git push -f origin some_branch

Just to edit a commit message, run the amend command without adding changes.

To edit a commit without opening a file, run:

$ (some_branch) git commit --amend -m "Your new commit message"

There are three leves for Git config:

System level:

$ git config --list --system # to view
$ git config --system color.ui true # to set
$ git config --edit --system # to edit system config file

Global level:

$ git config --list --global # to view
$ git config --global user.name xyz # to set
$ git config --edit --global # to edit global config file

Repository level:

$ git config --list --local # to view
$ git config --local core.ignorecase true  # to set (--local optional)
$ git config --edit --local # to edit repository config file (--local optional)

View all settings:

$ git config --list --show-origin

Conflicts between Windows Git and WSL Git?

If you are having issues with changes showing in Windows Git and not Windows Subsystem Linux Git (For a Windows WSL Dev set-up) then check the settings of each environment by using:

$ git config --list --show-origin

Remove any conflicting settings then try again.

Change default branch from master to main

1. Create main branch locally, taking the history from master

-m is for move (or mv), to rename files

git branch -m master main

2. Push the new local main branch to the remote repo (GitHub)

git push -u origin main

3. Switch the current HEAD to the main branch

git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/main

4. Change the default branch on GitHub to main

https://docs.github.com/en/github/administering-a-repository/setting-the-default-branch

5. Delete the master branch on the remote

git push origin --delete master

If you know the last commit message of the deleted branch you can do this:

$ git reflog

# search for message
fd0e4da HEAD@{14}: commit: This is the commit message I want
$ git checkout fd0e4da # checkout revision

# or
$ git checkout HEAD@{14}
$ git branch my-recovered-branch # create branch
$ git push origin my-recovered-branch:my-recovered-branch # push branch
# other Alternative
$ git commit -m "Something terribly misguided" # this is what you want to undo
$ git reset HEAD~
# << edit files as necessary >>
$ git add ...
$ git commit -c ORIG_HEAD # -c ORIG_HEAD will open an editor, which initially contains the log message from the old commit and allows you to edit it

Filename too long in git for windows

The better solution is enable the longpath parameter from git:

$ git config --system core.longpaths true

But a work arround that works is remove node_modules folder from git:

$ git rm -r --cached node_modules
$ vi .gitignore

Add node_modules in new row inside .gitignore file. After do this, push your modifications:

$ git add .gitignore
$ git commit -m "node_modules removed"
$ git push

Specify multiple users for myself in .gitconfig?

Want to have different git credentials for one specific repository?

You can configure an individual git repo to use a specific user/email address which overrides the global configuration.

To list out the config for the repo:

$ git config --list

From the root of the repo, run:

$ git config user.name 'Your Name'
$ git config user.email 'your@email.com'

Whereas the default user/email is configured in your ~/.gitconfig

$ git config --global user.name 'Your Name'
$ git config --global user.email 'your@email.com'

Rebase changes

If you're working on a team and there have been changes to the main branch you want to push your changes to, you can rebase before submitting a PR.

In this scenario we're going to rebase our feature branch off of the develop branch.

# switch from your feature to get latest develop changes
$ git checkout develop
$ git pull

# checkout the feature branch and rebase
$ git checkout feature
$ git rebase develop

Then use the prompts from there in conjunction with your text editor to add in the changes.

$ git add # add a change
$ git rebase --continue # continue the rebase
$ git rebase --skip # have an unrelated change, nothing to correct
$ git rebase --abort # oh DERP! Want to start over?

Rebase accept incoming in bulk

If you have a large file (like a package-lock.json) that you want to accept all the incoming changes from then.

Whilst you're in rebase you'll need to check out the file from your incoming branch then add it as the new file.

$ git checkout temp-branch -- package-lock.json # checkout the file
$ git add package-lock.json # add the file whilst in rebase
$ git rebase --continue # continue with the things

See differences between two branches

If you want to see the difference between two branches then use the $ git built in diff tool:

$ git diff branch1..branch2

See differences between two files

If you want to see the difference between two file across different branches then use:

$ git diff branch1..branch2 package.json

Squash a series of commits and rewrite the history by writing them as one

$ git rebase -i

this puts you in the interactive rebasing tool.

Type s to apply squash to a commit with the previous one. Repeat the s command for as many commits as you need.

Squash the last 3 commits and write new commit message from scratch:

$ git reset --soft HEAD~3 &&
git commit

Take a commit that lives in a separate branch and apply the same changes on the current branch

single commit:

$ git cherry-pick <commit>

for multiple commits:

$ git cherry-pick <commit1> <commit2> <commit3>

Restore the status of a file to the last commit (revert changes)

$ git checkout -- <filename>

You can do it without the --, but if the filename looks like a branch or tag (or other revision identifier), it may get confused, so using -- is best.

You can also check out a particular version of a file:

$ git checkout v1.2.3 -- file         # tag v1.2.3
$ git checkout stable -- file         # stable branch
$ git checkout origin/master -- file  # upstream master
$ git checkout HEAD -- file           # the version from the most recent commit
$ git checkout HEAD^ -- file          # the version before the most recent commit

Show a pretty graph of the commit history

$ git log --pretty=format:"%h %s" --graph

Get a prettier log

$ git log --pretty=format:"%h - %an, %ar : %s"

Git ref log

Want to know what work you have done on a repo? Use git reflog to display all the commits:

$ git reflog show -a # show all changes for the last 90 days
$ git reflog --pretty=short
$ git reflog --date=iso # show changes with a date

Cant remember what your last git commit said?

$ git show

Get a shorter status

$ git status -s

Checkout a pull request locally

$ git fetch origin pull/<id>/head:<branch>
$ git checkout <branch>

List the commits that involve a specific file

$ git log --follow -- <filename>

List the commits that involve a specific file, including the commits content

$ git log --follow -p -- <filename>

List the repository contributors ordering by the number of commits

$ git shortlog -s -n

Undo the last commit you pushed to the remote

# to undo a git push
$ git push -f origin HEAD^:master

# to get to previous commit (preserves working tree)
$ git reset --soft HEAD

# to get back to previous commit (you'll lose working tree)
$ git reset --hard HEAD^

# other option and they said the best option
$ git revert -n HEAD 

Pick every change you haven’t already committed and create a new branch

$ git checkout -b <branch>

Stop tracking a file, but keep it in the file system

$ git rm -r --cached

Get the name of the branch where a specific commit was made

$ git branch --contains <commit>

The git remote set-url command takes two arguments:

  • An existing remote name, e.g., origin or upstream are two common choices.
  • A new URL for the remote. For example:
    • If you're updating to use HTTPS, your URL might look like: https://github.com/USERNAME/REPOSITORY.git
    • If you're updating to use SSH, your URL might look like: git@github.com:USERNAME/REPOSITORY.git

Switching remote URLs from SSH to HTTPS

  1. Open Git Bash.
  2. Change the current working directory to your local project.
  3. List your existing remotes in order to get the name of the remote you want to change.
$ git remote -v
origin  git@github.com:USERNAME/REPOSITORY.git (fetch)
origin  git@github.com:USERNAME/REPOSITORY.git (push)
  1. Change your remote's URL from SSH to HTTPS with the git remote set-url command.
$ git remote set-url origin https://github.com/USERNAME/REPOSITORY.git
  1. Verify that the remote URL has changed.
$ git remote -v
origin  https://github.com/USERNAME/REPOSITORY.git (fetch)
origin  https://github.com/USERNAME/REPOSITORY.git (push)

The next time you git fetch, git pull, or git push to the remote repository, you'll be asked for your GitHub username and password.

Switching remote URLs from HTTPS to SSH

  1. Open Git Bash.
  2. Change the current working directory to your local project.
  3. List your existing remotes in order to get the name of the remote you want to change.
$ git remote -v
origin  https://github.com/USERNAME/REPOSITORY.git (fetch)
origin  https://github.com/USERNAME/REPOSITORY.git (push)
  1. Change your remote's URL from HTTPS to SSH with the git remote set-url command.
$ git remote set-url origin git@github.com:USERNAME/REPOSITORY.git
  1. Verify that the remote URL has changed.
$ git remote -v
origin  git@github.com:USERNAME/REPOSITORY.git (fetch)
origin  git@github.com:USERNAME/REPOSITORY.git (push)

Caching your GitHub password in Git (Linux)

Turn on the credential helper so that Git will save your password in memory for some time. By default, Git will cache your password for 15 minutes.

In Terminal, enter the following:

$ git config --global credential.helper cache # Set git to use the credential memory cache

To change the default password cache timeout, enter the following:

$ git config --global credential.helper 'cache --timeout=3600' # Set the cache to timeout after 1 hour (setting is in seconds)
  1. Make sure you can run code --help from the command line and you get help
  2. From the command line, run git config --global core.editor "code --wait"

Now you can run git config --global -e and use VS Code as editor for configuring Git.

Add the following to enable support for using VS Code as diff tool:

[diff]
    tool = default-difftool
[difftool "default-difftool"]
    cmd = code --wait --diff $LOCAL $REMOTE

This leverages the new --diff option you can pass to VS Code to compare two files side by side.

To summarize, here are some examples of where you can use Git with VS Code:

  • git rebase HEAD~3 -i allows to interactive rebase using VS Code
  • git commit allows to use VS Code for the commit message
  • git add -p followed by e for interactive add
  • git difftool <commit>^ <commit> allows to use VS Code as diff editor for changes

Resources

Articles

Guides

Books