The company that I'm working is working with SVN but I would like to start working with git to take advantage of the light branching and stashing features (disclaimer, I'm pretty new to git). I've started with git-svn and I'm trying to figure out the ideal git-svn workflow for what I'm trying to do (and suggestions if what I'm trying to do needs tweaking).
I've read through git svn workflow - feature branches and merge and a few other posts but its still not clear how I should approach it.
How I plan to work:
I plan on having my master branch be clean from development and only used for merging/rebase/dcommit.
I would like break apart each new feature/bug into separate git branches so they can be worked on independently. Meaning, I can work on one feature for a few hours, then put it aside and work on the next issue. When I was in SVN it was a problem when I had two different features/bugs in one file because when it came time to commit, I would remember that it had both changes and temporarily take out what I didn't want to commit now - a pain.
And the are some features which are while I might want to work on now, will not be added to the main repo for some time.
After a feature is ready to be shared/tested in the main repo, I'll merge/rebase into my master branch and then dcommit to the svn-repo. I only want to have one SVN commit message for each dcommit - I want to be committing in more often with comments more specific to me and then dcommit to svn with a message for the rest of the team. I assume for this I'll either be using a git merge --squash or a git rebase --interactive for this.
The basic git flow I've envisioned is like this:
// it begins...
git svn clone <repo>
//
git checkout -b feature 1
// work commit, work commit
//
git checkout -b bug-123
// work commit, work commit
// bug-123 finished - ready to send back
// got back to master for step 5
git checkout master
// get whatever changes other devs did
git svn rebase
//
git checkout bug-123
// rebase branch so I have fewer smaller changes. not sure here..
git rebase master || git svn rebase
// Assuming I'm doing a FF rebase so my commits are just addons to the current repo
// I don't know if I rebase the master or svn repo or it doesn't matter.
// need to get my changes back to master to send off
git checkout master
// add my changes to master
git rebase bug-123 (--interactive?) || git merge --squash bug-123
// do I add a new commit message here?
// push my changes back out to the team
git dcommit
So there are a few questions:
How should I get the changes into the branch I want to commit - by rebasing the master or the svn branch
how do I get the changes back into the main branch - rebase or merge - remember, I want only one commit for each commit - unless this is going to complicate things - I really would prefer to keep my git commits separate from the SVN commits because I might start something - it's half-working, and want to commit it so I could try something else - but I don't want to commit these broken steps.
would it make sense to dcommit directly from the working branch (eg bug-123)?
how do I get the changes from bug-123 back now into feature-1? I'm assuming I'll do it via the SVN repo - meaning the changes that I added will get merged in when I do the rebase when it's time to add feature-1 to the repo - but maybe not.
I'm no expert, but these are the experiences I've made (related answer).
I think it doesn't matter. The important thing is that you rebase the latest changes from SVN into the branch you are going to dcommit from.
Let other branches receive the changes through SVN. If you want a single SVN commit from a series of git commits, squash them together first.
I think this doesn't matter either. You're going to rebase the latest changes from SVN, and need to get them linearly in front of your Git commits. If you do git svn rebase in master, and then rebase master into a feature branch, or the other way around is same-same. Afterwards you probably want to delete the branch, as it has done its work (as per SVN restrictions, you're not allowed to merge again).
Always let changes flow into other branches and repos through SVN rebasing.
Just try it out and try to get the most simple/practical workflow for you and your team. Try to keep branches short-lived (SVN won't get any notion of them anyway), and remember that the commits must always be linearized at the top of your log before you dcommit back.
Related
I have looked at many past posts without a specific response. I used git reset --hard to get me to a point in time when my code was not all jacked up. Yes I should have used a branch but I didn't. Now I have a message of HEAD is now at 0600b73 fixed error. What I would like to know is how to commit those changes, so I can push them back to Git, so they are the current head? I am not even sure if VS Code even recorded the changes. Git can be confusing so any help would be appreciated.
You haven't actually proven you have changes, HEAD is now at 0600b73 fixed error., that does not mean you have changes. That basically means that you moved the HEAD of git to a commit, generally you want it on a branch.
git status will tell you if you have things that need to be committed.
I am not even sure if VS Code even recorded the changes
VScode has some cool features around git but it doesn't actually record changes, unless you are referring to saving files. If you save the file, well it saves.
What you probably want to do is (I am assuming you actually do have changes):
confirm you have changes git status
move to a branch git checkout -b my-fix
add those changes git add . (adds all changes/also make sure you are at the root of the repo) or git add -p will let you look closely at changes and give you an interface to decide if you want to stage the change or not.
commit the changes git commit -m "Your message" or you can do a longer message with git commit -p
At this point you can merge this branch in to master, push the branch. It's up to you.
push your changes, git push origin my-fix, make a pull request and merge to master. You will then want to change to master and pull master
merge git checkout master , git merge my-fix
rebase git checkout master , git rebase my-fix
Here is some git learning material:
https://learngitbranching.js.org/
https://www.codecademy.com/learn/learn-git
https://try.github.io/
https://www.atlassian.com/git
I am using git-svn in my workplace since our current version control server is subversion and switching completely to git does not seem to be on the horizon for now (*cry*)
My workflow is as follows
I have the following branches
master tracks remotes/trunk
local/0.4 tracks remotes/0.4
work is my development branch for the master branch
work-0.4 is my development branch for the local/0.4 branch
I work in my work branches, then I merge to master and local/0.4 using
git merge --no-ff <branchname>
After that I check in to svn via
git svn dcommit
and I use
svn.pushmergeinfo=true
to update the svn:mergeinfo properties so my colleagues won't get angry with me messing up that metadata for them :)
However, I just had the following problem which stumps me.
I had done two commits on the work-0.4 branch, then I merged these to my local/0.4 branch with git merge --no-ff work-0.4. After this, I did git svn dcommit and recieved the following message
Committing to https://svn-server ...
e138050f6ebd2f2ca99cbefc5e48acae412e1f86 is merged into revision f5f2345e8e5fc64
20423bdc00397b5853b3759c4, but does not have git-svn metadata. Either dcommit the
branch or use a local cherry-pick, FF merge, or rebase instead of
an explicit merge commit.
After some rebasing and reset'ing of branches I managed to push everything to svn, but my solution entailed doing a rebase of my local/0.4 branch to the work-0.4 branch which in turn meant that I did not get to squash my two git-commits into one svn-commit :/
I feel that I'm probably doing something wrong with my workflow here, and it might be related to svn.pushmergeinfo. The docs for svn.pushmergeinfo says
config key: svn.pushmergeinfo
+
This option will cause git-svn to attempt to automatically populate the
svn:mergeinfo property in the SVN repository when possible. Currently, this can
only be done when dcommitting non-fast-forward merges where all parents but the
first have already been pushed into SVN.
and to be honest, I'm not quite sure that I understand that correctly? Am I doing something weird here that makes svn.pushmergeinfo not work correctly? How should I structure my workflow to optimally work with git-svn correctly (setting proper mergeinfos etc)?
I am working on a git-svn project with two branches, lets call them
trunk
branches/foo
How can i merge branches/foo to trunk?
they both have the latest update
Thanks
It is inadvisable to merge two SVN branches via Git. If in Git you merge from your branches/foo clone to your trunk clone and then managed to successfully push back to SVN, the files would be correctly updated on trunk, but SVN wouldn't be aware that it's the result of a merge - no merge-tracking information will be updated in SVN.
In fact it gets more complicated than that - when you merge between two Git branches that are both tracking remote SVN repos, git-svn can get really confused and it's very easy to mess up your repository. This is because git-svn looks back through your Git log to find the SVN tracking information, and if it finds a merge then it won't necessarily head down the branch you expect. So even if you've merged from branches/foo into trunk and you're now on trunk, it's possible that a dcommit would push back to branches/foo.
Better to switch back to your regular SVN tools to do merges and just use git-svn for development.
Another roof option could be next:
checkout your trunk branch # git checkout -b trunk git-svn-trunk
and cherry-pick dev commits into trunk branch,
i prefer pick one by one and solve conflict slowly
after that you have a 2 branches with the same commits
maybe do you want remove dev branch and create a new dev branch from trunk branch,
now this branch (new dev branch) has a correct git-svn reference to your svn trunk...
keep recommendations write by #simonp answer
i hope this help to you
I've been using GIT for a couple of weeks now and trying to understand how to switch branches without commiting files. This is what I have done.
Cloned a git repository and have a local master branch.
Created a new local branch (Branch2) which is based on a remote branch.
Made changes to 2 files in the master branch.
What I want to do now is switch from master to Branch2.
The changes I made to the master branch are for local dev purposes only and should never be committed.
But when I try to do this in eclipse (i.e I double click on the local branch I try to switch to) it keeps telling me that there are uncommitted changes and I need to commit, stash or reset.
Can anyone tell me how i can make a change to a local file and have git ignore this change so that I don't get prompted with this message?
Note: if you need to stash a work in progress from Eclipse, Egit now supports stash:
Have a look at git stash. Stash allows you to store uncommitted changes.
Option 1
git stash
git checkout -b Branch2
Your changes will be stored in git (locally). When you want to re-apply those changes, you will do git stash pop and it will apply those changes for you.
Option 2
git stash
git stash branch temporarybranch
This will take your uncommitted changes to a new branch and keep them there for you. Compared to the previous option, this allows you to keep these branches on the server by pushing this new branch.
Hope it helps
If you don't want the changes to be ever made public you should just commit them in your own feature branch and not on the master branch.
You can create a new branch, give it a name that reflects the changes, maybe prefix is with something like "experimental-" and then commit to that branch before switching to your other branch.
You can use git stash to stash your changes, or use git stash to commit them directly to a new branch as mentioned by Ege Akpinar.
I can never seem to figure out how to use git. I just do random commands and it works eventually. This is what I usually do when I want to push:
Fetch from upstream
Commit
Push to upstream
However, the above steps don't work sometimes. For example, when I do fetch from upstream, my local branch doesn't get updated.
How do I merge the remote branch into my local branch? Is there a difference between pull and fetch?
"git pull" is equivalent to "git fetch" followed by "git merge"
What you want to do is:
git commit -am "your message here"
This commits your current changes locally, and only locally. Now, assuming branch "foo":
git pull origin foo
This does a "git fetch" followed by a "git merge". Everything in this step is done to your local branch, and still has no effect on the remote branch. Depending on how your git is setup, you might need to specify the branch.
If you have a merge conflict, you will have to fix the files listed, then add them back:
git add path/to/resolved.file
When you are done, push everything you have from your local changes, to the remote server:
git push origin foo
If you pull before committing, that might cause your local branch to not be updated.
tl;dr, always commit before pulling!
Well to understand differences betwene git fetch and git pull look here.
In the simplest terms, "git pull" does a "git fetch" followed by a
"git merge".
You can do a "git fetch" at any time to update your local copy of a
remote branch. This operation never changes any of your own branches
and is safe to do without changing your working copy. I have even
heard of people running "git fetch" periodically in a cron job in the
background (although I wouldn't recommend doing this).
Working with git in eclipse might be a little bit tricky, but if you understand git basics, you should cope with it. I recommend you to read one of git tutorials, so you will be able to understand basic git operations.
The first step to learn git: Don't use egit.
Now, you are fetching and pulling from upstream. That makes me think that several people have write-access to the same repository, so we probably don't want to be doing a whole lot of merges to complicate history. It would be best to do this. I'm assuming you have already committed a changes or a set of changes to your local master branch that you want to place on the upstream repository which has been pushed to by someone else while you were making your commits.
First, we fetch the new changes but don't use them yet. This updates upstream/master to the new head of the upstream master branch.
git fetch upstream master
Now, we need to pull in these changes. This command rewrites history, and we are assuming
that you have not published your changes anywhere yet.
git rebase upstream/master master
If you have published your changes, this messier command is the one you should use (do not use both, just use this one!)
git merge upstream/master master
Now, we can push:
git push upstream master
The first two steps can be shorted to git pull --rebase and git pull for the rebase and merge versions respectively.
If you are already on the master branch, most of those second arguments are superfluous but I wrote them in for clarity. Notably, giving a second argument to git-rebase or git-merge will simply check out that branch before doing the operation. Supplying master to fetch and push is only necessary if you don't have the refs set up to automatically fetch and push master.