License : Creative Commons Attribution 4.0 International (CC BY-NC-SA 4.0)
Copyright :
Hervé Frezza-Buet,
Jérémy Fix,
CentraleSupelec
Last modified : April 26, 2024 02:04
Link to the source : index.md
When you work with a computer, as a team or alone, you often need to save your progress, go back to a previous state of your work, allow for collaborators to contribute. This is what git
is used for.
Using git
is very simple, it does not require any complicated install or setup. This is why, even for a simple student labwork, handling your project directory with git
is a good and lightweight idea.
git
This labwork makes a quite rapid presentation of git
and you are recommended to read the git
manual (Pro Git) available on the git homepage
, as well as some nice contributions:
git
commands.The main Git elements are :
A file database. It is a directory (quite hidden to the user since it is within the .git
directory) where all the versions of the files managed by git are stored. A specific version of some specific file that is stored is called a “blob” (Binary Large OBject). git
does not manage “delta”s, i.e. it does not store an original file and then the successive modifications (i.e. deltas) that occurred to it. It stores a full copy of the first version of the file (one blob), a full copy of the second version (another blob corresponding to the same file), etc.
A working directory. This is the directory of your project. Git puts here the appropriate version of the files that it manages when, for example, you ask it to retrieve some specific version of your project. This is what the user sees, so git modifies the files in the working directory when you ask it to see something else.
A stage/index. Let us call it index. This contains the “current” version of all the files that git
handles. This is not the working directory, since a file in the working directory may have been modified compared to the version that is stored in the index. The index can be viewed as the last snapshot, under construction, of your project that git knows.
The history of commits. Commits are snapshots of your project (one commit is very similar to what the index is). They are organized as a tree, as detailed further. This tree organization makes git able to organize the snapshots as an history of your project life, allowing several “stories” to be followed in parallel, as explained further.
The main element of git is a “commit”. It can be viewed as a snapshot of your entire project. This snapshot is indeed the list of the blob references corresponding to the files (at the right version) that belong to the picture. The index (or staging area) can be viewed as the current snapshot, under construction. We can progressively add elements to the index and, at some point, create a commit from the index; git
then registers the snapshot and assigns it a label.
The files in the working directory can have different status:
untracked : No version of them is actually present in the index, i.e. git does not take care of them.
tracked : Git knows about them, i.e. the index contains a version of the file. A tracked file can itself have one of the following status:
unmodified : the file in the working directory is the same as in the index
modified : the file in the working directory is different from the index
staged : modifications of the file have been added to the snapshot under construction
Note that a file can be both modified and staged if, at some points, we decided to store a version of the file in the index and the file was later modified without being again added to the index.
In order to change the status of a file within the index you can call the following command :
git add myfile
: this adds the file myfile
in the index (it becomes tracked if not already, or staged if already tracked), with the version corresponding to what myfile is in the working directory. This is useful when you add a brand new file to the index, or when you want to notify the index that your file has changed.
git rm myfile
: This removes the file myfile
from the index, as well as from the working directory.
The current state of the index (and the working directory) can be seen by the command git status
When you are ready to take a snapshot of the current state of the index, you can do it (and save the snapshot) by creating a “commit”. The command is git commit -m "some message"
. You are expected to write an informative commit message.
The commit is a bit more than a snapshot of the index. As a snapshot, it consists of a list of blob names, i.e. the list of the files in a specific version. It also contains an information about some “parent” commit (there are sometimes several parents). A parent commit of a commit can be seen as the snapshot that was taken just before. So examining a commit, its parent(s), the parent(s) of its parent(s)… we can unroll the history of your project modifications.
The elements gathered by git
are a bag of blobs, a bag of commit, each one referencing a list of blobs and some parent commit(s). That is mainly it !
Once you know the reference of a commit, you can ask git
to “realize” it in the working directory, in order to retrieve (we say checkout
) the project state corresponding to that snapshot. Then, git writes or overwrites in the working directory the files whose blobs are listed in the commit, i.e. it restores the version of all the files mentioned in the commit.
Nevertheless, the idea is not to be able to list all the commits i,wn the “bags of commits” handled by git and ask for the realization of one of them in the working directory. Commits are indeed accessible by “branches”.
A branch is nothing more than a reference to one specific commit. So when you have a branch at your disposal, you can access to the commit it refers… but also, from that commit, to its parent(s), and the parent(s) of the parent(s)…. recursively.
In other words, a branch is an entry point to some snapshot of your project that enables you to see all the history until this point.
It is time to do some experiments. In some directory, type
mylogin@mymachine:~$ mkdir git_labwork
mylogin@mymachine:~$ cd git_labwork
mylogin@mymachine:~/git_labwork$ mkdir getting_started_project
mylogin@mymachine:~/git_labwork$ cd getting_started_project
mylogin@mymachine:~/git_labwork/getting_started_project$ git init
git
may refuse to do anything while you have not filled your name and e-mail in the global configuration files. Do it when you are asked to, git
tells you how to proceed.
Now, the directory getting_started_project
is the git
working directory, and all the necessary stuff to handle versioning of that directory is set up (it is indeed hidden in the .git
sub-directory)
mylogin@mymachine:~/git_labwork/getting_started_project$ ls -al
Let us create three empty text files in the directory, and see that they are untracked. Execute the following commands one by one.
mylogin@mymachine:~/git_labwork/getting_started_project$ touch animals.txt objects.txt concepts.txt
mylogin@mymachine:~/git_labwork/getting_started_project$ git status
We have just created three empty files in our working directory.
We now build up our first snapshot by adding entries into the index.
mylogin@mymachine:~/git_labwork/getting_started_project$ git add animals.txt
mylogin@mymachine:~/git_labwork/getting_started_project$ git status
mylogin@mymachine:~/git_labwork/getting_started_project$ git add objects.txt concepts.txt
mylogin@mymachine:~/git_labwork/getting_started_project$ git status
Now, the three files are in the index.
Edit animals.txt, write “fish” in it, and save. Then try
mylogin@mymachine:~/git_labwork/getting_started_project$ git status
Git tells you that you have added previously this file in the index, but that the working directory contains a newer version. As git suggests, you can either overwrite that new version with the one that is currently in the index (i.e. without the fish), or, on the contrary, overwrite the file in the index with the new version of the file that is in the working directory. The former is the checkout
command, the latter, that we will actually do, is the add
command.
mylogin@mymachine:~/git_labwork/getting_started_project$ git add animals.txt
mylogin@mymachine:~/git_labwork/getting_started_project$ git status
Let us see that we have no commit yet and no branch. To see the currently available branch (i.e. entry points to commit histories), type
mylogin@mymachine:~/git_labwork/getting_started_project$ git branch
You see… nothing !
Ok, let us build our first commit. Let us call it “c-001”. Usually, give it a name corresponding to what you have done. Here, it should rather be “Creation of first .txt files”.
mylogin@mymachine:~/git_labwork/getting_started_project$ git commit -m "c-001"
Now, retry
mylogin@mymachine:~/git_labwork/getting_started_project$ git branch
mylogin@mymachine:~/git_labwork/getting_started_project$ git status
The command git branch
shows that git
has automatically created a branch for you. This branch is indeed an entry to your first commit. It is named “master”. The last commit is indeed the commit we have just created. In git
, there is a variable called “HEAD” that corresponds to the “commit currently considered”. Here, HEAD refers to the commit referred to by branch “master”. This is why you have a symbol "*" in front of the branch name “master”.
Note that now, the index and the commit “c-001” refer to the same blobs, i.e. the same version of the three *.txt
files that are stored in the git
internal database. Let us go further in the history.
Modify the objects file and add a “lamp” in it. Let us take a new snapshot of this new version of our project. We should add the modified file in the index and then take a snapshot, like this (do not do it)
mylogin@mymachine:~/git_labwork/getting_started_project$ git add object.txt
mylogin@mymachine:~/git_labwork/getting_started_project$ git commit -m "c-002"
But the commit
command has a nice “a” option that tells to automatically put the last version of modified tracked files in the index before actually committing. So instead of the previous lines, you can rather type
mylogin@mymachine:~/git_labwork/getting_started_project$ git commit -am "c-002"
This has many effects :
master
, that was a pointer to the same commit as HEAD, is the new commit “c-002”. The HEAD is shifted to that new commit as well. Moreover, the commit “c-002” is created so that its parent is the commit previously designated by HEAD, i.e. the commit “c-001”.We can display this by typing
mylogin@mymachine:~/git_labwork/getting_started_project$ git log --oneline
The code at the beginning of the line are the commit identifiers, the “(HEAD -> master)” string means that the HEAD is on the branch “master”, i.e. the commit referenced by that branch. Then, git log recursively explores the commits by accessing their parents. This is why, from commit “c-002”, we can see “c-001”.
Let us now create another branch. It consists of creating another reference to the commit designated by HEAD. Let us call this reference “farm”, since we will add farm-related stuff in our text files.
mylogin@mymachine:~/git_labwork/getting_started_project$ git branch farm
creates the new branch. Let us see it.
mylogin@mymachine:~/git_labwork/getting_started_project$ git branch
Both branches “farm” and “master” points to the same commit “c-002”. The HEAD is still associated to the branch “master”. If we make a new commit, as the head is associated to the branch master, the new commit will be added as the son of “c-002”, the HEAD and the branch master will be shifted to it. Indeed, we rather want the branch “master” to be still referencing commit “c-002”, and the branch “farm” to be shifted (with the HEAD as well) to our new farm related commit. To do so, we only need to tell git that the next shift will rather concern the branch farm.
mylogin@mymachine:~/git_labwork/getting_started_project$ git checkout farm
Check with
mylogin@mymachine:~/git_labwork/getting_started_project$ git branch
that the "*" symbol has moved. In the text files, add farm related elements. Then, commit this change
mylogin@mymachine:~/git_labwork/getting_started_project$ git commit -am "c-003 farm elements added"
Add other farm animals in animals.txt
and commit this new change.
mylogin@mymachine:~/git_labwork/getting_started_project$ git commit -am "c-004 farm extra animals added"
Type
mylogin@mymachine:~/git_labwork/getting_started_project$ git log --oneline
To see the new history. All along that history, you visit commit “c-002” and git reminds you that is is actually the commit pointed by branch “master”.
Let us put back the HEAD to be associated to “master” (and consequently pointing commit “c-002”).
mylogin@mymachine:~/git_labwork/getting_started_project$ git checkout master
and check the status
mylogin@mymachine:~/git_labwork/getting_started_project$ git branch
mylogin@mymachine:~/git_labwork/getting_started_project$ git log --oneline
mylogin@mymachine:~/git_labwork/getting_started_project$ more animals.txt
As you see when inspecting the file animal.txt
, moving the head to another commit makes git
modify the files in your working directory from the blobs listed in that commit. Let us add a “crocodile” in animal.txt
. Then commit.
mylogin@mymachine:~/git_labwork/getting_started_project$ git commit -am "c-005 crocodile"
Add a “snail” in the file animal.txt
, and commit.
mylogin@mymachine:~/git_labwork/getting_started_project$ git commit -am "c-006 snail"
and check the status
mylogin@mymachine:~/git_labwork/getting_started_project$ git log --oneline
Indeed, there is a more informative way to check all branches.
mylogin@mymachine:~/git_labwork/getting_started_project$ git log --all --decorate --oneline --graph
In commit “c-005”, we have added a dangerous animal. Let us create a branch from here, in order to add other dangerous things. We have to go back, i.e. place the HEAD pointer to commit “c-005”. This commit is not a commit designated by a branch. This can be done with the following command, where xxxx should be replaced by the identifier of your commit “c-005”.
mylogin@mymachine:~/git_labwork/getting_started_project$ git checkout xxxx
Git says that our HEAD is “detached”. It means that it is no more associated to a branch. Let us create a branch from there
mylogin@mymachine:~/git_labwork/getting_started_project$ git branch dangerous
Then, modify your text files and add dangerous things in them. Commit this
mylogin@mymachine:~/git_labwork/getting_started_project$ git commit -am "c-007 dangerous"
mylogin@mymachine:~/git_labwork/getting_started_project$ git log --all --decorate --oneline --graph
As you can see, we have made a mistake. We have actually created a branch, but the commit “c-007” is not a part of it. Indeed, we have forgotten to checkout that branch in order to tell HEAD to be associated with it.
Let us undo the last commit.
mylogin@mymachine:~/git_labwork/getting_started_project$ git reset --soft HEAD~
mylogin@mymachine:~/git_labwork/getting_started_project$ git log --all --decorate --oneline --graph
The --soft
flag tells to not alter the files in the working directory. The HEAD~
tag means “parent of HEAD”. We could have used the commit reference instead. Now, let us do our commit “c-007” right.
mylogin@mymachine:~/git_labwork/getting_started_project$ git checkout dangerous
mylogin@mymachine:~/git_labwork/getting_started_project$ git commit -am "c-007 dangerous"
mylogin@mymachine:~/git_labwork/getting_started_project$ git log --all --decorate --oneline --graph
Now let us gather all the partial modifications. This is the merging operations. Let us consider the master branch as the final one. So let us first go there.
mylogin@mymachine:~/git_labwork/getting_started_project$ git checkout master
mylogin@mymachine:~/git_labwork/getting_started_project$ git merge dangerous
Git is supposed to create a new commit, that corresponds to the merge of all file contents. If the merge cannot be done automatically, you have to manually edit the files and then commit your change… that will be the commit corresponding to the merge. Git tells you which files are in conflict and modifies their content so that you can easily see where is the problem when you edit the files.
Once the editing of conflicting files is done
mylogin@mymachine:~/git_labwork/getting_started_project$ git commit -am "c-008 dangerous merged to master"
mylogin@mymachine:~/git_labwork/getting_started_project$ git log --all --decorate --oneline --graph
Note that this new commit has two parents. Once again, this commit may have been done automatically if git was able to merge the two parent commits without requiring any help from you. This is typically the case when the two branches differ on distinct files.
If you do not intend to add commits from the commit that is still referencing “c-007”, you can delete the branch “dangerous” (not the commit it refers).
mylogin@mymachine:~/git_labwork/getting_started_project$ git branch -d dangerous
mylogin@mymachine:~/git_labwork/getting_started_project$ git log --all --decorate --oneline --graph
Let us merge the “farm” branch to the “master” branch (we are still in that branch)
mylogin@mymachine:~/git_labwork/getting_started_project$ git merge farm
If needed, solve the conflicts and commit the merge result. Then you can delete the branch “farm”.
mylogin@mymachine:~/git_labwork/getting_started_project$ git branch -d farm
mylogin@mymachine:~/git_labwork/getting_started_project$ git log --all --decorate --oneline --graph
One of the smartest features of git
, as for any versioning system, is the ability to collaborate with others. The principle of git is that every collaborator hosts his/her own version of the shared repository, and s/he synchronizes it with others explicitly.
In this case, all the collaborators need a meeting point, i.e. a place where a common version can be shared. Such a place is a “bare” git repository : git
repository without any index nor working directory.
Usually, your institution (e.g. gitlab-student.centralesupelec.fr), free providers (e.g github), provides you with the ability to create or join bare repositories. But you can also create bare repositories on your drive which is what we are going to do for the purpose of this tutorial.
Keep the terminal where we have worked so far open, let us name it “terminal 1”. Open a new one. In the following, some_path
means the path of the directory where git_labwork
is.
Let us create a bare repository. The usage is to name the repository with a .git
suffix.
mylogin@mymachine:~$ cd some_path/git_labwork
mylogin@mymachine:some_path/git_labwork$ mkdir shared_repository.git
mylogin@mymachine:some_path/git_labwork$ ls
mylogin@mymachine:some_path/git_labwork$ cd shared_repository.git
mylogin@mymachine:some_path/git_labwork/shared_repository.git$ git --bare init
Now, let us create the working space of the collaborator “Juliet”. It is obtaines by “cloning” the bare repository.
mylogin@mymachine:~$ cd some_path/git_labwork
mylogin@mymachine:some_path/git_labwork$ mkdir juliet
mylogin@mymachine:some_path/git_labwork$ cd juliet
mylogin@mymachine:some_path/git_labwork/juliet$ git clone some_path/git_labwork/shared_repository.git
mylogin@mymachine:some_path/git_labwork/juliet$ cd shared_repository
Let us name this terminal “terminal Juliet”. As git says, we have cloned an empty repository, which is usually not the case when you are cloning a repository because you are joining a collaborative project. Let us put what we have done so far in the bare repository so that Juliet can get it.
Swich to “terminal 1”, we are in our initial project. Let us declare a distant repository.
mylogin@mymachine:~/git_labwork/getting_started_project$ git remote add shared some_path/git_labwork/shared_repository.git/
mylogin@mymachine:~/git_labwork/getting_started_project$ git remote -v
We have declared a remote repository, providing its location and giving it the name “shared”. The second line shows the remote repositories that git
knows for this project, telling that we can both fetch commits from it or push commits to it.
Switch to “terminal Juliet”, and type
mylogin@mymachine:some_path/git_labwork/juliet/shared_repository$ git remote -v
You will see that, as this repository has been created by cloning another one, it has automatically a declared remote repository. The default name for it is “origin”.
Let us switch back to “terminal 1”
We can push our master branch to the remote repository (named “shared” here).
mylogin@mymachine:~/git_labwork/getting_started_project$ git push shared master
And that’s it. Switch to “terminal Juliet”, and get the new branch available in the shared (bare) repository.
mylogin@mymachine:some_path/git_labwork/juliet/shared_repository$ git pull
mylogin@mymachine:some_path/git_labwork/juliet/shared_repository$ git log --all --decorate --oneline --graph
Open a third terminal, that we will name “terminal Romeo”, and type:
mylogin@mymachine:~$ cd some_path/git_labwork
mylogin@mymachine:some_path$ mkdir romeo
mylogin@mymachine:some_path/git_labwork/romeo$ cd romeo
mylogin@mymachine:some_path/git_labwork/romeo$ git clone some_path/git_labwork/shared_repository.git
mylogin@mymachine:some_path/git_labwork/romeo$ cd shared_repository
mylogin@mymachine:some_path/git_labwork/romeo/shared_repository$ git log --all --decorate --oneline --graph
Being Romeo, add the word “love” in concepts.txt
, save and commit :
mylogin@mymachine:some_path/git_labwork/romeo/shared_repository$ git commit -am "c-010 I'm in love"
mylogin@mymachine:some_path/git_labwork/romeo/shared_repository$ git log --all --decorate --oneline --graph
At this stage, Juliet does not know that change. You can see it from the log, since git
tells you where the remote HEAD (i.e. origin/HEAD) is. Let us make Juliet know Romeo’s modification. Staying in the “terminal Romeo”, type :
mylogin@mymachine:some_path/git_labwork/romeo/shared_repository$ git push
mylogin@mymachine:some_path/git_labwork/romeo/shared_repository$ git log --all --decorate --oneline --graph
Switch to “terminal Juliet”, and type (one by one, as usual) :
mylogin@mymachine:some_path/git_labwork/juliet/shared_repository$ git log --all --decorate --oneline --graph
mylogin@mymachine:some_path/git_labwork/juliet/shared_repository$ git pull
mylogin@mymachine:some_path/git_labwork/juliet/shared_repository$ git log --all --decorate --oneline --graph
Add the name “reciprocity” in concepts.txt
, commit and push.
mylogin@mymachine:some_path/git_labwork/juliet/shared_repository$ git commit -am "c-011 I love you too Romeo"
mylogin@mymachine:some_path/git_labwork/juliet/shared_repository$ git log --all --decorate --oneline --graph
mylogin@mymachine:some_path/git_labwork/juliet/shared_repository$ git push
mylogin@mymachine:some_path/git_labwork/juliet/shared_repository$ git log --all --decorate --oneline --graph
Switch to “terminal Romeo”.
Add a new file musics.txt
, edit it and put “Sunday Bloody Sunday” in it. Save. Let us commit and push this change.
mylogin@mymachine:some_path/git_labwork/romeo/shared_repository$ git add musics.txt
mylogin@mymachine:some_path/git_labwork/romeo/shared_repository$ git commit -am "c-012 I love U2"
mylogin@mymachine:some_path/git_labwork/romeo/shared_repository$ git log --all --decorate --oneline --graph
mylogin@mymachine:some_path/git_labwork/romeo/shared_repository$ git push
The push fails, since the remote branch has commit “c-011” that we (Romeo) don’t have. We have first to pull the branch (as suggested), and merge it with our current commit.
mylogin@mymachine:some_path/git_labwork/romeo/shared_repository$ git pull
Indeed, git
adds as if commits “c-011” and “c-012” were developed in parallel branches, which is the case due to synchronization issues between Romeo and Juliet. Git opens an editor for you to name that new merged commit, you can simply quit the editor and accept the proposed name.
Now, Romeo can push (but Juliet will have to pull before pushing something else).
mylogin@mymachine:some_path/git_labwork/romeo/shared_repository$ git log --all --decorate --oneline --graph
mylogin@mymachine:some_path/git_labwork/romeo/shared_repository$ git push
Create a new git repository from scratch
mylogin@mymachine:~$ cd some_path/git_labwork
mylogin@mymachine:some_path/git_labwork$ mkdir big_project
mylogin@mymachine:some_path/git_labwork$ cd big_project
mylogin@mymachine:some_path/git_labwork/big_project$ git init
Download application.py and title.py in your repository, add them to the index, and commit with a message “first commit”. Let us tag this commit as the version-1.0 of our project.
mylogin@mymachine:some_path/git_labwork/big_project$ git tag version-1.0
A tag is like a branch that cannot move to another commit. So here, we have tagged in our history that this commit was the stable version of our project.
Of course, read the python files, and try the application
mylogin@mymachine:some_path/git_labwork/big_project$ python3 application.py Schwarzenegger male
mylogin@mymachine:some_path/git_labwork/big_project$ python3 application.py Kardashian female
We would like to add a new feature in the greeting
function that colors the name of the person in red or blue according to his/her sex.
As this is a further development, let us create a branch for this.
mylogin@mymachine:some_path/git_labwork/big_project$ git branch colors
mylogin@mymachine:some_path/git_labwork/big_project$ git checkout colors
add this function definition in application.py
, and commit with name “color_from_sex implemented”.
import termcolor
def color_from_sex(msg, sex) :
if sex == 'male' :
return termcolor.colored(msg, 'blue')
else :
return termcolor.colored(msg, 'red')
Modify the greeting
function so that it prints the name with the appropriate color, using color_from_sex
. Save, test, but do not commit yet.
Let us suppose that you receive a bug report from the users. Indeed, whatever the sex, your greeting always print “Mr.”. This requires a hotfix. You have to create a branch for this, from the master branch. Your working directory needs to be saved. A commit could do the job, but it is inelegant to create commits just for saving your working directory temporarily.
The solution is to stash. It saves your working directory as well as the index on a specific stack, so that you can retrieve it later.
mylogin@mymachine:some_path/git_labwork/big_project$ git stash push
You can display that stack…
mylogin@mymachine:some_path/git_labwork/big_project$ git stash list
… or see the stash operation in your history :
mylogin@mymachine:some_path/git_labwork/big_project$ git log --all --decorate --oneline --graph
Then, let us go back to the release branch, i.e. bring it on our working directory and index. This is what checkout is.
mylogin@mymachine:some_path/git_labwork/big_project$ git checkout master
You can visualize the status of your git session.
mylogin@mymachine:some_path/git_labwork/big_project$ git status
mylogin@mymachine:some_path/git_labwork/big_project$ git log --all --decorate --oneline --graph
mylogin@mymachine:some_path/git_labwork/big_project$ git stash list
let us create a branch to fix de bug and go on that branch.
mylogin@mymachine:some_path/git_labwork/big_project$ git checkout -b hotfix
mylogin@mymachine:some_path/git_labwork/big_project$ git log --all --decorate --oneline --graph
Modify title.py
to make the gender
function actually sensitive to the sex. Commit this change with message “bug fix”. Test it. It should work… but colorization is not there. As the last commit works fine, we need to merge the hotfix branch and remove it.
mylogin@mymachine:some_path/git_labwork/big_project$ git checkout master
mylogin@mymachine:some_path/git_labwork/big_project$ git log --all --decorate --oneline --graph
mylogin@mymachine:some_path/git_labwork/big_project$ git merge hotfix
mylogin@mymachine:some_path/git_labwork/big_project$ git branch -d hotfix
mylogin@mymachine:some_path/git_labwork/big_project$ git log --all --decorate --oneline --graph
Here, the merging only consists in adding the “bug fix” commit to the master branch. Indeed, while we were working on the bug fix on the hotfix branch, there has been no further commits on the master branch, so the merge is very easy (i.e. so called “fast forward”).
Now, the bug issue is resolved, we can go back on our ongoing work on colors.
mylogin@mymachine:some_path/git_labwork/big_project$ git checkout colors
mylogin@mymachine:some_path/git_labwork/big_project$ git log --all --decorate --oneline --graph
We are now at the level on our last commit on the colors branch, that commit is “color_from_sex implemented”. Remember that there had been a supplementary work from that commit, saved in the stash. Let us retrieve it.
mylogin@mymachine:some_path/git_labwork/big_project$ git stash pop
mylogin@mymachine:some_path/git_labwork/big_project$ git log --all --decorate --oneline --graph
Now, we can commit a new “greetings modified to display colors” commit.
mylogin@mymachine:some_path/git_labwork/big_project$ git commit -am "greetings modified to display colors"
mylogin@mymachine:some_path/git_labwork/big_project$ git log --all --decorate --oneline --graph
Test with
mylogin@mymachine:some_path/git_labwork/big_project$ python3 application.py Schwarzenegger male
mylogin@mymachine:some_path/git_labwork/big_project$ python3 application.py Kardashian female
Of course, the bug is still there, in that branch. As we intend to develop the colors branch further before merging to the master branch, but as we want the bug to be solved in our current branch, we have to merge master in it.
mylogin@mymachine:some_path/git_labwork/big_project$ git merge master
mylogin@mymachine:some_path/git_labwork/big_project$ git log --all --decorate --oneline --graph
mylogin@mymachine:some_path/git_labwork/big_project$ python3 application.py Kardashian female
Indeed, we would like the word “Hello” to be displayed in green. Change this, test, and commit “Hello in green”.
Our work with color is finished now. We can integrate the change in the master branch, and remove the colors branch.
mylogin@mymachine:some_path/git_labwork/big_project$ git checkout master
mylogin@mymachine:some_path/git_labwork/big_project$ git merge colors
mylogin@mymachine:some_path/git_labwork/big_project$ git log --all --decorate --oneline --graph
mylogin@mymachine:some_path/git_labwork/big_project$ git branch -d colors
mylogin@mymachine:some_path/git_labwork/big_project$ git tag version-2.0
mylogin@mymachine:some_path/git_labwork/big_project$ git log --all --decorate --oneline --graph
If you want to play with version 1 of your project again, you can go to the tag.
mylogin@mymachine:some_path/git_labwork/big_project$ git checkout version-1.0
mylogin@mymachine:some_path/git_labwork/big_project$ git log --all --decorate --oneline --graph
mylogin@mymachine:some_path/git_labwork/big_project$ python3 application.py Kardashian female
You see that there are no colors and the bug is still there. You could start another branch from here, as git
suggests, so that the HEAD would be associated with a branch (this is not the case here, tags are not branches and so a checkout on a tag renders your HEAD detached).
Let us go back to the last version.
mylogin@mymachine:some_path/git_labwork/big_project$ git checkout version-2.0
mylogin@mymachine:some_path/git_labwork/big_project$ git log --all --decorate --oneline --graph
mylogin@mymachine:some_path/git_labwork/big_project$ python3 application.py Kardashian female
Try to play with this animated site