Win a copy of Head First Android this week in the Android forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Tim Cooke
  • Campbell Ritchie
  • Paul Clapham
  • Ron McLeod
  • Liutauras Vilda
Sheriffs:
  • Jeanne Boyarsky
  • Rob Spoor
  • Bear Bibeault
Saloon Keepers:
  • Jesse Silverman
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
Bartenders:
  • Piet Souris
  • Al Hobbs
  • salvin francis

Need help with using git

 
Rancher
Posts: 259
13
Eclipse IDE C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
i've never used GIT before, need some help with using it.
i have eclipse and it comes with GIT, so i followed instructions to create a local repository for my project, pretty sure all the project was committed.
after that i changed a few things in my project, saved the files and ran it. i didn't do a new commit. but when i run the project, i don't see my changes.
my project is using javaFX and one thing i changed is the fxml file, so i should be seeing a new GUI, but i still see the old GUI.
 
S Fox
Rancher
Posts: 259
13
Eclipse IDE C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
i figured out what the problem is. my FXML file used to be stored in eclipse/workspace and when i created the git repo all the files are moved to a new location git/repository. so i saved my new FXML file into the old location and that's why it doesn't work.

am i suppose to be editing the FXML file inside the repo directly? how am i able to roll back changes to the fxml file if i am editing the one that i committed and saving over it?
Staff note (Paul Clapham) :

This seems like it's asking about Eclipse and its implementation of GIT, so I've moved it to the Eclipse forum.

 
Marshal
Posts: 26912
82
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Typically when you have a repository, it's supposed to keep at least the latest good version of your code artifacts. But it's a repository, which means a storehouse. You don't change files there.

I can't speak for how Eclipse works with GIT, but I use Eclipse with Subversion. I work in the Eclipse project, and when I decide that modified code artifacts are clean, I commit them to the repository. I expect it would be the same with GIT.

I'm surprised that you said the files were "moved" to a GIT repository. I would have expected them to be copied, leaving the original versions in your Eclipse project.
 
S Fox
Rancher
Posts: 259
13
Eclipse IDE C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
yeah it did copy the files to the repo, the originals are still in the workspace but i don't think they're being used for anything anymore.
i replaced the old fxml file in the repo with my new one, ran my app, it worked fine. then i tried to do a new commit.
it told me this commit creates a master branch, so apparently i did not do any commit before this one. i thought i did.
so i guess i have it all working properly now, but i'm still really confused about how this all works.
 
Saloon Keeper
Posts: 13394
296
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes, you work directly from your local repository. If you don't, you lose many of the benefits that Git offers you, such as generating diffs between your current work space and your last commit.

I advise against using your IDE's Git tools. Familiarize yourself with the command line, so you get a feeling for Git itself and you can fix stuff when you or your IDE inevitably messes up.

In a local repositories, there are three separate areas where your code exists: The working tree, the index (or staging area) and commits.

Commits are versions of your code that you've saved for all time*. A commit records changes in the code relative to one or more parent commits.

The index is like a partial commit before you've actually committed it. You don't always want to create a commit of ALL the changes you've made in your working tree, you stage the changes that you do want to commit to the index first. The index is also really useful if you've made some changes that you don't want to commit yet, but you want to overwrite some of your changes because you want to try out a different solution. When you're happy with the new solution you can overwrite the changes in the index, and if the experiment failed you can restore the version of the code from your index.

The index and the commits live inside a hidden .git folder in the root of your repository. Don't worry about overwriting code in your working tree, because Git keeps track of the old code in the .git folder.

Finally, I've found it very helpful not to think of a branch as a sequence of commits, but rather think of all commits as one big directed graph, and a branch is just a sticky note that assigns a name to a particular node (commit) in the graph.

Thinking of it this way really helps with the checkout and reset commands because there is a special sticky note called HEAD which represents the commit version that you've currently checked out in your working tree. In order to make new commits, the HEAD note must be at the same commit that has a branch note. When you make a new commit, both the HEAD and branch notes are moved to the latest commit. The reset command allows you to move the HEAD and branch notes to a commit you already made.

When the HEAD note is at a commit that does not have a branch note associated with it, you're in a so called 'Detached HEAD' state. You can look at the checked out code in a detached state, but you can not make new commits before first assigning a branch note to the checked out commit.

Here are the most important commands:

CommandPurpose
addAdd changes from the working tree to the index.
commitMake a new commit from the changes in the index and move the branch and HEAD sticky notes to the new commit.
restoreThrow away changes you've made by reverting to a version of the code from the index or the checked out commit.
resetMove the branch and HEAD notes to a specific commit and check out the version of the code at that commit.
checkoutMove only the HEAD note to a specific commit and check out the version of the code at that commit.
branchCreate a new branch sticky note at the checked out commit (the commit with the HEAD sticky note.
mergeTake all changes from the given branch relative to your current branch, and create a new commit that has both versions of the code as parents.

You can practice some of these commands at https://learngitbranching.js.org/.

* The nice thing about Git is that it makes it difficult to lose committed changes, so don't worry about trying out various commands. Even if you make a mess, your code is still there somewhere. Git will refuse to perform operations that will cause you to lose committed work, unless you provide the -f or --force command line switches.

The index and working tree are not this well protected, so if you're afraid you're gonna lose changes, make a commit! Repeat this mantra: "Commit early, commit often".
 
Sheriff
Posts: 7111
184
Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I agree with Stephan that you should learn command line git to do anything other than adding a git repository and simple staging and committing in Eclipse. Once you get your feet wet with the command line, here's what can be useful in Eclipse git.

* Git has a what Eclipse calls a "perspective", like debugging has.  You can open it with Windows > Perspective > Open Perspective > Other and choose Git.  On my layout, there are icons in the top right-hand corner showing the possible perspectives.  You can use these to change between the normal Java and Git perspectives.
* Eclipse calls adding to the index "staging."  When you choose a repository from the left-hand window, Eclipse will show you Unstaged Changes, Staged Changes, and a Commit comment area.  Any changes you've made to a file in the repository, or if you've added a file, will show in the unstaged area.  Moving files from Unstaged to Staged is adding them to the git index.
* You commit files that are staged.  Group commits so that they have some logical commonality.  Write a commit message and press commit.
* Anything other than the above, I do at the command line.  Eclipse picks up any changes without a problem.
 
S Fox
Rancher
Posts: 259
13
Eclipse IDE C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
thanks guys i played around a bit on that simulation site.

stephan said:

In order to make new commits, the HEAD note must be at the same commit that has a branch note. When you make a new commit, both the HEAD and branch notes are moved to the latest commit. The reset command allows you to move the HEAD and branch notes to a commit you already made.



the git simulator allows me to detach the head from the branch and i am able to do commits while the head is attached directly to a commit node without any branch tag on it. is that not supposed to be possible in the real world?

also from my experimenting on that site, it seems that doing "branch -f" is exactly the same thing as doing a rebase ?

in one of these simulation exercises, it has me putting the commits from 3 side branches onto the main branch. but it has me putting them on that main branch in the order they all were committed in. that doesn't seem to be necessary? as long as all the commits are on the branch, the order that the commits are in should not matter at all right?

also i don't quite understand how merging branches works yet. lets say i have two branches of a simple hello world app, and in one branch it says "hello" and in the other it says "goodbye" how would merge work in that kind of situation?
 
Stephan van Hulst
Saloon Keeper
Posts: 13394
296
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

S Fox wrote:the git simulator allows me to detach the head from the branch and i am able to do commits while the head is attached directly to a commit node without any branch tag on it. is that not supposed to be possible in the real world?


I'm sorry, that was my mistake. Yes, you ARE allowed to create commits in a detached HEAD mode. The problem is that Git won't track which commit you were at when you switch back to one of your other branches, and unless you have a good memory or write down the commit hash, you won't easily find back the work you did while in a detached HEAD state. So making commits in a detached HEAD state is useful when you want to experiment a little and then 'throw away' your work when you switch back to a real branch. It's not advisable to perform experiments this way though. Because branches are really only pointers to a commit, they are very cheap, so you might as well make an experimental branch instead of using a detached HEAD. You never know what code you write that you might end up wanting to save. In practice, detached HEAD is only used to check out an old version of the code so you can look around in it quickly, or run it to debug it or see how it works (for instance, if one of your customers is running an older version).

also from my experimenting on that site, it seems that doing "branch -f" is exactly the same thing as doing a rebase ?


No. In a rebase, you take the changes of the current working branch relative to the common ancestor with your target branch, and replay the changes on top of the target branch. The current branch is moved to the latest rebased commit (which now has the target branch as one of its ancestors), while the target branch is unaffected. Remember: Git commands normally make changes in the currently checked out branch, not target branches. When you perform "git branch targetBranch -f" on an existing branch named "targetBranch", the only thing you do is move the "targetBranch" sticky note to the same commit as your currently checked out commit. No changes are made to your current branch, and any commits that were in the target branch that weren't part of any other branch, are now 'lost'.

as long as all the commits are on the branch, the order that the commits are in should not matter at all right?


Yes and no. It doesn't matter in terms of what the resulting code looks like. Regardless of the order, the code will be the same and running the application will yield the same results. It does matter in terms of history: Application developers often have to look back through the commit history to find out why certain changes were made. Commits were often made in some sort of logical order, so you will want to try and preserve that order while rebasing.

also i don't quite understand how merging branches works yet. lets say i have two branches of a simple hello world app, and in one branch it says "hello" and in the other it says "goodbye" how would merge work in that kind of situation?


In a merge, Git will replay changes from the target branch onto your current branch. For a single file, it does this by generating diffs between the two files, and then simply overwriting the lines in your current file if changes were made in the merging file and not in your current file. Let's say you had one branch named "master". Then you created a new feature branch named "goodbye" from it. The master branch already contained the line that prints out "hello", and the feature branch changes that line to print "goodbye". Then you merge the two branches. Git will make a diff of the file and see that the lines are different, but because the line that prints "goodbye" was already based on the line that prints "hello", Git simply overwrites the version that said "goodbye".

What happens when two lines conflict and one of the two versions was not based on the other version? For instance, another developer changed the version on the master branch to print "bye bye" before you had the chance to merge your work. The line that you changed to print "goodbye" was NOT based on the line in the master branch to print "bye bye". Git will then create what is called a "merge conflict".

At the end of the merge operation, if you have any conflicting changes that Git could not resolve itself, your working tree will be in a "MERGING" state, and Git will have converted any of your textual* files that contained conflicts to a new "diff" format. Basically, the sections of your file that conflicted will be replaced with BOTH versions of the code, separated by special markers. It's now up to YOU to resolve the merge conflict by choosing which of the two versions of the code you want to keep, and remove the other version and the conflict markers. However, you may also make other changes to the file, in the same way you would normally make changes to it. This happens when you need some code from both versions. Here is an example. This was the original code:

Now, one branch changed the code so the greet() method would accept a name to greet, and another branch changed the code so the greet() method would accept a printer to print the greeting to, instead of using standard output. This results in the following merge conflict:

Resolving this conflict is more complex than just picking one of the two versions of the code. We have to apply our developer's insight™ to make a sensible merge of the code:

* Git can also create diffs for binary files, but you have to install a separate diff provider that can do this for Git.

When you've changed your working tree so that there are no more files with conflict markers, you can add the changes (your conflict resolutions) to the index and then commit the so called "merge commit".

Please note that conflict resolution is one area where your IDE really shines: instead of showing you a file with conflict markers, it will show you a side-by-side diff of the changes in the two different versions with check boxes that will allow you to select which version you want to keep working with. Then, in a third editor it will show you the resulting code, where you can also apply your developer's insight™ to make further manual edits to the code.

So all of this seems like a lot of pain, right? Why not use git rebase instead of git merge every time? Well, you can get merge conflicts when you're performing a rebase too. If the changes that you want to replay on top of the target branch conflict with changes that were made to the target branch in the mean time, you will also have to perform conflict resolution. You have to do this separately for every commit that's involved in the rebase operation, so in the end you're doing just as much work when rebasing as you are when merging. Why pick one over the other?

The difference is in how the commit history looks at the end of the operation. In a merge operation, the commit history looks more messy, with added commits that contain little code and only serve to record a merge between two branches. On the other hand, your history contains all the commits in their original form. When you rebase, the commit history is more linear and there are no extra merge commits. The problem is that rebasing creates new commits (with new commit hashes) for the replayed changes, and throws the old rebased commits away (it doesn't really, they're just not associated with a branch any longer). If a different developer was working on a branch that they based off a commit that you rebased, then they will run into trouble when trying to merge their work into the main branch, because Git thinks that the commits that they were working off of are completely new and not a part of the main branch yet. Your fellow developers will then find out who rebased their commits and then scream at you. This is not figurative or just theoretical. They will literally actually scream at you.

Here's a good way to do things: Before merging your feature/bugfix/hotfix branch to a develop/master/staging/release branch, make sure that your current branch is up to date with the target branch. If your current branch is not shared with other developers (usually in bugfixes, hotfixes and minor features) you can rebase your current branch on the target branch**. This will keep your commit history clean, and there are no other developers to yell at you. Then checkout the target branch and use a git merge to pull in the feature branch.

When you're working on a shared branch (usually for a major feature), you ALWAYS use git merge instead of git rebase. A nifty way to keep the master branch clean is to make an agreement with your fellow developers that all work is merged to a feature-staging branch, and when everybody is done with their part of the major feature and all work has been merged to the feature-staging branch, the feature-staging branch is rebased on the master branch and then merged in. Everybody then throws away their own copies of the feature branch.

** A really good trick to clean up history before merging a bugfix, hotfix or minor feature to master is to use a squash rebase on your branch first. This will squash all your commits into a single commit with a single, clear commit message. That leaves you free to use dumb commit messages while you're working on your bug or feature, and then you can clean it all up before you merge your branch into master. IMPORTANT: When performing a rebase of ANY kind you MUST delete your branch from the origin server after you've merged it to master, because you want to prevent other developers from continuing work on a branch that has been rebased. If you don't do this, screaming will ensue.
 
S Fox
Rancher
Posts: 259
13
Eclipse IDE C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
right now it's just me working on my own code, im not collaborating on it with anyone but i needed a better way to save my work. so i don't need to worry about messing up someone elses branch that they have already checked out.

i understand that you can undo a commit, but can you undo a merge or rebase? undoing a branch -f should be easy since it just moved a tag, right? how about undoing the deletion of a branch? or undoing a prune?

i've gone through pretty much all the git simulator exercises, and while i know how to do some things i don't really have a sense of how it impacts the underlying codebase. it's just a bunch of dots in the graph that i am pushing around it doesn't show what happened to any code. this is why it appears to me that "branch -f" is the same thing as doing a rebase. the simulator accepts either way as a solution to the problem and the graph ends up looking exactly the same either way you did it.

so i guess i will start experimenting with the real one, i'll make a copy of my project so i don't accidentally destroy it
 
Marshal
Posts: 8124
572
Mac OS X VI Editor BSD Linux
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:So making commits in a detached HEAD state is useful when you want to experiment a little and then 'throw away' your work when you switch back to a real branch. It's not advisable to perform experiments this way though.


Agree it is not advisable to commit code which is not being tracked by the branch. The main reason for that is, that commits which aren't tracked by the branch may be garbage collected. So if you checkout to a branch and after an X amount of time wnat to get back to your untracked commit - it may be gone already. Similarly as in Java, they are marked as eligible to be garbage collected, but you don't know when it will happen.

As Stephan said. If you want to experiment with some code from the past - [1] checkout the commit you are interested to base your experimental development on; [2] create branch (being at that commit); and that way you are safe to go.

I too recommend to do Git related work from the command line while you learning it. That is an IDE agnostic way of having an understanding of it. In the future you'll reach the point where you may want to do that with an IDE, because I think you can be more productive with it.
 
Stephan van Hulst
Saloon Keeper
Posts: 13394
296
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

S Fox wrote:i understand that you can undo a commit, but can you undo a merge or rebase?


A merge is just a new commit, so you undo a merge by resetting the branch to one of HEAD's parents. For instance:  git reset HEAD^1.

To undo a rebase, you have to reset the branch to the commit the branch was at before the rebase. You can look up the commit ID with git reflog.

undoing a branch -f should be easy since it just moved a tag, right?


Only if the branch already existed, otherwise a new one was created.

It's simple: just don't use this command. There is no reason. If you want to move a branch, use the reset command. Also, don't use the word "tag" to refer to branches. A tag is a very specific and different thing in Git.

how about undoing the deletion of a branch?


By recreating the branch, using either git branch <branchname> or git checkout -b <branchname>, while having checked out the commit that the branch was at.

or undoing a prune?


Unless you know the names of the branches you deleted, you can't recreate them. Fortunately, the commits still exist, AND you can probably look up the branch names using git reflog. But why are you worried about this? I only prune branches months after they have been deleted from the origin server, and the work had already been merged into master.

i don't really have a sense of how it impacts the underlying codebase. it's just a bunch of dots in the graph that i am pushing around it doesn't show what happened to any code.


You get this through experience. But being able to visualize the commit history is a very important first step that many beginners never bother to learn.

this is why it appears to me that "branch -f" is the same thing as doing a rebase.


That's odd, because using the two commands in the simulator gave me two very different results.

so i guess i will start experimenting with the real one, i'll make a copy of my project so i don't accidentally destroy it


Why? Just dont use the -f switch and you won't destroy anything. The entire philosophy behind Git is that all your work is always saved somewhere, unless you actively go out of your way to destroy it.
 
reply
    Bookmark Topic Watch Topic
  • New Topic