Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to understand Git branch, merge and rebase

Tags:

git

branch

rebase

I know the thread which says that rebase is for small changes of teamMates, while merge for large changes.

I keep three Gits of three teammates in the following directory structure where we all have the same initial code:

project 
      | - I
      | - myTeamMate1
      | - myTeamMate2

The branches are not in the same Git. This means that I cannot use rebase and merge. I have used vimdiff to sync changes between teamMates. However, this is time-consuming.

I have unsuccessfully tried to make the following directory structure where all branches are under one Git:

project
      | - I - myTeamMate1 - myTeamMate2

However, I run clone command for me and for my teammate:

git clone <url>

and I get the error message after running the second clone for my teammate

fatal: destination path 'dotFiles' already exists and is not an empty directory.

Which directory structure should I use with a team of 3 people, such that I can use rebase and merge commands?

like image 656
Léo Léopold Hertz 준영 Avatar asked May 24 '09 18:05

Léo Léopold Hertz 준영


4 Answers

Just some other thoughts to complete Samuel's answer.

  • Unlike SVN, branches and directories are completely unrelated in Git: having 3 branches (one for each member of the team) does not mean 3 directories. That is not what you meant in your question (since your directories are actually 3 roots for 3 Git repositories), but I prefer mention it explicitly just in case ;)

  • Git being DVCS, the 3 repositories can be anywhere (not in 3 directories on the same computer). If they are reachable through an UNC path (\\desktop\path\to\repo), they can be designated as remote.

  • Git clone does allow you to get references to remotes branches, but does not create tracking local branches allowing you to get the work of your colleagues. The ruby module "remote branches" can help.

  • Be wary of rebase as it rewrites the SHA-1 of your branch (since you replay your commits on top of another branch): if your teammates based their merges on your branches, they will have to merge all your commits every time, even those already merged!
    It is best to have 2 branches in this case:

    • a working branch you are using for your development and rebase (to integrate the works of your peers, although even that operation could be done in its own branch)
    • a publishing public branch, on which you only merge your stable work, and which can then be used by other remote repositories as a source for merges.
like image 93
VonC Avatar answered Oct 22 '22 14:10

VonC


The fact that they are not inside the same git as you state doesn't limit you in any way. Git is distributed, which means that you can fetch between those repositories, merge, rebase, and so on.

Look at git remote --help to see how you can name your teammates repositories in yours so that you can easily import their changes, rebase onto them or perform merges. There is no need to change your directory structure, yours is perfectly usable.

like image 43
Samuel Tardieu Avatar answered Oct 22 '22 15:10

Samuel Tardieu


Code examples

To track a remote branch

git remote add -t master Hnr git://github.com/userName/files.git

This does not download you the branch. It just edits the file .git/config and adds a few lines which tell Git how where and how to get data remotely.

To get your teamMate's branch, run

git fetch Hnr

To see that you really have your teamMates' branch, run

git branch -a

or to see just your friends' branches

git branch -r

The above two commands caused my confusion initially, since I did not know them. This made me try other unnecessary commands to have the branches for me.

2nd way to have your friend's branch

However, note that you can use git-clone to have your friend's code to a separate directory as follows

git clone UrlAtGithub

Then, you can apparently use Git-remote as above to have a branch at your Git repo:

git remote add master Hnr PATH/ToYourFriendRepo.git

Conclusion: You can use two ways to have your teamMate's branch for you, either by git-clone or without it. Both ways require the use of git remote add. The advantage of the latter seems to be that you need to run one command less. The former then again gives you your teamMates' whole repo to your hardDisk.

Please, see Git's manuals for how you can update your remote branches. (NB remote branch can be at your computer. It does not have to be in a remote computer. Your branch can be the remote branch too, but this restricts your workflow.)


You may next want to merge your friend's specific file to your branch. In that case, it is enough to know the 5 first letters of your friend's commit to merge the file.

[I am not sure how you can do the following:] You need to run, for instance

git merge 76a32

You may get the following output

CONFLICT (add/add): Merge conflict in shells/externalPrograms
Auto-merging shells/smallApps/extract
CONFLICT (add/add): Merge conflict in shells/smallApps/extract
Auto-merging shells/smallApps/extract~
CONFLICT (add/add): Merge conflict in shells/smallApps/extract~
Automatic merge failed; fix conflicts and then commit the result.

In that case, your files differ significantly from your friend's ones and Git cannot decide which file to take. You need to run apparently the following

git rebase

and you get

shells/smallApps/extract: needs merge
shells/smallApps/extract~: needs merge
cannot rebase: you have unstaged changes

Exercise 1 : However, I am now in stuck, since my tig does not show my friend's commit at my Git tree. How can you get your friend's commit 76a32 to your Git tree which branch is in your Git?


You may now have solved the problem. The problem was in that I ignored to solve the conflicts about which Git gave me notifications. Google saves the day again at the official Git site:

If there are conflicts--for example, if the same file is modified in two different ways in the remote branch and the local branch--then you are warned --

The next problem is to clean up the problematic parts and merge again. You see something similar to the following in your problematic files -- have fun! (I finally get to real problems ;)

alt text http://dl.getdropbox.com/u/175564/exampleGitProblemSolving.png


Problem in diffing and merging dotFiles in Mac's FileMerge

I needed to update my Git, since only the newest Git has difftool -command. You can find a solution at the thread.

Difftool allows you to start dotFiles in FileMerge from terminal. You cannot access them in GUI. It works like

git difftool master:README dev:README

Problem with your account in Github after adding a new remote account

Your Github account may have been disappeared in .git/config. In that case, you need to run the following code

git remote add -f YourUserName [email protected]

You then may notice that you cannot git-push normally by

git push origin master

You may get the following error message

fatal: 'origin' does not appear to be a git repository
fatal: The remote end hung up unexpectedly

You may also try the following commands to solve the problem

git push Masi master

and all 3 under 2 permutations of Masi, master and origin. However, none of the commands did not work.

Exercise 2: How can you commit to your github account as you have a teamMate in your remote list?

Origin is a shortname for your actual external git-repo, for instance, at Github. The content of your variable origin may have been replaced by another remote repo. In this case, I recommend you to create a new variable by

git remote add github [email protected]:myLogin/myProject.git

Note that you could have origin2 in the place of github. Origin is just a convention in naming the repo.

You can then simply run

git push github master

You may have a passphrase in your ssh-key. If you have, you may get a permission denied -warning. If you did, please see the thread.

like image 5
Léo Léopold Hertz 준영 Avatar answered Oct 22 '22 16:10

Léo Léopold Hertz 준영


Truth be told, I started to work on typing a nice, long, detailed response... but I this is already explained much better than I could at http://excess.org/article/2008/07/ogre-git-tutorial/. He covers the use of different branches, remotes, and merging. It's also done in screencast, so take an hour, grab some coffee, and enjoy the lecture.

Specific to your question: you shouldn't use a directory setup. Git doesn't handle branching with directories in the same way that SVN does with branch folders. Branches in git are an entirely different thing. While you may not setup a central repository (I recommend it), you should setup a single master branch that everybody commits their final, clean work to.

One example repository of mine has a screenshot at Wikimedia Commons. In my example, "bartender" submits his code only in tar chunks, so I have to import it myself to manage it. "master" (shown here only as remotes/elf/master) is a public svn repository that I import and base changes off of. "autocracy" is my own baseline for the code, and "private" is where I keep a config file with passwords that I want to manage but never publish. Check the timestamps on private, and you'll notice they don't line up with the branches below. This is because I rebase that branch onto "autocracy" instead of merging.

You'll notice two remote references: elf and bard. These are two remote machines of mine that host the software. I can push and pull my branches to there as I wish. In your case, you'd have remote repositories of your other developers, and they'd modify their own branches. Watching the tutorial will give you a better idea of how it works. Good luck :)

like image 4
Jeff Ferland Avatar answered Oct 22 '22 15:10

Jeff Ferland