Asked  6 Months ago    Answers:  5   Viewed   93 times

I'm working on a team with a few developers using git on BitBucket. We are all working on a dev branch, not pushing to master until a release.

One of the developers committed incorrect code that overwrote my own by accident, and now I am trying to push the correct code back to the repo. I have been reading on this error for a few days now, I can't push to the repo anymore because I am getting the following error:

 ! [rejected]        master -> dev (fetch first)
error: failed to push some refs to 'https://myusername@bitbucket.org/repo_user/repo_name.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

I follow the instructions and pull, but then I receive a merge conflict. After entering a message for the merge conflict, my local code is now the incorrect code that the other developer uploaded by accident (as expected from the pull). So I replace the incorrect code with the backup I copied before commiting, and when I try to push again, I get the same error.

It is really frustrating, I really want to help out my team and contribute, but I can't because of this error. Does anyone know how to solve this issue? I would very much appreciate any help.

These are the commands I run in order to commit, if it helps anyone out:

git pull remotename master:dev
git add --all
git commit -m "some message"
git pull remotename master:dev
git push remotename master:dev

I would have thought that if I kept this order, I would not receive merge conflicts. I guess I was wrong. Thanks again

Update: I should add that I have looked for a few hours on Google and stackoverflow, and followed different instructions, but I still can't push to the dev branch.

 Answers

79

git pull <remote> master:dev will fetch the remote/master branch and merge it into your local/dev branch.

git pull <remote> dev will fetch the remote/dev branch, and merge it into your current branch.

I think you said the conflicting commit is on remote/dev, so that is the branch you probably intended to fetch and merge.

In that case, you weren't actually merging the conflict into your local branch, which is sort of weird since you said you saw the incorrect code in your working copy. You might want to check what is going on in remote/master.

Tuesday, June 1, 2021
 
nomie
answered 6 Months ago
93

Merging a branch means that you want to add the changes suggested by the branch. You can NOT selectively merge a branch. It get's merged as a whole.

To see what is the diff b/w two branches for reviewing before merging, run

git diff master my_branch

If you don't feel like the code in the my_branch is up to your standards OR is errorenous, don't merge it.

Saturday, May 29, 2021
 
scessor
answered 7 Months ago
68

This happens if you initialized a new github repo with README and/or LICENSE file

git remote add origin [//your github url]

//pull those changes

git pull origin master 

// or optionally, 'git pull origin master --allow-unrelated-histories' if you have initialized repo in github and also committed locally

//now, push your work to your new repo

git push origin master

Now you will be able to push your repository to github. Basically, you have to merge those new initialized files with your work. git pull fetches and merges for you. You can also fetch and merge if that suits you.

Monday, June 7, 2021
 
themihai
answered 6 Months ago
89

in order to see the differences, first you need to fetch the commits from the origin repository:

git fetch origin

Now you can see the diffs (Assuming you are on the master branch) git diff HEAD..origin/master

Now you are armed with the knowledge you seek to decide to merge or rebase before pushing your changes.

Friday, June 11, 2021
 
Wilk
answered 6 Months ago
29

This is all moderately difficult (actual difficulty level varies depending on circumstances and your familiarity with Git).

If the files in E and F are truly identical, the (or an) easy way to do this would be to put in a graft (with git replace or the grafts file) so that Git pretends that G's parent commit is commit E. That is, you have:

A--B--C--D--E   <-- master

F-------------G--H--I   <-- refs/remotes/rem/P1

and git diff master rem/P1~4 produces no output at all (master names commit E, rem/P1~4 names commit F, and the two trees for E and F match exactly).

You wish, at least as an intermediate product perhaps, that you had this:

A--B--C--D--E   <-- master
             
F             G--H--I   <-- refs/remotes/rem/P1

That is, you'd like Git to pretend, at least for some purposes and some period of time, that commit G has commit E as its parent.

Using git replace to emulate the old horrible-hack grafts

Git grafts do precisely that: they tell Git to pretend that the parent(s) of some commit is some other commit(s). But these have been deprecated in favor of the more generic git replace. You can use git replace to make a new commit G' that resembles (but supersedes, at least, for most Git commands) G, with the one difference being that G' has E as its parent.

You can then use git filter-branch to re-copy commits in the repository so that this replacement becomes real and permanent, rather than just a copy. You will, of course, get new commit hashes for the new commits (G' can keep its hash but you must get a new H' and I'). See this answer by Jakub Narębski, and then How do git grafts and replace differ? (Are grafts now deprecated?), where VonC links to Jakub's answers.

(Git grafts do still work, and you can just put the hash for commits G and E into .git/info/grafts: echo $(git rev-parse rem/P1~3) $(git rev-parse master) > .git/info/grafts, for instance. But they are a horrible hack and if you do this sort of trick it's best to just run your filter-branch immediately afterward, as Jakub notes.)

Using git rebase

You can also use git rebase --onto, as you were attempting, but you must start this rebase using an existing (ordinary, local) branch name (I'm not sure where emptybranch came from here) that points to commit I. I think maybe the step you are missing might be making this regular ordinary local branch name:

git checkout -b rewrite rem/P1

for instance, assuming the name rem/P1 resolves to commit I. Or git checkout -b rewrite <hash-of-I>, if you have that hash in front of you for easy cut/paste. At that point you will have this:

A--B--C--D--E   <-- master

F-------------G--H--I   <-- HEAD -> rewrite, rem/P1

That is, you're now on this new rewrite branch, which points to commit I. Now you can git rebase --onto master HEAD~3 to copy the most recent 3 commits on the current branch—G, H, and I. The copies will be G', H', and I', with the parent of G' being E—the commit to which master points—and the parent of H' being G' and so on:

              G'-H'-I'   <-- HEAD -> rewrite
             /
A--B--C--D--E   <-- master

F-------------G--H--I   <-- rem/P1

Now you can delete the remote and its remote-tracking branch since you have the commit chain you want. You can also fast-forward master to point to commit I' at any time, if that's what you want.

Sunday, August 15, 2021
 
Alexander Trauzzi
answered 4 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share