I have forked original repository into my github account and cloned the same into my workspace. After working for a week on my local branch I want to push my local branch to my forked repository and then merge it with original repository. But I can see that files that I have modified in my local branch have also been modified in the original repository. I can think of two approaches for merging my local branch safely.
Should I first get the latest changes from the original repository into my local branch using git pull? In this case will the complete file be overridden or only parts of the file that has changed in the original repository preserving my local changes.
Second approach is to go ahead with pushing my changes to my forked repository and then merge it with original repository. Here I am assuming that Git considers a conflict only if there are two different versions of the same line in a file. In case the two versions of the file have changes in different parts of the file they can be merged safely.
I am also little unclear about when Git merges two versions of a file. How does it decide which version of the file will take precedence over the other.
Any other approach to do the same is welcome.
First of all, in such scenario it is hard to avoid conflicts at all, and generally working on the same repository with other people you should be prepared to resolve conflicts once in a while.
In your case I would use git rebase and utilize git branches, which are a really useful feature when used well.
Create separate branch with your changes locally
Revert your local master branch to the state before this changes
Update local master branch with changes from the original repository
Push your master branch to your remote repository (so that your forked version matches the original repository)
Rebase your local feature branch onto master. In this step you'll probably need to resolve some conflicts. But it would be easier, as you are based on current master (destination of your changes), and you are in control what should go in, and what should not. Also, you can easily test your solution after rebase, and make some changes before issueing a pull request.
Push local feature branch with your changes to your remote repository.
Create pull request to the original repository.
// I assume that your local master branch is set up to track origin/master branch, where origin is your forked version of the original repository.
// 1. Local branch named "my-new-feature"
$ git branch my-new-feature
// 2. Reset your master branch back to the state before changes
$ git fetch origin
$ git reset --hard origin/master
// 3. Update local master branch. First you need to add the original repository as a remote (let's name it "upstream")
$ git remote add upstream https://github.com/some-user/some-project.git
$ git fetch upstream
// you should still be on your local master branch. Now update this local branch with changes from the original repo
$ git rebase upstream/master
// 4. Push your local master to your forked repository
$ git push origin master
// 5. Rebase your changes onto master
$ git checkout my-new-feature
$ git rebase master
// This is the place where you are most likely to have conficts. Read git messages, as it helps you what to do.
// Once all conflicts have been resolved, stage your changes but do not commit. If committed they will not be detected by ongoing rebase.
$ git add .
$ git rebase --continue
// 6. Push your local branch with newest changes
$ git push origin my-new-feature
// 7. Issue a pull request on GitHub using your just pushed branch
Also, git merges two files based on the direction of the merge. If you are on a branch A-branch, and you run git merge B-branch, then files from B-branch have "higher priority" and their changes will be most likely applied automatically.
I will suggest the first approch as you listed: pull the changes from the original repo first. Reasons as below:
It will save energies for the users who view pull request and merge the branches.
If there has conflicts for mering the pull request, you should also resolve the conflicts again in your local repo, and then push to the fork repo again.
Pull changes from the original repo only overwrite parts of files not all files. Situations as below:
Files neither changed in original repo nor your local repo: these files won’t changed.
Files changed in the original repo but not changed in your local repo: these files will be overwrited as the version of the original repo in your local repo.
Files not changed in original repo but changed in your local repo: these files won’t be overwrite.
File both changed in original repo and in your local repo: these files will show as conflicts, you should resolve the conflicts manually.
To pull the changes from original repo, you’d better pull with --rebase option (pull the change from original repo first, then apply your local changes on the top of the latest original repo:
git pull <remote> <branch> --rebase
Assume the commit histroy as below after git fetch (origin is the remote for the fork repo, upstream is the remote for the original repo):
…---A---B---C---D---E master, origin/master
\
F---G---H upstream/master
Then you can execute below commands:
git pull upstream master --rebase
git push origin master -f
Then the commit history will be:
…---A---B---F---G---H---C'---D'---F' master, origin/master
|
upstream/master
Then you can create a PR to merge the fork repo master branch into the original repo. It will be convenient for PR viewers and approvers.
Related
I justed messed up my GIT Remote Repository and Local repository by updating the current code with older commit using git checkout <revision-no>.
Assume that I am at commit state A-B-C-D and I want to revert the complete project state to B, which means I want same package structure and files as it was pushed to B. Is there a way to do this?
I tried git reset --hard HEAD, unfortunately I am still seeing files committed at level D in my local repository and remote repository.
Maybe you are in a "detached state" since you did a git checkout {commitId}.
This may work:
git checkout master and then
git reset --hard {commitId of B}
In general, git checkout is for updating(reverting) the local working files and modifying the position of the HEAD pointer. It can be used for looking at previous commits and switching branches without actually changing anything in the project. git reset is for actually modifying a branch pointer to revert a project branch to an earlier commit. At this point, your HEAD is still pointing to an earlier commit. So you need to set it back to end of the current branch:
git checkout <branch name>
I have a local workspace which I want to save in git, this wasnt a local git repo until now.Just workspace
The steps I did in git bash
cd myworkspace
git init
git add .
git commit -m "First commit"
git remote add origin https://github.com/username/eclipse.git
git push origin master
By doing this I got an error
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to 'https://github.com/username/eclipse.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
then I did this
git pull origin master
warning: no common commits
remote: Counting objects: 4, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (4/4), done.
From https://github.com/koushikpaul1/eclipse
* branch master -> FETCH_HEAD
* [new branch] master -> origin/master
fatal: refusing to merge unrelated histories
Anyone can help me with this error ,
Note : I created my git repo as a java one so currently it has only
.gitignore and README.md
while googling I found the steps to check in an existing workspace into git are
$ cd my_project
$ git init
$ git add *
$ git commit -m "First commit"
$ git remote add origin https://github.com/yourname/my_project.git
$ git pull origin master
$ git push origin master
But I am stuck at the second last step.
Many Thanks !
The issue here is you already init repository on your local workspace which already contain some files. When you create repository on GitHub and init it with .gitignore and README.md it also contain some files.
When you push your project git will reject because it does not know how to merge your content.
Here are solutions
Use git push -f which will push all your local repository to remote repository but this will also replace .gitignore and README.md, then you can them manually later.
Delete your remote git repository and reinit it as bare repository (do not check init with .gitignore, README.md) then try to push again.
Just clone remote repository to your local workspace then manually add your files to the cloned repository
For more info visit:
https://help.github.com/articles/creating-a-new-repository/
See number 5.
There are a number of optional items you can pre-populate your
repository with. If you're importing an existing repository to GitHub,
don't choose any of these options, as you may introduce a merge
conflict. You can choose to add these files from the command line
later.
You can create a README, which is a document describing your project.
You can create a .gitignore file, which is a set of ignore rules.
You can choose to add a software license for your project.
I have a new project in Eclipse in the directory ProjectDirectory which contains the src, lib, etc. folders. Note that this project has never before communicated with any repository.
I have a git repository https://github.com/myrepo/mygit.git with a username user and a password pass (note that this is fake info). In that repository, I currently have some files.
I want to do the following.
Remove ALL the current contents in the git repository
Add the new contents from my Eclipse project into this repository. This should result in no conflicts or no errors whatsoever, since I want to completely replace the current repository with these files.
With specific instructions, what set of commands in the terminal would I write to accomplish this?
Its fully simple. First go into the directory in terminal where the eclipse project is.
To start putting this under version managment:
git init
Then add the origin as the git repo ( copy your ssh read+write access from github, this you see when you are loggin in on github and navigates to the actual repositorys directory ):
git remote add origin <copied_adress_from_github>
So now in the last step you will need to overwrite forced the remote repo with:
git push -f origin master
You can start commiting, making branches etc... However if on the remote repo there was other branches you want to remove them with:
git push origin --delete <branch_name>
I have gone thru the egit tutorial doc here http://wiki.eclipse.org/EGit/User_Guide.
I now have a git repository with an eclipse project on my laptop and can push this to a remote git repository on git hub. However, this means I have two git repositories - one local and one remote. I'm thinking I'd prefer to just use the remote one only. This would mean any time I commit, it commits to the remote and there is no local repository.
Is it possible to this egit?
Thanks.
git is a distributed version control system. By definition this means that each developer has its own repository.
I have not experience with egit but you can configure a hook to automatically make a push after a commit.
Also, in a git cli you could set an alias to make the commit and push process in only one step, but anyway, the local repository will be need.
You should always have a local repository to work with. First pull the repository to local repository, perform changes and push back to the remote repository.
I have a situation where I have an elderly CVS repository which we would like to convert to git once and for all while keeping full history etc.
All folders at the root of the repository contains Eclipse projects (either plain or dynamic web projects) including .classpath and .project. We use Team ProjectSets to check out the projects we need for a given task (where the project set is located in the project containing the main, and the rest are library projects).
When the Team ProjectSet is checked out, the workspace is fully populated.
This approach has worked pretty well for many years (except the project set part which came with 3.5), and we would like to work in a similar way with git if possible, but we are uncertain how.
I've played somewhat with git cvs import but it failed - probably due to us not using modules.
How would you suggest we do this, and how should we work with git to allow our current usage of shared library projects? Would we HAVE to introduce maven and create maven modules for our library projects? Or just ant ivy?
EDIT: I've now managed to convert our CVS repository to Subversion with a suitable cvs2svn invocation and found that Eclipse recognizes the resulting Subversion repository nicely. Unfortunately after cloning http://github.com/iteman/svn2git` and trying to run bin/svn2git I get
tra#Sandbox:~/cvsgit/svn2git/svn2git$ bin/svn2git
bin/svn2git:35:in `initialize': wrong number of arguments (2 for 1) (ArgumentError)
from bin/svn2git:35:in `new'
from bin/svn2git:35
This is with Ubuntu 10.04.1 LTS Server and I've tried various sudo things with Ruby and its gems without fully understanding what I did as I am not a Ruby programmer so I may have messed up things a bit. I'd appreciate advice - if the easiest is to install another Linux variant to do the conversion, that is fine.
EDIT:
https://help.ubuntu.com/community/Git
http://css.dzone.com/articles/subversion-git-morning
Edit: My first try with the default svn2git completed successfully (after a while), and I get a nice repository where git branch -a reports roughly
tra#Sandbox:~/gitroot/svnroot$ git branch -a
* master
remotes/XX64_DEPLOYED_CODE
remotes/Beta1
remotes/Beta2
remotes/SV46
... lots more
We are interested in being able to check out the SV46 branch and work with it (we basically do not care about the tags, just actual branches). I have set up gitosis and pushed this repository to gitosis, and cloned it to another computer to find out how to do the "work with SV46" bit with Eclipse. THAT repository does not know of all the branches:
tra#TRA ~/git/git00 (master)
$ git branch -a
* master
remotes/origin/HEAD -> origin/master
remotes/origin/master
Do I need to massage the original result from svn2git to get the information into the gitosis repository? Do I need to clone with an argument? Should I redo the svn2git step with the suggested version instead of the one shipping with Ubuntu?
EDIT: It turned out that publishing the svn2git generated repository with "git push --mirror" made things shown up in the gitosis repository. I now see the following inside gitosis (trimmed):
tra#Sandbox:/srv/gitosis/repositories/git01.git$ git branch -a
* master
remotes/XX64_DEPLOYED_CODE
remotes/Basic_Beta1
remotes/Beta1
remotes/Beta2
remotes/SV46
... lots more
tra#Sandbox:/srv/gitosis/repositories/git01.git$ git branch
* master
tra#Sandbox:/srv/gitosis/repositories/git01.git$ git tag -l
tra#Sandbox:/srv/gitosis/repositories/git01.git$
Trying to clone this repository with git clone gitosis#sandbox:git01 -b remotes/SV46 or git clone gitosis#sandbox:git01 -b SV46 both tell me that the remote branch is not found upstream origin, using HEAD instead.
Am I barking up the wrong tree?
First of all, using submodules for independent parts of your Central VCS repository (i.e. your CVS repo) is always good (see "What are the Git limits?").
That mean you will end up with many independent Git repo, that is "set of files evolving independently one from another", which is why submodules exist.
So multiple Git import (in multiple repo) are required.
But since git cvs import is not always up to the task, I would recommend:
cvs2svn in order to get an SVN repo first (just one repo)
svn2git in order to properly convert your SVN repo to a git one (i.e. transforming SVN branches into Git branch and SVN tags into Git tags)