GitHub Tutorial
- Apply for free GitHub Team, which allows unlimited users and private repositories.
Push an existing repository
-
Initialize an existing project to start tracking with
git
.-
Go into the directory containing the project.
-
Type
git init
. - Type
git add .
to add all of the relevant files. This step is called âstaging.â- Youâll probably want to create a
.gitignore
file right away, to indicate all of the files you donât want to track. Usegit add .gitignore
, too.
- Youâll probably want to create a
-
Type
git commit -m 'commit message'
.commit
records changes to the local repository.git generally requires a non-empty commit message.
-
-
Create a online repo and connect it to your local git project.
- Go to GitHub, click the new repository button in the top-right. Youâll have an option there to initialize the repository with a README file.
- Click the âCreate repositoryâ button.
- Connect your local repo to the remote repo you just created using the following cmds.
Note that# add repo name "origin" to the remote repo at the URL $ git remote add origin https://github.com/my1396/Damage-Function.git # rename the "current" local branch to main $ git branch -M main # push update from the current local branch (main) to remote (origin) repo's main branch; -u is a shortname for --set-upstream; first parameter is upstream then 2nd parameter is local repo # local and remote branch names should be matching $ git push -u origin main
main
can be replaced bymaster
for older repositories. - Then use GitHub Desktop to manage the repo committing, syncing, ..., later on.
- Go to GitHub, click the new repository button in the top-right. Youâll have an option there to initialize the repository with a README file.
Ref: https://kbroman.org/github_tutorial/pages/init.html
Q: Is it worth using GitHub Desktop?
A: Yes and no. It is useful if you just want to do basic management of your repositories. There are many things you cannot do with GitHub Desktop, e.g., you cannot rename a file. You need to do it with commond line or using online GitHub. Github desktop hides a lot of the details of handling git, making it difficult to debug. Additionally, git integration into almost any IDE is available and possibly more powerful, such as VS code git extension allows to rename a file directly.
Troubleshooting
Error: git pull origin main
returns
You have divergent branches and need to specify how to reconcile them.
You can do so by running one of the following commands sometime before your next pull:
git config pull.rebase false # merge
git config pull.rebase true # rebase
git config pull.ff only # fast-forward only
fatal: Need to specify how to reconcile divergent branches.
âDivergent branchesâ ćžžćșç°äș remote repo ćć§ćæ¶äžæŻç©șçăèżç§æ
ć”äžïŒéèŠć
git pull
ććč¶ remote ć localïŒç¶ćć git push
ă
Fix: run git pull origin main --rebase
.
Github common commands
Documentation: https://git-scm.com/docs/git-push
You can change the language using the top-right language tab.
äžæïŒhttps://git-scm.com/book/zh/v2/Git-ćæŻ-ćæŻçźä»
git add
Add file contents to the staging area.
git add .
recursively stage changes from the current working directory
git add -A | --all
stage all changes in the Git repository
Q: How to view the commit history?
A: Use git log
. Executing the command would display:
To navigate the list of commits, use the up and down arrow keys. To exit, press q
.
Q: Should I push every single commit?
A: Committing to your local repository you are basically saying âI trust this code.â When you feel you want your teammates to see your changes, you push
to remote. If you collaborate with others, pushing more frequently would have a lower risk of conflict.
Q: What are local and remote repositories?
A:
- Local repositories are about tracking your changes to protect the work you do.
- Remote repositories are for distributing the work to all your teammates and tracking everyoneâs changes.
Git Remote Configurations
git remote
Creating and modifying git remote configurations
Commonly used git remote
subcommands:
-
Create a new connection to a remote repository.
git remote add <name> <url> # Example: add repo name "origin" to the remote repo at the URL git remote add origin https://github.com/my1396/Damage-Function.git
After adding a remote, youâll be able to use
ïŒnameïŒ
as a convenient shortcut forïŒurlïŒ
in other Git commands. -
Remove the connection to the remote repository called
ïŒnameïŒ
.git remote rm <name>
-
Rename a remote connection from
ïŒold-nameïŒ
toïŒnew-nameïŒ
.git remote rename <old-name> <new-name>
-
Show your remotes
git remote
without any flags will list previously stored remote connections$ git remote origin
git remote [-v | --verbose]
show remote URL after name.-v
stands for âverbose.â$ git remote -v origin https://github.com/my1396/Econ-Study.git (fetch) origin https://github.com/my1396/Econ-Study.git (push)
git remote show <remote-repo-name>
give detailed output on the configuration of a remote given by<remote-repo-name>
.$ git remote show origin * remote origin Fetch URL: https://github.com/my1396/Econ-Study.git Push URL: https://github.com/my1396/Econ-Study.git HEAD branch: main Remote branch: main tracked Local branch configured for 'git pull': main merges with remote main Local ref configured for 'git push': main pushes to main (up to date)
Repoâs configuration file
-
Path:
./.git/config
git remote add
command will modify the configuration file.You can directly edit the
./.git/config
file with a text editor. -
Looks like the following
[core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true ignorecase = true precomposeunicode = true [remote "origin"] url = https://github.com/my1396/R-Notes.git fetch = +refs/heads/*:refs/remotes/origin/* [pull] ff = only [branch "main"] remote = origin merge = refs/heads/main [lfs] repositoryformatversion = 0
url
tellsgit fetch origin
where to fetch the repositoryfetch
refspec tellsgit fetch origin
which names to create or update in your own repository.
git rev-parse --is-inside-work-tree
check is a folder is a git repository. Which will print âtrueâ to STDOUT if you are in a git repos working tree.
- Note that it still returns output to STDERR if you are outside of a git repo (and does not print âfalseâ).
git fetch
: downloads commits, files from a remote repository into your local repo, but it doesnât integrate any of this new data into your working files.
git pull <remote>
: fetch
+ merge
. Directly integrates changes into your current working copy files. This command does two main things:
- first, it executes
git fetch
which contacts the remote repository and pulls down any data it doesnât already have, including updates to branches and tags. - Second, it merges one of these branches (usually the corresponding branch) into your current branch, combining the remote changes with your local ones.
Q: Why git fetch
is safer?
A: git fetch
will download the remote content and not alter the state of the local repository. Alternatively, git pull
will download remote content and immediately attempt to change the local state to match that content. This may unintentionally cause the local repository to get in a conflicted state.
Common options of git pull
:
git pull <remote>
Fetch the specified remoteâs copy of the current branch and immediately merge it into the local copy.
git pull --rebase <remote>
fetches the remote content but does not create a new merge commit, Instead of using git merge
to integrate the remote branch with the local one, use git rebase
.
Case scenario: you are working on new-feature
and before you push, you pull
the remote repo to make sure you have the latest code in case some has made changes.
# fectch + merge
git checkout new-feature
git fetch origin
git merge origin
# pull
git checkout new-feature
git pull --rebase origin # append your change to the main
git push [options] <remote-repo> <remote-branch>
: update remote repository with local changes you committed. See HERE for command arguments.
<remote-repo>
: The remote repository that is the destination of a push operation. This parameter can be either a URL or the name of a remote.<remote-branch>
: The name of the branch in the remote repository where the changes should be pushed.
You often encounter git push origin main
when working with git. Why origin
and main
?
-
origin
is the default name given to the remote repository when you clone a repository.It acts as a shorthand for the remote repositoryâs URL (e.g., a repository hosted on GitHub, GitLab, or another Git server).
origin
specifies the remote repository that should receive the changes. -
main
is the name of a branch in your Git repository.By convention,
main
often serves as the default branch for a repository. It typically contains the latest stable version of the code.The branch name specifies which branch in the remote repository should receive the changes. Without specifying the branch, Git might use a default branch or require additional configuration.
Rename File
Rename a file, a directory, or a symlink
git mv [<options>] <source> <destination>
Move or rename a file, directory, or symlink.
<source>
which must exist and be either a file, symlink or directory<destination>
is the new file name, symlink or directory
Basic Syntax
To move or rename a file using git mv, simply specify the existing and new paths of the file after the command:
git mv ./old_directory/old_file.ext ./new_directory/new_file.ext
Renaming or moving files with git mv
preserves the fileâs history and is especially useful in collaborative development to maintain a clear and organized project structure.
- If you do the renaming manually, the change will be recorded as delete and add a new file, the changes of the file wonât be preserved.
# if the file you plan to rename is in your current directory
# use file name directly
git mv gfg1.py gfg2.py
Troubleshooting
fatal: not under version control, source=_posts/2023-10-12-Bibli.md, destination=_posts/2023-10-12-Jekyll-Bibli.md
Cause: The error happens because the parent folder has special character (_posts/
).
Fix: Enclose file names with quotes.
git mv "_posts/2023-10-12-Bibli.md" "_posts/2023-10-12-Jekyll-Bibli.md"
git rm
The primary function of git rm
is to remove tracked files from the Git index. Additionally, git rm
can be used to remove files from both the staging index and the working directory.
-r
the option is shorthand for ârecursiveâ. When operating in recursive modegit rm
will remove a target directory and all the contents of that directory.--cached
The--
separator option is used to explicitly distinguish between a list of file names and the arguments being passed togit rm
. This is useful if some of the file names have syntax that might be mistaken for other options.- The cached option specifies that the removal should happen only on the staging index. Working directory files will be left alone.
Q: Do I need to quote file names?
A: Depends on your shell, has nothing to do with git
.
Most shells âtokenizeâ the command line â that is, split it into a sequence of discrete elements â using whitespace. So, for example
rm one file
will attempt to remove a file named one
and a file named file
, whereas
rm 'one file'
will attempt to remove a single file named one file
.
The principle is
- it does NOT matter whether you quote when your file name/path does NOT contain spaces.
- when you write
commit
messages, usually write inside quotes as it is common to have spaces inside your message.
Git doesnât track directories, so it wonât remove ones that become empty as a result of a merge or other change. However, you can use git clean -fd
to remove untracked directories (the -fd
flag means force removal of untracked files and directories).
git restore .
discards all unstaged files in current working directory use.
For one specific file use: git restore <path/to/file/to/revert>
gitignore
foo/
will match a directory foo
and paths underneath it. foo
and /foo
have the same effect. The leading slash doesnât matter.
*
matches anything (zero, one, or more characters) except a slash /
.
?
matches one single character except a slash /
.
A line starting with #
serves as a comment.
To match files that begin with a hash, put a backslash (â\
â, escape character) in front of the first hash.
Delete a file in .gitignore
after you have already added it to the repo.
How to make Git forget about a file that was tracked, but is now in .gitignore
?
.gitignore
is only for untracked files.
# This removes all files from the repository and adds them back (this time respecting the rules in your .gitignore).
git rm -rf --cached "Shared folder.Rproj"
git add .
git commit -m "clear cache"
git push
If you make changes to your repository, the workflow is add
$\rightarrow$ commit
$\rightarrow$ push.
Undo local changes
Until you push your changes to a remote repository, changes you make in Git are only in your local development environment.
When you make a change, but have not yet staged it, you can undo your work.
git reset --hard
Undo staged local changes:
git reset --hard
Undo committed local changes. When you commit to your local repository (git commit
), Git records your changes. Because you did not push to a remote repository yet, your changes are not public (or shared with other developers). At this point, you can undo your changes.
git-blame
: Show what revision and author last modified each line of a file.
Failure When Push Large Files
Github Error:
-
RPC failed; HTTP 400 curl 22 The requested URL returned error: 400 Bad Request
-
RPC failed; curl 55 Failed sending data to the peer send-pack: unexpected disconnect while reading sideband packet.
This is an HTTP buffer issue. Happens when you are pushing a large amount of data.
Fix:
- Increase the buffer will solve the issue. [Easiest solution] Or,
- you could push by small batches of changes. Or,
- use Git Large File Storage.
git config http.postBuffer 524288000
git pull && git push
Q: what does http.postBuffer
do?
A: This option changes the size of the buffer that Git uses when pushing data to a remote over HTTP or HTTPS.
The default of httpBuffer size is set to 1MB for https. Please note the only acceptable values are 524288000 (500mb), 1048576000 (1 GB) and 2147483648 (2 GB). Anything above it, is considered out of range.
git config http.postBuffer 524288000
will set the httpBuffer size to 500 MB.
To remove the file that you have already committed, you are going to need to reset your HEAD to the commit before the one that contains your file. Make sure you are performing a soft reset.
git reset --soft HEAD~1
1 is the number of commits you need to move back, can be greater than 1.
Git Large File Storage
./install.sh.
install Git Large File Storage from source.
Go to the Git repository where you want to use Git LFS, select the file types youâd like Git LFS to manage (or directly edit your .gitattributes). You can configure additional file extensions at anytime.
git lfs track "*.psd"
git lfs track "*.png"
Now make sure .gitattributes is tracked. Your tracked filesâ details are saved inside a .gitattributes
so make sure to add .gitattributes
to persist tracking when other users clone the project.
git add .gitattributes
You should then be able to safely add, commit and push!
git add file.png
git commit -m "Add design file"
git push origin main
Branch management
Q: What are different branches for?
A: There are different types of branches, including the main branch (usually called âmasterâ or âmainâ), feature branches, release branches, and hotfix branches. Each branch serves a specific purpose and helps developers manage their codebase better.
Q: Can I clone a specific branch?
A: Yes. Run the following code
git clone --branch <branchname> --single-branch <remote-repo-url>
--branch
(two hyphens) can be replaced by -b
(one hyphen).
Cloning a specific branch in Git is a useful feature that allows developers to work on specific features or bug fixes without cloning the entire repository.
But you may want to clone all branches first, and then work on your own branch. When you finish, you can merge your updates into the main
branch. This makes it easier to compare differences and make sure your branch is in sync with with the main
branch.
To this end, you need to run
// this will clone all branches
git clone <remote-repo-url>
Then you could checkout
to one specific branch to work.
These could be achieved by one combined command too with the argument --branch <branchname>
.
// clone all branch then switch to <branchname>
git clone --branch <branchname> <remote-repo-url>
// or using -b alias for --branch
git clone -b <branchname> <remote-repo-url>
A downside of clone
the whole repository is that you will fetch all files from each branch. You might not want this if the repository has a large history.
Collaborations
You can also open Pull Requests between separate branches on GitHub. This often presents a good way for collaborating with people who have access to the same repository. You donât want to all be pushing to the main
branch all the time. Instead, each person can create their own branch, work separately, and then open a pull request to merge that branch into main
.
If you create a local branch in your repo, you can push it to GitHub as follows:
First, make sure that you are on the branch that you want to push:
$ git branch
Then run
# -u option will set up a link between local and remote upstream branches
# -u is used when you have your initial push of your update
$ git push -u origin <branch-name>
to push the current local (active) branch to the remote branch <branch-name>
.
-u
is a shortname for --set-upstream
;
- the 1st parameter is the upstream repo,
- the 2nd parameter is the local repo.
After establishing the upstream at the initial push, you can use git push
with no argument for later updates.
Note that branch names should be matching between local and remote repositories. When you run git push origin main
, Git pushes the commits from your local main
branch to the corresponding main
branch on the remote repository.
-
git branch
with no argument (or with--list
) will print a list of branches linked to the current repo.Could be used to check which branch I am currently on. Your current branch (i.e., the branch that
HEAD
points to) is prefixed by*
and highlighted in green.(base) menghan@Nord16 Shared folder $ git branch * Menghan coauthor master
-
git branch Menghan
create a branch calledMenghan
// create a branch $ git branch <branch-name> // switch to the branch $ git checkout <branch-name>
Or, there is a combined command first creating a branch then switching to it
// create a branch and switch to the branch $ git checkout -b <branch-name>
Now we want to add this branch remotely. All we have to do is push it to our Git provider such as GitHub using the command below:
$ git push -u origin <branch-name>
-
git branch -d Menghan
delete the local branchMenghan
-
git branch -r
show remote-tracking branches.Remote branched are just like local branches, except they map to commits from somebody elseâs repository. Remote branches are prefixed by the remote they belong to so that you donât mix them up with local branches.
MY-Nuffield:Shared folder Menghan$ git branch -r origin/HEAD -> origin/master origin/Menghan origin/coauthor origin/master
Q: What is
HEAD
?
A:HEAD
stores the current commit hash ID, representing the currently checked-out-commit repository.origin/Menghan
,origin/coauthor
, andorigin/master
are remote-tracking names Git created for human to read, Git itself uses big ugly hash IDs.ref: https://stackoverflow.com/questions/74561949/why-does-head-show-up-in-git-branch-remote
Q: What is origin
?
A: origin
is the remote name, stored in your .git/config
.
-
git branch -a
shows both local and remote branches.(base) menghan@Nord16 Shared folder % git branch -a * Menghan coauthor master remotes/origin/HEAD -> origin/master remotes/origin/Menghan remotes/origin/coauthor remotes/origin/master
The first three are local branchesl the last four are remote branches.
-
git branch -M <main>
rename the current branch tomain
.
git push <remote> <remote-branch>
Push commits made on your local branch to a remote rep.
- E.g.,
git push origin main
push your local changes to the remote repository on themain
branch.- Where git push initiates the push,
origin
refers to the remote counterpart of the project, andmain
is the remote branch name. This is common when you are the only contributor to your project, and you want to directly edit the default branch of your project with changes.
- Where git push initiates the push,
<remote>
is the destination remote repo name of a push operation. This parameter can be either a URL or the name of a remote.- When the command line does not specify where to push with the
<remote>
argument,branch.*.remote
configuration for the current branch is consulted to determine where to push. If the configuration is missing, it defaults to origin.
- When the command line does not specify where to push with the
<remote-branch>
is a branch name in the remote repository where the changes should be pushed.
git push origin <branch>
will push the current branch to the remote counterpart of that branch.
git push origin
will push the current branch to the branch of the matching name in the remote repository (aka, âbranch configured upstreamâ), if it exists.
Otherwise, it will not push and notify that the current branch has no remote counterpart (error message: â<branchname> has no upstream branchâ).
-
The default branch in your project is conventionally a branch named âmainâ. This branch is the version of the project that goes into production or the version from which you will create further branches to isolate changes, and merge back into the default branch.
-
If a project you are working on is older, the default branch might be named âmasterâ, which GitHub changed to remove references to slavery in conventional terminology. Itâs important to check the name of the default branch.
-
-u
, or--set-upstream
:git push -u origin main
orgit push --set-upstream origin main
Creates a remote branch and sets it upstream of the current branch you are pushing. The relationship between the current branch and upstream branch is remembered, such that you will not have to continually connect the remote and local branches when pushing commits.
- It is recommended to use
-u
flag for the first push on a specific branch. When you use the-u
flag, Git will create a link between your local branch and the remote branch. - Once a link btw your local and remote branches is created, you donât need to specify repo and branch in the future
pull
andpush
, Git will remember which remote branch corresponds to your local branch.
- It is recommended to use
-
-f
,--force
: Pushes that would delete or overwrite existing code are usually blocked. With this command, pushes from your local repository would be forced onto the remote repository, potentially deleting or overwriting other commits! -
-d
,--delete
: Deletes the remote branches listed. Eg,git push origin --delete <branch name>
-
--all
: Pushes all local branches to remote repository
Solve the no upstream branch
error message: create a remote branch with the same name as the local branch and push changes to the remote branch (aka, âset upstreamâ).
$ git push --set-upstream origin
.
Merge
git merge <source-branch>
add the changes from <source-branch>
into your current branch. Use this command when you have finished building a feature in a separate branch, u.e., <source-branch>
, and want to bring those changes into your current branch.
To do a merge (locally), git checkout
the branch you want to merge INTO. Then type git merge <branch>
where <branch>
is the branch you want to merge FROM.
git checkout main # switch to the main branch
git merge new-feature # merge updates in new-feature to main
Now the main
branch is in sync with new-feature
.
When creating a merge commit Git will attempt to auto magically merge the separate histories for you. If Git encounters a piece of data that is changed in both histories it will be unable to automatically combine them. This scenario is a version control conflict and Git will need user intervention to continue.
Resolve conflicts: git mergetool
to check where the conflict occurs and why it occurs.
-
To see that which is the first edited text of the merge conflict in your file, search the file attached with conflict marker
<<<<<<<
.-
You can see the changes from the HEAD or base branch after the line
<<<<<<< HEAD
in your text editor. -
Next, you can see the divider like
=======
. It divides your changes from the changes in the other branch, followed by>>>>>>> BRANCH-NAME
. In the above example, user1 wrote â<h1> Git is a version control</h1>â in the base or HEAD branch and user2 wrote â<h2> Git is a version control system </h2>â. -
Decide whether you want to keep only your branchâs changes or the other branchâs changes, or create a new change. Delete the conflict markers
<<<<<<<
,=======
,>>>>>>>
and create final changes you want to merge.
-
To accept the changes, use the rebase
command. git rebase --continue
git checkout <Menghan>
switch to the branch Menghan
.
git checkout .
will forgo all unstaged changes.git checkout -b <new-branch>
create a new branch namednew-branch
and then checked out.
git branch (-m | -M) [<oldbranch>] <newbranch>
<oldbranch>
will be renamed to <newbranch>
. If <oldbranch>
had a corresponding reflog, it is renamed to match <newbranch>
, and a reflog entry is created to remember the branch renaming. If <newbranch>
exists, -M
must be used to force the rename to happen.
git remote add <name> <url>
Add a remote named <name>
for the repository at <url>
. This is used to configure the remote repo, created a reference using the repo <url>
.
-
<name>
is a short remote name for your reference. -
Now you can pass that remote name
<name>
togit fetch <name>
to download the contents.
Fetch a specific branch use git fetch <remote repo name> <branch name>
. E.g., git fetch origin test
.
Difference of fetch
from pull
: fetch does not merge; pull automatically merge remote to the current branch.
git update-index --skip-worktree <file>
causes the following error
The following pathspecs didnât match any eligible path, but they do match index entries outside the current sparse checkout:
-
If what you want to do is to remove that
<file>
and index entry, unset theskip-worktree
flag first, withgit update-index --no-skip-worktree "Shared folder.Rproj"
, and thengit rm
will work as expected. -
If what you want to do is to just remove the index entry, you can do that directly, at the core-command level,
git update-index --force-remove "Shared folder.Rproj"
, or unset the flag as above thengit rm --cached
it.
git push origin --delete Menghan
delete a remote branch.
git push -u origin Menghan
push updates from Menghan
(local) to origin
(remote) branch. -u
is equivalent to --set-upstream
.
Check history on Github
Code $\rightarrow$ History $\rightarrow$ click one commit, this will show your revision history.
Local repository content will change according to which branch you checkout
in terminal. You make changes at your local branch, then you merge the updates to the master
branch.
If your branch is ahead of your master â You get that message because you made changes in your local master and you didnât push them to remote. You need to navigate to master
and merge the change from the local branch.
Use the following code to fix the ahead problem.
git add -A
git commit -m "My commit"
git checkout master # have to first checkout to master [receiving branch]
git merge Menghan # merge from Menghan --> master
git push -u origin master # push master changes from the current branch to the remote repo master branch.
If your branch is behind your master: navigate to the local branch and merge change from master
.
git checkout master # you are switching your local branch to master
git pull # pull update from remote master
git checkout Menghan # switch back to your branch [receiving branch]
git merge master # from master --> Menghan
After merging it, check if there is a conflict or not. If there is NO CONFLICT then:
(base) menghan@Nord16 Shared folder $ git push
Everything up-to-date
If nothing was pushed, it is likely Git did NOT push the currect branch. In this case, you can explicitly specify the branch you want to push as follows.
(base) menghan@Nord16 Shared folder $ git push origin Menghan
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
To https://github.com/my1396/Damage-Function.git
39b1b00..6d5a038 Menghan -> Menghan
If there is a conflict then manually fix your file(s), then:
git add yourFile(s)
git commit -m 'updating my branch'
git push
Merge with GitHub Desktop
You want to merge master
(source) into Menghan
(target)
-
Navigate to the target repo
Menghan
-
Click menu bar Branch â Merge into the current branch
-
In the âMerge into
Menghan
â dialog box, click the source repomaster
-
Now
Menghan
is in sync withmaster
. You can push your local changes to the remote repository, in the repository bar, clickPush origin
.
Best Practices for Team Collaboration
Your repositoryâs main
branch, which is regarded as the authoritative branch, is the only branch present by default. Each co-author has their own branches where they make changes on. When they fill the changes are mature/final, they push to the main
branch.
-
Open the repo:
cd Repo-Name
(e.g.,cd budget-frontend
) -
Ensure you are on the main branch:
git checkout main
-
Ensure you are up-to-date:
git pull
You definitely want to make sure your project is up to date before you push your changes. Otherwise, you risk breaking the build for others.
-
Create a new branch for your task:
git checkout -b Your-Branch
-
Code on
Your-Branch
-
Add updates, commit, push to your remote branch
origin/Your-Branch
. -
Merge with the
main
branch.
Itâs a good practice to run git pull -r
before making any changes in your local repository.
This makes sure you have got the latest code in case someone may have changed the remote repo. If there are changes on the remote branch that you havenât pulled, you might encounter conflicts when you try to push your changes later.
-r
or --rebase
bases your changes from the current version from the repository. If you started doing some development and then another developer made an unrelated change.
git rebase
would fetch the changes from the remote repository and put them before/under your local branch without creating a merge
commit. Itâs particularly useful for maintaining a linear project history.
The following is a diagram of rebasing a Feature
branch onto main
. After rebasing, your Feature
will be on the tip of main
branch. This is like saying, âadd my changes to what my team members have already done.â
By default, the git pull
command performs a merge
, but you can force it to integrate the remote branch with a rebase by passing it the --rebase
option.
The major benefit of rebasing is that you get a much cleaner project history.
- First, it eliminates the unnecessary merge commits required by
git merge
. - Second, as you can see in the above diagram, rebasing also results in a perfectly linear project historyâyou can follow the tip of
feature
all the way to the beginning of the project without any forks.
Q: Are there any downsides/pitfalls with rebase
?
A: TL; DR: git rebase
will rewrite the project history, make it impossible for Git and your teammates to track any follow-up commits added to the feature.
Long Answer:
- Because a
rebase
moves commits (technically re-executes them), the commit date of all moved commits will be the time of the rebase and the git history might look like it lost the initial commit time.- So, if the exact date of a commit is needed in all tooling for some reason, then
merge
is the better option. But typically, a clean git history is much more useful than exact commit dates. - And the author-date field will continue to hold the original commit date where needed.
- So, if the exact date of a commit is needed in all tooling for some reason, then
- If the rebased branch has multiple commits that change the same line and that line was also changed in the base branch, you might need to solve merge conflicts for that same line multiple times, which you never need to do when merging. So, on average, thereâs more merge conflicts to solve.
The following shows a diagram of merging main
to Feature
.
An example of when git pull --rebase
could be useful: see Stack Overflow Page.
Q: When you use git rebase
instead of git merge
?
A: See a full discussion HERE. But in short,
merge
executes only one new commit.rebase
typically executes multiple (number of commits in current branch).merge
produces a new generated commit (the so called merge-commit).rebase
only moves existing commits.
Q: What is a merge
?
A: A commit, that combines all changes of a different branch into the current.
Q: What is a rebase
?
A: Re-comitting all commits of the current branch onto a different base commit.
Q: In which situations should we use a merge
?
A: Use merge whenever you want to add changes of a branched out branch back into the base branch.
Q: In which situations should we use a rebase
?
A: Use rebase
whenever you want to add changes of a base branch back to a branched out branch.
Q: What does it mean by âmerge
creates unnecessary merge commitsâ?
A: If multiple merges were needed in a feature branch, then the feature branch might even hold more merge commits than actual commits! Below is an example of Git hisotry when using merge
:
Note the many commits starting with Merge branch 'main' into ...
. They donât even exist if you rebase (there, you will only have pull request merge commits). Also many visual branch merge loops (main
into feature
into main
).
Q: How does a Git history look like when using rebase
?
A: Much cleaner Git history with much less merge commits and no cluttered visual branch merge loops whatsoever. Looks like the following:
Squash Commits
âCommit early, commit oftenâ is a popular mantra in software development when using Git. However, this can also lead to an overabundance of commits.
This is where the importance of squashing commits comes into play. Commits can be combined into a single commits by squashing.
For instance, letâs say we work on a feature implementing a login form, and we create the following four commits:
Once the feature is completed, for the overall project, these commits are too detailed. To ensure a clean history in the main branch, we squash these commits into a single commit:
The most common method to squash commits is using an interactive rebase. We start it using the command:
git rebase -i HEAD~<number_of_commits>
Replace <number_of_commits>
with the number of commits we want to squash.
In our case, we have four commits, so the command is:
git rebase -i HEAD~4
Remember again that this is a rebasing commandâââevery commit in the range HEAD~4..HEAD
with a changed message and all of its descendants will be rewritten.
âïžDonât include any commit youâve already pushed to a central serverâââdoing so will confuse other developers by providing an alternate version of the same change.
Executing this command will open an interactive command-line editor that looks something like this:
We see four commits that are listed in the opposite order. For each, we must decide which command to execute. We care about the pick
(p
) and squash
(s
) commands.
To squash these four commits into a single commit, we can pick
the first one and squash
the remaining three.
After we have made the changes, the scirpt should look like:
When you save and exit the editor, Git will execute the script and open a new text editor. The editor will display a default message comprising the messages from the four commits we are squashing:
Enter the commit message to accurately reflect the changes implemented by these combined commits.
Pusing Squashed Commits
The command above will act on the local repository. To update the remote repository, we need to push our changes. However, because we changed the commit history, we need to force push using the --force-with-lease
option:
git push --force-with-lease origin feature/login-form
This option ensures we only force push if the remote branch hasnât been updated since our last fetch or pull.
References:
https://www.datacamp.com/tutorial/git-squash-commits
https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History
Gists
Q: When should I use a Gist instead of a full-fledged Git repo?
A: Gist is meant for sharing code snippets. Usually, you either edit online directly or edit locally then copy-paste online, which will overwrite your whole hisotry. Not ideal if you want to track excactly what you changed every time.
- Gist: If itâs pieces of code designed to demonstrate a technique, teach a principle, or show off a solution, it goes in a Gist.
- GitHub: If itâs actual code intended to be run, used as is, or forked as boilerplate I put it in a proper repository. For each project, you build a Git repository, where you can have multiple directories and organize different file types, track changes, etc.
Q: Should I clone Gist locally so that I manage it as a regular Git repo?
A: No, I wouldnât do it. Each Gist will be one folder named by the Gist ID. It is not human readable. You can put it in a parent folder with a readable name, but imagine you have many Gists, then you have many (at least) two-level folders.
There is a workaround if you really need to edit locally. You can use the GistPad extension on VS Code. You can open, create, delete, fork, archive, and star gists/repositories, and then seamlessly begin editing files as if they were local, without ever cloning, pushing or pulling anything.
Q: How about put all Gist in one regular repo?
A: Not goog as you are putting lots of unrelated things together.
GitHub Status Page
Check GitHubâs status page to see if there are any ongoing issues with GitHub Actions or infrastructure that might be causing delays.
GitHub Education Benefits
GitHub Copilot is free to use for open source maintainers, teachers and students. We check eligibility monthly, per our policies.
-
Free: 50 agent mode or chat requests per mont; 2,000 completions per month
A âcompletionâ is counted each time Copilot provides a code suggestion, regardless of whether itâs accepted or not.
So nearly every char I type is one completion (as the suggestions change while I type) â no wonder that the free credits are gone in no time.
- Premium requests: up to 50 per month
-
Pro: Unlimited agent mode with GPT-4.1 and chats with GPT-4.1. Unlimited code completions.
- price: $10/mon.
- Premium requests: up to 300 per month
Q: What count for Premium requests?
A: Copilot Chat, agent mode, code review, and Copilot Extensions use premium requests, with usage varying by model. Purchase additional premium requests at $0.04/request.
Q: How to see how many requests I have left?
A: Click Copilot icon in the bottom left corner of VS Code
You can view information about
- features included in your plan,
- your progress towards any limits on your plan, and
-
the date your allowance resets.
The allowance resets on the first day of each month.
Application
After uploading proof, application was approved within five minutes.
Your academic benefits will become available within 72 hours of your verification.
The waiting time may vary depending on different factors, such as the volume of requests; it usually takes a few days, but sometimes it can take a little longer, even a couple of weeks.
You will receive an email and the GitHub show âcoupon applied.â Click the link to accept the access.
To redeem your Copilot Pro coupon, please sign up via this link.
After you click the link, the following page shows up.
If you have the GitHub Copilot extension already installed for your code editor and have it open, please restart your editor in order to access GitHub Copilot.
Valid for two years once approved. Expires in July 2027.
Once the benefits become available, you will be able to upgrade your organizations to GitHub Teams via your GitHub Education dashboard.
Benefits
Use of GitHub Copilot
-
GitHub Copilot is specifically designed for programming.
-
Copilot for inline code completion: the gray text represents ghost text with Copilotâs suggestions.
Accept suggestions with Tab.
-
Copilot Chat
- Type
/explain
and hit enter. Copilot will give you a detailed explanation of whatâs happening in the code. - Type your request and hit enter. Copilot will give you a plan, an updated code block, and a list of suggested changes. Hover over the code block, click the âApply in Editorâ button to accept the changes, and GitHub Copilot will make the updates for you.
- Type