Getting familiar with git - jniedzie/SVJanalysis_wiki GitHub Wiki
If you've never heard of the terms git
and GitHub
, or always wonder how to pull changes while you tons of uncommited changes, this tutorial is for you 😃
In a nutshell, git
is version control software that keeps track of the changes you make - such that you can understand what happened / revert changes if you broke your code - and allow several people to work together on the same project by taking care of "merging" their individual developments and "resolving conflicts" if need be.
GitHub
is online tool where you can safely store or share your code. In case your laptop dies, the code is still available on the GitHub servers, and anyone you wish to share the code with can download your code from GitHub.
If you haven't done it already, create and setup your git account by following the instructions in Setup your git account. Replace username by your user name in the command lines in this page.
Go to your GitHub account on your browser (https://github.com/username) and create a new repo called git_tutorial
. You can make it private for the purpose of this tutorial.
Now log in on the T3 and go to your tutorials
directory that was created in the Getting familiar with the terminal and command lines tutorial, or create it if you skipped this tutorial.
Now let's clone to repo (short for repository):
git clone [email protected]:username/git_tutorial.git
You should see the following message:
Cloning into 'git_tutorial'...
warning: You appear to have cloned an empty repository.
Don't worry, it's normal that your repo is empty at this stage!
Go into your repo:
cd git_tutorial
This step is only to be done for this tutorial. If the repo already exists, then the main branch already exists. Let's create the main branch:
git checkout -b main
You should see
Switched to a new branch 'main'
Create a file
echo "git_tutorial" > README.md
You can see that this file is not tracked and cannot be committed yet:
git status
You should see
$ git status
# On branch main
#
# Initial commit
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# README.md
nothing added to commit but untracked files present (use "git add" to track)
Add this file to the list of files to track for commits:
git add README.md
You can check that it has indeed been added to the list of tracked files:
git status
gives
# On branch main
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# new file: README.md
#
Now commit the changes:
git commit -m "First commit" README.md
Note: The text after -m is essential, it describes your commit. Try to use short and accurate description. Text like -m "change"
are prohibited.
Note 2: You do not need to add README.md
in this last command. git commit -m "First commit"
will commit all files that are in the list of tracked files and that have changed. This is useful if you have multiple changes and only make a commit for some of the modified files. The syntax is git commit -m "message" file1 file2 file3
You can check the list of commits done by using git log
:
commit 1d6c017e5466926688bc5cdb321309467a1a87cb
Author: Florian Eble <[email protected]>
Date: Wed Feb 22 11:31:15 2023 +0100
First commit
This commit has only been registered on your local branch on the T3 machine. To save the changes on GitHub, you need to push it to your remote branch. You can check that a remote destination already exists:
git remote -v
shows
origin [email protected]:username/git_tutorial.git (fetch)
origin [email protected]:username/git_tutorial.git (push)
This is where we created the repo. The name of the remote is called origin
.
Let's push the changes:
git push origin main
You can now go to the repo on GitHub and see that the commit has been pushed.
It is advised to never push directly to the main branch, because there is no code review and it is harder to solve conflicts / changes can erased if force pushing. Never force push!!!
Instead what we do is to create a development branch. Let's create our development branch! Replace username by your username or name in this command line:
git checkout -b devel_username
You can check the different local and remote branches by doing:
git branch -a
Let's create a new file:
echo 'echo Hello World!' > hello_world.sh
which you must add and commit. Try not to look at the solution yet!
Solution
git add hello_world.sh git commit -m "Adding hello world" hello_world.sh
Now we can push this new branch to the remote! Replace username by your name/username.
git push origin devel_username
You should see that a new branch has been created:
Counting objects: 4, done.
Delta compression using up to 72 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 307 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote:
remote: Create a pull request for 'devel_username' on GitHub by visiting:
remote: https://github.com/username/git_tutorial/pull/new/devel_username
remote:
To [email protected]:username/git_tutorial.git
* [new branch] devel_username -> devel_username
But your changes have not been added to the main branch, for this you need to do a merge request (aka pull request, or PR), as instructed in the above message. Copy the link in the text above (replacing by your username of course!) in your browser to make the PR. You can change the title and add a description if you wish. When you are done, click on Create pull request
.
At this stage, another team member should review your changes, approve them and merge your PR. To do so, you should click on the Files changed tab
where you can see the changes, add comments at places where you think the code should be improved.
For this tutorial we will merge the PR ourselves. Click on Merge pull request
and Confirm merge
. Click on Code
, you should now see your hello_world.sh
file on the remote branch main!
Important note: In real life, you would not merge your own PR, but only open it, and let your colleagues review your work. They will make comments and you can push commits to answer those comments. Once they are happy with the code, they will merge it!
Let's imagine that a colleague decided to write different than yours and make a PR. There will be a conflict! We will here simulate such a situation:
git checkout main
git checkout -b devel_colleague
echo 'echo Hello Crowd!' > hello_world.sh
git add hello_world.sh
git commit -m "Adding hello crowd" hello_world.sh
git push origin devel_colleague
Open a PR from devel_colleague
to main
. You should see Can't automatically merge
:
Click on Create pull request
. You can now see that the Merge pull request
is frozen, you cannot merge your colleague changes. Click on Resolve conflicts
.
You should see:
You can review the conflict and decide that your code makes the most sense 😉. So let's keep your code by editing the code on the online editor:
and click on Mark as resolved
and Confirm merge
. Click on Merge pull request
and Confirm merge
.
Note that your colleague needs to pull the changes before pushing to his remote development branch:
echo "Version 1.0" >> README.md
git commit -m "Adding version number" README.md
git push origin devel_colleague
will result in:
To [email protected]:username/git_tutorial.git
! [rejected] devel_colleague -> devel_colleague (fetch first)
error: failed to push some refs to '[email protected]:username/git_tutorial.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first merge the remote changes (e.g.,
hint: 'git pull') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
As instructed, pull changes from the remote:
git pull origin main
you will directly enter the default git text editor and will see:
Merge branch 'devel_colleague' of github.com:username/git_tutorial into devel_colleague
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
Write a meaningful description, like:
Merging after resolving conflicts
And exit the text editor. You will then see:
remote: Enumerating objects: 2, done.
remote: Counting objects: 100% (2/2), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 2 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (2/2), done.
From github.com:username/git_tutorial
* branch devel_colleague -> FETCH_HEAD
Merge made by the 'recursive' strategy.
hello_world.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
git log
now shows a complex history:
See git log output
commit 239e924f1cd4236a93ebaaa28a07b7e3eb95bbc7 Merge: 0aa111d 6ae1c5d Author: Florian Eble Date: Wed Feb 22 14:12:01 2023 +0100Merge branch 'main' of github.com:fleble/git_tutorial into devel_colleague Merging after resolving conflicts
commit 0aa111db89ad0ba8cbea3a7cc49b472c8a274276 Author: Florian Eble [email protected] Date: Wed Feb 22 14:11:37 2023 +0100
Adding version number
commit 6ae1c5d027b72ac9055b3930a160af293216fd81 Merge: f4d8b06 dd0c6da Author: Florian Eble [email protected] Date: Wed Feb 22 14:10:05 2023 +0100
Merge pull request #2 from fleble/devel_colleague Adding hello crowd
commit dd0c6da02aa367a7bc135eb0c4581b59d308786b Merge: 9167a45 f4d8b06 Author: Florian Eble [email protected] Date: Wed Feb 22 14:09:47 2023 +0100
Merge branch 'main' into devel_colleague
commit 9167a45b8aa66ade383a22c1f58d87daa50adecf Author: Florian Eble [email protected] Date: Wed Feb 22 14:09:02 2023 +0100
Adding hello crowd
commit f4d8b0621cb260a053adca555ed50b046ac994b1 Merge: 0793ccc 7cf219e Author: Florian Eble [email protected] Date: Wed Feb 22 14:08:39 2023 +0100
Merge pull request #1 from fleble/devel_fleble Adding hello world
commit 7cf219eee8b34eb2296958d4ac674447f2ee032d Author: Florian Eble [email protected] Date: Wed Feb 22 14:07:54 2023 +0100
Adding hello world
commit 0793cccaba9a10a5959a61087decd888849e3159 Author: Florian Eble [email protected] Date: Wed Feb 22 14:07:18 2023 +0100
First commit
Now your colleague can push his changes to the remote!
git push origin devel_colleague
You can also do the same in the terminal by pulling changes before pushing! Sometimes you do not have a choice, some conflicts cannot be resolved in the web editor, like when a file has been deleted/renamed by someone, and you modified it. Instructions are provided by git after you pulled.
Let's simulate this situation: Go to GitHub and open a PR to merge your colleague's latest developments.
Solution
1. Go to https://github.com/username/git_tutorial 2. Click on Pull requests 3. Click on New pull request 4. Change the compare branch to devel_colleague 5. Click on "Create pull request" 6. Click on "Create pull request" again 7. Click on "Merge pull request" and "Confirm merge"
Now execute the following commands in your terminal:
git checkout devel_username
echo "Version 2.0" >> README.md
git commit -m "Adding version number" README.md
Before pulling, check for conflicts by pulling changes from the main:
git pull origin main
You should see:
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (1/1), done.
From github.com:username/git_tutorial
* branch main -> FETCH_HEAD
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.
The output of the previous command informs you that the conflict is in README.md.
Open README.md
, you should see:
git_tutorial
<<<<<<< HEAD
Version 2.0
=======
Version 1.0
>>>>>>> 5f0418ddea0b779eb264a7be112f386ec54f9142
Edit into:
git_tutorial
Version 2.0
If you do a git status
you can see the conflict and what to do:
# On branch devel_fleble
# You have unmerged paths.
# (fix conflicts and run "git commit")
#
# Unmerged paths:
# (use "git add <file>..." to mark resolution)
#
# both modified: README.md
#
no changes added to commit (use "git add" and/or "git commit -a")
Apply the instructions:
git add README.md
git status
informs you of the current status:
# On branch devel_fleble
# All conflicts fixed but you are still merging.
# (use "git commit" to conclude merge)
#
nothing to commit, working directory clean
As instructed, do:
git commit
You will see:
Merge branch 'main' of github.com:fleble/git_tutorial into devel_fleble
Conflicts:
README.md
#
# It looks like you may be committing a merge.
# If this is not correct, please remove the file
# .git/MERGE_HEAD
# and try again.
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch devel_fleble
# All conflicts fixed but you are still merging.
# (use "git commit" to conclude merge)
#
You can add more info, or just exit the editor as the description is already pretty clear!
git log
shows a complex history.
See git log output
commit 6639602ebde973e01b5612e0bf874caeec0aede7 Merge: e84cfdd 5f0418d Author: Florian Eble Date: Wed Feb 22 14:30:44 2023 +0100Merge branch 'main' of github.com:fleble/git_tutorial into devel_fleble Conflicts: README.md
commit e84cfdd2fc273758e57fa1d1249cb320c2edcbe3 Author: Florian Eble [email protected] Date: Wed Feb 22 14:23:12 2023 +0100
Adding version number
commit 5f0418ddea0b779eb264a7be112f386ec54f9142 Merge: 6ae1c5d 239e924 Author: Florian Eble [email protected] Date: Wed Feb 22 14:22:10 2023 +0100
Merge pull request #3 from fleble/devel_colleague Devel colleague
commit 239e924f1cd4236a93ebaaa28a07b7e3eb95bbc7 Merge: 0aa111d 6ae1c5d Author: Florian Eble [email protected] Date: Wed Feb 22 14:12:01 2023 +0100
Merge branch 'main' of github.com:fleble/git_tutorial into devel_colleague Merging after resolving conflicts
commit 0aa111db89ad0ba8cbea3a7cc49b472c8a274276 Author: Florian Eble [email protected] Date: Wed Feb 22 14:11:37 2023 +0100
Adding version number
commit 6ae1c5d027b72ac9055b3930a160af293216fd81 Merge: f4d8b06 dd0c6da Author: Florian Eble [email protected] Date: Wed Feb 22 14:10:05 2023 +0100
Merge pull request #2 from fleble/devel_colleague Adding hello crowd
commit dd0c6da02aa367a7bc135eb0c4581b59d308786b Merge: 9167a45 f4d8b06 Author: Florian Eble [email protected] Date: Wed Feb 22 14:09:47 2023 +0100
Merge branch 'main' into devel_colleague
commit 9167a45b8aa66ade383a22c1f58d87daa50adecf Author: Florian Eble [email protected] Date: Wed Feb 22 14:09:02 2023 +0100
Adding hello crowd
commit f4d8b0621cb260a053adca555ed50b046ac994b1 Merge: 0793ccc 7cf219e Author: Florian Eble [email protected] Date: Wed Feb 22 14:08:39 2023 +0100
Merge pull request #1 from fleble/devel_fleble Adding hello world
commit 7cf219eee8b34eb2296958d4ac674447f2ee032d Author: Florian Eble [email protected] Date: Wed Feb 22 14:07:54 2023 +0100
Adding hello world
commit 0793cccaba9a10a5959a61087decd888849e3159 Author: Florian Eble [email protected] Date: Wed Feb 22 14:07:18 2023 +0100
First commit
You can now push to your remote branch:
git push origin devel_username
and make a PR to the main branch. There is no conflict to resolve because you have already resolved it! You can look at the changes in the tab Files changed
:
Note that you can view changes in the terminal before you commit using git dif
:
echo "My name is ..." >> hello_world.sh
git diff hello_world.sh
shows:
diff --git a/hello_world.sh b/hello_world.sh
index a66926d..4b67ed3 100644
--- a/hello_world.sh
+++ b/hello_world.sh
@@ -1 +1,2 @@
echo Hello World!
+My name is ...
From this you know that the difference is that you added the line My name is ...
You can also view changes in most IDE, like VSCode.
Congratulations! You finished this tutorial! You can now install the framework (FW) following instructions in the Installation page.
Sometimes it happens that you have changes you don't want to commit now, and you want to pull changes from the main, or need to do it to solve conflicts for making a PR. This can become quite cumbersome. Here is a way to do this:
# Go to the root of the repository
git add -u .
git commit -m "Commit before pulling"
git pull --rebase origin main
# You might need to solve conflicts at this stage, follow instructions from git, you can abort at any time
git reset HEAD~
Some explanations:
-
git add -u .
add all files to the commit list. -
git pull --rebase origin main
pulls changes from main, putting your commits on top. -
git reset HEAD~
removes your commit "Commit before pulling" without discarding any changes!