一个单独开发者在本地仓库上的Git工作流程

6

我正在尝试优化个人的git工作流程,使其更易处理。

以下是我在本文中使用git的背景:

  • 单个开发者是唯一在仓库上工作的人。

  • 仅有一个存储在本地机器上的仓库副本。

  • 只有"dev"和"master"两个分支。

  • 所有工作都在"dev"分支上完成。

我想要实现的目标是让"master"分支上的提交版本只基于经过确认稳定的"dev"代码的工作生产版本。

实际上,我想要做的是:

  1. 当"dev"中的所有内容都经过测试并准备就绪时,更新"master"以成为"dev"分支文件树的精确克隆。

  2. 对"master"进行小修改以更新版本号等内容...

  3. 提交到更新后的"master"分支。

  4. 从"master"分支创建一个新标签。

我处理第一步的方法是切换到"master"分支,然后运行:

'git diff master dev | git apply -'

据我所了解,这将有效地清除“master”中的任何内容,并用“dev”的内容替换整个树。运行“git status”似乎显示这是基于上述#1所期望的结果。因此,第一个问题是:这正确吗?
在“master”分支接收到这些更新之后,我运行我的脚本来更新文件中的版本号。然后,我只需运行标准的“git add。”和“git commit -a”以添加所有更改。最后,我创建一个新的标签并返回到“dev”分支继续编码。所以,另一个问题是:在这个过程中会有任何引起问题的地方吗?
更新:我应该在第一次发布时就把这个放进去,但我之所以不简单地使用合并,是因为在主分支上更改版本号,然后尝试与开发分支中的更改合并会导致合并冲突。我知道它们是无关紧要的,但它仍然会停止这个过程。我之前使用过“merge -Xtheirs {branch}”来处理它,但我对此不太确定。
更新2:这里有一些我知道行不通的东西。我已经组合了一个适用于Mac OSX的bash脚本。第一个尝试使用合并:
#!/bin/bash -x

####################
### file: merge1 ###
####################

### clear out the old stuff so you can rerun
rm -rf .git
rm *.txt

### setup the repository
git init

### ignore merge and output files for clarity sake
echo -e "output*\nmerge*" > .gitignore
git add .gitignore

### make the intial commit and move over to dev
git commit -m "Initial commit"
git checkout -b dev

### add stuff to test1.txt in dev
echo -e "FILE1 LINE\nVERSION-XXX\nFILE1 LINE" > test1.txt
echo -e "File2 LINE\nVERSION-XXX\nFILE2 LINE" > test2.txt

### add the files and commit
git add .
git commit -m "Created test1.txt and test2.txt in dev."

### output the state of test1.
cat test1.txt > output-dev-test1-a.txt
cat test2.txt > output-dev-test2-a.txt

### move to master and do a first merge which will work
git checkout master
git merge dev

### Update the version numbers in master and commit it
sed -i "" -e 's/VERSION-XXX/VERSION-1.0/g' test*.txt
git commit -am "Updated version to 1.0 on master"

cat test1.txt > output-master-test1-a.txt
cat test2.txt > output-master-test2-a.txt

### switch back to dev and commit an update to test1.txt
git checkout dev
sed -i "" -e 's/LINE/CHANGED/' test*.txt
git commit -am "Updated content in test*.txt on dev"

### dump test1.txt for reference.
cat test1.txt > output-dev-test1-b.txt
cat test2.txt > output-dev-test2-b.txt

### swtich back to master
git checkout master

######################################################################
### BREAK
######################################################################

### this is where the merge fails because of a conflict
git merge dev

我尝试的另一种方法是使用-Xtheirs,一开始看起来似乎可以工作,但它并不更新所有内容。为了看到这一点,您可以删除上面“BREAK”后面的最后几行,并将其替换为:
### merge with -Xtheirs works here. Proper version "XXX" is showing.
git merge -Xtheirs dev

### but if we update the version number one more time on master
sed -i "" -e 's/VERSION-XXX/VERSION-2.0/g' test*.txt
git commit -am "Updated version to 2.0 on master"

### dump reference file
cat test1.txt > output-master-test1-b.txt
cat test2.txt > output-master-test2-b.txt

### Now, go back to dev and change something in only one of the files
git checkout dev
sed -i "" -e 's/CHANGED/ALTERED/g' test2.txt
git commit -am "Altered only test2.txt on dev."

cat test1.txt > output-dev-test1-c.txt
cat test2.txt > output-dev-test2-c.txt


### are finally return to master and merge again
git checkout master
git merge -Xtheirs dev

### dump reference file
cat test1.txt > output-master-test1-c.txt
cat test2.txt > output-master-test2-c.txt

没有冲突,但是'output-master-test1-c.txt'显示的是'VERSION-2.0'而不是所需的'VERSION-XXX'。看起来这是由于文件没有发生任何更改所造成的。'output-master-test2-c.txt'文件包含了预期的'VERSION-XXX'字符串。问题在于,尝试更新到3.0版本的查找和替换会在test1-c中失败,因为它无法识别VERSION字符串的2.0部分。

3个回答

7
您应该使用真正的合并而不是diff/apply hack。这很简单,只需
[master]$ git merge dev

当您在主分支上运行此命令(显示在提示符中),您将合并所有来自dev的更改。之后,您可以更新版本号,提交并创建标签。
[master]$ git commit -a -m "New version number."
[master]$ git tag version-1.x

就是这么简单。

实际上,您根本不需要主分支,您可以基于dev创建一个短期的发布分支,创建一个标签,然后删除该分支。

[dev]$ git checkout -b release dev
[release]$ git commit -a -m "New version number."
[release]$ git tag version-1.x
[release]$ git checkout dev
[dev]$ git branch -d release

我本应该在最初就把这个放进去,但是我在合并时遇到的问题是它总是出现需要解决的冲突。我相信这是因为我在将版本从dev移动到master后进行了更改。因此,当标准合并进来时,它会看到这一点并抱怨。我想避免处理这些问题。我只想让事情正常工作,并且我更喜欢保持master最新。(尽管我需要考虑像你建议的从tmp发布分支创建标签。) - Alan W. Smith
在我以前有一个中间分支的旧流程中,我使用了“git merge --no-ff -Xtheirs”。但我不确定它的确切工作方式。 - Alan W. Smith
我在回答的第二部分提到的发布分支方法将让您避免冲突。 - Adam Byrtek
那么什么时候使用 master - Abhishek Gupta

1

我做的事情非常相似(只有在我自己的软件上是唯一的开发人员时)...

我仅在主分支上工作。在不同的“版本”中,我创建一个悬空分支。

这使我能够通过检出来回到任何以前的版本。

A - B - C - D - E - F
     \               \
      1.0             1.1

对于我的需求来说,这很容易且足够好用。

如果我需要修复之前版本的一些错误,我只需从该分支开始工作并完成它们。


0

我想到了另一种方法来解决这个问题,我认为它可以满足我所有的需求。它的核心是在主分支上执行以下操作:

### pull the diff to make sure there are no conflict
git diff master dev | git apply -

### do merge without commit to make branch tree behave
git merge --no-commit --no-ff -s ours dev

### update the version numbers
sed -i "" -e "s/VERSION-XXX/VERSION-$1/g" *.txt

### now, add everything to master and commit
git add . 
git commit -m "Master commit $1"

这样可以确保“dev”中的所有版本号都保持为“XXX”,但在“master”中的所有文件中得到适当的更新。此外,在gitk中查看“master”分支的历史记录,您可以看到特定的“dev”版本是何时添加的。例如:

dev:      d1----d2----d3----d4----d5
         /  \           \     \
master: x    m1          m2    m3

这棵树是我一直在寻找的,让我更容易理解正在发生的事情。

这里有一个bash脚本(在Mac OSX上编写,如果有关系的话),我用它来测试和弄清楚这个问题。如果您有兴趣尝试其他策略,只需更新“doMerge”函数并运行脚本即可查看发生了什么。

#!/bin/bash

######################################################################
# Setup functions
######################################################################

function doMerge {

  ### add everything in dev
  git add .
  git commit -m "Commiting dev $1"

  ### switch to master
  git checkout master

  ### pull the diff to make sure there are no conflict
  git diff master dev | git apply -

  ### do merge without commit to make branch tree behave
  git merge --no-commit --no-ff -s ours dev

  ### update the version numbers
  sed -i "" -e "s/VERSION-XXX/VERSION-$1/g" *.txt

  ### now, add everything to master and commit
  git add . 
  git commit -m "Master commit $1"

  git tag -m "Created tag v-$a" -a "v-$1"

  ### and then switch back to dev so you are ready to work
  git checkout dev

}


### this just lets you see what's going on in the output
function showReport {

  echo "############################################################"
  echo "##### 'dev' branch files #####"
  echo "############################################################"

  DEVCNT=1
  while [ $DEVCNT -lt 4 ]; do
    cat $DEVCNT.txt
    echo "############################################################"
    let DEVCNT=DEVCNT+1 
  done

  git checkout master


  echo "############################################################"
  echo "##### 'master' branch files #####"
  echo "############################################################"

  MASTCNT=1
  while [ $MASTCNT -lt 4 ]; do
    cat $MASTCNT.txt
    echo "############################################################"
    let MASTCNT=MASTCNT+1 
  done
  echo ""

  git checkout dev

}


######################################################################
# Main
######################################################################

### clear out the old stuff so you can rerun
rm -rf .git
rm *.txt

### setup the repository
git init

### ignore merge and output files for clarity sake
echo "check-history" > .gitignore
git add .gitignore

git commit -m "added .gitignore"

### switch to dev
git checkout -b dev

### add some files
COUNTER=1
while [  $COUNTER -lt 10 ]; do
  echo "File $COUNTER - VERSION-XXX" > $COUNTER.txt
  echo "The quick brown fox jumps over the lazy dog" >> $COUNTER.txt
  let COUNTER=COUNTER+1 
done

### run the diff/apply/merge strategy and show the results
doMerge 1; showReport


echo "File 2 - VERSION-XXX" > 2.txt
echo "New Data" >> 2.txt

git commit -am "dev tmp commit 1"

echo "Additional data" >> 1.txt
echo "Additional data" >> 2.txt

doMerge 2; showReport

sed -i "" -e 's/quick/EXTREMELY FAST/' 3.txt

doMerge 3; showReport

从我的理解来看,这个方法是有效的。我将尝试一下并且如果发现了什么问题,会在这里反馈。当然,如果您知道其他更加正规的做法,我也非常感兴趣。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接