Lab: Skills - Using Git in Eclipse
There are several tasks you must complete
before the scheduled lab
period.
- You must create a GitHub account using your JMU eID
(e.g.,
bernstdh@dukes.jmu.edu
) and
generate a classic Personal Access Token for this project.
Note: If you don't know what "scopes" to select, the easiest thing to do
is select them all.
- You must ensure that you have installed the appropriate
version of Java, that you have installed the the
appropriate version of Eclipse, and that Eclipse is using
the appropriate version of Java.
- You must create a new Eclipse workspace for this lab
(since this lab is probably getting you ready for your final
project). For example, for CS300, I would use the following
directory:
/home/bernstdh/cs300/projectworkspace
.
NOTES: (1) Do not put the projectworkspace
directory under
an existing Eclipse workspace. (2) Do not put the
projectworkspace
directory on a networked drive (e.g.
OneDrive).
-
You must configure the Eclipse workspace to use the Checkstyle
configuration/checks file for the course and the course
formatter. (If you've forgotten how, see the course "Help" page
on "Installing and Configuring the Development Envronpment".)
- You must ensure that EGit (the Git plugin for Eclipse) was installed
when you installed Eclipse. You can check by clicking on
Preferences+Version Control (Team)
and looking for an
item named "Git". If it was not installed, you must install it
using one of the methods described
at
the EGit download page.
-
Make sure that EGit is configured with your JMU dukes email
address (e.g.,
bernstdh@dukes.jmu.edu
). For more
information, see the course "Help" page on
"Configuring Git in Eclipse".
The remaining tasks must be completed during the scheduled lab period, with
the members of your team.
1. Cloning a Repository:
This part of the lab will help you learn how to use Git
to clone an existing remote repository.
It
must be completed by everyone individually.
-
Outside of Eclipse, create a directory
named
projectrepository
in the directory under the
directory you use for this course
(e.g., /home/bernstdh/cs300/projectrepository
).
NOTE: (1) Do not put the projectrepository
directory
under the directory that contains the Eclipse workspace you just
created (e.g., do not use
/home/bernstdh/cs300/projectworkspace/projectrepository
).
(2) Do not put the projectrepository
directory on
a networked drive (e.g., OneDrive).
-
Open Eclipse using the workspace you created for this lab (see above)
before the scheduled lab period
(e.g.,
/home/bernstdh/cs300/projectworkspace
).
-
Open the Git Perspective. For more information, see the course "Help"
page on
perspectives
.
-
Clone the remote repository that is at the URI that you were given
for this lab (e.g., https://github.com/bernstdh/team00). For more
information on cloning a repository, see the course "Help" page on
Cloning a Repository.
Select the main branch (the name may vary but should be apparent
from the context, and should be unique),
use the
projectrepository
directory you just created
(e.g., /home/bernstdh/cs300/projectrepository
)
for the destination, and use origin
for the "Remote name".
-
Import the project (NOT the parent directory) into Eclipse.
(From the Git perspective, you
can right-click on the repository and select Import
Projects.)
-
Open the "Java Perspective".
-
If the project includes any JUnit tests: Right-click on the
project, pull down to Build Path and over to
Configure Build Path. Then, select the "Libarires"
tab, select "Classpath", click on Add Library,
select "JUnit", and click on Next. Then select the
appropriate version of JUnit and click on Finish.
-
If the project includes any JUnit tests, run them to make sure everything
is OK.
-
Because of a defect in some versions of Eclipse/Egit, you should
exit Eclipse and re-start it.
2. Working in a Team:
This part of the lab will help you learn how to use Git
when working in a team. It assumes that the members of the team are named
Alice, Bob, Carol, Dan, Eve, and Frank. (If you have fewer members in your
team, ignore the instructions for the last members.) Where possible,
everyone must watch what everyone else is doing.
-
Everyone but Bob: Watch Bob.
-
Bob: Change the
forContains()
method in
Check.java
so that it uses equalsIgnoreCase()
instead of equals()
, but do not save the file.
-
What happens on Bob's version of the project?
An asterisk (i.e., *) is added next to the file name (on the tab for
the file) to indicate that the file has been changed but not saved.
-
Bob: Save
Check.java
.
-
What happens on Bob's version of the project?
The * is removed to indicate that the file has been
saved. Also, A > is put next to Check.java
(and the package and project it is in) to indicate that it has been
modified since the last commit (and now differs from the code in the
local repository).
-
Bob: Compare your working version of
Check.java
with the latest version from the repository (called the ''HEAD
Revision'') to remind yourself of the change
you made. For more information, see the course "Help" page on
"Comparing Files".
-
Bob: Close the comparison.
-
Bob: Commit (but do not push) your change. For more information,
see the course "Help" page on the
"Summary of Common Git Commands".
-
Are Bob's changes available to the rest of the team?
No, because Bob has only committed the changes to Bob's local repository.
-
Everyone but Carol: Watch Carol.
-
Carol: Perform a pull.
For more information, see the course "Help" page on the
"Summary of Common Git Commands".
-
What message did Carol receive?
Something like "Nothing to update - everything up to date".
-
If Bob performs a push, will there be any potential conflicts?
No, since nobody has pushed any code since Bob cloned the project.
-
Everyone but Bob: Watch Bob.
-
Bob: Perform a push (of the main branch). For more information, see
the course "Help" page on the
"Summary of Common Git Commands".
-
What happens in everyone else's repository? Why?
Nothing. Though the code has changed in the central repository, the changes are
not automatically replicated in the local repositories.
-
Everyone but Carol: Watch Carol.
-
Carol: Change the call to
haystack[i].equals()
in Check.java
with a call to
haystack[i].endsWith()
, and save the file.
-
Is Carol's code in Carol's local repository?
No, because Carol hasn't committed it yet.
-
Carol: Commit (but do not push) the changes.
-
If Carol performs a push, will there be any potential conflicts?
Yes, since the code on the central repository has changed since the last time
Carol performed a pull.
-
Carol: Perform a push (of the main branch).
-
What message did Carol receive?
Something like "non-fast-forward", indicating that there was, indeed,
the potential for a conflict.
-
What does Carol need to do to remedy this situation?
Carol needs to pull the ''HEAD revision'' from the central repository,
make any necessary changes, and commit and push the revisions.
-
Carol: Start the process of resolving potential conflicts by
conducting a pull that merges. (Note: In general, you can
resolve potential conflicts either using a "Merge" or a
"Rebase". The difference is explained in the course "Help" page on
responding to non-fast-forward messages.)
This will show both versions
of the code so that you can decide on what code you should keep
from the two versions. When doing so,
change
endsWith()
to equals()
.
(Obviously, you will also need to delete the Git conflict markers
that are inserted into the code to highlight the differences.)
-
Carol:
Save the change and add the file to the index.
-
Carol: Commit the changes.
-
Carol: Push your local repository to the main branch on the
central server.
-
Why does this push complete successfully?
Because Carol incorporated the most recent revision from the
central repository into her local repository. The central server
recognizes this and accepts the push.
-
Everyone is about to start making changes to the code in their
local repository. Why should everyone perform a pull before they
start doing so?
To ensure that they have the most recent version of the code that is on
the central repository.
-
Everyone: Perform a pull to get ready to start working.
-
Alice: Create a method named
forContainsIgnoreCase()
that is passed a String[]
and String
and uses the equalsIgnoreCase()
method.
-
Bob: Change the
forContainsTest()
method in
the CheckTest
class so that it ensures that
the forContains()
method in the Check
class is case sensitive. (For example, check to ensure an
all-upper-case version of a word in the haystack
is
not found.)
-
Carol: Change the
forContainsTest_null()
method
in the CheckTest
class so that it tests for the case
when both the haystack
and the needle
are
null
.
-
Dan: Create a method named
forContains()
that is passed a List<String>
and String
and uses the equals()
method.
-
Eve: Create a method named
forContainsIgnoreCase()
that is passed a List<String>
and String
and uses the equalsIgnoreCase()
method.
-
Frank: Create a method named
forContains()
that is
passed an Iterable<String>
and String
and uses the equals()
method.
-
Everyone: Save your changes.
-
Where there any problems when anyone saved their files?
No, because each file was only saved to the team member's local file system.
-
Everyone: Perform a commit.
-
Where there any problems at this point?
No, because only the local repositories changed.
-
Everyone: Perform a push.
-
Where there any problems at this point?
Yes. The first push succeeded and all of the others failed.
-
Why?
Because, even though the changes didn't conflict in any meaningful
sense, the central server recognized that people made changes
to an "old" version and then tried to push them.
-
Everyone: Resolve the problems locally by conducting a pull.
-
What happened?
Hopefully, nobody had to do any work, because the system was able to merge
the files on its own. That is, it didn't find any differences
that it couldn't resolve on its own since all of the changes
were made in different parts of the file. However, if the system couldn't
resolve a change then you had to resolve the conflicts manually.
-
Everyone: Push your changes, performing any necessary pulls
in order to do so.
-
Why would it have been difficult for, say, Carol to add a test to
the
CheckTest
class that tested
the forContainsIgnoreCase()
methods that Alice was
adding to the Check
class?
Because, the code in the
CheckTest
class would not compile (since it would be using a method in the
Check
class that doesn't
exist in Carol's version.
Of course, Carol could add a stub to Carol's version of the Check
class, but that stub would conflict with Alice's actual implementation.
-
Given your answer to the previous question, what should a team do when
dividing tasks?
If possible, the team should try to ensure that interdependent tasks are not being completed by different people.
-
Everyone (Critical - Do Not Skip): Login to GitHub (using
your eID and password), click on the repository (on the left side
menu), click on [Insights] (on the top menu), click on
[Contributors] (on the left side menu), and make sure that your
commits appear under the appropriate username. (If they do not,
then you probably did something wrong during the setup process, most likely
when configuring EGit.)
-
Everyone: Time permitting, decide among yourself about how to make
some changes that will conflict, and make sure you can commit,
push and pull as necessary to resolve all of the conflicts.